OSDN Git Service

Nazghul-0.7.1
authormaruhiro <maruhiro@bridge.ocn.ne.jp>
Mon, 11 Feb 2013 11:47:51 +0000 (20:47 +0900)
committermaruhiro <maruhiro@bridge.ocn.ne.jp>
Mon, 11 Feb 2013 11:47:51 +0000 (20:47 +0900)
581 files changed:
AUTHORS [new file with mode: 0644]
COPYING [new file with mode: 0644]
ChangeLog [new file with mode: 0644]
INSTALL [new file with mode: 0644]
Makefile.am [new file with mode: 0644]
Makefile.in [new file with mode: 0644]
NEWS [new file with mode: 0644]
README [new file with mode: 0644]
aclocal.m4 [new file with mode: 0644]
config.guess [new file with mode: 0644]
config.h.in [new file with mode: 0644]
config.sub [new file with mode: 0644]
configure [new file with mode: 0644]
configure.ac [new file with mode: 0644]
depcomp [new file with mode: 0644]
doc/CVS/Entries [new file with mode: 0644]
doc/CVS/Entries.Log [new file with mode: 0644]
doc/CVS/Repository [new file with mode: 0644]
doc/CVS/Root [new file with mode: 0644]
doc/GAME_RULES [new file with mode: 0644]
doc/GHULSCRIPT [new file with mode: 0644]
doc/MAP_HACKERS_GUIDE [new file with mode: 0644]
doc/USERS_GUIDE [new file with mode: 0644]
doc/engine_extension_and_design/CVS/Entries [new file with mode: 0644]
doc/engine_extension_and_design/CVS/Repository [new file with mode: 0644]
doc/engine_extension_and_design/CVS/Root [new file with mode: 0644]
doc/engine_extension_and_design/ENGINE_CLEANUP [new file with mode: 0644]
doc/engine_extension_and_design/ENGINE_DESIGN_NOTES [new file with mode: 0644]
doc/engine_extension_and_design/README [new file with mode: 0644]
doc/engine_extension_and_design/my_TODO.2004.05.05.txt [new file with mode: 0644]
doc/null.gif [new file with mode: 0644]
doc/users_guide.html [new file with mode: 0644]
doc/world_building/CVS/Entries [new file with mode: 0644]
doc/world_building/CVS/Repository [new file with mode: 0644]
doc/world_building/CVS/Root [new file with mode: 0644]
doc/world_building/advancement.rogue.txt [new file with mode: 0644]
doc/world_building/advancement.warrior.txt [new file with mode: 0644]
doc/world_building/advancement.wizard.txt [new file with mode: 0644]
doc/world_building/advancement.wright.txt [new file with mode: 0644]
doc/world_building/being_tile_media.txt [new file with mode: 0644]
doc/world_building/music_loop_media.txt [new file with mode: 0644]
doc/world_building/sound_sample_media.txt [new file with mode: 0644]
doc/world_building/town_scale_tile_media.txt [new file with mode: 0644]
doc/world_building/wilderness_scale_tile_media.txt [new file with mode: 0644]
haxima.desktop [new file with mode: 0644]
icons/CVS/Entries [new file with mode: 0644]
icons/CVS/Repository [new file with mode: 0644]
icons/CVS/Root [new file with mode: 0644]
icons/haxima.ico [new file with mode: 0644]
icons/haxima.png [new file with mode: 0644]
icons/haxima.xcf [new file with mode: 0644]
install-sh [new file with mode: 0644]
m4/ChangeLog [new file with mode: 0644]
m4/Makefile.am [new file with mode: 0644]
m4/Makefile.in [new file with mode: 0644]
m4/acinclude.m4 [new file with mode: 0644]
m4/sdl.m4 [new file with mode: 0644]
missing [new file with mode: 0644]
src/Arms.cpp [new file with mode: 0644]
src/Arms.h [new file with mode: 0644]
src/Being.cpp [new file with mode: 0644]
src/Being.h [new file with mode: 0644]
src/Container.cpp [new file with mode: 0644]
src/Container.h [new file with mode: 0644]
src/Field.cpp [new file with mode: 0644]
src/Field.h [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/Makefile.am [new file with mode: 0644]
src/Makefile.in [new file with mode: 0644]
src/Missile.cpp [new file with mode: 0644]
src/Missile.h [new file with mode: 0644]
src/Party.cpp [new file with mode: 0644]
src/Party.h [new file with mode: 0644]
src/Reagent.cpp [new file with mode: 0644]
src/Reagent.h [new file with mode: 0644]
src/angband.c [new file with mode: 0644]
src/applet.h [new file with mode: 0644]
src/ascii.c [new file with mode: 0644]
src/ascii.h [new file with mode: 0644]
src/astar.c [new file with mode: 0644]
src/astar.h [new file with mode: 0644]
src/bitset.h [new file with mode: 0644]
src/blender.h [new file with mode: 0644]
src/cfg.c [new file with mode: 0644]
src/cfg.h [new file with mode: 0644]
src/character.cpp [new file with mode: 0644]
src/character.h [new file with mode: 0644]
src/clock.c [new file with mode: 0644]
src/clock.h [new file with mode: 0644]
src/closure.c [new file with mode: 0644]
src/closure.h [new file with mode: 0644]
src/cmd.c [new file with mode: 0644]
src/cmd.h [new file with mode: 0644]
src/cmdwin.c [new file with mode: 0644]
src/cmdwin.h [new file with mode: 0644]
src/combat.c [new file with mode: 0644]
src/combat.h [new file with mode: 0644]
src/common.c [new file with mode: 0644]
src/common.h [new file with mode: 0644]
src/console.c [new file with mode: 0644]
src/console.h [new file with mode: 0644]
src/constants.h [new file with mode: 0644]
src/conv.c [new file with mode: 0644]
src/conv.h [new file with mode: 0644]
src/ctrl.c [new file with mode: 0644]
src/ctrl.h [new file with mode: 0644]
src/cursor.cpp [new file with mode: 0644]
src/cursor.h [new file with mode: 0644]
src/debug.c [new file with mode: 0644]
src/debug.h [new file with mode: 0644]
src/dice.c [new file with mode: 0644]
src/dice.h [new file with mode: 0644]
src/dimensions.c [new file with mode: 0644]
src/dimensions.h [new file with mode: 0644]
src/dtable.c [new file with mode: 0644]
src/dtable.h [new file with mode: 0644]
src/dup_constants.h [new file with mode: 0644]
src/effect.c [new file with mode: 0644]
src/effect.h [new file with mode: 0644]
src/escape.c [new file with mode: 0644]
src/escape.h [new file with mode: 0644]
src/event.c [new file with mode: 0644]
src/event.h [new file with mode: 0644]
src/factions.h [new file with mode: 0644]
src/file.c [new file with mode: 0644]
src/file.h [new file with mode: 0644]
src/floodfill.c [new file with mode: 0644]
src/foogod.c [new file with mode: 0644]
src/foogod.h [new file with mode: 0644]
src/formation.c [new file with mode: 0644]
src/formation.h [new file with mode: 0644]
src/gob.c [new file with mode: 0644]
src/gob.h [new file with mode: 0644]
src/hash.c [new file with mode: 0644]
src/hash.h [new file with mode: 0644]
src/heap.c [new file with mode: 0644]
src/heap.h [new file with mode: 0644]
src/images.c [new file with mode: 0644]
src/images.h [new file with mode: 0644]
src/kern.c [new file with mode: 0644]
src/kern.h [new file with mode: 0644]
src/kern_intvar.c [new file with mode: 0644]
src/kern_intvar.h [new file with mode: 0644]
src/knapsack.c [new file with mode: 0644]
src/knapsack.h [new file with mode: 0644]
src/list.h [new file with mode: 0644]
src/log.c [new file with mode: 0644]
src/log.h [new file with mode: 0644]
src/los.c [new file with mode: 0644]
src/los.h [new file with mode: 0644]
src/macros.h [new file with mode: 0644]
src/magic.c [new file with mode: 0644]
src/magic.h [new file with mode: 0644]
src/map.c [new file with mode: 0644]
src/map.h [new file with mode: 0644]
src/menus.c [new file with mode: 0644]
src/menus.h [new file with mode: 0644]
src/mmode.c [new file with mode: 0644]
src/mmode.h [new file with mode: 0644]
src/nazghul.c [new file with mode: 0644]
src/nazghul.h [new file with mode: 0644]
src/node.c [new file with mode: 0644]
src/node.h [new file with mode: 0644]
src/object.c [new file with mode: 0644]
src/object.h [new file with mode: 0644]
src/objectfreezer.c [new file with mode: 0644]
src/objectfreezer.h [new file with mode: 0644]
src/occ.c [new file with mode: 0644]
src/occ.h [new file with mode: 0644]
src/olist.c [new file with mode: 0644]
src/olist.h [new file with mode: 0644]
src/opdefines.h [new file with mode: 0644]
src/pinfo.h [new file with mode: 0644]
src/place.c [new file with mode: 0644]
src/place.h [new file with mode: 0644]
src/play.c [new file with mode: 0644]
src/play.h [new file with mode: 0644]
src/player.cpp [new file with mode: 0644]
src/player.h [new file with mode: 0644]
src/ptable.c [new file with mode: 0644]
src/ptable.h [new file with mode: 0644]
src/repstr.c [new file with mode: 0644]
src/repstr.h [new file with mode: 0644]
src/result.h [new file with mode: 0644]
src/sched.c [new file with mode: 0644]
src/sched.h [new file with mode: 0644]
src/scheme-private.h [new file with mode: 0644]
src/scheme.c [new file with mode: 0644]
src/scheme.h [new file with mode: 0644]
src/screen.c [new file with mode: 0644]
src/screen.h [new file with mode: 0644]
src/screen_dims.h [new file with mode: 0644]
src/session.c [new file with mode: 0644]
src/session.h [new file with mode: 0644]
src/session_hooks.h [new file with mode: 0644]
src/session_queries.h [new file with mode: 0644]
src/skill.c [new file with mode: 0644]
src/skill.h [new file with mode: 0644]
src/skill_set.c [new file with mode: 0644]
src/skill_set.h [new file with mode: 0644]
src/skill_set_entry.c [new file with mode: 0644]
src/skill_set_entry.h [new file with mode: 0644]
src/sky.c [new file with mode: 0644]
src/sky.h [new file with mode: 0644]
src/sound.c [new file with mode: 0644]
src/sound.h [new file with mode: 0644]
src/species.c [new file with mode: 0644]
src/species.h [new file with mode: 0644]
src/sprite.c [new file with mode: 0644]
src/sprite.h [new file with mode: 0644]
src/status.c [new file with mode: 0644]
src/status.h [new file with mode: 0644]
src/templ.c [new file with mode: 0644]
src/templ.h [new file with mode: 0644]
src/terrain.c [new file with mode: 0644]
src/terrain.h [new file with mode: 0644]
src/terrain_editor.c [new file with mode: 0644]
src/terrain_editor.h [new file with mode: 0644]
src/terrain_map.c [new file with mode: 0644]
src/terrain_map.h [new file with mode: 0644]
src/tick.c [new file with mode: 0644]
src/tick.h [new file with mode: 0644]
src/tree.c [new file with mode: 0644]
src/tree.h [new file with mode: 0644]
src/vehicle.cpp [new file with mode: 0644]
src/vehicle.h [new file with mode: 0644]
src/vmask.c [new file with mode: 0644]
src/vmask.h [new file with mode: 0644]
src/wind.c [new file with mode: 0644]
src/wind.h [new file with mode: 0644]
src/wq.c [new file with mode: 0644]
src/wq.h [new file with mode: 0644]
src/ztats.c [new file with mode: 0644]
src/ztats.h [new file with mode: 0644]
src/ztats_arms.c [new file with mode: 0644]
src/ztats_arms.h [new file with mode: 0644]
src/ztats_container_pane.c [new file with mode: 0644]
src/ztats_container_pane.h [new file with mode: 0644]
src/ztats_items.c [new file with mode: 0644]
src/ztats_items.h [new file with mode: 0644]
src/ztats_misc.c [new file with mode: 0644]
src/ztats_misc.h [new file with mode: 0644]
src/ztats_pane.c [new file with mode: 0644]
src/ztats_pane.h [new file with mode: 0644]
src/ztats_pm.c [new file with mode: 0644]
src/ztats_pm.h [new file with mode: 0644]
src/ztats_reagents.c [new file with mode: 0644]
src/ztats_reagents.h [new file with mode: 0644]
src/ztats_spells.c [new file with mode: 0644]
src/ztats_spells.h [new file with mode: 0644]
worlds/Makefile.am [new file with mode: 0644]
worlds/Makefile.in [new file with mode: 0644]
worlds/haxima-1.002/640x480_splash.png [new file with mode: 0644]
worlds/haxima-1.002/Makefile.am [new file with mode: 0644]
worlds/haxima-1.002/Makefile.in [new file with mode: 0644]
worlds/haxima-1.002/abandoned-cellar.scm [new file with mode: 0644]
worlds/haxima-1.002/abandoned-farm.scm [new file with mode: 0644]
worlds/haxima-1.002/abe.scm [new file with mode: 0644]
worlds/haxima-1.002/abigail.scm [new file with mode: 0644]
worlds/haxima-1.002/ability.scm [new file with mode: 0644]
worlds/haxima-1.002/absalot.scm [new file with mode: 0644]
worlds/haxima-1.002/addons.png [new file with mode: 0644]
worlds/haxima-1.002/adornments.png [new file with mode: 0644]
worlds/haxima-1.002/ai.scm [new file with mode: 0644]
worlds/haxima-1.002/alchemist.scm [new file with mode: 0644]
worlds/haxima-1.002/alex.scm [new file with mode: 0644]
worlds/haxima-1.002/altar-room.scm [new file with mode: 0644]
worlds/haxima-1.002/amy.scm [new file with mode: 0644]
worlds/haxima-1.002/anaxes.scm [new file with mode: 0644]
worlds/haxima-1.002/ancient-derelict.scm [new file with mode: 0644]
worlds/haxima-1.002/angela.scm [new file with mode: 0644]
worlds/haxima-1.002/angriss-lair.scm [new file with mode: 0644]
worlds/haxima-1.002/angriss.scm [new file with mode: 0644]
worlds/haxima-1.002/ankh-shrine.scm [new file with mode: 0644]
worlds/haxima-1.002/anne.scm [new file with mode: 0644]
worlds/haxima-1.002/arms.png [new file with mode: 0644]
worlds/haxima-1.002/arms.scm [new file with mode: 0644]
worlds/haxima-1.002/bakup.scm [new file with mode: 0644]
worlds/haxima-1.002/bandit-hideout.scm [new file with mode: 0644]
worlds/haxima-1.002/bart.scm [new file with mode: 0644]
worlds/haxima-1.002/beds.scm [new file with mode: 0644]
worlds/haxima-1.002/bigobjects.png [new file with mode: 0644]
worlds/haxima-1.002/bill.scm [new file with mode: 0644]
worlds/haxima-1.002/bim.scm [new file with mode: 0644]
worlds/haxima-1.002/blendterrains.scm [new file with mode: 0644]
worlds/haxima-1.002/bodies.png [new file with mode: 0644]
worlds/haxima-1.002/bole.scm [new file with mode: 0644]
worlds/haxima-1.002/books.png [new file with mode: 0644]
worlds/haxima-1.002/books.scm [new file with mode: 0644]
worlds/haxima-1.002/boom.wav [new file with mode: 0644]
worlds/haxima-1.002/bridge.scm [new file with mode: 0644]
worlds/haxima-1.002/brundegardt.scm [new file with mode: 0644]
worlds/haxima-1.002/camping-map.scm [new file with mode: 0644]
worlds/haxima-1.002/cannon.wav [new file with mode: 0644]
worlds/haxima-1.002/cast-ui.scm [new file with mode: 0644]
worlds/haxima-1.002/chanticleer.scm [new file with mode: 0644]
worlds/haxima-1.002/charset.png [new file with mode: 0644]
worlds/haxima-1.002/chester.scm [new file with mode: 0644]
worlds/haxima-1.002/clothes.png [new file with mode: 0644]
worlds/haxima-1.002/combat-maps.scm [new file with mode: 0644]
worlds/haxima-1.002/containers.scm [new file with mode: 0644]
worlds/haxima-1.002/conv.scm [new file with mode: 0644]
worlds/haxima-1.002/creatures.png [new file with mode: 0644]
worlds/haxima-1.002/crypt.scm [new file with mode: 0644]
worlds/haxima-1.002/cursor.png [new file with mode: 0644]
worlds/haxima-1.002/damage.wav [new file with mode: 0644]
worlds/haxima-1.002/dank-cave.scm [new file with mode: 0644]
worlds/haxima-1.002/demo.scm [new file with mode: 0644]
worlds/haxima-1.002/demon-gate.scm [new file with mode: 0644]
worlds/haxima-1.002/dennis.scm [new file with mode: 0644]
worlds/haxima-1.002/deric.scm [new file with mode: 0644]
worlds/haxima-1.002/disarm-trap.scm [new file with mode: 0644]
worlds/haxima-1.002/dog_9.wav [new file with mode: 0644]
worlds/haxima-1.002/door.scm [new file with mode: 0644]
worlds/haxima-1.002/doris.scm [new file with mode: 0644]
worlds/haxima-1.002/douglas.scm [new file with mode: 0644]
worlds/haxima-1.002/drawbridge.scm [new file with mode: 0644]
worlds/haxima-1.002/earl.scm [new file with mode: 0644]
worlds/haxima-1.002/eastpass.scm [new file with mode: 0644]
worlds/haxima-1.002/edge-spawn.scm [new file with mode: 0644]
worlds/haxima-1.002/edward.scm [new file with mode: 0644]
worlds/haxima-1.002/effects.png [new file with mode: 0644]
worlds/haxima-1.002/effects.scm [new file with mode: 0644]
worlds/haxima-1.002/enchanter.scm [new file with mode: 0644]
worlds/haxima-1.002/enchanters-tower-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/enchanters-tower-zones.scm [new file with mode: 0644]
worlds/haxima-1.002/enchanters-tower.scm [new file with mode: 0644]
worlds/haxima-1.002/endless-deeps-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/endless-deeps.scm [new file with mode: 0644]
worlds/haxima-1.002/engineer.scm [new file with mode: 0644]
worlds/haxima-1.002/engineers-hut.scm [new file with mode: 0644]
worlds/haxima-1.002/enter_moongate.wav [new file with mode: 0644]
worlds/haxima-1.002/eye-of-brune.scm [new file with mode: 0644]
worlds/haxima-1.002/fields.scm [new file with mode: 0644]
worlds/haxima-1.002/fing.scm [new file with mode: 0644]
worlds/haxima-1.002/fire_sea.scm [new file with mode: 0644]
worlds/haxima-1.002/fireblast.wav [new file with mode: 0644]
worlds/haxima-1.002/florinth.scm [new file with mode: 0644]
worlds/haxima-1.002/food.png [new file with mode: 0644]
worlds/haxima-1.002/food.scm [new file with mode: 0644]
worlds/haxima-1.002/forsaken-prison.scm [new file with mode: 0644]
worlds/haxima-1.002/frame.png [new file with mode: 0644]
worlds/haxima-1.002/game.scm [new file with mode: 0644]
worlds/haxima-1.002/gamestart-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/gamestart-statues.scm [new file with mode: 0644]
worlds/haxima-1.002/gamestart.scm [new file with mode: 0644]
worlds/haxima-1.002/gate-guard.scm [new file with mode: 0644]
worlds/haxima-1.002/gen.scm [new file with mode: 0644]
worlds/haxima-1.002/generic-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/ghertie.scm [new file with mode: 0644]
worlds/haxima-1.002/gholet.scm [new file with mode: 0644]
worlds/haxima-1.002/glasdrin.scm [new file with mode: 0644]
worlds/haxima-1.002/goblin-kingdoms.scm [new file with mode: 0644]
worlds/haxima-1.002/gold_frame.png [new file with mode: 0644]
worlds/haxima-1.002/gong.wav [new file with mode: 0644]
worlds/haxima-1.002/green-tower-lower.scm [new file with mode: 0644]
worlds/haxima-1.002/green-tower.scm [new file with mode: 0644]
worlds/haxima-1.002/gregor.scm [new file with mode: 0644]
worlds/haxima-1.002/gregors-hut.scm [new file with mode: 0644]
worlds/haxima-1.002/gwen.scm [new file with mode: 0644]
worlds/haxima-1.002/hackle.scm [new file with mode: 0644]
worlds/haxima-1.002/haximatext.png [new file with mode: 0644]
worlds/haxima-1.002/henry.scm [new file with mode: 0644]
worlds/haxima-1.002/hidden.scm [new file with mode: 0644]
worlds/haxima-1.002/hirespeople.png [new file with mode: 0644]
worlds/haxima-1.002/horse.wav [new file with mode: 0644]
worlds/haxima-1.002/humanoids.png [new file with mode: 0644]
worlds/haxima-1.002/ifc.scm [new file with mode: 0644]
worlds/haxima-1.002/ilya.scm [new file with mode: 0644]
worlds/haxima-1.002/ini.scm [new file with mode: 0644]
worlds/haxima-1.002/init.scm [new file with mode: 0644]
worlds/haxima-1.002/items.scm [new file with mode: 0644]
worlds/haxima-1.002/jake.scm [new file with mode: 0644]
worlds/haxima-1.002/janice.scm [new file with mode: 0644]
worlds/haxima-1.002/jeffreys.scm [new file with mode: 0644]
worlds/haxima-1.002/jess.scm [new file with mode: 0644]
worlds/haxima-1.002/jewelry.png [new file with mode: 0644]
worlds/haxima-1.002/jewelry.scm [new file with mode: 0644]
worlds/haxima-1.002/jim.scm [new file with mode: 0644]
worlds/haxima-1.002/joel.scm [new file with mode: 0644]
worlds/haxima-1.002/jones.scm [new file with mode: 0644]
worlds/haxima-1.002/jorn.scm [new file with mode: 0644]
worlds/haxima-1.002/kalcifax.scm [new file with mode: 0644]
worlds/haxima-1.002/kama.scm [new file with mode: 0644]
worlds/haxima-1.002/kathryn.scm [new file with mode: 0644]
worlds/haxima-1.002/keep.scm [new file with mode: 0644]
worlds/haxima-1.002/keep_crypt_mech.scm [new file with mode: 0644]
worlds/haxima-1.002/kern-init.scm [new file with mode: 0644]
worlds/haxima-1.002/keys.scm [new file with mode: 0644]
worlds/haxima-1.002/kobj.scm [new file with mode: 0644]
worlds/haxima-1.002/kraken-lakes.scm [new file with mode: 0644]
worlds/haxima-1.002/kun.scm [new file with mode: 0644]
worlds/haxima-1.002/landslide.scm [new file with mode: 0644]
worlds/haxima-1.002/lever.scm [new file with mode: 0644]
worlds/haxima-1.002/lia.scm [new file with mode: 0644]
worlds/haxima-1.002/lich-tomb.scm [new file with mode: 0644]
worlds/haxima-1.002/lightning.wav [new file with mode: 0644]
worlds/haxima-1.002/loc.scm [new file with mode: 0644]
worlds/haxima-1.002/lost-halls-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/lost-halls.scm [new file with mode: 0644]
worlds/haxima-1.002/luximene.scm [new file with mode: 0644]
worlds/haxima-1.002/main-menu.scm [new file with mode: 0644]
worlds/haxima-1.002/mans-hideout.scm [new file with mode: 0644]
worlds/haxima-1.002/map.png [new file with mode: 0644]
worlds/haxima-1.002/may.scm [new file with mode: 0644]
worlds/haxima-1.002/meaney.scm [new file with mode: 0644]
worlds/haxima-1.002/melvin.scm [new file with mode: 0644]
worlds/haxima-1.002/merciful-death.scm [new file with mode: 0644]
worlds/haxima-1.002/mesmeme.scm [new file with mode: 0644]
worlds/haxima-1.002/miggs.scm [new file with mode: 0644]
worlds/haxima-1.002/mimic.scm [new file with mode: 0644]
worlds/haxima-1.002/minimal-game.scm [new file with mode: 0644]
worlds/haxima-1.002/minimal-start.scm [new file with mode: 0644]
worlds/haxima-1.002/money.png [new file with mode: 0644]
worlds/haxima-1.002/money.scm [new file with mode: 0644]
worlds/haxima-1.002/monster-generator.scm [new file with mode: 0644]
worlds/haxima-1.002/monsters.png [new file with mode: 0644]
worlds/haxima-1.002/moon.scm [new file with mode: 0644]
worlds/haxima-1.002/moongate-clearing.scm [new file with mode: 0644]
worlds/haxima-1.002/moongate.scm [new file with mode: 0644]
worlds/haxima-1.002/moons.png [new file with mode: 0644]
worlds/haxima-1.002/mouse.scm [new file with mode: 0644]
worlds/haxima-1.002/mushroom-cave.scm [new file with mode: 0644]
worlds/haxima-1.002/music/Lute-and-recorder-ballad.mid [new file with mode: 0644]
worlds/haxima-1.002/music/Lute-and-recorder-ballad.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/Makefile.am [new file with mode: 0644]
worlds/haxima-1.002/music/Makefile.in [new file with mode: 0644]
worlds/haxima-1.002/music/Minuet-like-Mozart.mid [new file with mode: 0644]
worlds/haxima-1.002/music/Minuet-like-Mozart.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/ballad.mid [new file with mode: 0644]
worlds/haxima-1.002/music/ballad.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/bassoons-and-harpsichord.mid [new file with mode: 0644]
worlds/haxima-1.002/music/bassoons-and-harpsichord.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/credits.txt [new file with mode: 0644]
worlds/haxima-1.002/music/double-trios.mid [new file with mode: 0644]
worlds/haxima-1.002/music/double-trios.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/dragon-quest.mid [new file with mode: 0644]
worlds/haxima-1.002/music/dragon-quest.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/dragon-slayer.mid [new file with mode: 0644]
worlds/haxima-1.002/music/dragon-slayer.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/fair-camelot.mid [new file with mode: 0644]
worlds/haxima-1.002/music/fair-camelot.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/game-music2.mid [new file with mode: 0644]
worlds/haxima-1.002/music/game-music2.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/harpsichord-piece.mid [new file with mode: 0644]
worlds/haxima-1.002/music/harpsichord-piece.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/into-battle.mid [new file with mode: 0644]
worlds/haxima-1.002/music/into-battle.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/medieval-quest.mid [new file with mode: 0644]
worlds/haxima-1.002/music/medieval-quest.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/minstrel-dance.mid [new file with mode: 0644]
worlds/haxima-1.002/music/minstrel-dance.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/music.scm [new file with mode: 0644]
worlds/haxima-1.002/music/plainchant-recorder-trio.mid [new file with mode: 0644]
worlds/haxima-1.002/music/plainchant-recorder-trio.ogg [new file with mode: 0644]
worlds/haxima-1.002/music/wind-trio.mid [new file with mode: 0644]
worlds/haxima-1.002/music/wind-trio.ogg [new file with mode: 0644]
worlds/haxima-1.002/nate.scm [new file with mode: 0644]
worlds/haxima-1.002/naz.scm [new file with mode: 0644]
worlds/haxima-1.002/necromancer.scm [new file with mode: 0644]
worlds/haxima-1.002/necromancers-lair.scm [new file with mode: 0644]
worlds/haxima-1.002/newfolks.png [new file with mode: 0644]
worlds/haxima-1.002/newmonst.png [new file with mode: 0644]
worlds/haxima-1.002/newterrain.png [new file with mode: 0644]
worlds/haxima-1.002/nossifer.scm [new file with mode: 0644]
worlds/haxima-1.002/npc-types.scm [new file with mode: 0644]
worlds/haxima-1.002/objs.scm [new file with mode: 0644]
worlds/haxima-1.002/occs.scm [new file with mode: 0644]
worlds/haxima-1.002/old-absalot.scm [new file with mode: 0644]
worlds/haxima-1.002/old-mine.scm [new file with mode: 0644]
worlds/haxima-1.002/oparine.scm [new file with mode: 0644]
worlds/haxima-1.002/oscar.scm [new file with mode: 0644]
worlds/haxima-1.002/palette.scm [new file with mode: 0644]
worlds/haxima-1.002/parties.scm [new file with mode: 0644]
worlds/haxima-1.002/patch.scm [new file with mode: 0644]
worlds/haxima-1.002/pitfalls.png [new file with mode: 0644]
worlds/haxima-1.002/pitfalls.scm [new file with mode: 0644]
worlds/haxima-1.002/player.scm [new file with mode: 0644]
worlds/haxima-1.002/poor-house.scm [new file with mode: 0644]
worlds/haxima-1.002/portals.scm [new file with mode: 0644]
worlds/haxima-1.002/portcullis.scm [new file with mode: 0644]
worlds/haxima-1.002/potions.png [new file with mode: 0644]
worlds/haxima-1.002/potions.scm [new file with mode: 0644]
worlds/haxima-1.002/powers.scm [new file with mode: 0644]
worlds/haxima-1.002/pre-entry-hooks.scm [new file with mode: 0644]
worlds/haxima-1.002/prices.scm [new file with mode: 0644]
worlds/haxima-1.002/prison.scm [new file with mode: 0644]
worlds/haxima-1.002/progress_bar_image.png [new file with mode: 0644]
worlds/haxima-1.002/pseudorandom-map.scm [new file with mode: 0644]
worlds/haxima-1.002/quest-sys.scm [new file with mode: 0644]
worlds/haxima-1.002/quests-data-static.scm [new file with mode: 0644]
worlds/haxima-1.002/quests-data.scm [new file with mode: 0644]
worlds/haxima-1.002/quests-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/quests.png [new file with mode: 0644]
worlds/haxima-1.002/r2a_mech.scm [new file with mode: 0644]
worlds/haxima-1.002/raise-merciful-death.scm [new file with mode: 0644]
worlds/haxima-1.002/reagents.png [new file with mode: 0644]
worlds/haxima-1.002/reagents.scm [new file with mode: 0644]
worlds/haxima-1.002/river.wav [new file with mode: 0644]
worlds/haxima-1.002/road_to_absalot.scm [new file with mode: 0644]
worlds/haxima-1.002/roland.scm [new file with mode: 0644]
worlds/haxima-1.002/rowing.wav [new file with mode: 0644]
worlds/haxima-1.002/rune.png [new file with mode: 0644]
worlds/haxima-1.002/runes.scm [new file with mode: 0644]
worlds/haxima-1.002/runestones.png [new file with mode: 0644]
worlds/haxima-1.002/scrolls.png [new file with mode: 0644]
worlds/haxima-1.002/scrolls.scm [new file with mode: 0644]
worlds/haxima-1.002/selene.scm [new file with mode: 0644]
worlds/haxima-1.002/sfx.png [new file with mode: 0644]
worlds/haxima-1.002/shapes.png [new file with mode: 0644]
worlds/haxima-1.002/shard.scm [new file with mode: 0644]
worlds/haxima-1.002/ship.png [new file with mode: 0644]
worlds/haxima-1.002/shroom.scm [new file with mode: 0644]
worlds/haxima-1.002/signs.png [new file with mode: 0644]
worlds/haxima-1.002/silas.scm [new file with mode: 0644]
worlds/haxima-1.002/skills.scm [new file with mode: 0644]
worlds/haxima-1.002/slimy-cavern-zones.scm [new file with mode: 0644]
worlds/haxima-1.002/slimy-cavern.scm [new file with mode: 0644]
worlds/haxima-1.002/slywan.scm [new file with mode: 0644]
worlds/haxima-1.002/sounds.scm [new file with mode: 0644]
worlds/haxima-1.002/special.png [new file with mode: 0644]
worlds/haxima-1.002/special.scm [new file with mode: 0644]
worlds/haxima-1.002/species.scm [new file with mode: 0644]
worlds/haxima-1.002/spells.png [new file with mode: 0644]
worlds/haxima-1.002/spells.scm [new file with mode: 0644]
worlds/haxima-1.002/spider.scm [new file with mode: 0644]
worlds/haxima-1.002/splash.png [new file with mode: 0644]
worlds/haxima-1.002/sprite-sets.scm [new file with mode: 0644]
worlds/haxima-1.002/sprites.scm [new file with mode: 0644]
worlds/haxima-1.002/start-new-game.scm [new file with mode: 0644]
worlds/haxima-1.002/statue-of-justice.scm [new file with mode: 0644]
worlds/haxima-1.002/step.scm [new file with mode: 0644]
worlds/haxima-1.002/steward.scm [new file with mode: 0644]
worlds/haxima-1.002/swish.wav [new file with mode: 0644]
worlds/haxima-1.002/talking-ankh.scm [new file with mode: 0644]
worlds/haxima-1.002/tbl.scm [new file with mode: 0644]
worlds/haxima-1.002/tblit.scm [new file with mode: 0644]
worlds/haxima-1.002/terrain-to-ptype.scm [new file with mode: 0644]
worlds/haxima-1.002/terrains.scm [new file with mode: 0644]
worlds/haxima-1.002/tetzl.scm [new file with mode: 0644]
worlds/haxima-1.002/the-man.scm [new file with mode: 0644]
worlds/haxima-1.002/thiefs_den.scm [new file with mode: 0644]
worlds/haxima-1.002/thorald.scm [new file with mode: 0644]
worlds/haxima-1.002/thud.scm [new file with mode: 0644]
worlds/haxima-1.002/ticktock.wav [new file with mode: 0644]
worlds/haxima-1.002/tim.scm [new file with mode: 0644]
worlds/haxima-1.002/timer.scm [new file with mode: 0644]
worlds/haxima-1.002/tools.png [new file with mode: 0644]
worlds/haxima-1.002/tools.scm [new file with mode: 0644]
worlds/haxima-1.002/tooth.scm [new file with mode: 0644]
worlds/haxima-1.002/tower.png [new file with mode: 0644]
worlds/haxima-1.002/town-entry.scm [new file with mode: 0644]
worlds/haxima-1.002/traps.scm [new file with mode: 0644]
worlds/haxima-1.002/traps_1.scm [new file with mode: 0644]
worlds/haxima-1.002/traps_2.scm [new file with mode: 0644]
worlds/haxima-1.002/traps_3.scm [new file with mode: 0644]
worlds/haxima-1.002/traps_3_mechs.scm [new file with mode: 0644]
worlds/haxima-1.002/traps_4.scm [new file with mode: 0644]
worlds/haxima-1.002/treasury.scm [new file with mode: 0644]
worlds/haxima-1.002/trigrave.scm [new file with mode: 0644]
worlds/haxima-1.002/troll.scm [new file with mode: 0644]
worlds/haxima-1.002/tutorial.scm [new file with mode: 0644]
worlds/haxima-1.002/tutorial_cave.scm [new file with mode: 0644]
worlds/haxima-1.002/tutorial_town.scm [new file with mode: 0644]
worlds/haxima-1.002/tutorial_wilderness.scm [new file with mode: 0644]
worlds/haxima-1.002/urt.scm [new file with mode: 0644]
worlds/haxima-1.002/valus.scm [new file with mode: 0644]
worlds/haxima-1.002/vehicles.scm [new file with mode: 0644]
worlds/haxima-1.002/void-temple.scm [new file with mode: 0644]
worlds/haxima-1.002/voidgap-mech.scm [new file with mode: 0644]
worlds/haxima-1.002/voidgap-passage.scm [new file with mode: 0644]
worlds/haxima-1.002/walk.wav [new file with mode: 0644]
worlds/haxima-1.002/warritrix.scm [new file with mode: 0644]
worlds/haxima-1.002/weather-vane.scm [new file with mode: 0644]
worlds/haxima-1.002/westpass.scm [new file with mode: 0644]
worlds/haxima-1.002/wind-bridge.scm [new file with mode: 0644]
worlds/haxima-1.002/wind_1a.wav [new file with mode: 0644]
worlds/haxima-1.002/yellow-slime.scm [new file with mode: 0644]
worlds/haxima-1.002/zane.scm [new file with mode: 0644]
worlds/haxima-1.002/zones.scm [new file with mode: 0644]
worlds/haxima-1.002/ztats-quest-ui.scm [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..2a62756
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,119 @@
+To find out what should go in this file, see "Information For
+Maintainers of GNU Software" (maintain.texi), the section called
+"Recording Contributors".
+
+In alphabetical order by last name....
+
+Amorim, Roberto:
+scripts/nazghul.iss:
+       Adding the Inno Setup script file used to generate the Windows installer
+
+Bauer, Andreas:
+In src/Makefile.in, worlds/Makefile.in, configure, configure.ac, configure.in,
+depcomp, install-sh, ltmain.sh, missing, mkinstalldirs, src/Makefile.am,
+Makefile.in, NEWS, RELEASE_NOTES, acinclude.m4, aclocal.m4, autogen.sh,
+config.guess, config.sub, AUTHORS, ChangeLog, Makefile.am
+        Changed build system to GNU-compliant scheme
+
+Douglas, Tim:
+In src/scheme.c:
+        Fixed compile error on Max OS X
+In src/skill.c, src/skill_set.c, src/skill_set_entry.c, src/templ.c:
+       checks for malloc.h, to fix OsX Build
+
+Gabbert, Kevin:
+In worlds/haxima-1.001/images/kgabbert
+        Created images in .png file(s)
+
+Garrison, Karl:
+In src/cmd.c, src/cmd.h, src/ctrl.c, src/event.h:
+       Added command to dump terrain sprites as one BMP per frame
+
+Gervais, David:
+In worlds/haxima-1.001/images/dgervais
+        Created images in .png file(s)
+
+Glasby, Sam:
+(See user sglasby in the ChangeLog)
+In src/combat.c, src/cursor.cpp, src/event.h, src/play.c, src/play.h:
+       Added an (X)amine command, which is an extended (L)ook.
+In src/play.c, src/character.cpp, src/character.h, src/combat.c, src/status.c:
+       Added pmask to Ztats display
+       Added ammo display to Attack prompt
+       Require confirmation for attack self
+In src/game.c, src/terrain.c, src/terrain.h, src/terrain_map.c
+       Lots of changes to terrain palettes.
+In src/event.h, src/play.c, src/terrain.c, src/terrain.h:
+       Added and implemented (T)errain editing command
+In worlds/haxima-1.001/images
+        Reorganized images throughout all
+In worlds/haxima-1.001/images/sglasby
+        Created images in .png file(s)
+In worlds/haxima-1.001 created:
+        P_terrain_test.scm, P_terrain_test.scm, scenery.scm
+In worlds/haxima-1.001 made changes throughout:
+        session.scm, sprites.scm, sprite-sets.scm, palette.scm, objs.scm,
+        moongate-clearing.scm
+
+Johansson, Janne:
+In src/terrain_map.c, fixes for compiler warnings.
+In configure.ac, fix for SDL_image.h include path
+In doc/GAME_RULES, doc/MAP_HACKERS_GUIDE, doc/USERS_GUIDE, doc/world_building/sound_sample_media.txt:
+       various nitpicks in docs and spelling fixes
+In src/ascii.c, uninitialized nitpickings. shuts gcc4 up
+In src/terrain_map.c, fixing compiler warnings
+
+Links, Bernhard:
+In configure.ac, change for checking SDL install
+In worlds/haxima-1.002/Makefile.am, added missing file(s)
+In src/haxima.c, scheme.c, images.c, common.c, sound.c, session.c: added
+        commandline include dir and save dir
+
+McNutt, Gordon:
+(See user gmcnutt in the ChangeLog)
+In worlds/haxima-1.001:
+        First version of all files except images/* other than images/gmcnutt,
+        and P_terrain_test.scm, P_terrain_test.scm, scenery.scm
+In worlds/haxima-1.002:
+        All files, some re-used from haxima-1.001
+Everywhere else:
+        Most changes except where otherwise noted.
+
+Parker, Kris:
+(See user kaypy in the ChangeLog)
+In worlds/haxima-1.002/shapes.png, provided human knight sprite based on
+        existing sprite and added transparency to some sprites
+In worlds/haxima-1.002/food.png and addons.png, added transparency to some
+        sprites
+Added worlds/haxima-1.002/newmonst.png, newfolks.png
+In worlds/haxima-1.002/building.png, added the tower sprite
+In worlds/haxima-1.002/sprite-sets.scm, sprites.scm and npc-types.scm, added
+        new goblin sprites
+In worlds/haxima-1.002/mouse.scm, minor bugfix
+Added nazghul.nsi, nazinst.ico
+In src/factions.h, minor bugfix
+
+Patersen, Jim (http://www.mfiles.co.uk):
+In worlds/haxima-1.002/music:
+        ballad.mid
+        dragon-slayer.mid
+        into-battle.mid
+        Minuet-like-Mozart.mid
+        bassoons-and-harpsichord.mid  
+        fair-camelot.mid       
+        Lute-and-recorder-ballad.mid  
+        plainchant-recorder-trio.mid
+        double-trios.mid              
+        game-music2.mid        
+        medieval-quest.mid            
+        wind-trio.mid
+        dragon-quest.mid              
+        harpsichord-piece.mid  
+        minstrel-dance.mid
+
+Riberdy, Steve:
+In worlds/haxima-1.002/runestones.png, provided the images
+
+Steele, Joshua:
+In worlds/haxima-1.001/images/jsteele
+        Created images in .png file(s)
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..fd87e1e
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,15259 @@
+2010-12-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/nazghul.iss:
+       Updated version number and URL. Changed the program name to haxima.
+
+2010-08-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/cmd.c, src/node.c, src/node.h, src/place.c, src/player.cpp, src/session.c, src/status.c:
+       Fixed all the warnings related to strict aliasing and type punning. We now compile warning-free with gcc 4.4.4.
+
+2010-08-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.h, src/menus.c, src/menus.h, src/nazghul.c, src/object.c, src/object.h, src/occ.c, src/occ.h, src/place.c, src/place.h, src/player.cpp, src/player.h, src/sched.c, src/sched.h, src/scheme.c, src/screen.c, src/screen.h, src/session.c, src/session.h, src/sky.c, src/sound.c, src/sound.h, src/species.c, src/species.h, src/sprite.c, src/sprite.h, src/status.c, src/status.h, src/terrain.c, src/terrain.h, src/terrain_editor.c, src/terrain_map.c, src/terrain_map.h, src/tree.c, src/tree.h, src/vehicle.cpp, src/vehicle.h, src/vmask.c, src/ztats_container_pane.c, src/ztats_container_pane.h, src/Arms.cpp, src/Arms.h, src/Being.cpp, src/Being.h, src/Field.cpp, src/Field.h, src/Missile.cpp, src/Missile.h, src/Party.cpp, src/ascii.c, src/astar.c, src/cfg.c, src/cfg.h, src/character.cpp, src/character.h, src/clock.c, src/clock.h, src/closure.c, src/closure.h, src/cmd.c, src/cmd.h, src/cmdwin.c, src/cmdwin.h, src/common.c, src/common.h, src/console.c, src/console.h, src/conv.c, src/ctrl.c, src/debug.c, src/debug.h, src/dice.c, src/dice.h, src/dimensions.c, src/dtable.c, src/dtable.h, src/effect.c, src/effect.h, src/factions.h, src/file.c, src/file.h, src/foogod.c, src/foogod.h, src/images.c, src/images.h, src/kern.c, src/kern_intvar.c, src/kern_intvar.h, src/log.c, src/log.h, src/los.c, src/los.h, src/magic.c, src/magic.h, src/map.c:
+       Fixed compiler warnings related to const vs non-const char pointers
+
+2010-03-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c:
+       Don't load the demo if the player has a saved game. In this case he probably just wants to Journey Onward with minimal delay.
+
+2009-10-19  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       game version number incremented
+
+       * src/kern.c:
+       kern.c gets USE_QUESTS from ../config.h, the same way USE_SKILLS works
+
+       * win32/config.h, win32/readme.txt: tweaks to win32 build
+
+2009-10-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, COPYING, NEWS, AUTHORS: Update for 0.7.0 release
+
+2009-10-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE:
+       Added CTRL-E)val to the USERS_GUIDE with an example string for teleporting the player.
+
+       * src/cmd.c: CTRL-E)val now gives a prompt.
+
+       * worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/tbl.scm:
+       Bandit quest log stuff now done.
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/event.c, src/event.h, src/session.c, src/session.h:
+       Added CTRL-E to developer mode. This will let you enter a Scheme expression in the cmdwin and then the kernel will evaluate it. I will not be responsible for the results.
+
+2009-10-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE: Corrected some spell listings
+
+       * worlds/haxima-1.002/tools.scm:
+       Shortened the time it takes to pick locks
+
+       * worlds/haxima-1.002/skills.scm:
+       Reshuffled skills so that wanderer will get pickpocket eventually; also removed butcher from the lists since there isn't a lot one can do with it yet.
+
+       * worlds/haxima-1.002/naz.scm:
+       Made NPC's level depend on number of player party members
+
+       * worlds/haxima-1.002/disarm-trap.scm:
+       Disarm skill depended on wrong ability
+
+       * worlds/haxima-1.002/glasdrin.scm:
+       Made the Stewardess's chest invisible (to justify the MAN's hint about Wis Quas), and removed the magic lock and burn trap (I see no need to make it the most-protected chest in the game).
+
+2009-10-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm:
+       Made the Disarm Traps spell fallible. Bonus is the average of magical and thiefly abilities.
+
+2009-10-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm:
+       An Sanct (Unlock Mundane) can now fail. Caster's bonus is the average of white-magic and thief abilities
+
+       * worlds/haxima-1.002/potions.scm:
+       Changed stats potions as per kaypy's suggestion. Chance and degree of working now drops as base stat increases.
+
+2009-10-01  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/necromancer.scm:
+       necromancer conv changes with warritrix status
+
+       * worlds/haxima-1.002/lost-halls-mech.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/quests-data.scm:
+       can no longer find warritrix before quest
+
+       * worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/steward.scm:
+       a ream of quest debugging
+
+       * worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/steward.scm:
+       convs tweaked to delay warritrix mission
+
+2009-09-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/console.c, src/console.h, src/player.cpp:
+       Fixed a crasher that occurred when a console color push/pop crossed a newline boundary
+
+       * worlds/haxima-1.002/species.scm:
+       Gave bats vision radius 19 since they may attack the player when he's in the voidship
+
+       * worlds/haxima-1.002/runes.scm:
+       Fixed a crasher when getting the warritrix rune
+
+2009-09-29  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quests-data.scm: purged a duplicate entry
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/warritrix.scm:
+       using quest-data-complete preferentially
+
+       * worlds/haxima-1.002/quests-mech.scm: A bunch more documentation
+       Added a quest-data-complete method
+
+2009-09-28  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/jeffreys.scm:
+       A bunch more triggers for Warritrix info updates
+
+       * worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm:
+       Some quest documentation
+
+2009-09-27  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/warritrix.scm:
+       Wise quests pass 1- linked in results of find-in-files: wise
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm:
+       Placeholder quest entries for all of the wise
+
+2009-09-26  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/quests.png, worlds/haxima-1.002/sprites.scm:
+       Partial work toward tracking the players progress at finding the various wise
+
+       * worlds/library/artwork/hirespeople/paladin.xcf, worlds/haxima-1.002/hirespeople.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/valus.scm:
+       Added a bedraggled version of the paladin sprite for those in disgrace
+
+       * worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/player.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/warritrix.scm:
+       Convert and fix glasdrin convs
+
+2009-09-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/skills.scm: Jump should span at least one tile
+
+2009-09-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp: X)amine was showing the names of un-met NPC's
+
+       * worlds/haxima-1.002/runes.scm: Fixed a crasher when picking up runes
+
+       * worlds/haxima-1.002/effects.scm:
+       Think I finally got the slimes tuned right.
+
+       * worlds/haxima-1.002/sounds.scm: Fixed path to ballad.ogg
+
+2009-09-18  kaypy  <kaypy@localhost.localdomain>
+
+       * win32/Makefile: added terrain editor to win32
+
+2009-09-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/session.c: Fix for problem starting new game on x86_64
+
+2009-09-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm: Tuning slime split probability
+
+       * worlds/haxima-1.002/spells.scm:
+       Added royal cape as an ingredient to all the ward spells
+
+       * worlds/haxima-1.002/slywan.scm:
+       Change slywan's alignment directly to avoid 'Slyway is charmed' log message
+
+       * worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/tooth.scm:
+       Added grease to merchandise of earl and tooth
+
+       * worlds/haxima-1.002/books.scm:
+       Added royal cape to the books on ward spells
+
+2009-09-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp: Fixed a hang on rendezvous
+
+       * worlds/haxima-1.002/music/Makefile.am: Fixed music installation
+
+2009-09-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/skills.scm: Tuning skills
+
+       * worlds/haxima-1.002/quests-data-static.scm:
+       Fixed some typos in the quest text
+
+       * worlds/haxima-1.002/potions.scm:
+       Decided that gain-stats potions are rare enough that they shouldn't fail
+
+       * worlds/haxima-1.002/pitfalls.scm:
+       Fixed a cut-and-paste that prevents the Arm Trap skill from working
+
+       * worlds/haxima-1.002/edward.scm: Fixed typo in conv
+
+       * worlds/haxima-1.002/nate.scm: Nate responds to NAME keyword
+
+       * worlds/haxima-1.002/lia.scm: Made some scrolls cheaper
+
+       * worlds/haxima-1.002/shroom.scm:
+       Shroom responds to queries about royal cape
+
+       * worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/tim.scm:
+       Some characters shouldn't respond to the 'common folk' keywords
+
+       * worlds/haxima-1.002/ability.scm: Ratlings summon more critters
+
+       * src/ztats.c, src/kern.c:
+       Fixed a crasher due to the quest pane not removing itself during session teardown
+
+       * worlds/haxima-1.002/effects.scm:
+       Fixed a bug that prevented ensnare from being removed
+
+       * src/map.c: Xray works in total darkness
+
+2009-09-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp:
+       Fixed a crasher that occurred after talking to party members in wilderness mode
+
+2009-09-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/start-new-game.scm: Removed reference to florinth
+
+       * worlds/haxima-1.002/quests-data-static.scm: Grammatical error
+
+       * worlds/haxima-1.002/shard.scm: Removed refs to florinth
+
+       * worlds/haxima-1.002/gen.scm: Removed some spaces and uppercases words
+
+2009-08-30  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/chanticleer.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/player.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/steward.scm:
+       First pass at warritrix and absalot rune quest info
+
+2009-08-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac: Turned on skills and quests by default
+
+2009-08-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm:
+       Fix for 1843026: vial slimes set to user's faction
+
+2009-06-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/common.h, src/dimensions.c, src/player.cpp, src/vehicle.cpp, src/wind.c, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/vehicles.scm:
+       Fix for 1900156: Has anyone seen East or South winds for a while?
+
+       Haxima:
+       o In cast-wind-change don't allow HERE
+       o Alway ensure at least 10 turns on a wind change spell
+       o For ships switched tailwind to be better than crosswind
+
+       Kernel:
+       o Log to the console whenever the wind shifts
+       o Change wind directions to be 8-way instead of 4-way (changed vehicle code to
+         accomodate)
+       o Make wind widget wide enough for longest string
+       o Log player party movement cost in developer mode
+
+2009-06-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Fix for 1900157: kern_ui_select_party_member() unconditionally uses
+       cmdwin_pop() after calling select_party_member(), but in cases where there is
+       only one party member there was nothing to pop. Now there is.
+
+       * worlds/haxima-1.002/runes.scm:
+       Fix for crasher when picking up certain runes
+
+       * src/character.cpp, src/play.c:
+       Fix for 2129810: added some explanatory log messages
+
+       * win32/Makefile, win32/config.h: Fix for 2360126: applied patch
+
+2009-06-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.c: Fix for 2364311: avoid divide-by-zero error
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Fix for 2364368: added sleep immunity to demons (incl Nossifer)
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm:
+       Fix for 2398446: added list of acid-immune weapon types
+
+       * worlds/haxima-1.002/alchemist.scm:
+       Fix for 2404468: reworded 'search' to be 'probe'
+
+       * worlds/haxima-1.002/alchemist.scm:
+       Fix for 2404478: reworded a statement
+
+       * worlds/haxima-1.002/640x480_splash.png, worlds/haxima-1.002/splash.png:
+       Fix for 2466986: removed version number from splash images
+
+       * worlds/haxima-1.002/gamestart-mech.scm:
+       Fix for 2467008: make the blue gate in the character creation map black
+
+2009-04-11  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/jewelry.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/the-man.scm:
+       pirate rune quest and subquests
+       I think I have tested most of the paths through this, but it gets a touch baroque and thus could use more playtesting
+
+       * worlds/haxima-1.002/gamestart.scm, worlds/haxima-1.002/start-new-game.scm:
+       moved cheating tweaks into gamestart where they can tweak more
+
+       * worlds/haxima-1.002/effects.scm: added a generalized on-death method
+
+       * worlds/haxima-1.002/kobj.scm, worlds/haxima-1.002/powers.scm:
+       added an ifc for objects that need a callback when obtained via odd means such as pickpocketing (basically, anything that doesnt go via ifc-get ought to trigger ifc-receive instead)
+
+2009-04-09  kaypy  <kaypy@localhost.localdomain>
+
+       * src/map.c: Rounding tweak for viewscreens with even numbers of tiles
+
+       * src/closure.h: gcc didnt like repeated identifier
+
+2008-12-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Added another tombstone
+
+2008-12-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Added a tombstone
+
+2008-12-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/event.c, src/terrain_editor.c:
+       Engine changes:
+       o The terrain editor UI now has two status panes: the terrain palette and a
+         list of commands.
+
+2008-12-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.c: Fixed mouse-clicking on the map while zoomed out
+
+2008-12-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Accidentally committed my test version of this earlier, restoring it.
+
+       * src/terrain_editor.c, src/terrain_map.c, src/terrain_map.h:
+       Added undo (ctrl-z) and redo (ctrl-r) commands to terrain editor
+
+2008-11-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/terrain.c, src/terrain.h: Removed dead code
+
+       * src/terrain.c, src/terrain.h:
+       Removed the current terrain index and quick entries from the palette struct and terrain code (moved to terrain editor on my last commit)
+
+       * src/terrain_editor.c:
+       Part 1 of moving the current terrain and quick terrain settings from the palette struct to the terrain editor code
+
+       * src/terrain_editor.c:
+       Terrain editor now correctly handles dragging the mouse to paint
+
+       * worlds/haxima-1.002/florinth.scm:
+       The great and wicked city of Florinth. Now mostly blank.
+
+       * src/cmd.c, src/cmd.h, src/map.c, src/status.c, src/terrain.c, src/terrain.h, src/terrain_editor.c:
+       Engine changes:
+       o Terrain editor now displays the terrain pallete in a scrolling status
+         window. Clicking on a terrain selects it for "painting".
+
+       * src/Makefile.am, src/cmd.c, src/cmd.h, src/terrain_editor.c, src/terrain_editor.h:
+       Engine changes:
+       o Moved code for terrain editing from cmd.c to newly created terrain_editor.c.
+
+       * src/status.c, src/status.h:
+       Changed a comment and removed some dead code
+
+2008-11-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/terrain.h, src/terrain.c:
+       Engine changes:
+       o Terrain palette entries are now listed in two ways: by glyph lookup (the old
+         way, which helps load maps faster) and now by the order in which things are
+         added to the palette (the even older way, which allows the map editor to list
+         them in the same order as the script)
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/start-new-game.scm:
+       Changes to haxima:
+       o (mk-dungeon-level ...) now binds rooms in diagonal directions.
+
+       * src/character.cpp, src/common.c, src/place.c, src/place.h:
+       Engine changes:
+       o After exiting to wilderness, the party is positioned on the tile adjacent to
+         the town in the exit direction. We'll see how this goes.
+
+2008-11-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/start-new-game.scm:
+       Forgot the island on my last commit.
+
+       * worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/start-new-game.scm:
+       Extended the Shard. Added new island.
+
+2008-11-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h:
+       Prompt the user to abort a task on damage. Allow them to ignore damage.
+
+       * worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/skills.scm:
+       Another attempt to tune skill level requirements
+
+       * worlds/haxima-1.002/effects.scm: Removed some debug
+
+       * worlds/haxima-1.002/powers.scm:
+       Pickpocket rolls to succeed before showing target inventory
+
+       * worlds/haxima-1.002/skills.scm: Made lockpicking a passive skill
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/pitfalls.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/tools.scm:
+       Changes to haxima:
+       o Arming traps now entails some risk
+       o Tweaked stealth mode rolls
+
+       * scripts/dice_rolls.pl:
+       Perl script for computing dice roll probablities with 2 dice
+
+2008-11-24  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm:
+       void temple rune quest upgraded
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/warritrix.scm:
+       spider rune quest upgraded
+       angriss' lair location given by description
+       (sextant coords from goblins just seemed wierd)
+
+       * worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/special.scm:
+       moving angriss' lair a little (to a more readily describably location)
+
+2008-11-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Changes to haxima:
+       o Added a "stuck" effect that works like ensnare but rolls against thiefly
+         ability
+       o Wriggle now has a very good chance of getting stuck.
+
+2008-11-23  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm:
+       fire sea rune quest (such as it is) upgraded
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/runes.scm:
+       kurpolis rune quest upgraded
+
+       * worlds/haxima-1.002/quest-sys.scm: quest-set-icon! fixed
+
+2008-11-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/pitfalls.scm:
+       Changes to haxima:
+       o Using pitfalls entails some risk. Roll against thiefly ability. This is the
+         arm trap skill.
+
+2008-11-23  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/quests-mech.scm:
+       a batch of subquests (although they wont all be set at once for much longer)
+
+       * worlds/haxima-1.002/conv.scm: typo
+
+       * worlds/haxima-1.002/runestones.png, worlds/haxima-1.002/sprites.scm:
+       runestone group sprite
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm:
+       dragons blood quest upgraded
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/ztats-quest-ui.scm:
+       tweaked quest-status callback. Also made the display routine actually invoke it
+
+2008-11-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Changes to haxima:
+       o Reduced fatigue time
+       o Added warrior skill sets
+       o Jump now causes fatigue and is blocked by it
+       o Tuned jump range
+       o Bugfix: can't sprint through people or impassable terrain
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/disarm-trap.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/the-man.scm:
+       Changes to haxima:
+       o Removed mana cost for skills.
+       o Removed ap cost for some skills (replacing with multi-turn tasks)
+       o Removed the "detect trap" skill. Use existing s)earch command instead,
+         thiefly ability already used to roll for success. Magic detect trap left
+         as-is (no trip chance).
+       o Modified the "disarm trap" skill to be multi-turn
+       o When describing doors and chests, disarmed traps are annotated
+
+       * worlds/haxima-1.002/game.scm: Revised canonical difficulty classes
+
+2008-11-22  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/ztats-quest-ui.scm:
+       support for subquests
+
+       * worlds/haxima-1.002/gregor.scm: 'if' glitch
+       decapitalization
+
+2008-11-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Changes to haxima:
+       o Added simple fatigue effect
+       o Sprint causes fatigue
+       o Fatigue prevents sprint
+
+       * src/cmd.c, src/result.h: Engine changes:
+       o New result code: not-now
+
+       * worlds/haxima-1.002/skills.scm:
+       Fixing some errors; not sure what I was testing before my last commit
+
+       * worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/skills.scm:
+       Changes to haxima:
+       o Added two new ability calculators for strength-based acrobatics and
+         dexterity-based acrobatics.
+       o The sprint skill now uses strength-based acrobatics to compute max range.
+
+       * worlds/haxima-1.002/tools.scm: Time to pick a lock depends on dc
+
+2008-11-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/ctrl.c, src/foogod.c, src/foogod.h, src/player.cpp:
+       Foogod title bar now shows party movement mode and active party member
+
+       * worlds/haxima-1.002/conv.scm: No need to *lie* about the directions
+
+       * worlds/haxima-1.002/tools.scm:
+       Using picklocks now takes multiple turns
+
+       * worlds/haxima-1.002/conv.scm:
+       Made default directions somewhat helpful
+
+       * worlds/library/artwork/creatures/chicken.xcf: Changes to chicken art
+
+       * src/character.cpp:
+       Was passing the gob incorrectly to the task procedure
+
+       * src/cmd.c, src/cmd.h: Can't quit while engaged in a task
+
+2008-11-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm:
+       Charm only hurts diplomacy on failure against a non-immune target
+
+       * worlds/haxima-1.002/effects.scm:
+       Paralyzed party members cannot rendezvous in follow mode
+
+2008-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/player.cpp: Can't rendezvous to exit if a party member is charmed
+
+       * src/character.cpp:
+       o NPC's now (in addition to PC's) log messages when they start, end or abort a
+         task.
+       o setPlayerControlled(false) (ie, charm) cancels tasks
+       o Fixed an extra space char in describe(); made spacing consistent; changed "a
+         LX" to "an LX"
+
+       * worlds/haxima-1.002/creatures.png, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/scrolls.png, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/trigrave.scm:
+       Chickens
+
+       * worlds/library/artwork/creatures/chicken.xcf: Chicken
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/scrolls.png, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/spells.png, worlds/haxima-1.002/spells.scm:
+       Decided to go ahead and incorporate my test scroll as a new spell: Rel Xen Quas or Beastly Illusion will charm it's target with faction-monster, making decent folk attack them. Not sure if it's useful. Also tweaked some of the spell sprites to make party effect sprites more consistent with Vas An Nox.
+
+       * worlds/haxima-1.002/scrolls.scm:
+       Added a scroll to test charm on oneself
+
+       * worlds/haxima-1.002/effects.scm:
+       Modified the charm effect to use kern-char-set-player-controlled as well as changing the target's current faction
+
+       * src/character.cpp, src/cmd.c:
+       Changed setPlayerControlled for charm; it tries to do the right thing for party control when in solo or follow mode
+
+       * src/object.c: Removed some dead code
+
+2008-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp: Death and sleep cancel tasks
+
+       * src/cmd.c:
+       Loitering disabled while any party member is engaged in a task
+
+       * src/character.cpp:
+       Only save AP debt; a positive would be carried over as an unwarranted ap bonus when the game restarts
+
+       * src/character.cpp: Removed some old debug
+
+       * src/player.cpp:
+       Party cannot exit to wilderness while one or more is engaged in a task
+
+2008-11-16  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/tbl.scm: added is-tbl? check
+       also, lisp if syntax is a cruel abuse upon generations of innocent coders
+
+       * worlds/haxima-1.002/alchemist.scm:
+       "find out about runes" quest upgraded (missed a file)
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm:
+       "find out about runes" quest upgraded
+
+       * worlds/haxima-1.002/naz.scm: removed some debugging messages
+
+       * worlds/haxima-1.002/quests-mech.scm:
+       alter quest feedback to prevent colour glitches
+
+2008-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/tools.scm:
+       Added a special object to test multi-turn tasks.
+
+       * src/object.c, src/object.h, src/player.cpp, src/character.cpp, src/character.h, src/cmd.c, src/kern.c:
+       This set of changes is a second pass at implementing multi-turn tasks. It is
+       far from well-tested and I'm certain it breaks the charm effect. But the basics
+       of task starting, completing, aborting and saving/reloading are functional, and
+       the party control management that goes along with it. Tasks in wilderness are
+       not supported yet. Canceling tasks are accomplished by setting the PC to solo
+       mode (the player will be prompted to confirm).
+
+       o Added kern-char-task-begin, -end, -continue and -abort.
+       o Added corresponding methods to the Character class
+       o Ripped a bunch of code out of setCurrentFaction that was used to implement
+         charm, but was munging things up now, and which probably never belonged there
+         in the first place.
+       o Similarly I tore out the code I recently put in setControlMode, for similar
+         reasons.
+       o Had to touch a few other places to prevent code from overriding the PC
+         control mode while it was engaged in the task.
+
+2008-11-16  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/abe.scm: tweaks to Abe's conv
+
+2008-11-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/escape.c, src/escape.h:
+       Might need these to build after my last commit.
+
+       * src/Makefile.am, src/character.cpp, src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c, src/play.c, src/player.cpp:
+       Added an ESC interrupt menu. This allows the user to take some action when the active PC is stuck with a high AP debt. The intention is to use this for multi-turn tasks as well.
+
+2008-11-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/conv.c:
+       Another bug fixed in keyword highlighting: fen comes before fens
+
+2008-11-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/conv.c:
+       Short keywords that appeared with punctuation after them were not getting highlighted
+
+       * src/kern.c:
+       Bug introduced on my last commit: don't register NIL conversations
+
+       * src/conv.c, src/conv.h, src/kern.c, src/scheme-private.h, src/scheme.c:
+       Processing conversation keywords is now done lazily, when a conversation is entered the first time. This fixes a bug where in some save files the file containing a conversation is loaded after the character that uses it.
+
+       * worlds/haxima-1.002/gregor.scm:
+       End conv if Gregor kills Nate when Nate is speaker
+
+       * worlds/haxima-1.002/gregor.scm: Changed who shoots the deathball
+
+2008-11-13  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/thiefs_den.scm, worlds/haxima-1.002/traps_1.scm, worlds/haxima-1.002/traps_2.scm, worlds/haxima-1.002/traps_3.scm, worlds/haxima-1.002/traps_4.scm:
+       thief quest upgraded
+
+       * worlds/haxima-1.002/hackle.scm: swapping allcaps for colour highlight
+
+       * worlds/haxima-1.002/chanticleer.scm: typo
+
+2008-11-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/tools.scm:
+       Reverted lockpicking and unlock spells; removed unlock as a skill
+
+       * worlds/haxima-1.002/demo.scm:
+       Renamed the Gate Portal as Demo Scene to make the starting console message clear that the player is watching a demo
+
+       * src/kern.c:
+       kern.c includes config.h so the quest status page will work when configured.
+
+       * worlds/haxima-1.002/gregor.scm:
+       Gregor kills Nate. Cleaned up his conv a bit, too.
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/quest-talk-to.scm:
+       Getting rid of obsolete quest file
+
+       * src/conv.c: Bugfix: short keywords not getting detected in some cases
+
+       * worlds/haxima-1.002/ini.scm:
+       For Ini, 'deep' was a keyword but he gave the default reply unless he was flagged as ready to join the party. I added an alternate default reply so it doesn't look like a bug.
+
+       * scripts/RELEASE_CHECKOFF: Some updated notes
+
+2008-11-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/npc-types.scm:
+       Changes to haxima:
+       o The camping ambush was still being added via the obsolete
+         kern-set-camping-proc. Fixed it to use kern-add-hook.
+       o Fixed the statue curse: same problem. Now uses kern-rm-hook as well.
+       o Reverted faction-glasdrin to be its own value so that the exile curse won't
+         affect the player in all cities. Fixed the glasdrin guard spawn pts to spawn
+         guards specific to glasdrin so they will enforce the exile curse.
+
+       * src/kern.c, src/session.c, src/session.h: Engine:
+       o Session no longer saves its hooks. All session hooks are either being loaded
+         on startup via script files or via effects. Saving them was just causing them
+         to be added multiple times on reload.
+       o Added kern-rm-hook and session_rm_sym_hook. To be removed, a hook proc must
+         have been a symbol.
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/tools.scm:
+       Changes to haxima:
+       o Picklocks are no longer u)sable, the player must y)use the picklock skill
+       o Breaking lockpicks is done in the skill based on critical failure
+       o First pass at level requirements for wrogue skills
+
+       * src/cmd.c, src/ctrl.c, src/result.h: Engine:
+       o Added #include to enable skills if configured
+       o Added a new result code: critical failure
+       o Colorized reporting of result codes in the console
+
+2008-11-11  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/music/Lute-and-recorder-ballad.ogg, worlds/haxima-1.002/music/Minuet-like-Mozart.ogg, worlds/haxima-1.002/music/ballad.ogg, worlds/haxima-1.002/music/bassoons-and-harpsichord.ogg, worlds/haxima-1.002/music/double-trios.ogg, worlds/haxima-1.002/music/dragon-quest.ogg, worlds/haxima-1.002/music/dragon-slayer.ogg, worlds/haxima-1.002/music/fair-camelot.ogg, worlds/haxima-1.002/music/game-music2.ogg, worlds/haxima-1.002/music/harpsichord-piece.ogg, worlds/haxima-1.002/music/into-battle.ogg, worlds/haxima-1.002/music/medieval-quest.ogg, worlds/haxima-1.002/music/minstrel-dance.ogg, worlds/haxima-1.002/music/music.scm, worlds/haxima-1.002/music/plainchant-recorder-trio.ogg, worlds/haxima-1.002/music/wind-trio.ogg:
+       Lets try Ogg music
+
+2008-11-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/powers.scm:
+       Changes to haxima:
+       o Locked and magically locked doors and chests have a difficulty
+         class. Currently everything defaults to "normal".
+       o The lock and magic unlock powers roll to succeed.
+
+       * worlds/haxima-1.002/statue-of-justice.scm:
+       Status of Justice's name is known to player
+
+       * worlds/haxima-1.002/game.scm:
+       Removed some commented-out code; added some generic difficulty class values; changed glasdrin faction to match normal men (otherwise guards in glasdrin won't attack if you assault the populace or get exiled by the statue)
+
+2008-11-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/conv.c:
+       Maybe I should at least *compile* my changes before checking them in.
+
+       * src/conv.c:
+       Fixed crasher if unknown NPC initiaites conversation with player
+
+       * worlds/haxima-1.002/gamestart.scm:
+       Statue names are automatically known to player
+
+       * worlds/haxima-1.002/gamestart-statues.scm:
+       Gave the starting statues some personality.
+
+2008-11-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/nazghul.c: Removed some dead code
+
+       * COPYING, src/ascii.c, src/cmd.c, src/ctrl.c, src/images.c, src/images.h, src/map.c, src/menus.c, src/play.c, src/screen.h, src/screen_dims.h, src/sprite.c, worlds/haxima-1.002/kern-init.scm:
+       I did not get all of Eero's 16bpp patch applied. He sent me some new patches, which are applied now.
+
+       * src/character.cpp, src/cmd.c, src/combat.c, src/conv.c, src/kern.c, src/log.c, src/log.h, src/nazghul.c, src/player.cpp:
+       Added log_banner(), which provides a consistent format for especially notable log messages. Converted some existing messages over to use it.
+
+       * src/scheme.c:
+       Fixing a crash that may occur when a hook procedure loads a file.
+
+       * configure.ac: Bumped version to 0.7.0 on trunk for next time
+
+       * configure.ac: Bumped version to 0.6.2 for next time
+
+       * NEWS: Updated NEWS
+
+       * src/character.cpp, src/character.h, src/conv.c, src/kern.c:
+       In conversations, the NPC's name is not printed until the player queries NAME
+
+       * NEWS: Added a few more changes to NEWS
+
+       * src/Makefile.am: Removed bitfield.h from source list
+
+       * NEWS: Updated NEWS for 0.6.1 release
+
+       * worlds/haxima-1.002/bart.scm: Removed duplicate word in conv
+
+2008-11-09  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm:
+       uses kern-set-start-proc to initiate hotfix
+
+       * worlds/haxima-1.002/game.scm:
+       hotfix for saves with voidgap/deeps bug.
+
+       still needs hook code in kern
+
+2008-11-08  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm: pullling in spell fixes
+
+       * worlds/haxima-1.002/voidgap-passage.scm: pulling in fix from 1.4
+
+       * worlds/haxima-1.002/scrolls.scm: pull in scroll fixes
+
+       * worlds/haxima-1.002/necromancer.scm:
+       pulled in conversation fix from 1.16
+
+       * worlds/haxima-1.002/naz.scm:
+       pulled in some fixes and stuff I will need for save update
+
+       * worlds/haxima-1.002/mouse.scm: pulled in conversation fix from 1.19
+
+       * worlds/haxima-1.002/enchanter.scm: pulled in spelling fix from 1.25
+
+2008-11-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/fields.scm:
+       Ported over chance to avoid sleep fields so that permanent sleep fields are not unavoidably lethal to one-man parties
+
+       * worlds/haxima-1.002/effects.scm:
+       Ported over fix for FR 2216959- prevent multiple protection spells on one character.
+
+       * worlds/haxima-1.002/silas.scm:
+       Ported over fix for Silas not giving the player a clue about the final rune
+
+2008-11-08  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/silas.scm:
+       silas is more forthcoming about the final rune
+
+       * worlds/haxima-1.002/powers.scm:
+       undo cone tweak- had undesirable side effects
+
+       * worlds/haxima-1.002/powers.scm:
+       fixed poison wind and sleep wind spells. tweaked cone display
+
+       * worlds/haxima-1.002/fields.scm:
+       sleep fields have a slight avoidance chance, so a character stuck in a permanent sleep field will have a chance to get out eventually
+
+       * src/kern.c:
+       (kern-script-version) with no arguments returns current version
+
+2008-11-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac: Bumped version to 0.6.1 in prep for next release
+
+       * src/Makefile.am, src/nazghul.c, src/nazghul.h, src/screen.c:
+       Merged over Eero's 16bpp patch
+
+2008-11-07  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm:
+       quickfix for FR 2216959- prevent multiple protection spells on one character.
+
+       * worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/quests-data-static.scm:
+       adding quest update notifications
+       tweaked order of quest completion
+
+       * worlds/haxima-1.002/quests-mech.scm: bug fixing in quest callbacks
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/start-new-game.scm:
+       moved quest-ui flag to somewhere it doesnt break reloads
+
+       * worlds/haxima-1.002/enchanter.scm:
+       use quest complete with notification
+
+       * worlds/haxima-1.002/quests-mech.scm: quest notifications
+       used wrong loading type for refreshing questlist on save load
+
+       * worlds/haxima-1.002/quests-data-static.scm: bugfix- unmatched quotes
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       disable quest ui based on script side tag
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       added script side quest interface disabling
+
+       * worlds/haxima-1.002/quests-mech.scm:
+       added procedure to reload quests-data to refresh quest info
+       mechanisms to handle postponing experience granted for partial completion of unassigned quests
+
+       * worlds/haxima-1.002/quests-data.scm:
+       quest data should now be created/expanded as necessary for out of date save games, provided they load quests-data.scm in the first place
+
+2008-10-29  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quests-data-static.scm:
+       Passing a function a bunch of arguments and passing it a list containing those arguments are not the same thing. It is important to remember this.
+
+2008-10-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Bugfix: if you hit ESC when selecting a guard for camping it would deref a null pointer when checking if the guard was dead
+
+2008-10-26  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quests-data-static.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/start-new-game.scm:
+       Separated out static quest data from quest utilities
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       Second pass at fixing quest description listing- Scrolling now respects lower limit of description text
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/ztats-quest-ui.scm:
+       First pass at fixing quest description listing- No longer draws over bottom of display when overlong
+
+       * src/event.c, src/kern.c, src/ztats.c: Tweaks to menu controls
+
+       * worlds/haxima-1.002/quests-data.scm:
+       Quests should now all use the kern-ui-paginate-text function to lay out text nicely
+
+       * src/kern.c:
+       Added a kern function that takes a list of lines of text and returns them in a paginated format.
+
+2008-10-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac, src/kern.c:
+       Disabling the quest UI by default, since it's still half-baked. Developers may
+       enable it with a configure option:
+
+          ./configure --with-quests
+
+       Or by editing config.h:
+
+          #define USE_QUESTS
+
+       This does *not* effectively disable quests, however. Some conversation scripts
+       are broken, apparently because they can't get quest data.
+
+       * src/ctrl.c, configure.ac, src/cmd.c:
+       Disabling the Y)use command (and hence skills) by default, in preparation for
+       the next release, since skills are still half-baked. For developers, there is
+       now a configure option to enable them:
+
+         ./configure --with-skills
+
+       Or, if you do not use configure, add this to config.h:
+
+         #define USE_SKILLS 1
+
+2008-10-06  kaypy  <kaypy@localhost.localdomain>
+
+       * scripts/retab.html:
+       A javascript app that handles lining up those tables like in arms.scm nicely
+
+       * worlds/library/artwork/terrain/city.xcf: Larger set of buildings
+
+       * worlds/library/artwork/terrain/towns.xcf:
+       Some higher res collections of houses
+
+2008-10-05  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/sprites.scm:
+       Some towns use the new tower icons
+
+       * worlds/haxima-1.002/bigobjects.png:
+       a bunch of stuff hadnt worked quite right with the towers
+       (mostly scaling had been set to nearest pixel, rather than antialiasing)
+
+       * worlds/library/artwork/terrain/tower.xcf:
+       saved at right resolution this time.
+
+       * worlds/haxima-1.002/bigobjects.png: big tower sprites
+
+       * worlds/library/artwork/terrain/tower.xcf:
+       tower, intact or ruined, with optional town
+
+2008-09-27  kaypy  <kaypy@localhost.localdomain>
+
+       * INSTALL:
+       Added a few of the more recent libraries to the requirements list
+       Some additional instructions for cvs builds and a pointer to the win32
+       instructions
+
+2008-09-26  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/books.scm:
+       inital quest to go meet the enchanter
+
+       * worlds/haxima-1.002/kobj.scm:
+       signal-kobj now safely ignores inputs to non-present ifcs
+
+       * worlds/haxima-1.002/start-new-game.scm: start was a little off-center
+
+       * worlds/haxima-1.002/tbl.scm:
+       tbls were not roundtripping to savefiles correctly
+       also tightened specifications of tbl-append
+
+       * worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/quests-mech.scm:
+       additional 'whereami' text after talking to N
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quests-mech.scm:
+       quests kept in order of in progress/complete/failed
+       fixed some bugs resulting from unexpected behaviour of pair? function
+
+2008-09-24  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/abe.scm:
+       removed now redundant quest update calls
+
+       * worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/quests-data.scm:
+       updating prebuild quests can trigger status update hook
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       quest list ui colored based on completion state
+
+       * worlds/haxima-1.002/quest-sys.scm:
+       quest completion includes failure option
+
+       * worlds/haxima-1.002/tbl.scm:
+       mechanism to preload a tbl when building it
+
+2008-09-22  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/gamestart-mech.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/abe.scm:
+       Uses optional tags rather title for quest lookups
+       Reconciles active and pregenerated quests after reload
+
+2008-09-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/quests-mech.scm: Spelling fix
+
+2008-09-15  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/abe.scm:
+       More detail on the 'Where am I?' quest
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       Cleaned out some superflouous debugging printlns
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/ztats-quest-ui.scm:
+       A few more quests started
+       Prev patches had broken zstats-quest-ui up/down controls
+
+       * worlds/haxima-1.002/quests-mech.scm, worlds/haxima-1.002/quests.png, worlds/haxima-1.002/quests-data.scm, worlds/haxima-1.002/tbl.scm, worlds/haxima-1.002/ztats-quest-ui.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quest-talk-to.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gamestart-mech.scm:
+       quests reenabled
+       quests have icons
+       quests can be removed from the log entirely
+       quests can be retrieved by title (assuming uniqueness, otherwise will get the first one)
+       a databank of not-yet-assigned quests is available, but not mandatory- Im thinking this is useful for quests that may have changes before the player recieves them
+       added some initial cases
+
+2008-09-13  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/ztats-quest-ui.scm:
+       quests take a list of strings for description, to allow longer, wrapped descriptions.
+
+       * src/sprite.h, src/sprite.c, src/kern.c:
+       Added a mechanism to directly paint a sprite in a sdl_rect. Intended for use with scripted UI panels
+
+2008-06-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/conv.c, src/conv.h, src/menus.c, src/nazghul.c, src/sound.c, src/sound.h:
+       Added a menu option for keyword highlighting
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Added version number to new game script
+
+       * src/session.h, src/session.c, src/ascii.h, src/kern.c, src/play.c:
+       Added support for script version number. If a session fails to load, check the version number and report it to the player.
+
+       * configure.ac:
+       Bumped the version number. Added min script version number.
+
+       * src/screen.c: Moved the screen's temp buf off the stack
+
+       * src/session.c:
+       Fixed some crashes that occur on a load error. session_del() should not assume
+       the player has been loaded, and session_load() was double-deallocating the
+       scheme instance.
+
+       * src/play.c: On load error, print 'error' in red
+
+       * src/scheme.c:
+       Reverting my last changes to this file; they caused a double-deallocation
+
+2008-06-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/foogod.c:
+       bugfix: don't assume the cfg contains progress-bar-image-filename
+
+       * src/menus.c: Bugfix: sometimes error popup was blank
+
+       * src/nazghul.c:
+       Using the primitive error dialog window for library init errors early in startup.
+
+       * src/terrain.c, src/scheme.c, src/sprite.c, src/Being.h, src/character.cpp, src/kern.c, src/Being.cpp:
+       Fixed some leaks; attempted to fix some other complaints from valgrind
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       Fixing a bug in my last commit
+
+2008-06-06  kaypy  <kaypy@localhost.localdomain>
+
+       * win32/readme.txt:
+       Updated based on latest attempt to compile the system from scratch
+
+2008-06-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm: Turning off the quest ui stuff for now
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       Changed quest ui to expect the player party gob to be a table
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quest-talk-to.scm:
+       Changed conv check hooks to expect the player party gob to be a table
+
+       * src/conv.c, src/sprite.c: Checking in turned-off portrait test code.
+
+       * src/status.c, src/applet.h:
+       Added optional get_desired_height call for applets
+
+       * src/kern.c, src/object.c, src/object.h: Added kern-set-portrait
+
+       * src/scheme.c:
+       Fixed a bug where a comment at the end of a loaded file could choke the interpreter
+
+2008-05-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/bitset.h, src/conv.c, src/conv.h, src/kern.c:
+       Kernel changes:
+       o Keywords which have already been used in a conversation are highlighted
+         gray. Unused keywords are highlighted magenta. The engine "remembers" used
+         keywords until the next time the game is loaded. In other words, it does not
+         save this info as part of the session save file.
+
+       * worlds/haxima-1.002/gregor.scm:
+       Removed colorizing markup now that keywords can be automatically highlighted
+
+       * src/kern.c, src/object.c, src/object.h, src/character.cpp, src/cmd.c, src/conv.c, src/conv.h:
+       Conversation keyword highlighting
+
+       * src/log.c: Added some brackets to an if
+
+2008-05-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/minimal-start.scm, worlds/haxima-1.002/monsters.png, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/tutorial.scm:
+       Fixed main game to work with my recent changes
+
+2008-05-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/sounds.scm, src/scheme-private.h, src/session.c, src/session.h, worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/minimal-start.scm, worlds/haxima-1.002/quest-talk-to.scm, src/closure.c, src/kern.c:
+       Kernel changes:
+       o Moved the scm macros from kern.c to scheme-private.h for everyone to enjoy
+       o Removed some duplicate macros from closure.c
+       o Changed kern-add-hook to expect a symbol for the handler
+       o Added session_hook_id_to_str and session_str_to_hook_id
+       o session now saves the registered hook handlers (except for
+         new_game_start_hook, which needs to be a special case for now at least)
+
+       Haxima changes:
+       o Had to update all the kern-add-hook calls to match the kernel changes
+       o Finally got my prototype quest offer to be persistent across sessions,
+         remove itself when accepted, and in general work the way I want it to.
+
+2008-05-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/minimal-start.scm:
+       Experimental end-of-conv hook that will run multiple handlers; prototyping quest offers to run as handlers and remove themselves when accepted
+
+       * worlds/haxima-1.002/tbl.scm: Added tbl-rm! and tbl-for-each-val
+
+       * src/kern.c:
+       Added kern-define, for preserving scheme variables across sessions
+
+2008-05-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c: Fixed a crasher in the new unpack_rect fx
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/minimal-start.scm, src/closure.c, src/closure.h, src/gob.c, src/kern.c, src/session.c, src/session.h, src/session_hooks.h, src/session_queries.h, worlds/haxima-1.002/demo.scm, src/Makefile.am, src/character.cpp:
+       Kernel changes:
+       o Split session hooks and queries up into separate tables.
+       o Hooks can have multiple handlers. Running the hooks does not return a value.
+       o Queries only have one handler and return an int.
+
+       Haxima changes:
+       o Fixed the query registration as per the kernel changes.
+       o Random experimental stuff in minimal-*.scm
+
+       * worlds/haxima-1.002/enchanter.scm: Spelling fix
+
+2008-05-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/minimal-start.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quest-talk-to.scm, worlds/haxima-1.002/tbl.scm, worlds/haxima-1.002/ztats-quest-ui.scm, src/conv.c, src/session_hooks.h:
+       Kernel changes:
+       o Added conv_end_hook
+
+       Haxima changes:
+       o Re-implemented player gob in minimal game as a table.
+       o Changed quest stuff accordingly
+
+2008-05-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/quest-talk-to.scm, worlds/haxima-1.002/minimal-start.scm, worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/minimal-game.scm:
+       Haxima changes:
+       o Added a simplified talk-to quest which just awards xp when complete.
+
+       * worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/minimal-start.scm, worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quest-talk-to.scm:
+       Haxima changes:
+       o Had to change the quest ctor to require symbols instead of raw
+         procedures. This was necessary to support saving quests as part of the
+         object's gob (closures can't be saved).
+       o Added a proc for the conv_start_hook
+       o Talk-to quests can now be completed.
+
+2008-05-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm, worlds/haxima-1.002/minimal-start.scm, worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/tutorial.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/demo.scm, src/session.h, src/session_hooks.h, src/menus.c, src/play.c, src/session.c, src/conv.c, src/kern.c, src/character.cpp, src/closure.c, src/closure.h, src/combat.c, src/Makefile.am:
+       Kernel changes:
+       o Consolidated all of our ad-hoc session hook procedures (camping, start game,
+         change music, query combat attributes, etc) into one table. This means they
+         can re-use the same code to load, run and clean them up, instead of having to
+         cut-and-paste them. There's also a new session_hooks.h file where all of the
+         hooks need only be declared once. After adding your hook there, you just need
+         to write the code to call it from someplace in the kernel source (a one-line
+         change).
+       o Added a conv_start_hook (for talk-to quests).
+
+       Haxima changes:
+       o Replaced all the new-obsolete kern calls with kern-add-hook.
+
+       Note: the changed kern calls are not ones needed by saved games, only by the
+       new game startup scripts, so this should not break save-game compatibility.
+
+2008-05-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/minimal-game.scm, worlds/haxima-1.002/minimal-start.scm:
+       Adding a very simple but fast-loading game for development and test
+
+2008-05-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/ztats-quest-ui.scm:
+       Exported ASCII_H to the script as kern-ascii-h
+
+       * src/quest.h, src/Makefile.am, src/quest.c:
+       Removed old prototype quest stuff
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm, src/applet.h, src/kern.c, src/ztats.c:
+       Kernel changes:
+       o Changed kern-event-push/pop-keyhandler to kern-event-run-keyhandler
+       o Removed the unused "stop" operation from the applet struct
+       o Added kern-screen-erase and kern-screen-update
+
+       Haxima changes:
+       o Added quest viewer applet for individual quest details
+
+       * src/ztats.h, worlds/haxima-1.002/ztats-quest-ui.scm, src/status.h, src/ztats.c, src/macros.h, src/status.c, src/cmd.c, src/kern.c, src/applet.h, src/Makefile.am:
+       Kernel changes:
+       o Added an applet struct
+       o Added statusRunApplet and statusGetCurrentApplet
+       o Added a "select" operation to the ztats panes
+       o Converted the ztats UI to run as an applet
+
+       Haxima changes:
+       o Modified quest log ui to implement a nop "select" proc
+
+2008-05-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/event.c, src/event.h, src/kern.c, src/status.c, src/ztats.c, src/ztats_pane.h:
+       Kernel changes:
+       o eventPopKeyHandler now returns the keyhandler that was popped
+       o added kern-event-push-keyhandler
+       o added kern-event-pop-keyhandler
+       o added a 'select' operation to the ztats_pane
+       o added eventRunKeyHandler to manage all the boilerplate of
+         pushing/running/popping key handlers
+
+       * src/event.h, src/kern.c, src/event.c:
+       Fix for bug [ 1734069 ] pathfinder confused by diagonal gaps. The pathfinder
+       was written so that if the character could get one tile away from the
+       destination then this was good enough. This is ok for for combat pathfinding
+       and following the leader; but for commuting it's not ok when the last step is
+       impassable, because the character needs to actually get there or it will keep
+       trying to commute over and over. I added a new pathfinding flag to indicate
+       that "adjacent is NOT ok", and set this flag for commuting.
+
+2008-05-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       Got the quest log listing pane to scroll properly
+
+       * worlds/haxima-1.002/game.scm: Added scroll directions
+
+       * worlds/haxima-1.002/naz.scm: Added some rect and incr/decr utilities
+
+       * src/status.h:
+       Ensure enum (which must be in synch with script) starts at zero
+
+2008-05-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm, src/kern.c:
+       kernel passes ztats ui dimension rect as a list back to scheme; added kern-screen-shade
+
+       * worlds/haxima-1.002/quest-sys.scm, worlds/haxima-1.002/quest-talk-to.scm, worlds/haxima-1.002/ztats-quest-ui.scm, src/kern.c:
+       Kernel changes:
+       o kern-screen-print expects the rect arg to be a list now
+
+       Script changes:
+       o ztats-quest-ui.scm was
+         ...updated to match kern-screen-print
+         ...modified to print all the quests attached to the party
+       o quest-sys.scm prints a console msg when a quest is assigned
+
+       * worlds/haxima-1.002/naz.scm:
+       Added two new utilities: repeat and string-lower
+
+       * worlds/haxima-1.002/game.scm: Load the quest files
+
+       * src/kern.c:
+       kern-obj-get-place returns NIL if the object has a NULL place
+
+       * worlds/haxima-1.002/ztats-quest-ui.scm:
+       Display a little bit about current quests
+
+       * worlds/haxima-1.002/quest-talk-to.scm: Added basic talk-to quest type
+
+       * worlds/haxima-1.002/quest-sys.scm: Added basic quest type
+
+       * worlds/haxima-1.002/sounds.scm:
+       Changed music-on-combat-change to check for a null location (fixes a crashed when we start the game on the world map)
+
+       * worlds/haxima-1.002/naz.scm:
+       Added some more utilities, and changed player-member-loc to check for a null location
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/ztats-quest-ui.scm:
+       Added ztats-quest-ui.scm, which implements a stub for a quest log ztats pane.
+
+       * src/kern.c:
+       Added kern-ztats-add-pane, kern-ztats-set-title and kern-screen-print.
+
+       * src/gob.c: Just a todo comment
+
+2008-05-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ztats_spells.h, src/ztats_reagents.c, src/ztats_reagents.h, src/ztats_spells.c, src/ztats_pm.h, src/ztats_pm.c, src/ztats_misc.h, src/ztats_pane.c, src/ztats_pane.h, src/ztats_items.c, src/ztats_items.h, src/ztats_misc.c, src/ztats_container_pane.h, src/ztats_container_pane.c, src/ztats_arms.c, src/ztats_arms.h, src/ztats.h, src/ztats.c, src/quest.h, src/status.c, src/status.h, src/player.h, src/quest.c, src/kern.c, src/player.cpp, src/Makefile.am, src/Party.cpp, src/Party.h:
+       Rewrote ztats UI.
+
+       * src/sound.h:
+       Fixed a c++ name-mangling compile error that cropped up out of the blue
+
+       * src/sound.c: Fixed what looks like an = vs == bug
+
+       * src/combat.c: Removed some dead code
+
+2008-05-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac, worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/music/Makefile.am:
+       Andreas Bauer's fix for the music installation
+
+2008-04-06  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/mouse.scm:
+       fix for 1934040- kat/thud will no longer talk after betraying you.
+
+2008-03-17  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/voidgap-passage.scm:
+       fix for 1916322- the voidgap dungeon setup wrote some garbage over the endless deepness setup
+
+2008-03-02  kaypy  <kaypy@localhost.localdomain>
+
+       * src/menus.c, src/nazghul.c, src/play.c, src/sound.c, src/sound.h:
+       music-volume setting (unfortunately doesnt work on midi!)
+       better handling of music loading errors
+
+       * src/menus.c: Added music credits to title page
+
+2008-03-01  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/void-temple.scm, worlds/haxima-1.002/voidgap-passage.scm, worlds/haxima-1.002/westpass.scm, worlds/haxima-1.002/abandoned-cellar.scm, worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/altar-room.scm, worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/ankh-shrine.scm, worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/crypt.scm, worlds/haxima-1.002/dank-cave.scm, worlds/haxima-1.002/eastpass.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/forsaken-prison.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/lich-tomb.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/necromancers-lair.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/old-mine.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/prison.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/thiefs_den.scm, worlds/haxima-1.002/traps_1.scm, worlds/haxima-1.002/traps_2.scm, worlds/haxima-1.002/traps_3.scm, worlds/haxima-1.002/traps_4.scm, worlds/haxima-1.002/treasury.scm, worlds/haxima-1.002/trigrave.scm:
+       Add music data to all the places
+
+       * worlds/haxima-1.002/game.scm: Init music hooks
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       Music compatible random maps content freezing
+
+       * worlds/haxima-1.002/statue-of-justice.scm: Typo in text
+
+       * worlds/haxima-1.002/gamestart-statues.scm: Fixed spelling
+       Statues respond to abbreviated stat names
+
+       * worlds/haxima-1.002/naz.scm:
+       Method to retrieve location of player party members (which occasionally differs from the location of the player party)
+
+       * worlds/haxima-1.002/sounds.scm:
+       Utility methods for tracking music in and out of combat (+ transitions) for different places
+
+       * worlds/haxima-1.002/music/wind-trio.mid, worlds/haxima-1.002/music/Lute-and-recorder-ballad.mid, worlds/haxima-1.002/music/Minuet-like-Mozart.mid, worlds/haxima-1.002/music/ballad.mid, worlds/haxima-1.002/music/bassoons-and-harpsichord.mid, worlds/haxima-1.002/music/credits.txt, worlds/haxima-1.002/music/double-trios.mid, worlds/haxima-1.002/music/dragon-quest.mid, worlds/haxima-1.002/music/dragon-slayer.mid, worlds/haxima-1.002/music/fair-camelot.mid, worlds/haxima-1.002/music/game-music2.mid, worlds/haxima-1.002/music/harpsichord-piece.mid, worlds/haxima-1.002/music/into-battle.mid, worlds/haxima-1.002/music/medieval-quest.mid, worlds/haxima-1.002/music/minstrel-dance.mid, worlds/haxima-1.002/music/music.scm, worlds/haxima-1.002/music/plainchant-recorder-trio.mid:
+       Added Jim Paterson's midi music (the zip on the ftp site says we have permission)
+
+       * src/kern.c, src/session.c, src/session.h:
+       Hooks for game start and for changes in combat state
+
+       * src/combat.c:
+       Entering combat map sets combat state _after_ participants are positioned (helps with combat state change hook)
+
+2008-02-23  kaypy  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/combat.c, src/place.c:
+       Combat.state is more proactive abour tracking changes
+
+       * src/sound.c:
+       accepts a full path, so you can point it at your local mp3s if you want
+
+2008-02-21  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/sounds.scm, src/sound.c, src/sound.h, src/kern.c, src/play.c, src/session.c, src/session.h:
+       First pass at shuffle play music
+
+       * src/sound.c:
+       Music seems to work, for sufficiently hacky values of 'work'
+
+2008-02-04  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/gamestart-mech.scm, worlds/haxima-1.002/gamestart-statues.scm, worlds/haxima-1.002/gamestart.scm:
+       working statue char creation
+
+       * worlds/haxima-1.002/start-new-game.scm: initial stats tweaked
+
+2008-02-03  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/bigobjects.png, worlds/haxima-1.002/gamestart-mech.scm, worlds/haxima-1.002/gamestart-statues.scm, worlds/haxima-1.002/gamestart.scm, worlds/haxima-1.002/sprites.scm:
+       First pass at statue/conversation based character generation
+       Not yet functional
+
+       * worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/sfx.png:
+       Added acid fields (I just needed something yellow, really)
+
+2008-01-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/session.c: Fixed a 3k leak that happened on quit
+
+2008-01-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/play.c:
+       Bugfix: reloading a game with a start-proc would not run the start-proc, which might result in a crash
+
+2007-12-30  kaypy  <kaypy@localhost.localdomain>
+
+       * src/sound.c: more paranoid memory handling
+       removed music for the moment
+
+2007-12-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/status.c, src/status.h:
+       y)use ui now scrolls like everything else
+
+2007-12-09  sglasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/kern-init.scm:
+       Added a new config value for the progress bar image file.
+
+       * src/foogod.c: Changed foogod_load_progress_bar_sprites() to load
+       a distinct file, rather than load the image from an
+       inline XPM.
+
+       (A rather strange problem, perhaps associated with
+       an oddly-build RPM of SDL_image came up for OpenSUSE,
+       so it seems better to use a PNG.)
+
+       * worlds/haxima-1.002/progress_bar_image.png:
+       The progress bar sprite pieces, as a PNG file.
+       (There was a problem under at least one compilation environment,
+       with loading this image as an inline XPM.)
+
+       * worlds/haxima-1.002/tetzl.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/thorald.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/tim.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/valus.scm, worlds/haxima-1.002/warritrix.scm, worlds/haxima-1.002/zane.scm:
+       Added various comments.
+
+       * worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/steward.scm:
+       Added some comments.
+
+2007-12-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/valus.scm:
+       Added asides for Ini
+
+       * src/kern.c: Oops. status.c doesn't like NULL containers.
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Pickpocket can fail (with consequences)
+
+       * worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/statue-of-justice.scm, src/cmd.c, src/kern.c, src/status.c, src/status.h:
+       kern-ui-select-item now takes a kchar arg and browses *their* inventory, instead of being hardcoded to the player. The pickpocket skill exploits this.
+
+       * src/terrain.c: Performance tweak for looking up terrains in palettes
+
+       * configure.ac: Sam's changes to configure.ac for SDL_Mixer
+
+2007-12-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/skills.scm:
+       Oops. Didn't see the multiplier on my last. Also added basic pickpocket skill.
+
+       * worlds/haxima-1.002/skills.scm: Skills use the base-skill-ap variable
+
+       * worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/tools.png:
+       Shiny new chest sprites
+
+       * worlds/library/artwork/furniture/chest.xcf: Art for new chest sprites
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/keys.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       Locked and magically locked chests with some ugly sprites for same.
+
+2007-12-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/effects.png, worlds/haxima-1.002/effects.scm:
+       Finished the 'curse of unrest' effect. The SOJ in glasdrin uses it.
+
+       * src/kern.c: NPC party ambush direction was not random
+
+       * src/combat.c:
+       Introducing a party into combat that did not come from the world map (or someplace) caused a crash
+
+       * src/Being.cpp: Turned off some debug
+
+2007-12-05  sglasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/patch.scm:
+       Added some comments.
+
+       * worlds/haxima-1.002/oscar.scm: Corrected some comments.
+
+       * worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/may.scm:
+       Various comments regarding description and location, etc.
+
+2007-12-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/images.c, src/images.h, src/screen.c, src/screen.h, src/sprite.c:
+       Eero's 16-bit patch
+
+       * src/status.c: Tab cleanup and removed a dead function
+
+       * src/Makefile.am, src/map.c, src/menus.c, src/play.c, src/cmd.c, src/ctrl.c, src/nazghul.c, src/nazghul.h:
+       Eero's cleanup patch
+
+       * src/nazghul.h:
+       file nazghul.h was added on branch release_0_6_0_rc2_maint on 2008-11-08 04:30:15 +0000
+
+       * src/combat.c: Turned off some debug
+
+       * src/screen_dims.h:
+       Eero's patch for n800 screen size (kern-init.scm already patched)
+
+2007-12-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/statue-of-justice.scm:
+       A start on the statue curses
+
+       * src/foogod.c:
+       Show extra effects on the party (currently unused, see Party::addEffect for why)
+
+       * src/kern.c: kern-char-set-sched
+
+2007-12-03  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/scrolls.scm:
+       feature 1843033 scrolls explicitly labelled
+
+       * worlds/haxima-1.002/scrolls.scm:
+       fix for 1843001 scrolls fail in wilderness combat
+
+2007-12-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/valus.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/prison.scm:
+       Replacement for the Stewardess
+
+       * worlds/haxima-1.002/shroom.scm: Minor conv fix
+
+2007-12-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/zones.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/janice.scm, worlds/haxima-1.002/jeffreys.scm:
+       Replacement for Jeffries.
+
+       * worlds/haxima-1.002/conv.scm: Tweaked generic glasdrin reply to JEFF
+
+       * worlds/haxima-1.002/jeffreys.scm:
+       Jeffries becomes a vagabond in Kun after the trial
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/steward.scm:
+       Oops. Broke some things on my last commit. Also, updated generic glasdrin conv.
+
+       * worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/player.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/warritrix.scm:
+       Added another player flag for the trial of glasdrin being over.
+
+2007-11-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/species.scm:
+       Implemented butchering as an example crafting skill. You'll need a deer. Currently these aren't autogenerated anywhere.
+
+       * src/ctrl.c: Turned on y)use
+
+       * worlds/haxima-1.002/occs.scm:
+       Added preliminary crafting ability to occs
+
+       * worlds/haxima-1.002/occs.scm:
+       Fixed what looks like a bug in dexterity defense
+
+       * worlds/haxima-1.002/kern-init.scm:
+       Added 880x640 splash from Eero's 16bit patch
+
+       * worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/player.scm:
+       Jeffreys and Stewardess act guilty after player finds Warritrix
+
+       * worlds/haxima-1.002/zones.scm: Bug in holy grail table settings
+
+2007-11-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Removed redefinitions of stuff in player.scm
+
+       * worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/warritrix.scm:
+       Added a gob for the player party.
+
+       * src/player.cpp: Player party object now saves its gob
+
+2007-11-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/foogod.c: Improved progress bar sprite
+
+       * worlds/haxima-1.002/newterrain.png: Put the SOJ on a pedastal
+
+       * src/object.c, src/status.c:
+       Fixing a bug I found by accidentally reloading a new game. Normally this is not possible, I had a weird case. It still doesn't work do to that, there are more bugs.
+
+       * worlds/haxima-1.002/newterrain.png:
+       Should have checked in the new image with the new statue sprite
+
+       * worlds/haxima-1.002/statue-of-justice.scm: Fixed a typo in the xamine
+
+       * worlds/haxima-1.002/game.scm:
+       Fixed the dtable problem I created last time I committed this file
+
+       * worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/statue-of-justice.scm:
+       Changed SOJ's sprite
+
+       * worlds/library/artwork/terrain/headless_statue_with_sword.xcf:
+       New statue sprite
+
+       * worlds/haxima-1.002/game.scm:
+       This should have gone in with my last batch of glasdrin changes
+
+2007-11-26  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/luximene.scm: correction to schedule comment
+
+       * worlds/haxima-1.002/naz.scm:
+       pick-loc checks for valid target locations
+
+       * worlds/haxima-1.002/books.scm: some typos in journal
+
+       * worlds/haxima-1.002/necromancer.scm:
+       fix for 1838195- necromancer now checks you have the skull
+
+2007-11-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/warritrix.scm:
+       Fixed up some conversation bits
+
+       * worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/warritrix.scm:
+       Trading names between the MAN and the Warritrix.
+
+       * worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/steward.scm:
+       The SOJ now exiles the player if he accuses without evidence
+
+2007-11-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/statue-of-justice.scm:
+       Stewardess now punished when convicted. The townsfolk of glasdrin are now all armed.
+
+       * worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/steward.scm:
+       The status of justice in glasdrin will now hold a trial
+
+       * src/cmd.c, src/cmd.h, src/kern.c: Added kern-ui-select-item
+
+       * src/Being.cpp:
+       If an NPC is using a cached path, and the next step is occupied, it discards the cached path so it will recompute next time
+
+       * src/status.c: Renamed a function
+
+2007-11-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/statue-of-justice.scm, worlds/haxima-1.002/terrains.scm:
+       Added statue of justice (doesn't do much yet)
+
+2007-11-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/glasdrin.scm:
+       Added Stewardess's Journal
+
+2007-11-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/foogod.c: Made the progress bar purty.
+
+       * src/foogod.c, src/session.c:
+       The progress bar code generated in the save files is now a pretty good match to actual load times. Not perfect, but probably good enough.
+
+       * worlds/haxima-1.002/tutorial.scm: Added progress bar to tutorial
+
+2007-11-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Progress bar now pretty good for start-new-game
+
+       * worlds/haxima-1.002/game.scm:
+       Pulled progress bar stuff out of generic file
+
+       * src/menus.c, src/play.c, src/session.c, src/session.h, src/kern.c, src/foogod.c:
+       Game-saving code generates (imperfect) progress bar info; delay switching foogod window back to normal so the complete progress bar is visible for a little bit of time
+
+       * worlds/haxima-1.002/books.scm: Fixed mismatched parenthesis
+
+2007-11-20  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm: projectile weapons use missile sound
+
+       * worlds/haxima-1.002/ifc.scm, src/object.h, src/object.c, src/ctrl.c:
+       callback on weapon just before attack
+
+2007-11-20  sglasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/luximene.scm:
+       Checking references to places and such.
+
+       Added notes on who and where the various characters are.
+
+       * worlds/haxima-1.002/kalcifax.scm:
+       Added some notes on who and where Kalcifax is.
+
+       * worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/gen.scm:
+       Added some notes to Kama on who and where he is.
+
+       Added some detail to a cultural interest shared by Gen and Kama.
+
+       * worlds/haxima-1.002/books.scm:
+       Added a book related to an interest of Gen's.
+
+2007-11-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm: progress bar for demo
+
+       * worlds/haxima-1.002/game.scm:
+       Use progress bar (weakly; works ok for demo but not calibrated right for new or loaded games
+
+       * src/status.c, src/nazghul.c, src/foogod.c, src/foogod.h, src/kern.c:
+       Progress bar
+
+2007-11-19  sglasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/jeffreys.scm:
+       Checking place references and such.
+       Added notes regarding the who and where NPCs are / are at.
+
+       * worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/henry.scm:
+       Checking for consistency in place references and such.
+       Added some comments regarding the what and where that NPCs are / are at.
+
+       * worlds/haxima-1.002/gen.scm:
+       Added some missing responses for Goblin root words.
+       Added a few composite words related to character types,
+       and to make the ability to get Gen to join less subtle.
+       Grouped/organized some keywords to keep the Goblin language responses together.
+
+       Added notes regarding the type and location of Gen.
+
+2007-11-18  sglasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/fing.scm:
+       Checking location references and such.
+       Removed some duplicate definitions of a constant
+       for Trigrave inn prices.
+       Added comments for NPCs type and location.
+
+       * worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/edward.scm:
+       Checking references to places and such.
+       Adding suitable comments as to
+       what (species, gender, profession) an NPC is,
+       and where (what zone) they are at.
+       Removed some duplicate instances of a trigrave inn price constant.
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/anne.scm:
+       Double-checking place references and such,
+       added comments where needed in regards to
+       what (species, gender, profession) is
+       and where (what zone) the NPC may be found.
+
+2007-11-18  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm: npcs use same cone attack as PCs
+
+       * worlds/haxima-1.002/powers.scm:
+       cleaned up, debugged and enhanced cone attacks
+
+       * worlds/haxima-1.002/fireblast.wav, worlds/haxima-1.002/sounds.scm:
+       fireblast sound for cone spells
+
+2007-11-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demon-gate.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/talking-ankh.scm, worlds/haxima-1.002/ankh-shrine.scm:
+       Changed the end-game map to match the demo map
+
+2007-11-18  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm: one word: oops
+
+       * worlds/haxima-1.002/demo.scm: passive-ai no longer includes std-ai:
+       the beggar was moving off when hit by stray fields
+
+       * worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/ability.scm:
+       collateral check for lightning bolt
+
+       * worlds/haxima-1.002/powers.scm:
+       various bugs in collateral damage routine fixed
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/powers.scm:
+       collateral check added to fireball
+
+2007-11-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm:
+       Final (famous last words) changes to the demo maps. Just undid Kris's blending, probably.
+
+       * worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/terrains.scm:
+       Added a non-los blocking version of t_trees
+
+2007-11-18  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm: blended aging terrains
+
+       * worlds/haxima-1.002/demo.scm: ai tweaks
+       deer in 'ages passed'
+       sound effect for closing gate
+       display refreshes & pauses when npcs are added
+
+       * worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/sprite-sets.scm:
+       deer sprite
+
+2007-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm: More aging of the demo scene.
+
+       * worlds/haxima-1.002/demo.scm:
+       Started the accelerated aging process on the demo scene
+
+       * worlds/haxima-1.002/demo.scm:
+       Demo: sprites animate during pauses; player gets a chance to see that the altars are glowing, not the runes
+
+       * worlds/haxima-1.002/ability.scm:
+       NPC wizards may now cast flame wind and lightning. Watch out.
+
+       * worlds/haxima-1.002/powers.scm:
+       Renamed a parameter to make it clear that it is a LOCATION and not a kernel object
+
+       * src/kern.c: Fixed a debug statement
+
+       * worlds/haxima-1.002/demo.scm:
+       Added some special effects to the part where the wise close the gate
+
+2007-11-17  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/creatures.png, worlds/library/artwork/creatures/deer.xcf:
+       first pass at a deer
+
+2007-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm: Changes to demo scene:
+       o The sprites of the wise are non-random
+       o Added random traveler sprites, depending on profession
+       o Sparsed the travelers even more
+       o Repaint the screen for each loot item the beggar picks up
+
+2007-11-17  kaypy  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/character.h:
+       character uses object sprites, rather than having a second local sprite
+
+       * worlds/haxima-1.002/demo.scm: more line end problems
+       beggar is more indestructable
+       beggar cleans up loot and exits
+
+       * worlds/haxima-1.002/demo.scm:
+       reinforcements wander around for a bit instead of immediately exitting
+
+       * worlds/haxima-1.002/demo.scm: guards exit after the wise leave
+
+       * worlds/haxima-1.002/demo.scm: tweaked traveler ratios
+       wise have variety of appearances
+       human reinforcements appear in more timely fashion
+       runes are collected asynchronously
+       map tweaked
+
+       * worlds/haxima-1.002/demo.scm: fixeed line endings
+
+2007-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm:
+       Kris's improvements to the demo scene: another demon wave and reinforcements to repel them.
+
+       * src/menus.c, worlds/haxima-1.002/demo.scm:
+       When the demo is done the main menu goes back to the splash screen. At that point the player can opt to show the demo again.
+
+2007-11-17  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm: clone spell more effective
+       sleep spell tweaked
+
+2007-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demon-gate.scm, src/kern.c:
+       Made kern-end-game more general by moving messages to the script
+
+       * src/menus.c:
+       Demo only starts automatically the first time the main menu comes up after starting the program. After that the option to play it appears in the menu.
+
+2007-11-16  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/lightning.wav, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/sounds.scm:
+       added lightning sound
+       fixed some bugs in field wall behaviour
+
+       * worlds/haxima-1.002/demo.scm: uses altar-on-grass sprites
+       centers view nicely in reduced size mode
+
+2007-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/blendmap.pl: Blender can handle 3-wide glyphs now
+
+       * worlds/haxima-1.002/demo.scm: Blended the demo map.
+
+       * src/kern.c, src/map.c, src/map.h:
+       Adding kern-map-blit-image, which isn't currently used anywhere, or planned to be used, but I already wrote and tested the code so might as well commit it.
+
+       * worlds/haxima-1.002/demo.scm: More tweaks to the demo scene
+
+       * worlds/haxima-1.002/effects.scm:
+       No more 'poison field immune to poison' messages
+
+2007-11-16  kaypy  <kaypy@localhost.localdomain>
+
+       * src/ctrl.c, src/Being.cpp:
+       fix for 1822685- adds AP cost to handling mechs by bumping into them
+
+2007-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm, worlds/haxima-1.002/gold_frame.png, worlds/haxima-1.002/haximatext.png:
+       Added a frame around the demo scene
+
+2007-11-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm, worlds/haxima-1.002/haximatext.png:
+       Added the logo above the demo. Started tweaking the demo map.
+
+2007-11-15  kaypy  <kaypy@localhost.localdomain>
+
+       * src/place.c: virtual cost of nasty tiles scaled to AP_per_turn
+
+       * src/Being.cpp:
+       npcs reevaluate their options before crossing nasty tiles
+
+       * worlds/haxima-1.002/sfx.png, worlds/haxima-1.002/sprites.scm:
+       transparent field sprites
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm:
+       remaining field spells use wall effect
+
+       * worlds/haxima-1.002/moon.scm:
+       dimming the moons a trifle- night is awfully well lit
+
+       * src/kern.c: mmode set if kern-mk-field-type
+       removed some debugging
+
+2007-11-14  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm:
+       field walls are 'solid', with extra diagonal blocking cells that cost 1/2
+
+       * worlds/library/artwork/logos/haximatext.svg:
+       vector form of the haxima text
+
+       * worlds/library/artwork/logos/haximasplashbig.xcf, worlds/library/artwork/logos/haximasplashsmall.xcf:
+       layered versions of the splash screens
+
+2007-11-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm:
+       Demo scene script now runs to completion.
+
+2007-11-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/demo.scm:
+       In the intro scene the wise now appear and walk to the altars
+
+2007-11-13  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm:
+       in flam grav now uses first pass at wall style field spells
+
+       * worlds/haxima-1.002/powers.scm:
+       most missile spells have sound applied
+
+       * worlds/haxima-1.002/boom.wav, worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/swish.wav:
+       some more sound added:
+       swishes and bangs fo magical projectiles
+       a first pass at some changing music tracks (but I still dont have uploadable music tracks to change...)
+
+2007-11-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/demo.scm:
+       Pulled game.scm inline into demo.scm and trimmed it to speed up demo loading.
+
+       * worlds/haxima-1.002/terrains.scm:
+       removed obsolete terrain-blender calls
+
+       * src/kern.c: Added kern-log-flush
+
+2007-11-12  kaypy  <kaypy@localhost.localdomain>
+
+       * win32/Makefile, win32/config.h, win32/configure, win32/haxima.ico, win32/readme.txt, win32/res.rc, win32/src_config.h:
+       First pass at including 'everything you need to make win32 builds go'
+
+2007-11-11  kaypy  <kaypy@localhost.localdomain>
+
+       * src/sound.c: cleaning up old code
+
+       * src/combat.c, src/combat.h, src/player.cpp, src/session.c:
+       fix for 1829927- reset combat state between games
+
+       * worlds/haxima-1.002/sprites.scm: alters have cobblestone background
+
+       * worlds/haxima-1.002/terrains.scm: altars have boulder passability
+
+       * nazghul.nsi: 0.6.0 installer
+
+       * worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/gong.wav:
+       clocks chime on the hour
+
+       * src/kern.c, src/clock.c, src/clock.h: kern call to get clock ticks
+
+2007-11-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c: Got rid of initial splash/demo flicker
+
+       * worlds/haxima-1.002/kern-init.scm:
+       Turning on the demo scene. To turn off just comment out the relevant line in kern-init.scm.
+
+       * worlds/haxima-1.002/demo.scm: Updated the demo scene a bit
+
+       * src/menus.c, src/place.c:
+       Kernel support for running a demo in the map viewer while processing the main menu
+
+       * src/session.h: Added a demo-mode flag to the session struct
+
+       * src/map.c: Removed another old debug statement
+
+       * src/kern.c:
+       Added kern-char-set-control-mode so that a player character may be forced into using an AI
+
+       * src/common.c, src/character.cpp: Removing some old debug
+
+2007-11-10  kaypy  <kaypy@localhost.localdomain>
+
+       * src/sound.c: Slight fade out when switching tracks
+
+       * worlds/haxima-1.002/sounds.scm:
+       Will play background music if insertmusic.mid is added (or the file is tweaked to point elsewhere)
+
+       * src/sound.h, src/kern.c, src/sound.c: First pass at music playing
+
+       * src/place.c: Removed some debugging cruft
+
+       * src/sound.c, src/sound.h:
+       Does most of the sound effects stuff again, but is rather buggy
+
+2007-11-09  kaypy  <kaypy@localhost.localdomain>
+
+       * src/sound.c: Converting sound to SDL_Mixer
+
+2007-11-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/demo.scm:
+       Started on a demo scene for the main menu
+
+       * worlds/haxima-1.002/silas.scm: Minor typographical change
+
+2007-11-08  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/enchanters-tower-mech.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/wind_1a.wav:
+       some tweaks to the sound
+       winds whistling through the brundegardt peaks
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/dog_9.wav:
+       tweaked ai to add sound effects as a 'free action'-
+       wolves will bark at random intervals
+
+       * src/kern.c: kern api call for plaing a oneoff sound 'at a location'
+
+       * src/sound.c:
+       minor tweak- maximum volume for oneoff sound completely separated from repeating volumes.
+
+       * src/sound.c:
+       ambient sounds fade out nicely as the player moves away (it was a touch jerky previously)
+
+       * worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/river.wav, worlds/haxima-1.002/sounds.scm:
+       general purpose "add some ambient noise here" object created
+       burbling river added to Gregors Hut as example
+
+2007-11-06  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ticktock.wav: a better clock sound
+
+       * src/sound.c:
+       was not properly checking for repeated sounds- it only checked up to the first free slot. Now it checks all
+
+       * worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/ticktock.wav, worlds/haxima-1.002/tools.scm:
+       first pass at a clock ticking. pity the wav sucks
+
+       * src/kern.c, src/place.c, src/place.h, src/sound.c, src/sound.h:
+       first pass at ambient sound
+
+       * src/sound.c: sound uses larger buffer to prevent glitches
+
+2007-11-04  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/lost-halls.scm: Missing dungeon sprite
+
+2007-11-03  kaypy  <kaypy@localhost.localdomain>
+
+       * AUTHORS: Update for 0.6.0
+
+       * ChangeLog: update for 0.6.0
+
+       * scripts/cvstochangelog.pl:
+       script to generate changelog from cvs log dump
+
+2007-11-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF: Added a few notes for clariication
+
+2007-11-02  kaypy  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/potions.scm:
+       some potions did not have right ap cost
+
+       * NEWS: changes for 0.6.0
+
+2007-11-02  Kris Parker  <kaypy@localhost.localdomain>
+
+       * NEWS:
+       changes for 0.6.0
+
+       * worlds/haxima-1.002/potions.scm:
+       some potions did not have right ap cost
+
+2007-11-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF:
+       Added a few notes for clariication
+
+2007-11-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/powers.scm:
+       a few area where treating an object as a character could cause crashes
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/start-new-game.scm:
+       added 'prisoner' faction, so that rolands captors dont try to kill him until he gets out
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/species.scm:
+       gints use their own mmode so that they are not considered to be flying
+
+2007-10-30  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/demon-gate.scm:
+       demongate triggers off a slight delay rather than off the player's action
+       prevents the UI doing wackyness to Nos' conversation
+       
+       "You have opened the way, and served your purpose well.
+            Now, receive your reward...  - ok!"
+
+       * worlds/haxima-1.002/spells.png, worlds/haxima-1.002/spells.scm:
+       use smoke icon for bet ylem hur spell
+
+2007-10-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm:
+       Smoke bombs have their own sprite now
+
+       * worlds/haxima-1.002/books.scm:
+       Added In Nox Por to the starter magic book. I don't see how one can make it through Brundegardt without it.
+
+       * worlds/haxima-1.002/meaney.scm:
+       Meaney will heal any time (no shop hours)
+
+       * worlds/haxima-1.002/moongate-clearing.scm:
+       Looks like t_spell_book_force_magick_123 doesn't exist anymore.
+
+2007-10-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/combat.c:
+       previous patch had ... undesirable ... side effects
+
+       * src/combat.c:
+       fix for 1821991: combat critters will be generated in substandard (eg hazardous) positions if nice positions are not available
+
+       * src/magic.c:
+       adjusted magic objtype to spell routine to work with new spell names
+
+2007-10-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/gregor.scm:
+       Removed a lot of the newlines from Gregor's conv. Sorry, but I have a very strong opinion about the way it looks.
+
+2007-10-28  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       kern_place_is_visible was unreliable in temporary combat maps
+
+       * worlds/haxima-1.002/moon.scm, worlds/haxima-1.002/start-new-game.scm:
+       moon positions reset, eclipse disabled
+
+       * worlds/haxima-1.002/moons.png:
+       gave the moons a slight shadow, so you can see a difference between 'new moon' and 'moon is on the other side of the planet'
+
+       * worlds/haxima-1.002/npc-types.scm:
+       fixed incorrect object type in accursed loot
+
+       * worlds/haxima-1.002/powers.scm:
+       fix for 1815725: gem now centers view before scrying
+
+       * worlds/haxima-1.002/shard.scm:
+       tweaked moongate destinations- the first gate you run across will take you to the enchanters tower
+
+       * worlds/haxima-1.002/terrains.scm:
+       swamp terrain effect was broken
+
+2007-10-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/kalcifax.scm:
+       Updated Kalcifax's conv to match the moongate change
+
+2007-10-27  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/abandoned-farm.scm:
+       Added a spellbook (curses), which belonged to Ilya's mother.
+
+       * worlds/haxima-1.002/angriss-lair.scm:
+       Added two spellbooks to the meat locker
+       - Force magick (battle)
+       - White magick 2
+
+       * worlds/haxima-1.002/books.scm:
+       Added the rest of the currently-planned spellbooks.
+       Checked them in a saved game, may still need some
+       upcasing of spell runes and other minor tweaks.
+       
+       Next, it will be needful to place at least one copy of each
+       somewhere in the game.  (And better yet, more than one
+       of at least the lesser / common ones.)
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Added two of the new spellbooks in loot areas.
+       - The Divination spellbook, near the Eye
+       - The Deadly Winds spellbook, in the griffin nest.
+
+       * worlds/haxima-1.002/enchanters-tower.scm:
+       Added various spellbooks to the treasuries and library.
+       The Enchanter has rather a lot of spellbooks, naturally.
+
+       * worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/necromancers-lair.scm:
+       Missed arg 2 of some kern-mk-obj calls.
+
+       * worlds/haxima-1.002/fire_sea.scm:
+       Added two spellbooks to the dragon hoard
+       - Misc enchantment
+       - Greater illusion
+       
+       Added a spellbook in the lava in the fire slime chamber
+       - Deadly Winds
+
+       * worlds/haxima-1.002/game.scm:
+       Trivial formatting change, did not merge for some reason.
+
+       * worlds/haxima-1.002/mans-hideout.scm:
+       Added two of the new spellbooks in the TOOLS room.
+       - The lesser illusions book
+       - The force magick / mechanisms book
+
+       * worlds/haxima-1.002/necromancers-lair.scm:
+       Added various spellbooks to the library.
+
+       * worlds/haxima-1.002/old-absalot.scm:
+       Added some suitable spellbooks to Silas's chest.
+
+       * worlds/haxima-1.002/road_to_absalot.scm:
+       Added a spellbook in the Fire Bridge
+       - Force magick (matter)
+
+       * worlds/haxima-1.002/thiefs_den.scm:
+       Added a few spellbooks (doubtless "collected")
+       to the thief's den.
+       - Lesser illusion
+       - Force magick (fields)
+       - Force magick (matter)
+
+       * worlds/haxima-1.002/treasury.scm:
+       Added three spellbooks to the treasury.
+       - Force magick (high magick)
+       - Greater illusions
+       - Gates
+
+2007-10-27  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/users_guide.html:
+       updated spell list in manual
+
+2007-10-26  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/books.scm:
+       Added spellbooks for white magic, force magic, necromancy.
+       Various others planned, as per notes in:
+           ftp://ftp.haxima.org/other/dev_notes/spell_book_notes.txt
+       
+       These will need to be placed in the world in sensible places.
+       Note that the scheme for these books is such
+       that some books overlap, and contain some of the same spells,
+       this is purposeful, as they have themes.
+
+       * worlds/haxima-1.002/spells.scm:
+       Spelling change for consistency.
+
+2007-10-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       smoke spell
+       dispell magic spell
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       single target sleep spell
+
+2007-10-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c:
+       Fixed a typo that caused some garbage in the cmdwin while attacking
+
+       * worlds/haxima-1.002/arms.scm:
+       Smoke only drifts in wind on the surface combat maps
+
+       * worlds/haxima-1.002/tim.scm:
+       Fixed grammar in Tim's conv
+
+2007-10-25  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/spells.scm:
+       The Vision <IN QUAS WIS> spell was too high Circle
+       to be at all practical.
+       
+       The reagent costs (nightshade + mandrake) are 8..11 + 8..11 gold,
+       whereas you can buy a gem for 10..20 gold.
+       
+       It may be sensible to increase gem prices as well,
+       but lowering the Circle of this spell will at least
+       make this more accessible, and less costly in MP.
+
+       * worlds/haxima-1.002/spells.scm:
+       Lined up the spell table again a bit,
+       and fixed a typo with Summon Slime.
+
+       * worlds/haxima-1.002/spells.scm:
+       Changed spell names to include an English name,
+       as well as the spell runes.
+       (No point in being obscure, and many/most players
+       will not know the the entire list by heart, by runes alone.)
+       
+       Some formatting, lined up the spell table.
+
+2007-10-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       When party members in follow mode move, the map is marked dirty but not repainted.
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/powers.scm:
+       Fixed a bug in In Nox Por. Added some messages around poisoning.
+
+2007-10-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm:
+       reverting flaming oil to dropping fire field
+
+       * worlds/haxima-1.002/powers.scm:
+       teleport range was borked by previous patch
+
+2007-10-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, src/event.c, src/skill.c, src/skill_set.c, src/skill_set_entry.c, src/templ.c:
+       Check config.h for HAVE_MALLOC_H
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/terrains.scm:
+       Reverted my forest visibility change (when Sam and Kris both agree I know I better listen). Added a forest terrain which is opaque, and fixed a couple of the town maps where I know opaque forest was presumed during the design.
+
+2007-10-23  Tim Douglas  <timdoug@localhost.localdomain>
+
+       * src/skill.c, src/skill_set.c, src/skill_set_entry.c, src/templ.c:
+       check to see if malloc.h exists before including it -- fixes OSX build
+
+2007-10-23  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp:
+       save actual AP per turn rather than adjusted value
+
+       * worlds/haxima-1.002/powers.scm:
+       telekinesis range was borked by previous patch
+
+2007-10-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm:
+       Inflated the base AP values to reduce the armour penalty
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Changed the moon starting positions and phases so that there is not an eclipse early in the first day and the player won't be given the opportunity to unwittingly teleport off to the Engineer's Hut on the first day.
+
+       * worlds/haxima-1.002/terrains.scm:
+       Making the basic forest type opaque, because we still have some town-scale maps that rely on forest to conceal hidden things
+
+2007-10-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/lost-halls-mech.scm, worlds/haxima-1.002/voidgap-mech.scm:
+       commented out random dungeon checking feedback
+
+       * worlds/haxima-1.002/powers.scm:
+       gave all powers a return code
+
+2007-10-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm:
+       Reverted to one-move-per-turn (I think)
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       Commented-out debug printlns
+
+       * worlds/haxima-1.002/roland.scm:
+       Fixed Roland to work with pathfinding changes
+
+2007-10-21  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/cmd.c:
+       Improved cmd_save_current_place()
+       by using file_open_in_save_dir() rather than fopen().
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/event.h:
+       Added an edit-mode command CTRL-O which invokes
+       cmd_save_current_place(), terrain_map_save().
+       
+       This is not finished yet, it lacks UI code to select a save file name.
+       (Currently saves to '_test_save_place' in the current directory.)
+
+       * src/cmd.c:
+       Added some command help to the Terraform command.
+
+       * src/cmd.c:
+       Changed the Terraform status text for the copy / set-pen command.
+       
+       Added a Terraform status text for the flood-fill command.
+
+       * src/session.c, src/session.h:
+       Added a couple of prototypes to enable a save-single-thing
+       function to be defined elsewhere.
+       
+       Also, where does Session->indent get initialized?
+       It looks like we may be relying on the compiler initializing it to 0.
+
+       * src/terrain_map.c:
+       Added some comments to the output of terrain_map_composite_save()
+       to aid manual editing of composite maps.
+
+2007-10-20  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/shard.scm:
+       Added some comments to aid manual editing of the shard map.
+
+2007-10-19  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm:
+       (aside) returns true if something is said, so you can stick a bunch of them in an (or) block
+
+       * worlds/haxima-1.002/conv.scm:
+       (aside) was glitchy in the case of null or not present speakers
+
+       * worlds/haxima-1.002/voidgap-mech.scm, worlds/haxima-1.002/voidgap-passage.scm:
+       fortified the dungeon entrance (its too close to town to be plausibly unguarded)
+       toned the dungeon down a fair bit
+
+2007-10-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/kern_intvar.c, src/object.c, src/object.h, src/place.c, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/tutorial.scm:
+       Improvements to kraken
+       
+       o Added a 'submerged' flag for objects
+       o Submerged object sprites are alpha-blended on the map
+       o Submerged objects get a bonus to defense (set by the script)
+       o Kraken submerge when coursing toward their target but surface to attack or
+         chomp
+       o Kraken will submerge and flee if they can't chomp their way to their target
+
+2007-10-18  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/luximene.scm:
+       Added responses for Luximene for the WISE and the ACCUrsed.
+           (The default responses presume a knowledge of
+           contemporary events, and did not fit.)
+
+       * worlds/haxima-1.002/necromancer.scm:
+       Enhanced some of the Necromancer's responses
+       related to the main quest, including some synonyms.
+       
+       Added to the response for HEALTH.
+
+2007-10-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm:
+       blink range clamped
+
+       * worlds/haxima-1.002/shard.scm:
+       world map rearranged to put void temple just out of teleport range of voidgap
+
+       * worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/voidgap-mech.scm, worlds/haxima-1.002/voidgap-passage.scm:
+       added new random dungeon "Tunnels to Voidgap"
+
+2007-10-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cursor.cpp:
+       The camera follows the cursor or any player characters if they move off-screen
+
+       * src/cmd.c:
+       The . key now means HERE when the player is prompted for a direction, like the 5 on the numeric keypad.
+
+2007-10-17  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/abe.scm:
+       Enhanced Abe's responses related to the RUNEs,
+       including a more explicit reference to RUNE
+       when speaking of the KEYs to the Demon Gate.
+
+       * worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/special.scm:
+       Updated all of the "hidden" places on the shard map
+       to match the angriss-lair implementation,
+       by which a step trigger is used to mark the location of
+       the once-hidden place when the player finds the exact location.
+
+       * worlds/haxima-1.002/books.scm:
+       Minor formatting in the starting spellbooks.
+       Added some emphasis to the letter from the Enchanter.
+
+       * worlds/haxima-1.002/gregor.scm:
+       Updated various responses.
+       Added some more synonyms.
+       Gregor gives clearer directions about how to reach the Enchanter.
+       Colorized many important keywords as RED,
+       and certain important non-keywords as GREEN.
+
+       * worlds/haxima-1.002/the-man.scm:
+       Added a response about the Accursed.
+       Added a synonym for Rogue / Wrogue.
+
+2007-10-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm:
+       Smoke now drifts in the wind
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/fields.scm:
+       Changes to smoke:
+       o Changed smoke from a field type to a regular object type
+       o Smoke now dissipates after a random interval
+       o Smoke is now at the projectile layer, so it is rendered over most other
+         objects (it is semi-transparent)
+
+       * worlds/haxima-1.002/terrains.scm:
+       x)amine shows translation for runic signs (SF feature request)
+
+2007-10-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/object.c:
+       disabling end of turn spam
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/powers.scm:
+       magic missile uses its own projectile rather than regular arrow
+
+       * worlds/haxima-1.002/lost-halls-mech.scm:
+       Misplaced rock
+
+       * worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/zane.scm:
+       typos
+
+2007-10-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/astar.c, src/astar.h, src/cmd.c, src/cmd.h, src/ctrl.c, src/event.c, src/event.h, src/kern.c, src/map.h, src/place.c, src/status.c, src/status.h, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/moon.scm, worlds/haxima-1.002/moons.png, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/zane.scm:
+       Changes to the merchant system.
+       
+       o Saying 'buy' or 'sell' may jump directly to the buy and sell menus.
+       o Merchants now give a "sales pitch" on every item they sell.
+       o Merchants may give more feedback if the player does or does not buy anything.
+
+       * src/kern.c:
+       Re-added kern-los-invalidate, but now it takes no args and just flushes all cached vmasks
+
+       * src/object.c:
+       Fixed bug where LOS was still blocked when smoke evaporated
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/sprites.scm:
+       Added smoke bombs.
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       Changes to low and mid-level summoning spells
+       o Switched the order of In Bet Xen (now L2) and Kal Xen (now L5)
+       o In Bet Xen and Kal Xen each now summon different critters depending on the
+         caster's power
+
+       * worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/tooth.scm:
+       A couple of merchants will trade in smoke bombs
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm:
+       We had two versions of terrain-ok-for-field. Removed one duplicate and fixed the remaining one to work if the location is off-map.
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Fixed a bug in loot drops (using var instead of tag) and added smoke bombs to wrogue loot.
+
+2007-10-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/hackle.scm:
+       Tweaks to the Hackle/Mesmeme discussion
+
+2007-10-11  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       added kern-missile-fire-to-max
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       lightning bolt spell added
+
+       * worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/traps_4.scm:
+       slightly easier labyrinth of burning glass
+
+       * worlds/haxima-1.002/spells.png, worlds/haxima-1.002/spells.scm:
+       lightning spell icon
+
+2007-10-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/play.c:
+       Undoing a fix I did earlier. This supposed fix seems to cause a hang when the party exits from combat after a reload. I can't reproduce the original problem after undoing the fix.
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.png, worlds/haxima-1.002/spells.scm:
+       Implemented feature request 1622424, Vas An Nox
+
+2007-10-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.c:
+       Lights outside the map view now cast light into the view.
+
+       * src/scheme.c:
+       Bugfix: loaded files ending in a comment with no newline would cause the next valid line to be discarded
+
+2007-10-09  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/object.c:
+       fading of movement sounds is linear rather than asymptotic
+
+       * src/sound.c:
+       first step to better sound: sound does not replay if it is already being played
+
+2007-10-08  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/character.cpp, src/cmd.c, src/common.h, src/ctrl.c, src/kern.c, src/play.c, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm:
+       - There is some cleanup in game.scm (AP values not used and so forth)
+         which remains, some of these should be scrapped, and some will be useful as
+         guidelines for setting other values.
+       
+       
+       I rather imagine that further drafts will be needed
+       before the system is tuned in a satisfactory way.
+       
+       In the meantime, the AP-per-round and AP costs
+       in (game.scm arms.scm) should produce interesting results.
+       
+       I recommend experimentation with the AP values,
+       there are many possibilities...
+
+       * src/status.c:
+       Various tweaks to status displays.
+       - Now shows range, AP cost, AP mod
+       - Ztats page contents reordered a bit.
+
+2007-10-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/trigrave.scm:
+       most npcs now have some sort of equipment
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/talking-ankh.scm, worlds/haxima-1.002/tetzl.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/thorald.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/tim.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/tutorial.scm, worlds/haxima-1.002/warritrix.scm, worlds/haxima-1.002/zane.scm:
+       removed the 'armour based' speed values from individual characters, now that modifications based on actual armour can be used instead
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm:
+       centralized speed settings into 3 values in game.scm, with everything else normalized off those
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/spells.scm:
+       centralized speed settings into values in game.scm, with everything else normalized off those
+
+2007-10-07  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/Makefile.am, src/kern_intvar.c, src/kern_intvar.h:
+       Adding a facility for the script to store a hash of
+           "name" => integer
+       values, for the purpose of declaring policy via script
+       which otherwise might require hard-coded constants in common.h
+       or similar.
+       
+       The first use of this feature will be to replace the use of
+       the constant NAZGHUL_BASE_ACTION_POINTS, so that the Action Point
+       costs for various actions are entirely controlled by the script.
+           (Movement and attack AP costs are already in game.scm arms.scm,
+           but some half dozen actions require that the kernal know
+           some AP cost to use.)
+       
+       The API for kern_intvar is nearly identical to that
+       for cfg.c cfg.h, save that integers are stored.
+       
+       A seperate hash is used, as the data stored is of
+       a per-session nature, rather than a global-for-all-games config nature.
+       
+       This data is not currently saved, but a function
+       kern_intvar_save() is provided.
+
+2007-10-07  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/combat.c, src/player.cpp, src/player.h:
+       party stops loitering when attacked in world map
+
+       * src/player.cpp:
+       party loitering check moved after turn start. loitering in the wilderness was accumulating AP otherwise...
+
+       * worlds/haxima-1.002/vehicles.scm:
+       onramps now cascade trigger to avoid appearance of 'half ramps'
+
+2007-10-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c:
+       Workaround for bug 1808708: if the player is kamping on a ship, a pirate ambush will abort kamping and switch back to the wilderness view.
+
+       * worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/naz.scm:
+       Changed the script adjacency-checking to use diagonals. This fixes the problem I saw where pirates could not pathfind in the wilderness to ambush the player. That problem only occurred if the pirates ended up diagonal to the player. This would have affected other npc party types as well.
+
+2007-10-06  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h:
+       added command for a party to absorb its members ap debt
+
+       * src/ctrl.c:
+       player party absorbs members ap debt as required
+       party AP is displayed in cmdwin prompt for now
+
+       * src/ctrl.c, src/object.c, src/place.c:
+       moved bump ifc behaviour to ctrl, with the handle behaviour
+       fixed incorrect bump callback
+
+       * src/player.cpp:
+       player gets diagonal movement costs
+
+       * worlds/haxima-1.002/camping-map.scm:
+       camping checks for passability before allowing npc parties to attack
+
+       * worlds/haxima-1.002/lost-halls-mech.scm, worlds/haxima-1.002/lost-halls.scm:
+       stairs portal based on bump rather than step
+
+       * worlds/haxima-1.002/npc-types.scm:
+       quick'n'nasty 'add loot drops' by dint of tweaking the standard drops from stock npcs
+
+       * worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/road_to_absalot.scm:
+       portal based on bump rather than step- can be used as virtual edge tile
+
+       * worlds/haxima-1.002/tutorial_town.scm:
+       diagonal entrances
+
+2007-10-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c:
+       Unlogged bugfix: pirate ship could end up on wrong side of map depending on whom was attacking whom
+
+       * src/kern.c:
+       Fix for bug 1612006: pirates disembark before ambushing the campsite
+
+       * src/macros.h:
+       Added normalize() macro
+
+       * src/play.c:
+       Unlogged bugfix: assert in combat if you reload during combat and immediately camp. Needed to reset the combat state on reload.
+
+       * worlds/haxima-1.002/camping-map.scm:
+       During camping, an ambushing npc party will now move toward the player. This way a pirate ambush will leave the ship next to the shore.
+
+       * worlds/haxima-1.002/naz.scm:
+       can-pathfind? proc checks adjacency first; the kernel pathfinding code returns null in this case, which is not to be confused with being unable to produce a path
+
+       * worlds/haxima-1.002/powers.scm:
+       Gate spell checks for passability
+
+2007-10-05  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/player.cpp:
+       player party checks for diagonal movement between impassable terrains
+
+       * src/player.cpp:
+       enable diagonal entrances to towns
+
+       * worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/eastpass.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/tutorial_town.scm, worlds/haxima-1.002/void-temple.scm, worlds/haxima-1.002/westpass.scm:
+       diagonal entrances
+
+       * worlds/haxima-1.002/arms.scm:
+       incorrect cannon projectile
+
+       * worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       secret in natural rock
+
+       * worlds/haxima-1.002/road_to_absalot.scm:
+       cleaned up natural rock walls
+
+       * worlds/haxima-1.002/shard.scm:
+       deep water removed from near merciful death to prevent pirate ships from being spawned there
+
+       * worlds/library/artwork/terrain/nrockwall.xcf:
+       hires natural rock wall terrains
+
+2007-10-04  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm:
+       fix for 1807516: logic error in conditional damage was only affecting non-beings
+
+2007-10-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/astar.c, src/character.cpp, src/place.c, src/place.h:
+       Fix for bug [ 1734069 ] pathfinder confused by diagonal gaps. The pathfinder
+       was written so that if the character could get one tile away from the
+       destination then this was good enough. This is ok for for combat pathfinding
+       and following the leader; but for commuting it's not ok when the last step is
+       impassable, because the character needs to actually get there or it will keep
+       trying to commute over and over. I added a new pathfinding flag to indicate
+       that "adjacent is NOT ok", and set this flag for commuting.
+
+       * worlds/haxima-1.002/douglas.scm:
+       Douglas notices Mesmeme in the player's party
+
+       * worlds/haxima-1.002/hackle.scm:
+       Hackle notices Mesmeme in the player party
+
+       * worlds/haxima-1.002/kama.scm:
+       When kama joins it improves player relations with forest goblins
+
+2007-10-02  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/forsaken-prison.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/lost-halls-mech.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/old-mine.scm, worlds/haxima-1.002/prison.scm, worlds/haxima-1.002/road_to_absalot.scm:
+       natural rock
+
+       * worlds/haxima-1.002/meaney.scm:
+       missing space in "come back during business hours" text
+
+       * worlds/haxima-1.002/silas.scm:
+       fixed missing 'dennis' conversation element
+
+2007-10-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.c, src/object.h, src/player.cpp, src/session.h, src/sprite.c, src/status.c:
+       Fix for bug 1632199 (An Tym animations). This breaks up the "synchronized
+       dancing" sprites and causes only player-controlled objects to be animated
+       during Time Stop.
+
+2007-09-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/door.scm:
+       fix for 1800347 door LOS glitches
+
+2007-09-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/session.c, src/session.h, src/terrain.h:
+       Moved terrains to their own list on load; first step toward showing a terrain palette
+
+2007-09-20  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/blenddat.txt, scripts/unblenddat.txt:
+       updated with newer terrains
+
+       * scripts/mergemap.pl:
+       merge more resistant to formatting issues
+
+       * scripts/palette.txt:
+       dense/light trees added
+
+2007-09-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/necromancer.scm:
+       When meeting the Necromancer, if the Luximene quest has been offered but not
+       completed,  then he checks if the player has the skull.
+
+2007-09-09  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ankh-shrine.scm, worlds/haxima-1.002/dank-cave.scm, worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm:
+       natural rock
+
+       * worlds/haxima-1.002/newterrain.png:
+       some black areas added to natural rock terrain to make is not quite so jarring when it appears without proper edging
+
+2007-09-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       natural rock
+
+       * worlds/haxima-1.002/naz.scm:
+       misplaced bracket in evade was causing ai to jam
+       also re-allowed diagonal evasion
+
+2007-08-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm:
+       scale up ability ap costs
+
+       * worlds/haxima-1.002/angriss-lair.scm:
+       natural rock in angriss' lair
+
+       * worlds/haxima-1.002/arms.scm:
+       projectiles have at least obj-ifc. nil ifcs do bad stuff
+
+       * worlds/haxima-1.002/powers.scm:
+       fix for 1781344 Crash on kill with VAS FLAM spell
+
+2007-08-19  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/map.c:
+       support for weapons that always fire to max range
+
+2007-08-04  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/template/kern-init.scm, worlds/template/start-new-game.scm, worlds/template/gfx/640x480_splash.png, worlds/template/gfx/addons.png, worlds/template/gfx/adornments.png, worlds/template/gfx/arms.png, worlds/template/gfx/bigobjects.png, worlds/template/gfx/bodies.png, worlds/template/gfx/books.png, worlds/template/gfx/cannon.wav, worlds/template/gfx/charset.png, worlds/template/gfx/clothes.png, worlds/template/gfx/cursor.png, worlds/template/gfx/damage.wav, worlds/template/gfx/effects.png, worlds/template/gfx/enter_moongate.wav, worlds/template/gfx/food.png, worlds/template/gfx/frame.png, worlds/template/gfx/hirespeople.png, worlds/template/gfx/horse.wav, worlds/template/gfx/humanoids.png, worlds/template/gfx/jewelry.png, worlds/template/gfx/map.png, worlds/template/gfx/money.png, worlds/template/gfx/monsters.png, worlds/template/gfx/moons.png, worlds/template/gfx/newfolkas.png, worlds/template/gfx/newfolks.png, worlds/template/gfx/newmonst.png, worlds/template/gfx/newterrain.png, worlds/template/gfx/occlogos.png, worlds/template/gfx/pitfalls.png, worlds/template/gfx/potions.png, worlds/template/gfx/reagents.png, worlds/template/gfx/rowing.wav, worlds/template/gfx/rune.png, worlds/template/gfx/runestones.png, worlds/template/gfx/scrolls.png, worlds/template/gfx/sfx.png, worlds/template/gfx/shapes.png, worlds/template/gfx/ship.png, worlds/template/gfx/signs.png, worlds/template/gfx/special.png, worlds/template/gfx/spells.png, worlds/template/gfx/splash.png, worlds/template/gfx/tools.png, worlds/template/gfx/tower.png, worlds/template/gfx/walk.wav, worlds/template/lib/ability.scm, worlds/template/lib/ai.scm, worlds/template/lib/arms.scm, worlds/template/lib/beds.scm, worlds/template/lib/bim.scm, worlds/template/lib/blendterrains.scm, worlds/template/lib/books.scm, worlds/template/lib/bridge.scm, worlds/template/lib/camping-map.scm, worlds/template/lib/cast-ui.scm, worlds/template/lib/combat-maps.scm, worlds/template/lib/containers.scm, worlds/template/lib/conv.scm, worlds/template/lib/door.scm, worlds/template/lib/drawbridge.scm, worlds/template/lib/edge-spawn.scm, worlds/template/lib/effects.scm, worlds/template/lib/fields.scm, worlds/template/lib/food.scm, worlds/template/lib/game.scm, worlds/template/lib/gate-guard.scm, worlds/template/lib/generic-mech.scm, worlds/template/lib/hidden.scm, worlds/template/lib/ifc.scm, worlds/template/lib/init.scm, worlds/template/lib/items.scm, worlds/template/lib/jewelry.scm, worlds/template/lib/keys.scm, worlds/template/lib/kobj.scm, worlds/template/lib/landslide.scm, worlds/template/lib/lever.scm, worlds/template/lib/loc.scm, worlds/template/lib/main-menu.scm, worlds/template/lib/mimic.scm, worlds/template/lib/money.scm, worlds/template/lib/monster-generator.scm, worlds/template/lib/moon.scm, worlds/template/lib/moongate.scm, worlds/template/lib/naz.scm, worlds/template/lib/npc-types.scm, worlds/template/lib/objs.scm, worlds/template/lib/occs.scm, worlds/template/lib/palette.scm, worlds/template/lib/parties.scm, worlds/template/lib/pitfalls.scm, worlds/template/lib/portals.scm, worlds/template/lib/portcullis.scm, worlds/template/lib/potions.scm, worlds/template/lib/powers.scm, worlds/template/lib/pre-entry-hooks.scm, worlds/template/lib/prices.scm, worlds/template/lib/pseudorandom-map.scm, worlds/template/lib/reagents.scm, worlds/template/lib/runes.scm, worlds/template/lib/scrolls.scm, worlds/template/lib/skills.scm, worlds/template/lib/sounds.scm, worlds/template/lib/special.scm, worlds/template/lib/species.scm, worlds/template/lib/spells.scm, worlds/template/lib/spider.scm, worlds/template/lib/sprite-sets.scm, worlds/template/lib/sprites.scm, worlds/template/lib/step.scm, worlds/template/lib/tblit.scm, worlds/template/lib/terrain-to-ptype.scm, worlds/template/lib/terrains.scm, worlds/template/lib/timer.scm, worlds/template/lib/tools.scm, worlds/template/lib/town-entry.scm, worlds/template/lib/traps.scm, worlds/template/lib/troll.scm, worlds/template/lib/vehicles.scm, worlds/template/lib/weather-vane.scm, worlds/template/lib/wind-bridge.scm, worlds/template/lib/yellow-slime.scm, worlds/template/people/sample-char.scm, worlds/template/places/sample.scm, worlds/template/places/world.scm, worlds/template/places/zones.scm:
+       First pass at a minimal template for new games
+
+2007-07-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Missile.cpp, src/Missile.h, src/kern.c, src/map.c, src/map.h:
+       Everything necessary for weapons that always fire to their maximum range, except for the map animation code, which is still disabled because it crashes if it goes off the map.
+
+       * worlds/haxima-1.002/arms.scm:
+       compatibility with fixed range weapons option
+
+2007-07-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Missile.cpp, src/Missile.h, src/common.h, src/kern.c, worlds/haxima-1.002/arms.scm:
+       Separated out MissileType from ArmsType, since they have a close approximation of nothing in common.
+
+       * src/Missile.cpp, src/Missile.h, src/map.c:
+       MissileTypes can now use the Enter ifc for custom handling of each tile they pass over
+
+2007-07-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/status.c:
+       reformatted
+
+       * src/status.c:
+       Reverting to a working version while I try to figure out a way to make it work AND do what we want
+
+2007-07-06  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/kern.c, src/map.c:
+       support for beam projectiles
+
+       * worlds/haxima-1.002/arms.scm:
+       stun wand uses beam attack
+
+       * worlds/haxima-1.002/sfx.png, worlds/haxima-1.002/sprites.scm:
+       lightning bolt sprite
+
+       * worlds/library/artwork/effects/heart.xcf, worlds/library/artwork/effects/lightning.xcf:
+       some sfx graphics
+
+2007-07-05  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       new kern methods:
+       kern-place-is-combat-map
+       kern-obj-get-hp
+
+       * worlds/haxima-1.002/ability.scm:
+       tweaked kraken deck chomp
+
+       * worlds/haxima-1.002/sfx.png:
+       spikier hit sprites
+
+2007-07-03  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/kern.c:
+       visibility based effects respect lighting levels
+
+       * src/kern.c, src/map.c, src/map.h:
+       kern-map-flash-sprite: manually bring up a sprite flash (like the damage flash, but with an arbitary sprite)
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/powers.scm:
+       charm & turn undead spells use flash effect and visibility based reporting
+
+       * worlds/haxima-1.002/powers.scm:
+       some glitches in turn undead fixed
+
+       * worlds/haxima-1.002/sfx.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       a couple of sprites for flash sprite effects
+
+       * worlds/haxima-1.002/species.scm:
+       ghosts are undead!
+
+2007-07-02  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       kern-place-is-visible? checks for whether a location can be seen
+
+       * worlds/haxima-1.002/naz.scm:
+       msg-log-visible displays a message if a given location is visible
+
+2007-07-01  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/status.c:
+       Fencepost error with tt not being refreshed after nn was updated,
+       could have led to painting one tile beyond the bottom bounds
+       of a Status window.
+
+       * src/status.c:
+       Added support for Status entries with a height
+       other than 2 text lines (2 * ASCII_H).
+       
+       Reorganized the Arms stats (displayed in Ready, Ztats, etc)
+       and added information on Range and Action Points required.
+       
+       The new layout groups attack-related and defense-related
+       Arms stats together, and has more obvious labels.
+       (The new layout is also 3 lines high, hence the previous change.)
+       
+       Updated some other Status mode titles.
+       (The Ztats header for party member pages is still not
+       working quite right; the new title displays upon initial
+       Ztats display, but not after paging back and forth.
+       Presumably it is being re-initialized somewhere.)
+       
+       Some minor formatting, typos fixed in comments,
+       and notes on the units used for "line" (TILE_H vs ASCII_H units)
+       in various places.
+
+2007-07-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm:
+       arms action points now proportionally defined
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       slimy cavern uses natural stone walls (experimental)
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/hirespeople/sleeper.xcf:
+       hires sleeping humanoid
+
+2007-06-30  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/gregors-hut.scm:
+       doors and windows use correct wall type
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/shapes.png:
+       transparency effects for moongates
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       rejigged doors to use composite sprites rather than combinatorial door explosion
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm:
+       animated slime potion
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm:
+       animated prismatic bolt, oil potion
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/tools.scm:
+       separated off hills pclass from forest plass as they should affect missiles differently
+       changed vhard to v-hard for clarity
+       added s-hard difficulty
+
+       * worlds/haxima-1.002/combat-maps.scm:
+       variable obacity forest terrains use forest combat map
+
+       * worlds/haxima-1.002/door.scm, worlds/haxima-1.002/poor-house.scm:
+       added some new door types
+
+       * worlds/haxima-1.002/game.scm:
+       reduced forest obstructivity to be more in line with its opacity
+
+       * worlds/haxima-1.002/game.scm:
+       sfast changed to s-fast
+
+       * worlds/haxima-1.002/gamestart-mech.scm:
+       one-off messages do not trigger for npcs
+
+       * worlds/haxima-1.002/shard.scm:
+       added some irregularity to forrest visibility near green tower
+
+2007-06-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/common.c, src/common.h, src/map.c, src/sprite.c, src/sprite.h:
+       Support for 8 way missile sprites
+
+       * src/map.c, src/map.h:
+       Simplified and sped up missile animations
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm:
+       separate arrow/bolt on ground sprites
+       directional spear sprite
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm:
+       Added diagonal arrow and bolt sprites
+
+       * worlds/haxima-1.002/arms.scm:
+       enabled magic sword animations
+       magic axe uses alternate return mmode
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm:
+       Returning animation for magic axe
+       Cannon has greater terrain penetration
+
+       * worlds/haxima-1.002/palette.scm:
+       another &*%^$ forgotten checkin
+
+2007-06-28  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/character.cpp, src/character.h:
+       NPCs kick player out of bed more sanely
+
+       * src/map.c, src/map.h, src/sprite.c, src/sprite.h:
+       support for animated projectiles
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm:
+       magic axe tumbles in flight
+
+2007-06-27  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/sprites.scm:
+       Cannon Sprites
+       The obligatory "Kris was too dumb to check this in the first time" checkin
+
+2007-06-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/kern.c:
+       kern-fire-missile had stopped triggering hit-loc events
+       added kern-armstype-fire-in-direction
+
+       * worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/terrains.scm:
+       upgraded ancient derelict and merciful death
+
+       * worlds/haxima-1.002/arms.scm:
+       cannon object
+
+       * worlds/haxima-1.002/arms.scm:
+       temp-ifc needed to be updated to reflect advanced hit-loc ifc
+
+       * worlds/haxima-1.002/terrains.scm:
+       ship terrains in table
+       is-deck updated
+
+       * worlds/haxima-1.002/vehicles.scm:
+       added working cannons to voidship combat map
+
+       * worlds/haxima-1.002/vehicles.scm:
+       added working cannons to ship combat map
+
+       * worlds/haxima-1.002/vehicles.scm:
+       cleaning up
+
+2007-06-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/zones.scm:
+       upgraded barts boat
+
+2007-06-24  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/character.cpp:
+       Repaint map after each (visible) NPC move.
+       
+       This improves the appearance when an NPC makes
+       multiple tiles of movement on one turn.
+       
+       (Before, such characters seemed to "blink" into the new position.)
+
+       * worlds/haxima-1.002/effects.scm:
+       Added a message when a character fails to resist paralysis,
+       losing his turn.
+
+       * worlds/haxima-1.002/terrains.scm:
+       Added a small glow to t_deep_lava, to improve the ambience
+       of the dragons lair entrance chamber.
+
+2007-06-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/ship.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/vehicles.scm:
+       support for objects in turnable vehicles combat maps
+       vehicle boarding ramps only available when terrain is suitable
+       vehicles have steering wheels again
+
+       * worlds/haxima-1.002/ship.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/vehicles.scm:
+       improved voidship
+       forgotten checkin for enemy vehicle compatibility
+
+2007-06-23  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/combat.c:
+       Enemy vehicles now use new combat map scheme
+
+       * src/combat.c, src/combat.h, src/kern.c, src/vehicle.h, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/pseudorandom-map.scm, worlds/haxima-1.002/ship.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/vehicles.scm:
+       First pass at scheme based vehicle maps
+
+2007-06-21  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/zane.scm:
+       - Added various items to merchants which seemed lacking.
+       
+       - Minor price tweaks on some items.
+       
+       - The Engineer now sells various devices (crossbows, sextans, chronometers)
+       
+       - The Alchemist now sells some additional potions, some at exorbitant rates.
+       
+       - Various types of bows and crossbows are available from merchants,
+         also spiked helm and shield.
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/moongate-clearing.scm:
+       Defined a couple of books with low-level spells,
+       added them to the start area.
+
+       * worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/tooth.scm:
+       Tidied up indentation in shop inventories.
+       Made t_arrow and t_bolt more consistently available.
+
+       * worlds/haxima-1.002/gamestart-mech.scm:
+       Added some feedback in the stats-setting mechanism.
+       
+       It would be nicer to print a message mentioning only the stat(s)
+       changed upon stepping on one of the special tiles,
+       but that would require restructuring how the mechanisms work.
+
+       * worlds/haxima-1.002/gamestart.scm:
+       Added the full variety of melee / missile / thrown weapons
+       and armor / shield, to the quick-start equipment for test purposes.
+
+       * worlds/haxima-1.002/moongate-clearing.scm:
+       Modest increase to the starting gear.
+
+2007-06-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/combat.c, src/kern.c, src/terrain.h, worlds/haxima-1.002/combat-maps.scm:
+       first pass at scheme based combat maps
+
+2007-06-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/player.cpp:
+       One of the new comments was causing the savegame to crash when reloading
+       (Dont ask me why comments in scheme can break things, but they seem to be able to...)
+
+       * worlds/haxima-1.002/effects.scm:
+       fire/lightning do not effect regular objects for the moment (it wasnt having any in game effect, and the graphic effects were occuring in places they oughtnt)
+
+2007-06-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm:
+       getting the rest of the missile drops happening
+       some cleanups in the ifc routine
+
+       * worlds/haxima-1.002/arms.scm:
+       ifc builder for missiles that should have a chance of being retrieved
+
+2007-06-10  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/kern.c:
+       Fixed a typo:  obj_decc_ref vs obj_dec_ref.
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/species.scm:
+       Comprehensive review / changes to Action Point costs
+       for weapons and unarmed attacks.
+       
+       Added new types of bows and crossbows.
+       Added magic axe (returns when thrown) -- should perhaps print a message?
+       Added thrown rocks
+           (This is not quite perfect yet,
+            only one species-native weapon at a time is supported,
+            so how does a character get one?
+            Perhaps add 99 of them into party inventory in start-new-game.scm,
+            but that seems a bit inelegant.)
+       
+       Tweaked damage values for a few weapons to improve their usefullness,
+       such as 2H weapons, thrown spear, and axe.
+       
+       Secondary weapons (spiked helm and spiked shield) have very low AP cost
+       for their minor attacks.
+       AP costs for dual-weapon-wielding still needs review.
+       
+       Some changes to beast/monster native weapons
+       (small fast t_F_fangs and great toothy f_G_fangs, with various AP costs).
+
+       * worlds/haxima-1.002/arms.scm:
+       Changed default AP cost for attacks to 75,
+       such that "speed-human" is sufficient for 2 attacks per round
+       (or 3 tiles of "norm" movement).
+       
+       Also, canonicalized the +to-hit for t_sling_4
+       (missed it in the previous checkin).
+
+2007-06-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       added an obj_inc_ref pair to kernel methods that can result in a move() (and hence to scheme callbacks with potentially destructive results)
+
+2007-06-09  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/place.c:
+       Minor formatting change when saving edge_entrance info.
+
+       * worlds/haxima-1.002/arms.scm:
+       Untabified various tables for consistency in formatting.
+       Tidied some columns.
+       Canonicalized some values like "0" --> "+0" and "2" --> "+2".
+
+2007-06-09  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Being.cpp, src/ctrl.c:
+       Critters stop trying to keep wandering around if they are killed by an energy field
+
+       * src/Party.cpp:
+       npc parties try to avoid harmful terrains when diagonally attacking
+
+       * src/combat.c:
+       Combat maps grab tiles that are adjactent (based on dx/dy) instead of what the parties happen to be on. Means npc diagonal attacks dont give such wierd results
+
+       * src/object.c:
+       fix for 1713270: objects now trigger sense updates on removal
+
+       * worlds/haxima-1.002/powers.scm:
+       added a "put field here" generic command that applies procs as appropriate and allows field to momentarily be placed eg over water, but they will vanish immediately after
+       (somehow the first attempt only committed the stuff that *uses* the command...)
+
+2007-06-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       fields use mmodes
+
+       * worlds/haxima-1.002/species.scm:
+       species speeds now defined relative to nominal human speed
+
+2007-06-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am:
+       Added missing objectfreezer files to build list
+
+       * src/cmd.c:
+       Bugfix for [ 1632199 ] An Tym bugs
+
+2007-06-05  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp:
+       if custom speed is 0, default to species speed
+
+       * src/object.c:
+       end of turn messages now check target is a being
+
+       * worlds/haxima-1.002/kobj.scm, worlds/haxima-1.002/npc-types.scm:
+       generic npcs use species speed
+       moving "can drop" function to kobj.scm
+
+       * worlds/haxima-1.002/powers.scm:
+       added a "put field here" generic command that applies procs as appropriate and allows field to momentarily be placed eg over water, but they will vanish immediately after
+
+2007-06-04  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, src/object.c, src/species.c:
+       Added per-character Action Points per round, in addition
+       to the existing Species-specific AP/round which stock characters inherit.
+       
+       These changes require corresponding changes in the .scm,
+       specifically, a new parameter passed to kern-mk-char.
+           (AP_per_turn aka spd, after the mp arg and before the lvl arg)
+       
+       The corresponding changes in the .scm files are in the next checkin.
+
+       * src/ctrl.c:
+       Removed the ESC-to-exit-combat keybinding.
+       
+       With ESC used for both exit-from-UI-things and exit-combat-map,
+       it was wasy to accidentally exit combat, leaving loot behind.
+       
+       Now, a message is printed in that case, mentioning both means
+       of exiting the combat map (the '<' command, and walking off the map edge).
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/talking-ankh.scm, worlds/haxima-1.002/tetzl.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/thorald.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/tim.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/tutorial.scm, worlds/haxima-1.002/warritrix.scm, worlds/haxima-1.002/zane.scm:
+       Script changes to match engine changes which add
+       per-character Action Points per round (spd) to match
+       the per-Species value which stock characters inherit.
+       
+       The values defined (largely in game.scm and species.scm)
+       will need a lot of balancing.
+       
+       For the moment, values which result in multiple tiles of
+       movement per round are set, so that the feature can be seen and tuned.
+
+2007-06-04  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       tweak to error messages
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/powers.scm:
+       prismatic gaze updated to use mostly powers based effects. This still doesnt solve the problem in bug 1687641, either its taken care of in the cast-ui phase, or the field spells can screw up too...
+
+       * worlds/haxima-1.002/blendterrains.scm:
+       tree corners had wrong pclass
+
+       * worlds/haxima-1.002/game.scm:
+       shoals were set to walking passable while I was testing drowning code and accidently got checked in
+
+2007-06-03  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/angband.c:
+       Trivial formatting change in OPAQUE and VISIBLE macros.
+
+2007-06-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/wind-bridge.scm:
+       chasm effect moved to wind-bridge code rather than terrain
+       objects marked "do not drop" for water or space
+
+       * worlds/haxima-1.002/npc-types.scm:
+       generic npcs will not drop objects on forbidden terrains
+
+2007-05-27  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/character.cpp, src/player.cpp, src/sprite.c:
+       Appended some text in saved games to label things.
+
+2007-05-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp:
+       fix for bug with npcs not using missile weapons
+
+2007-05-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm:
+       thrown weapons need a separate projectile type now. arms.scm wasnt giving them one, so it crashed whenever they were used...
+
+2007-05-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Missile.cpp, src/Missile.h, src/object.c, src/object.h:
+       ObjectType now has moment mode implemented
+
+       * src/cmd.c, src/ptable.h:
+       drop checks object mmode
+
+       * src/kern.c:
+       other object types use object mmode
+
+       * src/kern.c:
+       added kern-obj-get-movecost method- gets movement cost for a given object:pclass
+
+       * worlds/haxima-1.002/arms.scm:
+       projectiles and ammo separated in scm
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/ifc.scm:
+       mmodes for objects added
+
+       * worlds/haxima-1.002/arms.scm:
+       Separating ammo (on the ground or in inventory) from missiles (projectile in flight)
+
+       * worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/game.scm:
+       mmodes for fields added
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/terrains.scm:
+       added separate pclass for checking general canfly/canswim statuses
+
+       * worlds/haxima-1.002/npc-types.scm:
+       can-fly check based on can-fly pclass
+
+2007-05-23  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/character.cpp, src/kern.c:
+       Separating ammo (on the ground or in inventory) from missiles (projectile in flight)
+
+2007-05-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/runes.scm:
+       fix for bug 1720802: to make a one-off trigger on pickup, you can create a dummy object, and have its get-ifc swap in the real one (which doesnt have the pickup effect)
+
+2007-05-21  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/terrains.scm:
+       you now only fall into chasms or void if you are actually on a square with the space pclass
+       hence if you bump into a chasm square you are just blocked, but if it opens up beneath you then you are gone
+
+       * worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/terrains.scm:
+       fixed mountain terrains vs missile passibility in griffon peak
+
+2007-05-20  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/cmd.c:
+       ap for readying weapons revised, ap debt limit for equipping in combat
+
+       * src/cmd.c:
+       ap for getting objects revised, ap debt limit for getting large stacks in combat
+
+       * worlds/haxima-1.002/arms.scm:
+       ap for readying weapons revised, ap debt limit for equipping in combat
+       improved shield defense somewhat
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/species.scm:
+       many 'fast' critters should have reduced movement cost rather than extra AP
+
+       * worlds/haxima-1.002/naz.scm:
+       ap for getting objects revised
+
+2007-05-19  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/ctrl.c:
+       switching from solo to roundrobin doesnt end your turn
+
+       * src/ctrl.c, src/kern.c:
+       experimental dual-weapon ap mod. we may reverse it later, but I need to do more changes to those files, and this way its a separate cvs entry
+
+       * worlds/haxima-1.002/arms.scm:
+       flaming sword ap fixed
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/enchanters-tower-mech.scm, worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/keys.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/tools.scm:
+       usable item ap fixes
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       upgrades to random dungeons for lost halls. should have been checked in way back. oops
+
+       * worlds/haxima-1.002/shard.scm:
+       link shard to new lost halls
+
+2007-05-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Missile.cpp:
+       missile obstruction probability changed to percentile rather than d20
+
+       * src/cmd.c:
+       mix now takes a long time. ideally, you wouldnt get the spell until afterwards, but that'd be more complex
+
+       * src/cmd.c:
+       spells use ap as defined in spell list rather than hardcoded function
+
+       * src/common.h:
+       base action points now 50
+
+       * src/kern.c:
+       allow kern-place-set-neighbor to remove neighbors using null argument
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/start-new-game.scm:
+       base action points now 50
+       missile obstruction probability changed to percentile rather than d20
+
+       * worlds/haxima-1.002/ini.scm:
+       ini gives more information about the lost halls
+
+       * worlds/haxima-1.002/lost-halls-mech.scm, worlds/haxima-1.002/lost-halls.scm:
+       pseudorandomificated version of the lost halls
+
+       * worlds/haxima-1.002/spells.scm:
+       spell ap cost: 25+25/level
+
+2007-05-15  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Missile.cpp, src/Party.cpp, src/character.cpp, src/kern.c, src/place.c, src/place.h, src/player.cpp:
+       mechs now affect movement costs for their tiles.
+       this did terrible, terrible things to the AI, but it seems to work again now.
+
+2007-05-14  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/angband.c:
+       
+       
+       Added some commentary in check_ray_set() related to the
+       diagonal LOS artifact removal.
+
+2007-05-12  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Missile.cpp, src/Missile.h, src/kern.c, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm:
+       first pass at using terrain passibility for missile obstruction
+
+       * worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/terrains.scm:
+       added some variable density forests/trees
+
+2007-05-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/ctrl.c:
+       workaround for glitchyness with null objects in hooks
+       Better handling for obtructions when firing at empty tiles
+
+       * src/Missile.cpp:
+       partially opaque terrain partially blocks missiles
+
+       * src/dice.c, src/dice.h:
+       can access dice routines with numeric values instead of strings if needed
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/terrains.scm:
+       partial opacity tweaked and extended
+       blended terrains match their base terrains opacities
+
+2007-05-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/terrains.scm:
+       swamp now allows double avoidance check
+       flyers can still get poisoned, but have better chances than walkers
+       swamp will only trigger when the target is about to get a turn- poison is otherwise too lethal on the worldmap
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/terrains.scm:
+       blended lava terrain passability fixed
+       wall torches somewhat less lethal
+       wilderness scale lava terrain gives avoidance chance
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm:
+       mkdice routine made more generally available
+
+       * worlds/haxima-1.002/terrains.scm:
+       cleaned out some debugging
+
+2007-05-07  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm:
+       flaming sword now does fire damage
+
+       * worlds/haxima-1.002/arms.scm:
+       doom staff fireballs slowly use mana, plus some other extra effects
+
+2007-05-06  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Missile.cpp, src/Missile.h, src/ctrl.c, src/kern.c, src/object.c, src/object.h:
+       More detail available for weapon callbacks- now has user, target, whether it hit, and whether it did damage.
+       Callbacks on melee weapons should hopefully work, too, although I havent tested it.
+
+       * worlds/haxima-1.002/arms.scm:
+       More detail available for weapon callbacks
+
+2007-05-03  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp:
+       bug 1710622 added guard clauses to prevent dead people from getting synchronized or introduced
+
+       * worlds/haxima-1.002/scrolls.scm:
+       bug 1666217 scrolls now use their own context checking (for the important ones anyway, Ill deal with the rest some other time)
+
+2007-05-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Being.cpp:
+       fix for 1700846:
+       check for zero length paths even in impassable path regeneration
+
+       * worlds/haxima-1.002/arms.scm:
+       slime potion was using directional sprite type without having directional sprite images.
+
+2007-04-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       hiresed rock wall, rock secret
+       added rock window
+
+       * worlds/library/artwork/terrain/rockwall.xcf:
+       hires rock wall and associated terrains
+
+2007-03-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/objectfreezer.c:
+       a few checks for null before doing stuff on potentially empty trees
+
+       * src/objectfreezer.c, src/objectfreezer.h, src/session.c:
+       objects in the freezer need to be manually start() ed since they arent in the regular Session->data_objects list
+
+2007-03-27  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/objectfreezer.c:
+       copy lookup keys to prevent them being eaten by the garbage collector
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       pseudorandom maps now use objectfreezer to remember room contents
+
+2007-03-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c, src/objectfreezer.c, src/objectfreezer.h, src/session.c, src/session.h:
+       renamed objectfreezer methods to match rest of codebase
+       objectfreezer should no longer leak like a ruptured colander
+
+       * src/kern.c:
+       kern-obj-thaw-at handles locating object correctly
+
+       * src/objectfreezer.c, src/objectfreezer.h, src/session.c, src/session.h:
+       object freezer now works across save files
+
+2007-03-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c, src/objectfreezer.c, src/objectfreezer.h, src/session.h:
+       first pass at object freezer
+       at this stage can store objects for current session only (no save/load)
+
+2007-03-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/traps_3_mechs.scm:
+       Fix for 1682961: gave portcullises a separate handler for remote open/close events. It looks like they are only used by traps_3.
+
+2007-03-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Missile.cpp, src/angband.c:
+       Kernel changes:
+       o Bugfix: bushes were blocking missiles, because their transparency was
+         recently changed to be somewhere between transparent and opaque. The missile
+         code was interpreting anything non-transparent as opaque. Come to think of
+         it, this might not be quite what is wanted yet, because missiles (which use
+         bresenham) will fly further than los (which uses highly optimized
+         ray-casting) through semi-opaque terrain.
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/powers.scm:
+       Haxima changes:
+       o powers-resurrect checks if target is really dead
+       o cast-ui-dospell-nolos lets effect determine result code
+       o cleaned up some debug printlns
+
+2007-03-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/result.h, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/start-new-game.scm:
+       Kernel changes:
+       o Added new result codes to kernel
+       o Result evaluation uses a lookup table now instead of a switch statement
+       
+       Haxima changes:
+       o Fixed a couple of potion result codes
+       o Fixed the heal power result codes
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/runes.scm:
+       Haxima changes:
+       o Fixed result codes for using runes.
+
+2007-03-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/screen.c, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/items.scm, worlds/haxima-1.002/keys.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/tools.scm:
+       Kernel changes:
+       o 'use' now checks the return value of closure calls and log the results to the
+         console (exactly like 'yuse')
+       
+       Haxima changes:
+       o All the item procedures now return one of the standard result-* codes.
+
+2007-03-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/object.c, src/object.h, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       Kernel changes:
+       o All the ObjectType methods that invoke closure_exec() now pass the result
+         back to their caller.
+       
+       Haxima changes:
+       o Added new tool: rope & hook
+       o Added passive Reach skill for wrogues, which employs the rope & hook
+
+2007-03-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/screen.c:
+       Added debug routines to dump some SDL types
+
+2007-03-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/occs.scm:
+       Haxima changes:
+       o As the wrogue advances he can do more challenging things while in stealth
+         mode.
+
+       * worlds/haxima-1.002/effects.scm:
+       Haxima changes:
+       o The torch effect removes the stealth effect.
+
+2007-03-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/ctrl.c, src/kern.c, src/object.h, worlds/haxima-1.002/effects.scm:
+       Kernel changes:
+       o Added a bunch of foo-done hooks, where 'foo' is a character action that
+         should probably kick the character out of stealth mode.
+       
+       Haxima changes:
+       o Stealth effect removed when character attacks, gets, drops, uses, yuses,
+         opens, handles, mixes or casts.
+
+       * src/effect.c, src/effect.h, src/kern.c, src/object.c, src/session.c:
+       Undoing the multi-hook effect stuff. Not necessary, cumbersome, and doesn't
+       even work.
+
+2007-03-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/closure.c, src/closure.h, src/effect.h, src/kern.c, src/object.c, src/object.h, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/skills.scm:
+       First part of Stealth skill: character is invisible until mana runs out or it
+       moves.
+
+2007-03-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/angband.c, src/character.cpp, src/character.h, src/effect.c, src/effect.h, src/kern.c, src/object.c, src/object.h, worlds/haxima-1.002/effects.scm:
+       Changed hook id's from strings to bits. This is to allow an effects to run on
+       multiple hooks, a prerequisite of the rogue's Hide skill and its advanced forms
+       (Sneak and Invisibility). These changes are lightly tested so far (I tried a
+       torch).
+
+2007-02-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h:
+       Consolidated some more of the targeting functions
+
+2007-02-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/angband.c, src/place.c, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/terrains.scm:
+       Added variable-depth LOS.
+
+2007-02-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Haxima changes:
+       o Added wrogue skill: Disarm Trap. Works on chests and doors.
+
+2007-02-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Fixed new h)andle crash
+
+       * src/kern.c, src/scheme-private.h, src/scheme.c, src/scheme.h, src/session.c, worlds/haxima-1.002/mouse.scm:
+       Fixing last currently known memory leak. This also ensures that if a Scheme
+       variable refers to a destructible kernel object then the variable continues to
+       refer to a valid memory location in the kernel, even if the world object is
+       killed or "destroyed" (destroyed in a game sense, not a memory management
+       sense). Caveat: this protection only applies to Scheme variables created via
+       tagging an object (ie, kern-mk-char and kern-tag).
+       
+       Kernel changes:
+       o Scheme interpreter now supports a "custom finalizer" provided by the
+         kernel. Scheme cells may be flagged to invoke this when they are gc'd.
+       o The kern_mk_char and kern_tag -- which define Scheme variables to refer to
+         destructible kernel objects -- flag the reference and add an incremental ref
+         count to the referred object.
+       o The custom finalizer decrements the extra refcount.
+       o To prevent reference cycles (which do exist) between the kernel and
+         interpreter from causing a leak on session teardown, the scheme cleanup
+         function unprotects all cells before running the final gc.
+       
+       Haxima changes:
+       o Removed the hack in mouse.scm which manually added an extra refcount to Thud
+         and Kathryn. This hack caused these objects to leak. The above changes render
+         this unnecessary.
+
+       * src/scheme.c, src/session.c:
+       Replaced the big memory leak with a small one
+
+2007-02-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       Kernel changes:
+       o Yuse checks for tools and materials
+       o Yuse consumes materials
+       o Yuse UI shows material available
+       o Yuse UI show lack of tools or material in red; avail in green
+       
+       Haxima changes:
+       o Added grease
+       o Wriggle skill requires 1 grease
+
+       * worlds/haxima-1.002/skills.scm:
+       Sprint adds yusers current ap to extend range
+
+2007-02-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm, worlds/haxima-1.002/terrains.scm:
+       Added Wriggle skill.
+       
+       Kernel changes:
+       o Removed obsolete comment
+       
+       Haxima changes:
+       o Added new movement mode: "wriggle"
+       o Added new passability class: "bars"
+       o Changed portculli and windows to have pclass "bars"
+
+       * src/kern.c, src/place.c, src/place.h, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       At long, long, last...
+       
+       SPRINT IS FINISHED!!!
+       
+       Kernel changes:
+       o Added kern-place-apply-tile-effects
+       
+       Haxima changes:
+       o Sprint now moves the yuser and applies tile effects along the way
+
+2007-02-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/skills.scm:
+       Kernel changes:
+       o Added kern-place-get-movement-cost
+       
+       Haxima changes:
+       o Added (line x1 y1 x2 y2); returns a line as a list of (x.y) pairs
+       o Sprint destination targeting now accounts for movement cost
+
+2007-02-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/ANNOUNCEMENT, scripts/RELEASE_CHECKOFF, src/kern.c, src/templ.c, src/templ.h, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Some progress on Sprint: UI now builds a template of tiles for radius and LOS.
+
+2007-02-04  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/place.h:
+       direction when moving of edge of map is determined by location relative to map rather than direction of last move
+
+       * src/place.c:
+       removed a bunch of debugging output from the previous fix (oops)
+
+       * src/place.c:
+       fix for 1634496: diagonal movement now only checks neighbors for passability, rather than actually attempting to move onto them.
+
+2007-02-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/cmd.c, src/cmd.h, src/cursor.cpp, src/cursor.h, src/list.h, src/templ.c, src/templ.h:
+       Step 1 of a new targeting ui function. This will replace the existing
+       select_target and its kin when I'm completely done. The new function will allow
+       spells to auto-target friends, foes, or whatever; it will also enable some of
+       the UI enhancements I want for the Sprint skill.
+
+2007-02-03  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm:
+       tweaked random paramters- dungeon was not being very connected.
+       also centred checked area properly
+
+       * worlds/haxima-1.002/endless-deeps.scm:
+       special rooms are marked as not connecting to the dungeon
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       fixed problem with checking algorithm
+       a lot of cleaning up
+
+2007-01-30  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm:
+       endless deeps are checked for cohesion on first entry only
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       cohesion checking now creates new links based on an input factory function
+
+2007-01-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.c, src/status.c:
+       Adding action points to status display. Kind of useless right now.
+
+2007-01-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       cleaned out cohesion debugging output. set up checking in endless deeps
+
+2007-01-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/skill.h, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/pitfalls.scm, worlds/haxima-1.002/skills.scm:
+       Added support for "passive skills". Y)use does not apply to passive
+       skills. They are meant to be used by other parts of the script to check if a
+       character has a certain skill. For example, the 'use handler in the pitfall
+       objects (beartrap and caltrops) now checks if a character has the passive "arm
+       trap" skill.
+
+       * src/object.c:
+       Merged over set-ttl 0 bugfix
+
+       * src/object.c:
+       Should have tested that last fix. NOW the set-ttl 0 bug is fixed.
+
+       * src/object.c:
+       Fixed a (kern-obj-set-ttl kobj 0) crasher
+
+2007-01-28  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/humanoids/nixiesword.xcf:
+       nixie with sword
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       works once somewhere prototype of random map linking
+
+       * worlds/library/artwork/humanoids/nixiespear.xcf:
+       one spear nixie water subsprite was backwards
+
+2007-01-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/powers.scm:
+       Jumping now checks for blocking corner terrain at distance 1.
+
+2007-01-27  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/nixiespear.xcf:
+       nixie with spear
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/nixieciv.xcf:
+       tweaked nixie
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       "ugly but it works" prototype of random dungeon continuity testing. (doesnt yet fix unlinked areas)
+
+2007-01-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/skill.h, worlds/haxima-1.002/skills.scm:
+       Skills now have a "wilderness ok" flag. If the flag is not set the skill can't
+       be used in the wilderness.
+
+2007-01-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       random map links now contain passability data (for continuity testing)
+
+       * worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/humanoids.png, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/humanoids/nixieciv.xcf:
+       first pass at hires nixies
+
+2007-01-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * ChangeLog, Makefile.am, NEWS, haxima.desktop, worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/steward.scm:
+       Merging over icons, desktop and typo fixes from 0.5.6-rc2
+
+       * doc/USERS_GUIDE, doc/users_guide.html, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/reagents.scm:
+       Merging over 2nd typo fix from 0.5.6-rc2
+
+       * doc/USERS_GUIDE, doc/users_guide.html, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/reagents.scm, worlds/haxima-1.002/shroom.scm:
+       Applied mwinterrowd's 2nd typos patch
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/steward.scm:
+       Applying mwinterrowd's first typos patch
+
+2007-01-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       improvements to random dungeon hardlink storage
+
+       * worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       hooks in hardlinks reenabled
+
+2007-01-23  Janne Johansson  <icepic@localhost.localdomain>
+
+       * doc/GAME_RULES, doc/MAP_HACKERS_GUIDE, doc/USERS_GUIDE, doc/world_building/sound_sample_media.txt:
+       various nitpicks in docs and spelling fixes
+
+2007-01-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Makefile.am:
+       Added icons and .desktop to distro list
+
+       * haxima.desktop:
+       file haxima.desktop was initially added on branch release_0_5_5_maint.
+
+       * haxima.desktop:
+       Added icons and .desktop file
+
+       * worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Added Detect Trap as a skill
+
+2007-01-21  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/scheme.c:
+       save file support for vectors
+
+2007-01-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Added Jump skill
+
+2007-01-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/ascii.h, src/cmd.c, src/screen.c:
+       screenPrint now ignores the special control characters when figuring out how big strings are
+
+       * src/cmd.c, src/kern.c, src/status.c:
+       Kernel changes:
+       o kern_mk_skill_set checks for null skill
+       o Y)use skill listings now show required tools and material
+       o scrolling skills was not advancing selection
+       o Tweaked color format in skill listing
+
+2007-01-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * ChangeLog, NEWS, configure.ac:
+       Final update for 0.5.6-rc1
+
+2007-01-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm:
+       endless deeps uses random prng seeds to vary from game to game. Unfortunately, this can result in them not being particularly endless, or even being particularly not endless
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       z coordinate added to random dungeons.
+
+2007-01-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/cmd.c, src/object.h, src/scheme.c, src/status.c, src/status.h:
+       Some minor code cleanup and yet another experimental status browser function.
+
+2007-01-15  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       slightly simpler syntax for random dungeon hardlink hooks
+
+       * worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       store customisable hardlink function, and actual hardlink data
+
+2007-01-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       hooks added to allow random map templates to add objects as well as terrain
+
+2007-01-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/skill.h, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/skills.scm:
+       Y)using the unlock skill now works.
+
+2007-01-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac, src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c, src/node.c, src/node.h, src/occ.c, src/occ.h, src/scheme.c, src/scheme.h, src/session.c, src/skill.c, src/skill.h, src/skill_set.c, src/skill_set_entry.c, src/skill_set_entry.h, src/species.h, src/status.c, src/status.h, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/skills.scm:
+       y)use now shows occupation skills in the status browser
+
+2007-01-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/cfg.c, src/kern.c, src/repstr.c, src/repstr.h, src/session.h, src/skill.c, src/skill.h, src/skill_set.c, src/skill_set.h, src/skill_set_entry.c, src/skill_set_entry.h:
+       More skill groundwork
+
+2007-01-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Updated built-in help with k)amp and l)oiter
+
+       * src/kern.c, src/place.c, src/play.c, src/session.c, src/skill.h:
+       More bugfixes from 0.5.5 maintenance branch; mixed in with some skill stuff unfortunately
+
+       * src/kern.c:
+       One last tweak to get that time accel thing re-loading properly
+
+       * src/kern.c, src/session.c:
+       Bugfix for [ 1629974 ] loitering in wilderness uses too much food.
+       
+       Addendum to the previous fix. Saving/loading the floating-point time
+       acceleration value was not done properly, causing it to be zero on reload and
+       wreaking havoc.
+
+       * src/nazghul.c, src/play.c:
+       Moved the 'welcome to' with the version info to the initial startup (not the game load)
+
+       * src/object.c, src/player.cpp, src/session.h:
+       Merged bugfix from 0.5.5 maintenance branch
+
+       * src/object.c, src/player.cpp, src/session.h:
+       Bugfix for [ 1629974 ] loitering in wilderness uses too much food.
+       
+       Loitering for 1 hour was actually using up almost 32 hours. Time acceleration
+       was set to a value appropriate for one hour at town scale, not wilderness
+       scale. To make the values work out for wilderness scale I had to change time
+       acceleration to be a floating point and fix a few type casts.
+
+       * src/place.c, src/play.c:
+       Bugfix for [ 1624247 ] Delayed victory messages
+       
+       Combat status is now checked after every object executes. Seems inefficient but
+       I'm not noticing any performance hit.
+
+2007-01-06  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       prng parameters now in random map parameter object
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       terrain templates now in random map parameter object
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       blitstats construction formalized
+
+2007-01-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF:
+       Updated some notes on post-release maintenance
+
+       * src/kern.c, src/object.c, src/object.h, src/place.c, worlds/haxima-1.002/demon-gate.scm, worlds/haxima-1.002/powers.scm:
+       Merged bugfix from 0.5.5 maintenance branch
+
+       * src/kern.c, src/object.c, src/object.h, src/place.c, worlds/haxima-1.002/demon-gate.scm:
+       Bugfix for [ 1622833 ] Killing Nossifer with time stopped. Added a new object
+       attribute: ignoreTimeStop. The object which checks for end-of-game has this
+       attribute set.
+
+       * worlds/haxima-1.002/powers.scm:
+       Fix for [ 1629421 ] unusual fireball behavior vs. lich. Fixed a parenthesis
+       error in power.scm.
+
+2007-01-05  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       blitstats stored in map params
+
+       * worlds/haxima-1.002/npc-types.scm:
+       minor glitch- wrong sprite for deeps troll geomancer
+
+2007-01-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/place.c:
+       Merging bugfix from 0.5.5. maintenance branch
+
+       * src/place.c:
+       Bugfix for [ 1627495 ] crash when dying in tutorial cave
+       
+       There was a case where place_exec() would return w/o decrementing a refcount on
+       the player party, triggering an assert in session_del().
+
+2007-01-04  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       beginning to shift random map data into structures suitable for runtime storage
+
+2007-01-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/moongate.scm:
+       Merging bug fixes from 0.5.5 maintenance branch
+
+       * worlds/haxima-1.002/alchemist.scm:
+       Fix for [ 1626202 ] Alchemist and the passage into Absalot. Fixed some logic
+       bugs in the Alkie's conversation.
+
+       * worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/kama.scm:
+       Fix for [ 1626207 ] Releasing Kama from prison. Instead of pathfinding, Kama's
+       jail door is now tagged and stored in Kama's gob so he can check its state
+       directly.
+
+       * worlds/haxima-1.002/moongate.scm:
+       Fix for [ 1622837 ] Loopback moongate doesn't stay. Iff the source and
+       destination gates are the same don't set the destination gate sprite to
+       "closed" after showing the animation.
+
+2007-01-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Merging in NPC inventory count fix from 0.5.5 maintenance branch
+
+       * src/character.cpp:
+       Bugfix for [ 1623756 ] Jorn has too many magical items
+       
+       The code which arms NPC's was putting on and taking off different pieces of
+       equipment to try them out. Every time it took it off it incremented the
+       inventory counter, but it wasn't decrementing it when it put things on, so the
+       counts were messed up on all NPC's who arm themselves.
+
+2007-01-02  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/pseudorandom-map.scm:
+       changed namespace for generic random dungeon code
+
+       * worlds/haxima-1.002/pseudorandom-map.scm:
+       notes of room linkages added
+
+2007-01-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/bigobjects.png, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/monsters/dragonsleep.xcf:
+       sprite for sleeping dragon
+
+       * worlds/haxima-1.002/bigobjects.png, worlds/haxima-1.002/monsters.png, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/sprites.scm:
+       dragon sprites used
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/pseudorandom-map.scm, worlds/haxima-1.002/start-new-game.scm:
+       refactored generic random map code from the endless deeps to pseudorandom-map.scm
+
+       * worlds/library/artwork/monsters/dragon.xcf:
+       new attempt at dragon sprite
+
+2007-01-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/portcullis.scm:
+       Merging bugfixes from maintenance branch to main trunk
+
+       * worlds/haxima-1.002/Makefile.am:
+       Fixing the missing-distro-files problem once and for all.
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fields.scm:
+       Fix for 1622430: "Undead beings aren't immune to sleep fields". Field immunity
+       was just messed up in general.
+       
+       Also fixed 1623757: "Items can get poisoned". Poison wasn't checking that it
+       was being applied to a character.
+
+2006-12-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac:
+       Added the png link fix on the 0.5.6 branch
+
+       * src/Party.cpp:
+       If an NPC party tries to make a diagonal attack it selects a passable adjacent square to attack from instead.
+
+       * src/astar.c, src/astar.h, src/place.c:
+       Turned on diagonal movement for NPC pathfinding
+
+       * src/astar.c, src/character.cpp, src/common.c, src/ctrl.c, src/place.c, src/place.h:
+       Turning on diagonal movement for player characters only. Can't move through pinched corners.
+
+       * src/character.cpp, src/effect.c, src/kern.c, src/map.c, src/occ.c, src/session.c:
+       Fixed some memory leaks reported by a profiler. Thanks to Eero for giving me a report.
+
+       * src/cmd.c, src/kern.c, src/object.c, src/object.h, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/jewelry.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/start-new-game.scm:
+       Quest items can be tagged special, so they won't get dropped in temporary combat maps and lost forever.
+
+       * src/cmd.c:
+       Added direction prompt to d)rop
+
+       * src/cmd.c:
+       Added a quantity prompt to d)rop
+
+       * src/cmd.c, src/status.c:
+       Drop now respects readied arms
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/menus.c, src/status.c, src/status.h, worlds/haxima-1.002/spells.scm:
+       Initial cut at a D)rop command
+
+       * worlds/haxima-1.002/Makefile.am:
+       Added the 640x480 splash fix on the 0.5.6 branch
+
+       * worlds/haxima-1.002/portcullis.scm:
+       Bugfix 1622407: o)pen works on portcullises
+
+2006-12-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/kern.c, src/session.c, src/session.h, src/skill.c, src/skill.h, worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/skills.scm:
+       Started adding code to support skills
+
+       * src/cmd.c:
+       Bugfix: clicking on close window multiple times caused an endless loop
+
+2006-12-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am:
+       Missing small-screen splash in distro
+
+2006-12-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF:
+       Added instructions for uploading releases for release maintainers
+
+2006-12-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac:
+       Added check for libpng
+
+2006-12-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS, ChangeLog, NEWS, configure.ac, doc/USERS_GUIDE:
+       Final changes before release
+
+       * scripts/ANNOUNCEMENT:
+       Adding a file for boilerplate release announcements
+
+       * scripts/RELEASE_CHECKOFF:
+       Some tweaks to the release checkoff list
+
+       * worlds/haxima-1.002/Makefile.am:
+       The spell image file needs to be in the install
+
+       * worlds/haxima-1.002/spells.png, worlds/haxima-1.002/spells.scm:
+       Added all the spell sprites
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Fixing the start file
+
+2006-12-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/magic.c, src/magic.h, src/status.c, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/start-new-game.scm:
+       Spells ready to show sprites in status browser; other spell stats now shown
+
+2006-12-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       C)ast now shows how many mixtures are remaining
+
+       * src/cmd.c:
+       M)ix command now shows how many of that spell are already mixed before the player begins reagent selection
+
+       * src/cmd.c:
+       G)et and S)earch now use up standard AP
+
+       * src/cmd.c:
+       Disable '>' when standing over a town to prevent abuse
+
+       * src/map.c:
+       Bugfix: with fast critters sometimes the damage flash on their victim would appear to happen before they moved
+
+       * src/vmask.c:
+       Bugfix: one more time for that pernicious LOS bug; using the place pointer instead of it's name in the hash key
+
+2006-12-12  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png:
+       lich sprite added
+
+       * worlds/haxima-1.002/monsters.png, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm:
+       gazer sprites used
+
+       * worlds/haxima-1.002/sprites.scm:
+       lich sprite used
+
+       * worlds/library/spritenotes.txt:
+       old sprite notes I never got around to cvsing in
+
+       * worlds/library/artwork/humanoids/lich.xcf:
+       lich sprite
+
+       * worlds/library/artwork/monsters/gazer.xcf, worlds/library/artwork/monsters/gazersleep.xcf:
+       gazer sprites
+
+2006-12-11  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/skeletonarcher.xcf, worlds/library/artwork/humanoids/spearskeleton.xcf:
+       skeleton spearthrower and skeleton archer icons
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprites.scm:
+       skeleton sprites upgraded
+
+2006-12-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/users_guide.html:
+       Graphical foogod symbols added
+
+       * worlds/haxima-1.002/humanoids.png:
+       warrior skeleton sprite
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/deadarcher.xcf:
+       deadarcher- floating armour, with bow
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprites.scm:
+       craven archers use new icon
+
+       * worlds/library/artwork/humanoids/skeleton.xcf, worlds/library/artwork/humanoids/swordskeleton.xcf:
+       generic and warrior skeletons
+
+       * worlds/library/artwork/monsters/dragon.xcf:
+       Attempt at a dragon.
+
+2006-12-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * ChangeLog:
+       Updated
+
+       * doc/USERS_GUIDE:
+       Updated text USERS_GUIDE to reflect changes in foogod window icons
+
+       * src/combat.c, src/ctrl.c, src/pinfo.h, src/player.h:
+       Attempting to fix the sporadic camping-on-fireplace bug. Looks like it was caused by an unitialized and obsolete flag. Removing the flag
+
+       * src/ctrl.c:
+       Re-initialize the list of suggested targets for every attack cycle; should fix rare assert on line 663
+
+       * src/foogod.c, src/foogod.h, src/kern.c, src/object.c, src/session.c, src/session.h, worlds/haxima-1.002/effects.png, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/sprites.scm:
+       Replaced cryptic letters with cryptic icons to show global effects in the foogod window
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/npc-types.scm:
+       Nixies shouldn't have torches
+
+       * worlds/haxima-1.002/arms.scm:
+       Reducing the range of the doom staff by 1
+
+       * worlds/haxima-1.002/arms.scm:
+       Extending range of prismatic gaze by 1; Mesmeme a bit too underpowered in the late game
+
+       * worlds/haxima-1.002/conv.scm:
+       People in Oparine ought to know where it is
+
+       * worlds/haxima-1.002/dennis.scm:
+       Dennis replies to keyword Selene
+
+       * worlds/haxima-1.002/effects.scm:
+       Removed fizzle from prismatic attack; there are enough failure cases already
+
+       * worlds/haxima-1.002/engineer.scm:
+       Grammatical tweak to conv
+
+       * worlds/haxima-1.002/naz.scm:
+       Added make-allies
+
+       * worlds/haxima-1.002/road_to_absalot.scm:
+       What we need are a few more zorns
+
+       * worlds/haxima-1.002/silas.scm:
+       A few more tweaks to Silas
+
+       * worlds/haxima-1.002/silas.scm:
+       Improvements to Silas's conversation
+
+       * worlds/haxima-1.002/tblit.scm:
+       Annoying debug removed
+
+       * worlds/haxima-1.002/the-man.scm:
+       Spell recipe was wrong
+
+       * worlds/haxima-1.002/void-temple.scm:
+       Wisps were not appearing
+
+2006-12-09  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/object.c, src/place.c:
+       fix for examine crashing on parties
+       linebreaks in examine
+
+       * src/cmd.c, src/cmd.h:
+       added cardinal direction keyhandler for attack command
+
+       * worlds/haxima-1.002/ai.scm:
+       wisps use light
+
+       * worlds/haxima-1.002/ancient-derelict.scm:
+       loot on anchient derelict
+
+       * worlds/haxima-1.002/bigobjects.png, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/humanoids/balron.xcf:
+       bigger balron icon
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/npc-types.scm:
+       moved alternate alignment critters to npc-types
+
+       * worlds/haxima-1.002/road_to_absalot.scm:
+       tweaks to absalot:
+       alignment fixes
+       lava edging
+       removed too easy way through fort
+
+2006-12-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp:
+       On detailed x)amine a party describes its members
+
+       * worlds/haxima-1.002/anaxes.scm:
+       Forgot to add Lich's blood to Anaxes's drops
+
+       * worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/silas.scm:
+       Fixed loot and lich effects for Anaxes
+
+       * worlds/haxima-1.002/parties.scm:
+       More corrections to plural party names
+
+       * worlds/haxima-1.002/parties.scm:
+       Fixed some plural party names
+
+2006-12-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/map.c:
+       missile fire should now have less wierdness with obstructions
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/enchanters-tower.scm:
+       added bet flam hur spellbook
+
+       * worlds/haxima-1.002/enchanters-tower-mech.scm:
+       fix for mirror based crash
+
+       * worlds/haxima-1.002/endless-deeps.scm:
+       corpse loot fixed
+
+       * worlds/haxima-1.002/luximene.scm:
+       added lichs blood to luxs inventory
+
+2006-12-07  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanters-tower-mech.scm:
+       enchanters' oddly reflecting mirrors activate in timely fashion
+
+2006-12-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Bugfix: dead characters could give a 'wakes up' message when camping
+
+       * src/cmd.c:
+       Print a snarky message if the player selects a dead character to guard the camp
+
+       * src/effect.h, src/status.c:
+       Converted some magic numbers to named constants; fixed a ztats bug which caused multiple effects to be listed offset from column 0
+
+       * src/kern.c:
+       Added (kern-ticks-per-turn)
+
+       * src/player.cpp:
+       Bugfix: dead party members starving
+
+       * worlds/haxima-1.002/effects.scm:
+       Poison now permanent, so it doesn't wear off with 2 hours of camping. Poison and disease both apply more damage per turn in the wilderness than at town scale.
+
+       * worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/treasury.scm:
+       Bugfix: bad chest list
+
+2006-12-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Bugfix: when mixing, the number mixed flashes without a - separator; annoying
+
+       * src/player.cpp, src/session.c:
+       Bugfix: assert when quitting while aboard a vehicle
+
+2006-12-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c:
+       Adjusted console printout for attack verbage
+
+       * worlds/haxima-1.002/chanticleer.scm:
+       Fixed the hint about where to find the Lost Halls
+
+       * worlds/haxima-1.002/effects.scm:
+       Fixed typo in generic-burn
+
+       * worlds/haxima-1.002/effects.scm:
+       Removed superfluous console message for paralysis
+
+       * worlds/haxima-1.002/enchanters-tower-mech.scm:
+       Protect against evaluating tags on startup before they are declared
+
+       * worlds/haxima-1.002/spells.scm:
+       Tweak to format, moved Kal Xen Nox down with the other L8 spells
+
+2006-12-03  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/640x480_splash.png, worlds/haxima-1.002/splash.png:
+       Updated splash screens (now use a more up to date version of the logo, doesnt scale screenshot part of smaller splash)
+
+2006-12-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/character.cpp, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/traps_1.scm, worlds/haxima-1.002/traps_2.scm, worlds/haxima-1.002/traps_3.scm, worlds/haxima-1.002/traps_4.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Increased time that Thief's Door in Bole is open
+       o Added (floor ...) to a few more spots in powers.scm
+       
+       Kernel changes:
+       o When an NPC unreadies arms they are put back into personal inventory (fixes
+         acid on NPC's)
+       o Bugfix: NPC's with their "force drop" flag set would drop their inventories,
+         which are now abstract containers and don't function well as physical
+         objects. They now drop their contents directly instead.
+
+       * worlds/haxima-1.002/alchemist.scm:
+       Raised price of invisibility potion back up again
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Raised back up the price of precision instruments.
+       o Added prismatic_gaze as a natural weapon for gazers.
+
+       * worlds/haxima-1.002/conv.scm:
+       Grammar fix
+
+       * worlds/haxima-1.002/effects.scm:
+       Tweaks to console messages for burn and lightning effects
+
+       * worlds/haxima-1.002/game.scm:
+       Raising scroll prices back up a bit more
+
+2006-12-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c:
+       Tweaked credits
+
+       * src/nazghul.c, worlds/haxima-1.002/kern-init.scm:
+       Haxima changes:
+       o Updated kern-init.scm to reflect kernel changes.
+       
+       Kernel changes:
+       o Support a different splash screen for each supported screen dimension.
+
+       * src/nazghul.c:
+       Splash screen width computed wrong
+
+       * src/player.cpp, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/zane.scm:
+       Haxima changes:
+       o Shroom opens shop earlier
+       o Price deflation on potions, scrolls and misc items.
+       o Added an in-game spell book for reference
+       
+       Kernel changes:
+       o Time accelerated faster now while sleeping in town or k)amping
+
+       * worlds/haxima-1.002/640x480_splash.png, worlds/haxima-1.002/kern-init.scm:
+       Added the small splash image file
+
+       * worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/edward.scm:
+       Haxima changes:
+       o Tweaks to Edward to handle cases where the Wanderer is dead or not the party
+         leader.
+       o If player took Nate straight to jail Deric would not re-assign ranger.
+
+       * worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/gamestart.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/necromancers-lair.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/prison.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/tutorial_town.scm:
+       Haxima changes:
+       o Shroom opens shop earlier
+       o Price deflation on potions, scrolls and misc items.
+       o Added an in-game spell book for reference
+       o Converted some more chests from (list (list ...) ...) to '(( ...) ...)
+         format.
+       o Tweaked Zane's schedule zones
+       
+       Kernel changes:
+       o Time accelerated faster now while sleeping in town or k)amping
+
+2006-12-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/users_guide.html:
+       tweaked html manual
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/npc-types.scm:
+       removed light from several non tool using or dark appreciating critters
+
+       * worlds/haxima-1.002/cast-ui.scm:
+       fix for resurect spell in town
+
+2006-12-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Edward won't take Nate out of the party if he's the only living member.
+       o If the only living party member talks to his/her/itself, and asks
+         his/her/itself to leave, it will give itself some excuse not to.
+       
+       Kernel changes:
+       o Bugfix: if the current party leader was removed while in follow mode, the new
+         leader was not re-evaluated, and the kernel continued to try and use the
+         ex-member as the leader, causing a crash.
+       o When a party member leaves he/she/it unreadies all weapons instead of
+         removing them from party inventory.
+
+       * worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/zane.scm:
+       Haxima changes:
+       o Fixed the broken chests that used mk-content and add-content. At least, I
+         fixed the one or two I've tested thus far.
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Haxima changes:
+       o Removed door left stranded after my last map tweaks to Brundegardt.
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Weather vane was falling into the chasm...
+
+2006-11-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Missile.cpp, src/ctrl.c, src/ctrl.h, src/foogod.c, src/kern.c, src/player.cpp, src/player.h, src/session.c, src/session.h, src/vehicle.cpp, worlds/haxima-1.002/thorald.scm, worlds/haxima-1.002/tutorial.scm:
+       Haxima changes:
+       o Bugfix: tutorial crashed on load because of my changes last night to the
+         kernel. NPC party creation using (mk-npc-party ...) must be held off until
+         after (kern-mk-player ...).
+       o Thorald in the tutorial responds to 'mixi' as well as 'mix' with instruction
+         on mixing spells.
+       
+       Kernel changes:
+       o Bugfix: vehicle save code was incorrect; resulted in a null object.
+       o Bugfix: last night's kernel changes broke reload. Fixed this by moving the
+         global player_party variable into a field of the global session struct (down
+         to one global variable now, yee-haa!). Added a player_party macro which
+         references this field for backwards-compatibility.
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Tweaked the brundegardt fortress map again
+
+       * worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Removed some debug spew.
+       o Tweaked brundegardt fortress map
+
+       * worlds/haxima-1.002/gregor.scm:
+       Tweaked Gregor's conv
+
+2006-11-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/foogod.c, src/nazghul.c, src/object.c, src/place.c, src/play.c, src/player.cpp, src/player.h, src/session.c, src/status.c, src/vmask.c:
+       Risky kernel change that should fix the LOS bug for real. It also partially
+       cleans up a big memory leak I've been ignoring since I added the main menu
+       loop. The gist of it is I know destroy the current session before falling back
+       to the main loop. This fixes the LOS bug by removing all the player-controlled
+       beings, and hence their map views. The LOS bug was caused by a leftover map
+       view from the previous session remaining active. I expect to find a few more
+       (maybe a lot more) bugs after this change that are related to improper
+       cleanup. Stand bye for asserts and seg faults. If it's too bad I'll back this
+       out and workaround the LOS bug with an evil hack instead.
+
+       * worlds/haxima-1.002/Makefile.am:
+       Forgot to add a file to the distro list
+
+       * worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/landslide.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm:
+       Added landslide to slope of Griffin Peak
+
+       * worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Added griffin parties to wilderness encounters
+
+       * worlds/haxima-1.002/wind-bridge.scm:
+       Wind bridge now delays two turns before rotating
+
+2006-11-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/door.scm, worlds/haxima-1.002/traps.scm:
+       Haxima changes:
+       o S)earching doors now has some chance of detecting or tripping traps.
+       o Tweaked the difficulty stats on detecting/fumbling traps
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o Organized the effects a bit.
+       o When a sludge kraken dies it takes all its tentacles with it.
+
+       * worlds/haxima-1.002/splash.png:
+       Changed splash screen
+
+2006-11-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c, src/object.c, src/object.h, src/place.c, src/player.cpp, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/hidden.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/rune.png, worlds/haxima-1.002/traps.scm:
+       S)earch now detects traps on chests, with a chance of setting them off. Doors
+       do NOT support this yet.
+       
+       Haxima changes:
+       o Containers implement the search ifc and roll to detect or trigger traps
+       o Traps triggered by a s)earch are removed
+       o Containers implement the describe ifc and list their detected traps
+       
+       Kernel changes:
+       o Reworked code for describing objects to support a hook for custom
+         descriptions
+       o Added kern-log-begin/continue/end
+
+2006-11-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/thiefs_den.scm:
+       standardising on unabbreviated t_invisibility_potion. Mixing t_invisibility_potion and t_inv_potion was causing reusable chests
+
+       * worlds/haxima-1.002/bandit-hideout.scm:
+       bandit stockade blended
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       blended new areas. Added some minor encounters to empty areas
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       2 chests failing due to contents typos
+
+       * worlds/haxima-1.002/combat-maps.scm:
+       combat maps blended
+
+       * worlds/haxima-1.002/food.scm:
+       typo: s/wind/wine
+
+       * worlds/haxima-1.002/mans-hideout.scm:
+       I think this fixes the man's chests
+
+       * worlds/haxima-1.002/potions.scm:
+       removed total stats message on stat potions
+
+2006-11-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c:
+       Kernel changes:
+       o Auto-targeting now respects LOS.
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/pitfalls.scm:
+       Haxima changes:
+       o Some files missing from Makefile.am
+       o Fixed typo in Gregor's conv
+       o Only pitfalls (eg caltrops) planted by player will affect NPC's
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Improvements to one of the brundegardt dungeon rooms:
+       o Sludge kraken tentacles chomp deck into sludge shallows
+       o Added sludge shallows (passable to most things)
+       o Sludge krakens summon a few more tentacles
+
+       * worlds/haxima-1.002/bandit-hideout.scm:
+       Removing some caltrops
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/wind-bridge.scm:
+       Haxima changes:
+       o Chasms are now *very* unsafe for non-flying, non-abstract objects
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Rangers now use the ranger occupation
+
+2006-11-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/map.c:
+       Removed clock from map (these days its possible to get the time in-game)
+
+       * worlds/haxima-1.002/enchanters-tower.scm:
+       fixed script error after reload: mk-hidden must use 'object not object
+
+       * worlds/haxima-1.002/gamestart.scm:
+       Reverting to diagonal pillars in startup room
+
+       * worlds/haxima-1.002/kalcifax.scm:
+       Revert kalcifax to regular wizard sprite due to that bug with the mirrors and composite sprites
+
+       * worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/silas.scm:
+       Some other sprites I'd missed earlier
+
+2006-11-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       When camping underground resting until sunrise is no longer an option
+
+       * src/cmd.c, src/conv.c, src/conv.h, src/kern.c:
+       Minor feature enhancement: player and npc names highlighted in conversation
+
+       * src/menus.c:
+       Changed localtime_r to localtime for Mingw portability
+
+       * src/nazghul.c:
+       Flushing the vmask cache before starting a game to fix LOS bugs
+
+       * src/nazghul.c, src/play.c:
+       Closing the window now exits the program instead of dropping back to the main menu
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/gamestart.scm, worlds/haxima-1.002/map.png, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/nate.scm:
+       Misc tweaks and fixes
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/treasury.scm:
+       Bugfix: mk-treasure-chest needed to use a quoted list
+
+       * worlds/haxima-1.002/kathryn.scm:
+       Permanent fix for Kathryn's response to 'scroll'
+
+       * worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/tools.scm:
+       Sextant and In Wis both report location as [x=<x> y=<y>]
+
+2006-11-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.c, src/ctrl.c:
+       Disabling diagonal movement
+
+       * src/character.cpp, src/character.h, src/ctrl.c:
+       Seems like every year I have to fix this bug again: Bill and Sue have both
+       readied flaming oil. There are two in party inventory. Bill throws, leaving
+       only one, but ostensibly he and Sue both still have the weapon readied. This is
+       a crash waiting to happen. This time I fixed it by forcing Bill to unready, but
+       allowing Sue to remain readied.
+
+       * src/character.cpp:
+       Fixed another annoying must-be-in-follow-mode message when player is alone
+
+       * src/cmd.c:
+       Bugfix: opening doors was not decrementing action points
+
+       * src/kern.c:
+       Bugfix: kern-obj-get-name would (sometimes?) crash if the object had a null name
+
+       * src/kern.c, src/map.c, worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/eye-of-brune.scm, worlds/haxima-1.002/sprites.scm:
+       kernel:
+       o Added kern-image-load
+       o Added kern-image-free
+       o Moved kern-map-set-image
+       
+       haxima:
+       o Added Eye of Brune to Brundegardt tower
+
+       * src/menus.c:
+       Disabling the L)oad Game menu option. J)ourney Onward now works like L)oad
+       Game, with the most recently saved game always highlighted at the top by
+       default for quick access. If there is only one saved game then it just launches
+       it without showing the menu.
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/tim.scm, worlds/haxima-1.002/troll.scm:
+       Haxima changes:
+       o Trolls now hostile to generic monsters but less hostile to forest goblins.
+       o Finished adding NPC's to Griffin peaks and Brundegardt tower.
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm:
+       Started adding Griffins to the peak
+
+       * worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/start-new-game.scm:
+       Tweaks to brundegardt
+
+       * worlds/haxima-1.002/arms.scm:
+       Buffed slings a bit
+
+2006-11-23  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/thorald.scm, worlds/haxima-1.002/warritrix.scm:
+       typo fixes for bug 1591311
+
+       * worlds/haxima-1.002/bole.scm:
+       bole grove reblended
+
+       * worlds/haxima-1.002/bole.scm:
+       lake at bole reblended
+
+       * worlds/haxima-1.002/kathryn.scm:
+       quick fix for bug 1601241:
+       kathryn automatically goes to "dont have one". Otherwise it pulls the scroll from *your* inventory
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprites.scm:
+       some sprite tweaks
+
+2006-11-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/tools.scm:
+       kernel:
+       o Added kern-get-wind
+       o Added kern-place-add-on-entry-hook
+       o Moved facing support from Vehicle subclass up to base Object class
+       
+       haxima:
+       o Added a weather vane
+       o Added a wind bridge
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/items.scm, worlds/haxima-1.002/keys.scm:
+       Added doors-with-unique-keys
+
+       * worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/start-new-game.scm:
+       Haxima changes:
+       o Filled out Brundegardt tower levels 1, 2 and 3.
+
+2006-11-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/palette.txt:
+       tweaks to maptoxpm palette
+
+       * worlds/haxima-1.002/monsters.png:
+       quick n dirty griffon cub
+
+       * worlds/library/artwork/monsters/egg.xcf:
+       egg sprite
+
+       * worlds/library/artwork/monsters/griffoncub.xcf:
+       old griffon sprite on bigger template to scale down by 0.66
+
+2006-11-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/object.c, src/object.h, src/sprite.c, src/sprite.h, src/vehicle.cpp, src/vehicle.h, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/monsters/kraken.xcf:
+       kernel:
+       o Added kern-get-wind
+       o Added kern-place-add-on-entry-hook
+       o Moved facing support from Vehicle subclass up to base Object class
+       
+       haxima:
+       o Added a weather vane
+       o Added a wind bridge
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/weather-vane.scm, worlds/haxima-1.002/wind-bridge.scm:
+       Adding files
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/monsters.png, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm:
+       Sprites for ratling NPC's
+
+2006-11-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm:
+       Added Great Kraken
+
+2006-11-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o New npc: carabids (stone-munching beetles)
+       o Added objects to a few more brundegardt rooms
+
+       * worlds/library/artwork/monsters/kraken.xcf:
+       Added new kraken image
+
+2006-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/start-new-game.scm:
+       Haxima changes:
+       o Ratlings fear snakes
+       o Snakes eat rats and ratlings
+
+2006-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/mimic.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Added mimic npc type
+       o Added objects to Brundegardt Keep
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Added ratling npc types (currently borrowing the forest goblin sprites)
+       o Added objects to Ratling Warren
+
+2006-11-15  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/monsters.png, worlds/library/artwork/monsters/griffon.xcf:
+       griffon sprite
+
+2006-11-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Tweaks to dungeon rooms
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Added a bunch of rooms to Brundegardt
+
+2006-11-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/species.c, src/species.h, worlds/haxima-1.002/species.scm:
+       kernel:
+       o Added an armor dice bonus to the species struct, for scaly and chitinous
+         critters.
+       
+       haxima:
+       o Updated to match kernel change.
+
+       * worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       Haxima changes:
+       o Started on another room for Brundegardt
+       o Started adding the Carabid NPC type
+       o Tweaked some conversations related to the Brundegardt quest
+
+2006-11-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/ratling.xcf:
+       draft ratling
+
+       * worlds/haxima-1.002/monsters.png, worlds/library/artwork/monsters/beetle.xcf:
+       an attempt at a beetle
+
+       * worlds/library/artwork/monsters/beetle.xcf:
+       minor update
+
+2006-11-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/anaxes.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/conv.scm:
+       Haxima changes:
+       o Added a procedure for interjecting party member comments in a conversation
+       o Added Anaxes
+       o Made the Cave Shrine map
+
+       * worlds/haxima-1.002/brundegardt.scm:
+       Expanding Brundegardt
+
+2006-11-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/traps_1.scm:
+       Haxima changes:
+       o Made riddles slightly more general
+       o First pass at Entrance to Brundegart
+
+2006-11-11  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/haxima-1.002/hirespeople.png, worlds/library/artwork/hirespeople/generic.xcf, worlds/library/artwork/hirespeople/old_ranger.xcf, worlds/library/artwork/hirespeople/ranger_captain.xcf:
+       Minor consistency tweaks
+
+2006-11-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/start-new-game.scm:
+       Haxima changes:
+       o Doubled starting reagents
+       o Restored start-of-game to release state
+
+2006-11-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.c:
+       Fixed a recently-introduced bug in Object::setOnMap() that caused an assert in
+       combat_exit().
+
+       * src/scheme.c:
+       Hubert Maier's patch for Amiga OS
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/edward.scm:
+       Expanded Edward's conversation
+
+       * worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/hirespeople.png, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/hirespeople/generic.xcf:
+       artwork:
+       o Added some layers to the generic sprite
+       
+       haxima:
+       o Added an old townsman sprite, changed Gregor and Edward to use it
+
+2006-11-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/hirespeople.png, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm, worlds/library/artwork/hirespeople/ranger_captain.xcf:
+       Added a sprite for Ranger Captain. Deric now uses it.
+
+       * worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/hirespeople.png, worlds/haxima-1.002/sprites.scm, worlds/library/artwork/hirespeople/old_ranger.xcf:
+       Added an old ranger sprite. Gen uses it now.
+
+2006-11-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.h, src/object.c, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/brundegardt.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/edward.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/step.scm, worlds/haxima-1.002/traps.scm, worlds/haxima-1.002/zones.scm:
+       The Bandit quest (new quest for L1 players) is now pretty much done.
+
+2006-11-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/nate.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Deric gives player the bandit quest
+       o Added some generic ranger guards to Green Tower
+       o Player can recruit a generic ranger for the bandit quest
+       o Added Nate, the bandit leader
+
+2006-11-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cursor.cpp, src/kern.c, src/object.c, src/object.h:
+       Fixed Object::relocate() to distinguish between avoiding step triggers, sense
+       triggers, and both.
+
+2006-11-02  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/object.c:
+       sense/step mechanisms need to be double checked after hooks are called since they may be destroyed in the process
+
+       * worlds/library/artwork/humanoids/demon.xcf:
+       v2 demon
+
+2006-11-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/cmd.c, src/object.c, src/object.h, src/place.c, src/place.h, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/pitfalls.png, worlds/haxima-1.002/pitfalls.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/traps.scm:
+       Kernel changes:
+       o Fixed inventory saving/loading (recently broken)
+       o Fixed a bug that applied effects multiple time on startup (broken for a while
+         but I didn't know it)
+       
+       Haxima changes:
+       o Fixed saving from new game (recently broken)
+       o Fixed saving traps (recently broken)
+       o Fixed invisibility on pitfalls
+       o Pitfalls (caltrops and beartraps) can now be picked up and re-used
+
+       * worlds/haxima-1.002/pitfalls.png:
+       Slightly better sprites for the caltrops and beartrap
+
+2006-11-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/library/artwork/humanoids/demon.xcf:
+       Demon icon: first attempt
+
+2006-11-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am:
+       Adding pitfalls.scm/png to the install list
+
+2006-10-31  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/headless.xcf:
+       headless icon
+
+2006-10-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/tile.c, src/Attic/tile.h:
+       Removing unused files
+
+       * worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/pitfalls.png, worlds/haxima-1.002/pitfalls.scm, worlds/haxima-1.002/traps.scm:
+       Added caltrops and a beartrap
+
+2006-10-30  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/humanoids.png:
+       troll geomancer icon
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/trollfighter.xcf, worlds/library/artwork/humanoids/trollmage.xcf:
+       troll icon
+
+2006-10-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/traps.scm:
+       Haxima changes:
+       o Wis Sanct now lists the type of trap(s) attached to a chest or mechanism.
+       o An Sancy Ylem lists the type of trap(s) being disarmed.
+       o After a trap is detected with Wis Sanct, the chance of disarming it is
+         greatly improved.
+
+2006-10-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       sprite updates
+
+       * worlds/haxima-1.002/bigobjects.png, worlds/haxima-1.002/humanoids.png:
+       giants updated
+
+       * worlds/library/artwork/humanoids/giant.xcf:
+       hairier giant
+
+       * worlds/library/artwork/humanoids/giantmage.xcf:
+       giant mage
+
+2006-10-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/cmd.c, src/kern.c, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/tutorial.scm:
+       THIS WILL BREAK ALL SAVED GAMES!
+       
+       Kernel changes:
+       o Stripped trap support from the Container class. Containers should only be
+         used for abstract inventory "objects" now.
+       o Removed kern-obj-is-trapped? and kern-obj-rm-trap. These are done in the
+         script now.
+       o Changed kern-mk-container to kern-mk-inventory and removed the type and trap
+         parms.
+       
+       Haxima changes:
+       o Modified code as necessary to deal with the above.
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gamestart.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/Attic/player.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/traps.scm:
+       Haxima changes:
+       o Moved trap routines to their own file in traps.scm
+       o Removed the obsolete player.scm file
+       o Modified the character creation place: now that diagonal movement works the
+         player could miss the name prompt
+       o Changed all the places that refer directly to kern-mk-container to use one of
+         the wrapper functions in container.scm
+
+       * worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/zane.scm:
+       Haxima changes:
+       o Changed everything to use the new-style containers. Character inventories
+         should be the only things that use the kernel Container class now.
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/traps.scm:
+       Traps now implemented via a script object, instead of just a closure, so they can keep some state
+
+2006-10-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c, src/menus.h, src/nazghul.c:
+       The function which displays the error message when the kernel can't find the
+       config files no longer uses sleep(); instead it lets the user close the window
+       normally.
+
+2006-10-27  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/bigobjects.png:
+       area for 40x40 icons
+
+       * worlds/haxima-1.002/humanoids.png, worlds/library/artwork/humanoids/cgoblinfighter.xcf, worlds/library/artwork/humanoids/cgoblinmage.xcf, worlds/library/artwork/humanoids/cgoblinslinger.xcf, worlds/library/artwork/humanoids/fgoblinarcher.xcf, worlds/library/artwork/humanoids/fgoblinfighter.xcf, worlds/library/artwork/humanoids/fgoblinmage.xcf:
+       lots of goblins
+
+       * worlds/library/artwork/humanoids/cgoblinciv.xcf:
+       cave goblin paler
+
+       * worlds/library/artwork/humanoids/giant.xcf:
+       meaner, hairier giant. Think it still needs more hair tho
+
+2006-10-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/powers.scm:
+       Traps on doors now removable via An Sanct Ylem.
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/powers.scm:
+       Traps on doors now detectable via Wis Sanct.
+
+2006-10-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/start-new-game.scm:
+       Traps can now be added to chests or doors.
+
+       * worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/containers.scm:
+       Added ability to attach traps to the new container implementation. An unlimited
+       number of traps is supported. Removing, detecting and disarming traps is not
+       yet supported.
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/start-new-game.scm:
+       ;;----------------------------------------------------------------------------
+       ;; Containers - objects that contain stuff
+       ;;----------------------------------------------------------------------------
+       ;;----------------------------------------------------------------------------
+       ;; Local Procedures
+       ;;----------------------------------------------------------------------------
+       (define (add-content quantity type)
+         (list quantity type))
+       
+       (define (mk-contents . contents)
+         (filter notnull? contents))
+       
+       (define (roll-100 prob)
+         (>= prob (modulo (random-next) 100)))
+       
+       (define (roll-q dice type)
+         (add-content (kern-dice-roll dice) type))
+       
+       (define (roll-to-add prob dice type)
+         (if (roll-100 prob)
+             (roll-q dice type)
+             nil))
+       
+       ;;----------------------------------------------------------------------------
+       ;; Container Types
+       ;;----------------------------------------------------------------------------
+       (mk-obj-type 't_chest
+                    "chest"  s_chest
+                    layer-container nil)
+       
+       ;;----------------------------------------------------------------------------
+       ;; Container Constructors
+       ;;----------------------------------------------------------------------------
+       (define (mk-chest trap contents)
+         ;;(println "mk-chest: " trap contents)
+         (kern-mk-container t_chest trap contents))
+       
+       ;; mk-treasure-chest -- returns a chest with 1-10 random object types
+       (define (mk-treasure-chest)
+         (kern-mk-container t_chest
+                            nil
+                            (mk-treasure-list (+ 1
+                                                 (modulo (random-next)
+                                                         9)))))
+       
+       
+       ;;----------------------------------------------------------------------------
+       ;; Corpse -- not really a container, if you search it then it sort of acts like
+       ;; opening a container
+       ;;----------------------------------------------------------------------------
+       (define (corpse-mk loot)
+         (list loot))
+       (define (corpse-loot corpse) (car corpse))
+       (define (corpse-set-loot! corpse val) (set-car! corpse val))
+       (define (corpse-loot-entry-q loot) (car loot))
+       (define (corpse-loot-entry-type loot) (eval (cadr loot)))
+       
+       (define (corpse-search kobj)
+         (let* ((corpse (kobj-gob-data kobj))
+                (loot (corpse-loot corpse)))
+           (if (not (null? loot))
+               (let ((loc (kern-obj-get-location kobj)))
+                 (map (lambda (entry)
+                        (kern-obj-put-at (kern-mk-obj (corpse-loot-entry-type entry)
+                                                      (corpse-loot-entry-q entry))
+                                         loc))
+                      loot)
+                 (corpse-set-loot! corpse nil)))))
+       
+       (define corpse-ifc
+         (ifc nil
+              (method 'search corpse-search)))
+       
+       (mk-obj-type 't_corpse "corpse" s_corpse layer-item corpse-ifc)
+       
+       (define (mk-corpse)
+         (bind (kern-mk-obj t_corpse 1)
+               (corpse-mk nil)))
+       
+       ;; mk-corpse2 -- loot: a list of (quantity type) lists
+       (define (mk-corpse2 loot)
+         (bind (kern-mk-obj t_corpse 1)
+               (corpse-mk loot)))
+       
+       (define (mk-corpse-with-loot)
+         (mk-corpse2 (mk-quoted-treasure-list (+ 1(modulo (random-next)
+                                                          3)))))
+       
+       ;;----------------------------------------------------------------------------
+       ;; This next section is an experimental new container type. It attempts to
+       ;; bypass the kernel's built-in Container class and implement everything in the
+       ;; script as a normal kernel Object that responds to the 'open signal the same
+       ;; way a kernel Container would respond to the open command.
+       ;;
+       ;; This currently works. The next step is to implement the ability to add (and
+       ;; remove or disable) traps on a container. The means of doing so will be
+       ;; implemented here in the script, so the kernel won't need to know about
+       ;; trapped containers when this all works, and the kernel's Container class can
+       ;; be stripped back to a basic Inventory class.
+       
+       ;; Define the gob structure and procedures. The contents should be a single
+       ;; quoted list, for example:
+       ;;
+       ;;   '((t_sword 1)
+       ;;     (t_arrow 5)
+       ;;     (t_torch 2)))
+       ;;
+       ;; Using the quotes is not only cleaner in the declarations, it automatically
+       ;; ensures that the contents are safe to save and reload as part of the gob
+       ;; because they are stored in the gob merely as symbols.
+       ;;
+       ;; Each container has a (often empty) list of traps, where each trap is the
+       ;; symbol for a procedure of the form (foo <kchar> <kcontainer>). The symbol is
+       ;; used instead of the actual procedure so that the list of traps can be saved
+       ;; and re-loaded.
+       ;;
+       (define (mk-container contents) (list 'container contents nil))
+       (define (is-container? gob) (eq? (car gob) 'container))
+       (define (container-contents gob) (car (cdr gob)))
+       (define (container-traps gob) (car (cdr (cdr gob))))
+       (define (container-set-traps! gob traps) (set-car! (cdr (cdr gob)) traps))
+       (define (content-type content) (car content))
+       (define (content-quantity content) (cadr content))
+       (define (container-add-trap! gob trap)
+         (container-set-traps! gob
+                               (cons trap
+                                     (container-traps gob))))
+       
+       ;; This is the heart of the implementation. This procedure runs when the
+       ;; container object gets the 'open signal, which is sent by the kernel in
+       ;; response to the player's o)pen command followed by selection of this
+       ;; object. It expects kobj to be a kernel object which is bound to a container
+       ;; gob following the above format (the constructors further down illustrate how
+       ;; to create such an object).
+       ;;
+       ;; Opening the container creates objects based on the types and quantities
+       ;; listed in the container's content list and deposits these objects on the
+       ;; ground where the container is. Then it removes the container, which likely
+       ;; results in its destruction.
+       ;;
+       ;; Before opening this applies all the traps attached to the container. Note
+       ;; that the self-destruct trap, as currently implemented, does not work as
+       ;; expected, because it relies on the removal of the container from the map as
+       ;; a means of destroying it; and that is not sufficient here.
+       (define (kcontainer-open kobj kchar)
+         (let ((container (kobj-gob-data kobj))
+               (loc (kern-obj-get-location kobj))
+               (thief-dice (string-append "1d" (number->string (occ-ability-thief kchar))))
+               )
+           (println container)
+       
+           ;; Applying traps can destroy both kobj and kchar
+           (kern-obj-inc-ref kobj)
+           (kern-obj-inc-ref kchar)
+       
+           ;; Apply traps
+           (map (lambda (trap)
+                  (let ((roll (kern-dice-roll "1d20"))
+                        (bonus (kern-dice-roll thief-dice)))
+                    (println trap " roll:" roll "+" bonus)
+                    (cond ((or (= roll 20)
+                               (> (+ roll bonus) 20))
+                           (kern-log-msg (kern-obj-get-name kchar) " avoids a trap!"))
+                          (else
+                           (kern-log-msg (kern-obj-get-name kchar) " trips a trap!")
+                           (apply (eval trap) (list kchar kobj))))))
+                (container-traps container))
+       
+           ;; Spill contents
+           (map (lambda (content)
+                  (println content)
+                  (let ((newobj (kern-mk-obj (eval (content-type content))
+                                             (content-quantity content))))
+                    (kern-obj-put-at newobj loc)))
+                (container-contents container))
+       
+           ;; Remove the container from the map
+           (kern-obj-remove kobj)
+       
+           ;; Done with references
+           (kern-obj-dec-ref kobj)
+           (kern-obj-dec-ref kchar)
+           ))
+       
+       ;; This interface binds the 'open signal to our open procedure above.
+       (define container-ifc
+         (ifc '()
+              (method 'open kcontainer-open)))
+       
+       ;; This constructor makes new types of objects that conform to the container
+       ;; interface above. An example of usage is below, where I make a new chest
+       ;; type.
+       (define (mk-container-type tag name sprite)
+         (mk-obj-type tag name sprite layer-mechanism container-ifc))
+       
+       
+       ;; Test it out. First, make a new chest type.
+       (mk-container-type 't_chest2 "chest" s_chest)
+       
+       ;; Define a constructor for an object of the new chest type. Example usage:
+       ;;
+       ;; (put (mk-chest2 '((t_sword 1)
+       ;;                   (t_arrow 5)
+       ;;                   (t_torch 2)))
+       ;;      5 8)
+       ;;
+       ;; * Note the use of a quoted list.
+       ;;
+       (define (mk-chest2 ktype-q-pairs)
+         (bind (kern-mk-obj t_chest2 1)
+               (mk-container ktype-q-pairs)))
+       
+       (define (chest2-add-trap kobj trap)
+         (container-add-trap! (kobj-gob-data kobj) trap))
+
+2006-10-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/containers.scm:
+       Started a new implementation of container objects (like chests) that will be
+       done entirely in the script. This is a preliminary step to adding traps on
+       doors and other non-container mechanisms.
+
+2006-10-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.c, worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/bandit-hideout.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/step.scm:
+       Kernel changes:
+       o Bugfix: the crosshair object was triggering sense mechanisms
+       
+       Haxima changes:
+       o Started a new entry-level quest dungeon for L1 players
+
+2006-10-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/status.c:
+       Fixed some compiler errors and warnings that occur with newer versions of g++
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       I keep forgetting to undo my test changes to start-new-game.scm...
+
+2006-10-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmdwin.c:
+       Fixed some command error messages that were only being printed to the cmdwin, where they were promptly erased before the player could read them
+
+2006-10-15  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/library/artwork/humanoids/cgoblinciv.xcf:
+       basic cave goblin
+
+       * worlds/library/artwork/humanoids/deadknight.xcf:
+       Deathknight glow effects tweaked
+
+       * worlds/library/artwork/humanoids/fgoblinciv.xcf:
+       smaller goblin
+
+       * worlds/library/artwork/humanoids/giant.xcf:
+       draft giant/ettin
+
+2006-10-14  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/library/artwork/humanoids/fgoblinciv.xcf:
+       first attempt at forest goblins
+
+2006-10-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.c, src/sprite.c:
+       Added initial support for giant sprites.
+
+2006-10-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/hirespeople.png:
+       tonights icons in 32x32
+
+       * worlds/library/artwork/hirespeople/beggar.xcf:
+       beggar icon
+
+       * worlds/library/artwork/hirespeople/child.xcf, worlds/library/artwork/hirespeople/generic.xcf:
+       child icon added. generic townsman cleaned up
+
+       * worlds/library/artwork/hirespeople/fencer.xcf:
+       the companion_bard icon isnt used anywhere according to grep. (probably too generic looking). Anyway, Ive put together this 2 weapon fencer to get rid of the gaping hole in my icons page
+
+       * worlds/library/artwork/hirespeople/fighter.xcf, worlds/library/artwork/hirespeople/paladin.xcf:
+       fighter/paladin given shoulderguards
+
+       * worlds/library/artwork/hirespeople/jester.xcf:
+       jester icon
+
+       * worlds/library/artwork/hirespeople/knight.xcf:
+       knight icon
+
+       * worlds/library/artwork/hirespeople/minstrel.xcf:
+       minstrel icon
+
+       * worlds/library/artwork/humanoids/deadknight.xcf:
+       animated armour icon
+
+2006-10-12  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/library/artwork/hirespeople/fatwoman.xcf:
+       fat woman sprite
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/library/artwork/hirespeople/lady.xcf:
+       lady sprite
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/library/artwork/hirespeople/cloackedf.xcf, worlds/library/artwork/hirespeople/rmage.xcf, worlds/library/artwork/hirespeople/rogue.xcf, worlds/library/artwork/hirespeople/roguef.xcf, worlds/library/artwork/hirespeople/xbowman.xcf:
+       more sprites
+
+2006-10-11  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/library/artwork/hirespeople/avatar.xcf, worlds/library/artwork/hirespeople/shopkeep.xcf, worlds/library/artwork/hirespeople/shopkeepf.xcf:
+       new: female shopkeeper, avatar
+       shopkeeper now uses mages body weight, instead of fighters
+
+2006-10-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/hirespeople.png, worlds/library/artwork/hirespeople/druid.xcf:
+       new druid icon
+
+       * worlds/haxima-1.002/hirespeople.png:
+       shepherd icon replaced
+
+       * worlds/haxima-1.002/hirespeople.png:
+       initial batch of highres people icons
+
+       * worlds/library/artwork/hirespeople/enchanter.xcf, worlds/library/artwork/hirespeople/fighter.xcf, worlds/library/artwork/hirespeople/generic.xcf, worlds/library/artwork/hirespeople/mage.xcf, worlds/library/artwork/hirespeople/necromancer.xcf, worlds/library/artwork/hirespeople/paladin.xcf, worlds/library/artwork/hirespeople/pikeman.xcf, worlds/library/artwork/hirespeople/ranger.xcf, worlds/library/artwork/hirespeople/shopkeep.xcf, worlds/library/artwork/hirespeople/silas.xcf, worlds/library/artwork/hirespeople/tinker.xcf, worlds/library/artwork/hirespeople/wanderer.xcf:
+       initial batch of highres icon working files
+
+       * worlds/library/artwork/hirespeople/shepherd.xcf:
+       shepherd icon
+
+2006-10-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/images.c, src/nazghul.c, src/screen.c:
+       Added a C source code XPM to provide a set of "emergency" ASII images. These
+       are used to display a crude error message in a window if nazghul encounters an
+       error during or before it can load the basic init script.
+
+2006-10-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/conv.c, src/conv.h, src/menus.c, src/sched.c, src/sched.h:
+       o Bugfix: the filename prompt from the Save Game menu allowed invalid and
+         undesirable characters for filenames
+       o Bugfix: t)alking to an NPC when hostiles present caused assert
+       o Bugfix: deleting a saved game with a non-existent save file caused assert
+       o Bugfix: entering '%' during conversation caused a crash
+       o Bugfix: entering '^' during conversation caused error messages and problems
+         with text colors
+
+2006-10-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/ctrl.c:
+       Improved fleeing by another notch. Fleeing NPC's in town or wilderness combat
+       now attempt to pathfind to the nearest edge. Failing that, they fall back on
+       evasion. Failing that, they fall back on fighting.
+
+2006-10-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.h, src/character.cpp, src/character.h, src/ctrl.c:
+       o Improved the algorithm used by NPCs to flee. It now uses the basic adaptvie
+         evasion algorithm where it tries to run away from current hostile
+         positions. If a fleeing NPC gets stuck it doesn't just sit there helplessly,
+         but will turn and fight. More improvements are planned.
+
+2006-10-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/sched.h:
+       o Bugfix: "angry townfolk wont move or attack past their assigned
+         locations, making them pretty much sitting ducks". If hostiles are present,
+         the schedule is ignored and the AI run instead.
+
+       * src/cmd.c, src/result.h, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/powers.scm:
+       o Added a new result code from spells: result-no-hostiles
+       o The area effect sleep spell now returns result-no-hostiles if there are none,
+         so the console can tell the player why his sleep spell has no effect in town.
+
+2006-09-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/astar.c, src/cmd.c:
+       o Pathfinding code now uses diagonals
+       o Made the '5' key on the keypad mean "select" in the movecursor function
+       o When buying/selling, reverted foogod window to show party gold instead of UI
+         hints
+
+       * src/character.cpp:
+       o Bugfix: t)alk auto-targeting broken. I don't think it was actually
+         broken. Anyway, I can't reproduce it now. But I did fix something similar:
+         when reloading a saved game NPC's are no longer teleported to the upper left
+         corner of their appointment rectangle if they are already in the
+         rectangle. Without this NPC's could get stacked on the same tile on reload,
+         making the auto-targeting appear to "stick" on a character when it was
+         actually cycling over the characters hidden below it.
+
+       * src/cmd.c:
+       Tying to cast non-existend spells results in a None Mixed! error, so player cannot guess at spells without mixing them
+
+       * src/cmd.c, worlds/haxima-1.002/scrolls.png, worlds/haxima-1.002/scrolls.scm:
+       Kernel changes:
+       o Bugfix: x)amine with x-ray no longer says "Can't see!"
+       
+       Haxima changes:
+       o Added a Wis An Ylem (x-ray) scroll and sprite.
+
+       * src/cmd.c, src/combat.c, src/menus.c:
+       o Bugfix: NPC's attacking on diagonal hit assert
+       o When showing saved game screen screen shots, moved the "SCREEN SHOT" text
+         higher so the center is visible.
+
+       * src/cmd.c, src/ctrl.c, src/menus.c:
+       o Added diagonal movement using number keypad.
+       o Made the '5' key on the keypad mean "select" in most menus.
+       o Bugfix: cmdwin prompts had extra '-' in camping command
+
+       * src/object.c:
+       o Workaround: for [SF 1564243], crash on reload. The root cause is improper
+         order of destruction of objects. A good fix would use reference counts to
+         control that, but implementing it would probably add lots of new bugs, so I'm
+         too chicken to do it right now. I've logged a feature request to address this
+         when I'm feeling more courageous (or when this workaround proves to be
+         insufficient).
+
+       * worlds/haxima-1.002/goblin-kingdoms.scm:
+       Added some corpses to troll's den
+
+2006-09-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c, src/status.c, src/status.h:
+       Page up/down and Home/end now work with the saved game menus and other string or generic lists
+
+       * src/nazghul.c:
+       When the game ends it falls back to the main menu.
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/goblin-kingdoms.scm:
+       o Bugfix: fireball spell was being cast on the caster, not the target
+       o Added more combatants to the Goblin Crossroads dungeon room battle
+       o Added loot chests to the Shamans Grove dungeon room
+
+       * worlds/haxima-1.002/ai.scm:
+       Removing some debug
+
+       * worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/start-new-game.scm:
+       Added more loot to Roland's cave
+
+2006-09-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c, src/status.c, src/status.h:
+       Added a delete command to the load/save menus so players can delete saved games they don't want anymore.
+
+       * src/menus.c:
+       N)ew Game is now always top on the Save Game menu, and current saved game is always next
+
+2006-09-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c, src/status.c, src/status.h:
+       Hacked-in hotkeys for the main menus
+
+2006-09-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am:
+       updated makefile
+
+2006-09-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/cmd.c, src/cmd.h, src/foogod.c, src/foogod.h, src/kern.c, src/menus.c:
+       The foogod window now has a hint mode, where it can show UI hints
+
+       * src/cmd.c:
+       Only one AP taken per mix command
+
+       * worlds/haxima-1.002/charset.png:
+       Added symbols for sideways arrows
+
+2006-09-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.c, src/map.h, src/menus.c, src/nazghul.c, src/play.c:
+       Saved-game screenshots implemented, not fully tested yet
+
+2006-09-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanters-tower-mech.scm, worlds/haxima-1.002/enchanters-tower.scm:
+       more wierdness for enchy's new lab
+
+       * worlds/haxima-1.002/enchanters-tower-mech.scm, worlds/haxima-1.002/enchanters-tower.scm:
+       Enchanters tower expanded
+
+       * worlds/haxima-1.002/tools.scm:
+       clocks are impassable
+
+       * worlds/haxima-1.002/tools.scm:
+       gems work with new spell system
+       added invisible object based wall
+
+2006-09-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/map.c, src/map.h, src/menus.c, src/screen.c, src/screen.h:
+       o Added screenCapture(), which will save some or all of the current screen to a
+         PNG file.
+       o Saved-game screenshots partially implemented. Saving a game creates a
+         screenshot of the map named after the save file. The screenshots aren't yet
+         shown in the load/save menus.
+
+2006-09-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/list.h, src/menus.c:
+       o Re-organized the code that handles saved games to use a struct.
+       o The saved games are now presented in order sorted by save time, youngest
+       first.
+
+       * src/menus.c, src/menus.h:
+       o Menus now cache the saved game list instead of re-evaluating the script every
+         time for the save/load menus.
+       o When a game is saved, the saved name becomes the new "current" game.
+       o The current game is always listed at the top of the load/save list and is
+         highlighted by default for quick access. Other saves continue to be listed in
+         timestamp order, oldest last.
+
+2006-09-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/powers.scm:
+       field spells have variable duration
+
+2006-09-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/cmd.c, src/kern.c, src/menus.c, src/status.c, src/status.h:
+       Generic and string lists now specify titles in the status UI
+
+       * src/menus.c:
+       The filename for the currently loaded game is marked with an '*' in the load and save menus.
+
+2006-09-21  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/object.c:
+       fixed crash due to my last "fix" using obj_dec_ref too often
+
+2006-09-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/MAP_HACKERS_GUIDE:
+       Added some basic map-editing instructions
+
+       * src/cmd.c, src/menus.c, src/nazghul.c:
+       Dates now added to save game menu
+
+       * src/dimensions.c, src/dimensions.h:
+       Bugfix: STAT_W was counting the frame boundaries
+
+       * src/menus.c:
+       Bugfix: after choosing from the Load Saved Game menu, it would repaint but your selection would have not data
+
+       * src/menus.c:
+       Added dates to the Load Saved Game menu options
+
+       * worlds/haxima-1.002/Makefile.am:
+       Bugfix: some new files missing in the install list
+
+       * worlds/haxima-1.002/scrolls.scm:
+       Temp hack to keep saved games working with old scroll names
+
+2006-09-20  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/clock.c, src/clock.h, src/status.c:
+       effects display allows remaining duration and unknown duration
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       spell cleanups
+
+       * worlds/haxima-1.002/effects.scm:
+       another attempt at a light spell
+
+2006-09-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/menus.c, src/menus.h, src/scheme.c:
+       Journey Onward now loads most recently saved game. Load Game lets the player pick from available saved games.
+
+2006-09-19  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/object.c:
+       fixed crash in ifc sense handling when cutscene deleted mech
+
+       * worlds/haxima-1.002/cast-ui.scm:
+       vas rel por reinstated
+
+2006-09-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/thiefs_den.scm, worlds/haxima-1.002/tooth.scm:
+       most spells debugged
+
+2006-09-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/adornments.png, worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/sprites.scm:
+       o Moved paper-doll staff (and glow) to arms.png
+       o Added paper-doll halberd
+
+2006-09-17  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       new spell- web
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/enchanters-tower.scm:
+       a spellbook for one of the new spells
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm:
+       spell bug fixes
+
+       * worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       book shelf object
+
+2006-09-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating ... level 8!
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating 7
+
+2006-09-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/MAP_HACKERS_GUIDE, src/kern.c, src/object.c, src/sprite.c, src/sprite.h, worlds/haxima-1.002/arms.scm:
+       Kernel changes:
+       o Added kern-sprite-blit-over to allow layered non-composite sprites.
+       0 Bugfix when reloading a game that involves type gobs.
+       
+       Haxima changes:
+       o Made the staff "ready" sprite be blitted instead of composite. This preserves
+         its glow effect across a ready/unready cycle.
+
+       * src/kern.c, src/sprite.c, src/sprite.h, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/species.scm:
+       Kernel changes:
+       o Added kern-sprite-strip-decorations to facilitate rebuilding decorated
+         sprites
+       
+       Haxima changes:
+       o Changed the slot ordering for species to follow the rendering order for paper
+         dolls.
+       o Fixed the ready/unready effect hooks to rebuild the character's sprite if it
+         supports a paper-doll.
+       o Modified the staff arms type to store the paper-doll staff sprite in the type
+         gob.
+
+       * src/kern.c, src/sprite.c, src/sprite.h:
+       Got rid of kern-sprite-tint; apply-matrix is better
+
+       * worlds/haxima-1.002/naz.scm:
+       Made a version of mk-composite-sprite which doesn't clone the base sprite
+
+2006-09-15  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating 6
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating 5
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating 4
+
+2006-09-14  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell updating
+
+       * worlds/haxima-1.002/sprites.scm:
+       fixed sprites off by one
+
+2006-09-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/MAP_HACKERS_GUIDE:
+       Cleaned up the introduction
+
+       * doc/MAP_HACKERS_GUIDE:
+       Added docs for kern-type-set/get-gob and comments about object types and gobs
+
+       * src/Party.cpp, src/character.cpp, src/closure.c, src/closure.h, src/ctrl.c, src/object.c, src/object.h, src/place.c:
+       o Object hooks now run with variable argument lists.
+
+       * src/character.cpp, src/kern.c, src/object.c, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/start-new-game.scm:
+       Kernel changes:
+       o Changed kern-obj-type-set/get-gob to kern-type-set/get-gob
+       o Added Scheme-to-kernel conversions for the ready/unready hook names
+       o Bugfix: character was using a bad format arg for runHook() call
+       
+       Haxima changes:
+       o Added a placeholder ready and unready effect that just print the equipment
+         name and the affected slot.
+
+       * src/character.cpp, src/kern.c, src/object.c:
+       o Character's now run the "ready" and "unready" hooks
+       o Added kern-obj-type-set/get-gob
+
+2006-09-12  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/tools.scm:
+       fixed mirror/clock pclass being lost on reload
+
+2006-09-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/closure.c, src/closure.h, src/object.c, src/object.h, src/sprite.c:
+       A few preliminary changes needed for the READY/UNREADY hooks
+
+       * src/scheme.c:
+       Fixed the 'mismatched parenthesis: -1' error emitted by scheme when a file ends in )
+
+2006-09-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/adornments.png, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/sprites.scm:
+       o Added a staff and a staff glow sprite for wizards.
+
+       * worlds/haxima-1.002/adornments.png, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       o Added some humanoid hair sprites.
+
+       * worlds/haxima-1.002/bodies.png, worlds/haxima-1.002/clothes.png, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm:
+       o Added two more frames to the body and the robe template sprites.
+       o Added a mantle sprite to wear over robes.
+
+2006-09-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/object.c, src/object.h, src/place.c, src/place.h:
+       first pass at detailed xamine
+
+       * src/kern.c:
+       added kern-stdout-msg to log to stdout
+
+       * src/object.c, src/object.h:
+       new standard ifc: 'sense' to detect all incoming/outgoing objects
+
+       * worlds/haxima-1.002/addons.png:
+       switch icon symetry fixed so they dont move when flipped
+
+       * worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       more spell sorting
+
+       * worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/tools.scm:
+       clocks xamineable
+
+       * worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/step.scm:
+       sense ifc scheme implementation
+
+       * worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       improved mirror
+
+2006-09-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/MAP_HACKERS_GUIDE:
+       Time to start updating this
+
+       * src/Missile.cpp, src/character.cpp, src/kern.c, src/object.c, src/sprite.c, src/sprite.h, worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/adornments.png, worlds/haxima-1.002/bodies.png, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/clothes.png, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/step.scm, worlds/haxima-1.002/tools.scm:
+       Kernel changes:
+       o Objects now save their custom sprites, if they have any, by generating a
+         kern-obj-set-sprite call.
+       o Objects now use a 'let' block when saving themselves.
+       o Cloned sprites now take an optional tag. If none is provided their tag is set
+         to NULL.
+       o Composite sprites now save themselves.
+       o Added kern-sprite-apply-matrix, which will apply a color-correction matrix to
+         a sprite in order to change its color scheme.
+       
+       Haxima changes:
+       o Calls to kern-sprite-clone update to pass the tag.
+       o Added 3 new sprite sets for paper doll development (bodies, adornments and
+         clothes).
+       o Added an example call to kern-sprite-apply-matrix which turns a gray robe
+         blue.
+       o The enchanter now uses a paper doll sprite.
+       o The sensor object now takes its target as a tag so it can save/reload.
+       o The mirror object now takes its background sprite as a tag so it can
+         save/reload properly.
+
+       * src/sprite.c, worlds/haxima-1.002/bodies.png, worlds/haxima-1.002/clothes.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/start-new-game.scm:
+       Kernel changes:
+       o Fixed a bug in sprite_apply_matrix. Only the first frame of multi-frame
+         sprites was being processed correctly. Also added some minor speed hacks.
+       
+       Haxima changes:
+       o Added another animation frame to the body and robe sprites.
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Oops. Didn't mean to check in this file on the last commit.
+
+2006-09-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/sprite.c:
+       o Tinted sprites now use caching to improve rendering speed.
+
+       * src/sprite.c:
+       Added sprite_new_internal() to pave the way for optimized tinted sprites
+
+       * src/sprite.c:
+       Fixed faded sprites to work with new RGBA images
+
+2006-09-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Missile.cpp, src/cmdwin.c, src/kern.c, src/map.c, src/nazghul.c, src/object.c, src/place.c, src/play.c, src/player.cpp, src/screen.c, src/sky.c, src/sprite.c, src/sprite.h, src/status.c, src/Attic/tile.c, src/vehicle.cpp:
+       o Cleanup: changed sprite API to consistently use underscores instead of
+         mixed-case.
+
+       * src/Party.cpp, src/character.cpp, src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c, src/place.c, src/player.cpp, src/session.c, src/sky.c, src/sprite.c, src/sprite.h, src/vehicle.cpp:
+       o Made the sprite definition hidden outside of sprite.c.
+       o Removed the cmdDumpPalette function as a result of the above. I don't think
+         anyone uses it anymore.
+
+       * src/sprite.c:
+       o Cleanup: removed obsolete references to palettized surfaces from sprite.c.
+
+2006-09-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/kern.c:
+       Added the a)ttack cursor movement shortcut keys to t)alk and targeted spells.
+
+       * src/kern.c, src/sprite.c, src/sprite.h:
+       Initial (and very inefficient) cut at sprite-tinting.
+
+       * worlds/haxima-1.002/spells.scm:
+       Bugfix in grav por
+
+2006-09-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/portals.scm:
+       Added many clocks
+
+       * worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/tools.scm:
+       New furniture- mirrors
+
+2006-08-31  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/tools.scm:
+       Broken clock available. Example at abandoned farm
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/cast-ui.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/powers.scm, worlds/haxima-1.002/spells.scm:
+       1st circle spells with split off ui and caster stats
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/tools.scm:
+       Clock faces show approximate time
+
+2006-08-30  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       clock icon v3
+
+2006-08-29  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/trigrave.scm:
+       A few clocks added to the world.
+
+       * worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       Not entirely happy with the icon yet, but heres a clock town feature
+
+2006-08-28  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/null.gif, doc/users_guide.html:
+       2nd pass at manual.
+
+       * doc/users_guide.html, scripts/tocinator.pl:
+       autogenerated table of contents for manual
+
+       * doc/users_guide.html:
+       Manual setup notes added as comment
+
+2006-08-27  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/users_guide.html:
+       First pass at html manual. Still a fair amount of cleaning up needed
+
+       * src/clock.c, src/clock.h, src/cmd.c:
+       at gives vague description rather than accurate time
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/shapes.png:
+       alpha tweaks
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/potions.png:
+       arms and potion sprites alphanated
+
+       * worlds/haxima-1.002/books.png, worlds/haxima-1.002/food.png, worlds/haxima-1.002/jewelry.png:
+       transparent shadows
+
+       * worlds/haxima-1.002/effects.png:
+       Global effects (timestop, quicken, antimagic) given effect icons
+
+       * worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       added an in-game clock
+
+2006-08-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/screen.c, worlds/haxima-1.002/charset.png:
+       Support for 32 bit-per-pixel colored text added to ascii.c. Screen
+       bits-per-pixel changed to 32, and charset.png updated to the 32 PNGA version.
+
+       * src/cmd.c:
+       Fixed a couple of bugs in X)amine caused by recent cursor-movement changes
+
+       * src/images.c:
+       Transparent blitting now works for images with an alpha channel.
+
+       * src/screen.c:
+       Hack to support scaling images with alpha channel.
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/books.png, worlds/haxima-1.002/food.png, worlds/haxima-1.002/jewelry.png, worlds/haxima-1.002/money.png, worlds/haxima-1.002/moons.png, worlds/haxima-1.002/newfolks.png, worlds/haxima-1.002/newmonst.png, worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/reagents.png, worlds/haxima-1.002/rune.png, worlds/haxima-1.002/runestones.png, worlds/haxima-1.002/scrolls.png, worlds/haxima-1.002/shapes.png, worlds/haxima-1.002/special.png, worlds/haxima-1.002/tools.png:
+       Updated images to John's RGBA versions
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/start-new-game.scm:
+       Moved max-health to game.scm so it will be defined even for saved games
+
+2006-08-26  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/combat.c, src/player.cpp:
+       characters at top of party list move first and are placed further into maps on entry
+
+2006-08-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/screen_dims.h:
+       Forgot to add a new file on my last
+
+       * src/ascii.h, src/cfg.c, src/cfg.h, src/character.cpp, src/cmd.c, src/cmd.h, src/ctrl.c, src/dimensions.c, src/kern.c, src/menus.c, src/menus.h, src/nazghul.c, src/sound.c, src/sound.h, src/status.c:
+       o Added a Settings menu to change the screen size and turn sound on and
+         off. This is accessible from the startup menu or via the F10 key.
+       o Changed the way the status browser handles generic list selection. Instead of
+         always switching to tall mode it sets its height based on the number of entries
+         in the list.
+
+2006-08-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/cmdwin.c:
+       cmdwin_vpush now +1 vs nullpointers
+
+2006-08-20  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/USERS_GUIDE, worlds/haxima-1.002/arms.scm:
+       all weapons bonusized
+
+       * scripts/blenddat.txt:
+       re-blending rivers was broken
+
+       * src/Arms.cpp, src/Arms.h, src/kern.c, worlds/haxima-1.002/arms.scm:
+       bonus modifiers shifted out to arms.scm
+
+       * src/Arms.cpp, src/Arms.h, src/character.cpp, src/character.h, src/ctrl.c:
+       Instead of using fixed bonus modifiers, combat now queries them from weapons (which use fixed bonus modifiers- sigh)
+
+       * worlds/haxima-1.002/arms.scm:
+       melee weapon bonuses set
+
+2006-08-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/Missile.cpp, src/Party.cpp, src/character.cpp, src/cmd.c, src/cmd.h, src/kern.c, src/object.c, src/player.cpp, src/vehicle.cpp, src/vehicle.h, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/prices.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       o You can now sink empty ships with cannons.
+       o You can sell surplus ships to Bart in Oparine.
+       o You can name your ship when you board. Unnamed deserted ships will disappear
+         from the map after some time has passed.
+       o Tweaked down the sea monster encounters. Monotonous.
+       o Temporary NPC parties weren't saving their time-to-live, so on reload they
+         were permanent, meaning they accumulated until the player encountered them.
+
+       * src/cmd.c:
+       Pressing a digit followed by the arrow key will make the cursor jump that distance when targeting
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c:
+       Added shortcut keys for moving attack cursor
+
+       * src/ctrl.c:
+       Targeting self for attack switches weapons
+
+2006-08-19  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp:
+       (x % 0) does nasty things to the system, so adding one to base attack/defense bonus.
+
+       * src/character.cpp:
+       groupExitTo calling closure_exec with NULL caused crash
+
+       * src/character.cpp, src/character.h, src/ctrl.c, src/kern.c, src/session.c, src/session.h, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/occs.scm:
+       First pass at stats affecting combat
+
+2006-08-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/cmd.c, src/cmdwin.c, src/cmdwin.h, src/conv.c, src/ctrl.c, src/kern.c, src/menus.c, src/player.cpp, src/status.c, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/jess.scm:
+       Re-wrote the cmdwin API and updated callers
+
+       * src/closure.c:
+       Another way to fix closure_exec(0)
+
+       * src/closure.c:
+       closure_exec() now coerces returned floating-point values to ints
+
+       * src/cmd.c, src/event.c, src/event.h:
+       Mouse targeting done
+
+       * src/cmd.c, src/event.c, src/map.c, src/map.h:
+       Initial hack at mouse targeting
+
+       * src/cmdwin.c:
+       cmdwin now right-justifies if string is too long to fit in window
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shapes.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Added dirt and gravel terrain
+
+       * worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/potions.png, worlds/haxima-1.002/potions.scm:
+       Added some potion sprites
+
+       * worlds/haxima-1.002/arms.scm:
+       Needs some polish, but I had to add Vial of Slimes before I forgot about it
+
+       * worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/tooth.scm:
+       Vials of slime
+
+2006-08-17  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm:
+       Ok, the fireball now mostly does what I want, but its awfally hacky
+
+2006-08-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/arms.scm:
+       first pass at more interesting fireball
+
+       * worlds/haxima-1.002/potions.scm:
+       missing '+' in stat potions
+
+2006-08-15  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h:
+       added kern-obj-inflict-damage- damage stuff with diplomatic and xp side effects
+
+       * src/cmd.c, src/player.cpp, src/player.h:
+       Equipment sort on R)eady occurs before and after selection, rather that interrupt the ui
+
+       * src/kern.c:
+       Added kern-init-random  reseed rng based on time till script starts
+
+       * src/status.c:
+       Ready listing shows available quantity of weapons, not total quantity
+
+       * worlds/haxima-1.002/ability.scm:
+       magic missiles gives xp/annoys target
+
+       * worlds/haxima-1.002/game.scm:
+       Reseeds rng on script start
+
+       * worlds/haxima-1.002/spells.scm:
+       Cleaned out some debugging stuff left in by accident
+
+2006-08-14  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/cmd.c:
+       Confirmation for quit without saving
+
+2006-08-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/cmd.c, src/cmdwin.c:
+       U)sed and R)eadied items get moved to the top of the inventory list
+
+2006-08-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/trigrave.scm:
+       fixed ai typo
+
+2006-08-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, worlds/haxima-1.002/books.scm:
+       Added the L)oiter command to the docs
+
+       * doc/USERS_GUIDE:
+       Updated section on status codes
+
+       * doc/USERS_GUIDE:
+       Fixed up the comments around saving and quitting
+
+       * src/Makefile.am, src/cmd.c, src/cmd.h, src/common.c, src/common.h, src/ctrl.c, src/file.c, src/file.h, src/images.c, src/menus.c, src/nazghul.c, src/scheme.c, src/session.c, src/sound.c:
+       Part 1 of some cleanup; consolidating file utility functions
+
+       * src/Makefile.am, src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c, src/menus.c, src/menus.h, src/nazghul.c, src/node.c, src/node.h, src/play.c, src/session.c, worlds/haxima-1.002/kern-init.scm:
+       Initial cut at multiple save games
+
+       * src/character.cpp, src/kern.c, worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/zane.scm:
+       Feature request filled: NPC's as light sources
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/cmd.h, src/ctrl.c, src/file.c, src/player.cpp, src/player.h:
+       Hacked in a L)oiter command to pass time
+
+       * src/cmd.c, src/file.c, src/file.h, src/menus.c, src/nazghul.c, src/play.c, src/scheme.c, src/scheme.h, src/session.c, src/session.h:
+       Cleanup 2: everyplace is now using the same common file access functions
+
+       * worlds/haxima-1.002/gamestart-mech.scm, worlds/haxima-1.002/gamestart.scm, worlds/haxima-1.002/moongate.scm, worlds/haxima-1.002/start-new-game.scm:
+       Bugfix: subtle bug when saving/reloading from the character creation room
+
+2006-08-12  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/occs.scm:
+       First pass at combat occ-abilities
+
+       * worlds/haxima-1.002/potions.scm:
+       Testing stuff enhanced
+
+2006-08-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/status.c:
+       Bug in ztats showing items in use
+
+       * worlds/haxima-1.002/Makefile.am:
+       Some new files needed to be added so they will get installed with make install
+
+2006-08-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/newfolks.png, worlds/haxima-1.002/shapes.png:
+       Fixed some of the more excessive graphics glitches (perforated paladins, pink rats, etc)
+
+2006-08-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/status.c:
+       character::getXpForLevel(1) now returns 0
+       creating characters with 0 xp now gives them min xp for their level
+       creating characters with -ve xp now gives them random xp appropriate for their level
+
+       * src/status.c:
+       XP and Lvl labels were on wrong screens
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/start-new-game.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/tetzl.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/thorald.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/warritrix.scm, worlds/haxima-1.002/zane.scm:
+       Megapatch no 2: Most characters have random appropriate xp. All characters start at max hp/mp
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/tetzl.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/trigrave.scm:
+       mega stats tweakage.  Not that the player will notice, but *I* will know that everyone hv unique stats
+
+2006-08-07  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp:
+       Character::setLevel now sets experience appropriate for the new level rather than the old one
+
+       * src/status.c:
+       Status window now reads HP:<hp> MP:<mp> XP:<level>(<+ percent>%)
+
+2006-08-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/status.c:
+       Changed XP to LVL
+
+2006-08-06  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/ascii.c, src/screen.c, src/screen.h:
+       Text uses muted versions of colours
+
+       * src/character.cpp:
+       isAttackTargetInRange(NULL)  now returns true
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/ctrl.c, src/kern.c, src/player.cpp, src/status.c:
+       arms and weapons enumerations in Character now use an external interation index (allows multiple simultaneous enumeration)
+
+       * src/effect.c, src/kern.c:
+       icon support added to kern-mk-effect
+
+       * src/images.c:
+       image load error to stderr not stdout
+
+       * worlds/haxima-1.002/cursor.png:
+       nicer blue spinner
+
+       * worlds/haxima-1.002/cursor.png:
+       placeholder cursor.png
+
+       * worlds/haxima-1.002/effects.png:
+       added paralysis
+
+       * worlds/haxima-1.002/effects.png:
+       first attempt at effect icons
+
+       * worlds/haxima-1.002/effects.scm:
+       effect spites use s_whatever instead of 's_whatever
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/sprites.scm:
+       most effects should now have icons
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       First few effect sprites set
+
+       * worlds/haxima-1.002/gamestart-mech.scm, worlds/haxima-1.002/gamestart.scm:
+       character creation area
+
+       * worlds/haxima-1.002/potions.scm:
+       some booster potions for rapid playtesting
+
+       * worlds/haxima-1.002/sprites.scm:
+       fixed incrementing tile_number in effect sprites
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       uses character creation area
+
+2006-08-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/effect.c, src/kern.c, src/status.c:
+       Comment/formatting changes only
+
+       * src/effect.h:
+       Added a field for a status icon to the effect struct
+
+       * src/kern.c, src/status.c:
+       Added effect icons to the party status viewer
+
+       * src/kern.c:
+       kern_mk_effect must load sprites as pointers (not closures) or it throws a type error
+
+       * src/status.c:
+       Status now uses a set of standardized colors
+
+       * src/status.c:
+       Replaced the status code with the effect icon in the ztats view of the character effects
+
+       * src/status.c:
+       Added mini-icons to the party view for readied weapons
+
+2006-08-05  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/spells.scm:
+       new spell: burning hands (bet flam hur)
+
+       * worlds/haxima-1.002/spells.scm:
+       wind spells now fire at arbitary angles
+
+2006-08-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am:
+       Removed frame.h
+
+2006-08-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/place.c, src/place.h:
+       Fixed player party members not pathfinding over step triggers
+
+       * src/character.cpp, src/player.cpp:
+       Starvation is now a bit more serious
+
+       * src/cmd.c:
+       Spells with a cost of 1 were not using any action points when cast
+
+       * worlds/haxima-1.002/moongate.scm:
+       Fixed the problem where destination moongates remained open
+
+       * worlds/haxima-1.002/nossifer.scm:
+       Made Nossifer immune to charm
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/start-new-game.scm:
+       Undead now immune to sleep and magic kill (in addition to fire, poison and disease)
+
+       * worlds/haxima-1.002/species.scm:
+       Increased the vision radius of sea creatures so they will close with the player on sea/land or sea/ship combat maps
+
+       * worlds/haxima-1.002/spells.scm:
+       Added success/failure messages to spells that use contest-of-skill
+
+2006-08-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       When a PC tries to step off the edge of a map the code checks for a neighboring
+       place before it checks for a parent (this is opposite of what it used to
+       be). This allows towns to have side-exits to dungeon rooms (or other towns).
+
+       * worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/bole.scm:
+       Fixed up Bill's conv to match the change in the dryad location
+
+       * worlds/haxima-1.002/bole.scm:
+       Moved the dryad in Bole to a separate place accessible via a side-exit from Bole
+
+2006-07-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/foogod.c, src/kern.c, src/play.c, src/player.cpp, src/player.h, src/session.c, src/session.h:
+       Fixed saving, loading and general behavior of the turn counter in the foogod window
+
+       * src/foogod.c:
+       Fixed a bug introduced with turn count changes; starting nazghul with no save game arg would cause a crash
+
+       * worlds/haxima-1.002/hackle.scm:
+       Fixed endless loop in Hackle's heal conversation when player alone
+
+       * worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/npc-types.scm:
+       Yellow slimes no longer divide into green slimes.
+
+2006-07-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.h, src/Party.cpp, src/dimensions.c, src/nazghul.c, src/status.c:
+       Small overhaul of the status viewer code. This includes a partial fix for SF
+       Bug: [ 1518735 ] ztats - AC, by adding armament stats to all the relevant
+       viewer windows.
+
+       * src/ascii.c, src/character.cpp, src/character.h, src/status.c, worlds/haxima-1.002/books.scm:
+       Removed AC from the status display. Modified the color-control syntax: ^c+=
+       pushes the current color but doesn't change it, ^c+<color-code> pushes the
+       current color and sets the new current color to <color-code>.
+
+       * src/ascii.c, src/ascii.h, src/ctrl.c, src/screen.c, src/screen.h, src/session.c, src/status.c, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/gregor.scm:
+       Added support for colorized text. A few places in the code and the game scripts
+       were tweaked to test and demonstrate usage.
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/ctrl.c, src/effect.c, src/effect.h, src/status.c, worlds/haxima-1.002/effects.scm:
+       More fiddling with the stat UI. It's getting downright chatty now.
+
+       * src/status.c:
+       Added species and occupation to character stat UI
+
+2006-07-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/common.h, src/event.c, src/nazghul.c, src/play.c, src/play.h, src/session.c:
+       Moved some more global variables into the new cfg env.
+
+       * src/common.h, src/dimensions.c, src/dimensions.h, src/nazghul.c, src/screen.c:
+       Cleaned up the SCREEN_BPP stuff. For now it's hard-coded to 16 in screen.c.
+
+       * src/dimensions.c, src/dimensions.h, src/nazghul.c:
+       Changed the -m (map size) option to -r (screen res). dimensions.c now converts
+       the desired screen res to a map size that will accomodate it.
+
+2006-07-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/nazghul.c, src/session.c, worlds/haxima-1.002/bakup.scm, worlds/haxima-1.002/kern-init.scm:
+       Moved more stuff to the new cfg
+
+2006-07-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/ascii.c, src/ascii.h, src/cfg.c, src/cfg.h, src/cmdwin.c, src/common.h, src/foogod.c, src/images.c, src/kern.c, src/nazghul.c, src/scheme.c, src/screen.c, src/screen.h, src/session.c, src/session.h, src/sound.c, worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/kern-init.scm, worlds/haxima-1.002/moongate.scm:
+       This adds support for a general kernel initialization script. Early in startup,
+       right after parsing the command-line args, the kernel will attempt to load
+       INCLUDE_DIR/"kern-init.scm" to initialize itself enough to present the main
+       menu. This is done through the new kern-set-cfg/kern-get-cfg procedure calls,
+       and the new cfg.[ch] module, which basically provides a setenv/getenv-type
+       feature. Currently only a couple of values are in kern-init.scm, but I hope to
+       migrate more currently-hard-coded stuff out there in the days ahead. Beyond
+       that, the ability to load/save an options.scm file will enable us to have
+       persistent user options (eg, map viewer size and sound settings).
+
+       * src/nazghul.c, worlds/haxima-1.002/Makefile.am:
+       Had to add some files to the install process; fixed a warning about the missing init script
+
+2006-07-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/spells.scm:
+       spells updated to use occ abilities
+
+2006-07-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/scheme.h:
+       USE_TRACING should be off by default; must have committed it by mistake
+
+       * src/status.c, src/vmask.c:
+       Minor indentation and comment cleanup
+
+2006-07-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE:
+       Added a note about food consumption
+
+       * doc/USERS_GUIDE:
+       Added info on effects and an appendix for weapons and armor spoilers to the user's guide
+
+       * src/angband.c:
+       Fixed the LOS bugs related to map viewer sizes < 19x19
+
+       * src/map.c:
+       Minor comment cleanup
+
+       * worlds/haxima-1.002/arms.scm:
+       Melee and projectile weapons were adding an armor bonus instead of a deflection bonus
+
+2006-07-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/nazghul.c:
+       The show-all-terrain option was missing from the -h(elp) command option
+
+2006-07-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Party.cpp, src/common.c, src/common.h, src/console.c, src/dimensions.c, src/dimensions.h, src/map.c, src/nazghul.c, src/sky.c, src/status.c, src/status.h, src/vmask.h:
+       Just committed a CVS change to allow a smaller UI. In common.h, uncomment the
+       
+       //#define CONFIG_11X11_MAP
+       
+       line, recompile, and the screen will be 736x400. I've only done some limited
+       testing but things look surprisingly good. There might be a line-of-sight bug
+       and the splash screen needs some tweaks. Need to test some more and figure out
+       how to do this automatically and dynamically so rebuilds aren't required. By
+       reducing the console width from 42 to 30 characters the screen could be
+       640x400, which will satisfy the 640x480 crowd at least.
+
+2006-07-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/common.h, src/screen.c:
+       Smaller UI. In common.h, uncomment the
+       
+       //#define CONFIG_11X11_MAP
+       
+       line, recompile, and the screen will be 736x400.
+
+2006-07-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h:
+       Patch from Eero Tamminen for link error under Suse 9.1
+
+2006-07-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c:
+       added kern-get-total-minutes for numeric clock access
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/spells.scm:
+       circle 1 spells based on character abilities
+
+       * worlds/haxima-1.002/occs.scm:
+       fixed problem with getting abilities for chars without occs
+
+       * worlds/haxima-1.002/roland.scm:
+       roland now a warrior
+
+2006-07-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/zane.scm:
+       Brought Shroom's prices inline with other reagent-sellers; reduced prices on more expensive reagents with all sellers
+
+2006-07-03  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/play.c:
+       synchs place to reset sleepers on reload
+
+       * worlds/haxima-1.002/effects.scm:
+       sleep effect reactivates on reload
+
+       * worlds/haxima-1.002/effects.scm:
+       spawned off slimes are less powerful than thier 'parent's
+
+2006-07-02  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/mouse.scm:
+       Thud had escaped down the wrong branch of an if/else. Now recaptured. Also, now goes beserk back in town if not present (or is this too evil?) Note that this file still crashes if t or k are dead
+
+2006-07-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Fix for kern-char-leave-player where kchar is not in party; call is benignly ignored
+
+       * worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/moongate.scm, worlds/haxima-1.002/mouse.scm:
+       Cleaned up logic in mouse.scm. Modified kathryn.scm such that if Kathryn joins,
+       and Thud is alive, then Thud automatically joins. This simplifies some of the
+       logic in mouse.scm.
+
+2006-07-01  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/kern.c, src/occ.c, src/occ.h:
+       added gob facilities to occupations
+
+       * worlds/haxima-1.002/occs.scm:
+       occ data for magical ability (theyre just meaningless numbers till the spells get revamped tho)
+
+       * worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/tools.scm:
+       lockpicking based on occ gobs
+
+2006-07-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/map.c, src/map.h:
+       bugfix for [ 1475928 ]: look works in complete darkness. Using the lightmap, if
+       no light is hitting a tile then x)amine won't report it. Changed the wording of
+       x)amine to say "can't see!" regardless if the reason is out-of-LOS or too dark.
+
+       * src/occ.c:
+       Occ destructor deletes its optional gob
+
+       * src/play.c:
+        bugfix for [ 1475929 ]: sleeping npcs wake on reloads
+
+       * worlds/haxima-1.002/spells.scm:
+       The big list of spells doesn't need to be permanent once it's registered in the kernel; takes up memory, slows down gc, etc
+
+2006-06-30  Roberto Amorim  <wolfoxbr@localhost.localdomain>
+
+       * scripts/nazghul.iss:
+       Adding the Inno Setup script file used to generate the Windows installer
+
+2006-06-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS, ChangeLog, NEWS:
+       Final changes before 0.5.4 release
+
+       * doc/USERS_GUIDE:
+       Minor change to save/load notes
+
+       * scripts/RELEASE_CHECKOFF:
+       Added another note
+
+2006-06-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c:
+       Added kern-char-is-dead?
+
+       * src/player.cpp:
+       Dead party members were eating rations
+
+       * worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/zane.scm:
+       o Reduced reagent prices
+       o Bugfix: Angriss would accept dead party members, caused a crash
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm:
+       o Slime attacks increased slightly.
+       o NPC party generator, when determining how big to make the NPC party, doesn't
+         count dead member's as part of the player party size count
+       o Gazers given fangs as a natural weapon (instead of nothing)
+
+       * worlds/haxima-1.002/game.scm:
+       Renamed a variable
+
+2006-06-28  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/mouse.scm:
+       stray bracket removed
+
+2006-06-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac:
+       Bumped the version number
+
+       * src/map.c:
+       Put the clock display back on the map viewer since there is no other way to tell time yet in haxima
+
+       * src/player.cpp:
+       Camping in town took more time than player specified
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/ilya.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/zones.scm:
+       o Necromancer used generic response when asked about himself.
+       o People in Glasdrin couldn't give directions to Glasdrin.
+       o Ilya and Gregor were eating in the ULC of the kitchen. Gregor lacked a
+         complete schedule.
+       o Dropped sling damage by a point.
+
+       * worlds/haxima-1.002/mouse.scm:
+       Thud was not getting removed if he was dead but Kathryn was alive
+
+       * worlds/haxima-1.002/naz.scm:
+       Fixed the set-level procedure to simply call kern-char-set-level. It was trying
+       to set the hp and mp, too, but doing it incorrectly by not accounting for
+       custom mp and hp bonuses. This causes the Wanderer to start with 11/41 hit
+       points, making him wolf-meat.
+
+2006-06-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * nazghul.nsi, nazinst.ico:
+       upgraded w32 installer
+
+       * scripts/nazghulrun.au3:
+       compilable version of w32 save file backup script
+
+2006-06-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/closure.c, src/event.c, src/kern.c, src/opdefines.h, src/scheme-private.h, src/scheme.c, src/scheme.h, src/session.c, src/session.h:
+       Reverted scheme interpreter to previous version (w/o garbage collector
+       changes). I don't want to change something fundamental like the garbage
+       collector so soon before a release, and I want to do it differently anyway.
+
+       * worlds/haxima-1.002/Makefile.am:
+       Added some missing files to Makefile.am.
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Added sludge terrain. I think we need some sludge.
+
+2006-06-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/factions.h:
+       Quick fix for bug 1462932: checks for same faction in harm_relations.
+       make_hostile isnt given a similar check since that is only used in party-party attacks (and hence not player triggerable)
+
+2006-06-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/character.cpp, src/closure.c, src/event.c, src/kern.c, src/opdefines.h, src/play.c, src/scheme-private.h, src/scheme.c, src/scheme.h, src/session.c, src/session.h:
+       Fixing [ 1451252 ] Followers get stuck in follow mode. character::move now
+       checks for PC's trying to spin in follow mode. character::exec now passes the
+       flag to ignore companions to the pathfinding routine; I think it used to do
+       this and removing it was an early (bad) attempt to fix this bug.
+       
+       Also updating the Scheme garbage collector to use a new algorithm with less
+       latency.
+
+       * src/character.cpp:
+       Fixing [ 1460699 ] kama wanders while sleeping. In character::exec() it now
+       checks for sleeping as an activity like eating and doesn't move.
+
+2006-05-28  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/cmd.c:
+       No longer allows (and crashes on) diagonal wilderness (a)ttacks
+
+       * worlds/haxima-1.002/ai.scm:
+       the kraken ai needed to default to the kernel mode in a few more cases
+
+       * worlds/haxima-1.002/game.scm:
+       Added pclass-waterboulder, for boulders embedded in water terrain
+
+2006-04-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/blenddat.txt, scripts/palette.txt:
+       new terrains in terrain blending scripts
+
+       * src/kern.c:
+       mechanisms to retrieve unmodified stats added
+
+       * worlds/haxima-1.002/ai.scm:
+       kraken will now default to kernel ai if no targets visible (rather than just sitting there)
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/signs.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       a few new terrains: signs for character creation + new boulders
+
+       * worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/slimy-cavern.scm:
+       added boulders-in-water to maps
+
+       * worlds/haxima-1.002/tools.scm:
+       dex helps pick locks
+
+2006-04-17  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ai.scm:
+       Fix for: krakens poisoning themselves on swamps and chomping decks players are standing on
+
+2006-04-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ai.scm:
+       Fixing krakens to not pursue invisible foes
+
+2006-04-14  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/cmd.c, src/conv.c, src/conv.h:
+       The kern-conv-get-reply and kern-conv-get-string commands now use
+       our isprintable check
+
+2006-04-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c:
+       read/write access to character str/dex/int
+
+2006-04-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/blenddat.txt, scripts/blendmap.pl, scripts/palette.txt:
+       More terrain blending working. (Ongoing tweaks while blending new maps)
+
+       * scripts/blendmap.pl:
+       Documentation is your friend. It reduces the next person to use your softwares desire to murder you brutally
+
+       * worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/dank-cave.scm, worlds/haxima-1.002/eastpass.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/lich-tomb.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/talking-ankh.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/void-temple.scm, worlds/haxima-1.002/westpass.scm:
+       Maps use blended terrains
+
+       * worlds/haxima-1.002/blendterrains.scm, worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Support for blended terrains
+
+2006-04-09  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/blenddat.txt, scripts/blendmap.pl, scripts/unblenddat.txt:
+       Blending much more advanced and now handles most terrain types
+
+       * scripts/blendmap.pl:
+       Updated the help somewhat
+
+2006-04-05  Kris Parker  <kaypy@localhost.localdomain>
+
+       * doc/USERS_GUIDE:
+       Fixed ingredients in 'Mix' tutorial, and made it a better fit to the actual game interface
+
+       * worlds/haxima-1.002/conv.scm:
+       Typo in basic-engi
+
+2006-03-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/character.cpp:
+       Bugfix: followers get stuck in follow mode. They were switching places with one
+       another over and over in an attempt to reach the party leader. The option to
+       ignore companions is a flag passed to the pathfinding algorithm, in the case of
+       follow mode I no longer pass that flag, so followers will pathfind around one
+       another instead of switching places.
+
+2006-03-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/conv.c:
+       Bugfix: [1451180] Shift key adds letters in conversation
+       
+       The new isprintable(char c) function which replaced libc's isprint was declared to
+       take a char arg. Some values like 304 (the value for the left shift key on my system),
+       when downcast to 8 bits, fell into the 32-127 range and were declared
+       printable. Fixed this by changing to isprintable(int c).
+
+2006-03-23  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/blenddat.txt, scripts/blendmap.pl:
+       Blends more terrain types
+
+2006-03-22  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/blenddat.txt, scripts/blendmap.pl, scripts/splitmap.pl:
+       New toys: pre-rendered terrain blending, and splitting large maps down to tiles for composites
+
+       * worlds/haxima-1.002/shard.scm:
+       Added mountains south of eastpass
+
+2006-03-21  Kris Parker  <kaypy@localhost.localdomain>
+
+       * scripts/maptoxpm.pl, scripts/mergemap.pl, scripts/xpmtomap.pl:
+       Added some map editting scripts
+
+       * scripts/palette.txt:
+       Belatedly added palette data for map scripts
+
+2006-03-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Bugfix: wait on NPC bed (awake), when NPC tries to kick you out of bed we get
+       an assert because the player is not sleeping. Fixed this by having the NPC
+       check that the player is asleep first. Otherwise it waits for the player to
+       leave.
+
+2006-03-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/ilya.scm:
+       Ilya now gives correct directions to farm
+
+       * worlds/haxima-1.002/ini.scm:
+       Gave ini appropriate xp for level
+
+       * worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/zones.scm:
+       Jake&Percival no longer sleepwalk
+
+       * worlds/haxima-1.002/mesmeme.scm:
+       Mesmeme can now be asked to leave
+
+2006-03-16  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/endless-deeps.scm, worlds/haxima-1.002/trigrave.scm:
+       Dragon quest rune is now in Kurpolis deeps
+
+       * worlds/haxima-1.002/amy.scm:
+       Amy mentioned the accursed, but didnt provide any information on them. Now you get some gossip.
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/lever.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/sprites.scm:
+       Hidden lever now searchable
+
+       * worlds/haxima-1.002/terrains.scm:
+       Less specific water naming
+
+2006-03-14  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/gen.scm:
+       Gen now has appropriate xp for his level
+
+2006-03-13  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm:
+       Alchemist remembers completed quests
+
+2006-03-12  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/start-new-game.scm:
+       Linked in endless deeps level
+
+       * worlds/haxima-1.002/r2a_mech.scm, worlds/haxima-1.002/road_to_absalot.scm:
+       road to absalot now works after save/reload (oops)
+
+2006-03-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/warritrix.scm:
+       Fixed up the Warritrix's conversation
+
+2006-03-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/common.h, src/nazghul.c, src/play.c, src/screen.c, src/status.c:
+       Some minor cleanup, and a fix for the status display, which wasn't showing a
+       title on startup.
+
+       * src/kern.c:
+       Composite maps were not getting blended. It's not sufficient to blend the
+       sub-maps, because they're edges aren't blended and it makes their seams visible
+       in the composite map.
+
+2006-03-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/object.c:
+       Workaround for [ 1114054 ] messages for off-screen NPC's getting printed:
+       While the pathfinding code attempts to handle a mechanism it disables console
+       messages. This prevents mechanism scripts from printing to the console when
+       NPC's handle them during normal pathfinding.
+
+2006-03-08  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm:
+       Added more critters to the deeps
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm:
+       New random templates: lava and swamp
+
+       * worlds/haxima-1.002/endless-deeps-mech.scm, worlds/haxima-1.002/endless-deeps.scm:
+       Initial upload of third garrison and endless deeps
+
+       * worlds/haxima-1.002/joel.scm:
+       Joel still had the old paladins in the tunnel plot.
+
+2006-03-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       If the player handles a nameless mech the console prints "Fyodor handles a
+       hidden mechanism". Ie, nameless is assumed to mean "hidden". A hack, so if the
+       assumption becomes unwieldy we'll have to add some more support for different
+       types of "hidden-ness".
+
+2006-03-07  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/keep.scm:
+       Alternative treasure room access
+
+2006-03-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       [ 1437442 ] t)alk targets invisible people.
+       
+       Now it doesn't.
+
+       * worlds/haxima-1.002/abigail.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/lever.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/zones.scm:
+       Fix for [ 1434216 ] where's abigail?
+       
+       Added Abigail character.
+
+2006-03-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/blender.h, src/combat.c, src/kern.c:
+       The terrain blenders are now run on automatically-generated combat maps.
+
+       * src/play.c, src/session.c, src/wind.c, src/wind.h:
+       Fix for [ 1429543 ] wind not updated on load
+       
+       session_load() now calls windRepaint(). Also, added windSave() since I noticed
+       that the wind direction was not getting saved. session_save() now calls it.
+
+       * worlds/haxima-1.002/combat-maps.scm:
+       Fix for [ 1431953 ] bad default combat map with blended terrain
+       
+       The case for all existing blended terrains has been fixed by assigning a combat
+       map to each of them. This will have to be done for all future blended terrains
+       as well as they are added.
+
+2006-02-25  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/spells.scm:
+       Fix for invisibility spells not using up scrolls (they probaby didnt use reagents either)
+
+2006-02-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.h, src/player.cpp, src/player.h:
+       Fix for [ 1429541 ] extra ship on town entry
+       
+       Added a check to see if the player was in a vehicle when trying to move onto a
+       subplace. If so, denied.
+
+       * worlds/haxima-1.002/alchemist.scm:
+       A few stylistic tweaks to Alchemist's conv
+
+       * worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Restoring a few things that were accidentally removed
+
+2006-02-24  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Added path through road to absalot to match Alchemists lich quest
+
+2006-02-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Fix for [ 1425039 ] Solo mode + possession = lockup
+       
+       The charm works by setting a being's current faction to the
+       caster's. Character::setCurrentFaction() already checks if the character is a
+       party member, I added another check to see if the character was in solo mode,
+       and if so to set the party mode to follow.
+       
+       Also found a bug where unreadyAll() was calling
+       player_party->unrefInventoryObject(arms) after unready() already did, causing
+       some oddities in the player inventory.
+
+2006-02-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/place.c:
+       Turning off some noise debug
+
+       * src/place.c:
+       Fix for 1425025: abuse of party moded + save game.
+       
+       Fixed this by addressing the order in which objects are saved in the current
+       place. Previously, they were saved by tile order, so in addition to what the
+       bug report noted you could get some other odd things. Now, they're saved in
+       turn list order, and the current object is always saved at the head of the
+       list. This ensures that on reload the object which saved the game begins the
+       turn order and the place then continues executing objects in the original
+       order.
+
+2006-02-18  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/spells.scm:
+       Blink spells now only work withing LOS
+
+       * worlds/haxima-1.002/spells.scm:
+       Blink spells will no longer transport the caster onto an impassable terrain
+
+2006-02-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Aborting a spell should not cost mana
+
+2006-02-17  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/engineer.scm:
+       Quests now require component quantities as in the voidship plans.
+       TODO: grammer on 'we still need X' messages needs work
+
+2006-02-17  Janne Johansson  <icepic@localhost.localdomain>
+
+       * src/ascii.c:
+       uninitialized nitpickings. shuts gcc4 up
+
+2006-02-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c:
+       Got rid of some dead code I noticed thanks to Janne's last patch
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm:
+       Demons (and Nossifer) now immune to kill spell
+
+       * worlds/haxima-1.002/nossifer.scm:
+       Fix for 1425031: spelling/grammer errors in nossifer.scm. Fixed as suggested.
+
+2006-02-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF, src/Being.cpp, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/ctrl.c, src/event.c, src/kern.c, src/object.c, src/object.h, src/species.c, src/species.h, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/species.scm:
+       Fix for bug [ 1423898 ]: immobile critters. Critters like dryads and hydras are
+       supposed to be stationary. Early efforts to make this happen using the movement
+       modes and passability masks didn't work, so I did it in their AI's. But this
+       allowed their NPC parties to move on the map. With this change a species may
+       have a "stationary" flag. Any member of that species, and any party which
+       contains a living member of that species, will not move on the map, although
+       they will attack the player normally.
+
+2006-02-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Fix for 1421524: abuse of solo mode/rendezvous. If hostiles are around, solo
+       mode party member's no longer instantly pathfind to the party leader when the
+       player enters Follow mode.
+
+       * src/closure.c, src/map.c, src/scheme.c, src/tick.c, src/tick.h:
+       Changes for 64bit compilation based on Jason Tibbs patch
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Fix for 1423370: fire slimes divide into green slimes. Changed the slime-split
+       effect to be a generic split effect. It now has its own gob which specifies the
+       npc type tag to use to create the clone. Had to modify the generic npc
+       constructor in npc-types.scm to expect some effects to specify a gob ctor and
+       parms.
+
+2006-02-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/place.c, src/play.c:
+       Added a performance optimization: the pathfinding algorithm now makes a quick
+       check to see if the target is surrounded by impassible terrain. If so, it
+       aborts early. Makes all the difference for cases like sea creatures trying to
+       pathfind to the player party in the middle of dry land.
+
+2006-02-11  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/newterrain.png:
+       Added corner pieces for light forest. Also some plains corners without the shore effect
+
+2006-02-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/event.c, src/event.h, src/nazghul.c:
+       Fixed missing keystrokes by adding a backlog queue in event.c. Not the dramatic improvement I was hoping for, unfortunately.
+
+       * worlds/haxima-1.002/effects.scm:
+       Bomb traps no longer self-destrruct
+
+       * worlds/haxima-1.002/kama.scm:
+       After joining once, Kama gives coords to Angriss in response to RUKA
+
+2006-02-10  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/newterrain.png:
+       Added:
+       High resolution mountains & forests
+       Hill edge effects for blended terrain
+
+       * worlds/haxima-1.002/sprites.scm:
+       Added sprite definitions for hires mountains/forest
+
+       * worlds/haxima-1.002/tools.png:
+       Updated sextant
+
+2006-02-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       Added a sextant
+
+2006-02-09  Kris Parker  <kaypy@localhost.localdomain>
+
+       * worlds/haxima-1.002/rune.png:
+       Uploaded 'Etched' look for runic sign text
+
+2006-02-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/spells.scm:
+       Removed LAT and LONG from in-wis verbage, as Tristan points out these are backwards
+
+2006-02-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Missile.cpp, src/kern.c, src/object.c, src/terrain_map.c, src/terrain_map.h:
+       Arrows on the ground were spinning whenever anyone shot an arrow; similar for other ammo types
+
+       * src/kern.c, src/session.c, src/session.h:
+       Added kern-mk-blender, creates a terrain blender which is automatically applied to all maps as they are created
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/hidden.scm, worlds/haxima-1.002/newterrain.png, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm:
+       Searching for the S rune revealed it, but the player couldn't see it and might assume that searching for it put it in his inventory. This change adds the notion of a 'hidden' object which, when searched, becomes a normal visible object. This is done via a wrapper object which responds to the 'search' signal by creating the hidden object.
+
+       * worlds/haxima-1.002/green-tower.scm:
+       Moved the lever in GT
+
+       * worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm:
+       Converted kern-terrain-map blend calls to kern-mk-blender
+
+2006-02-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/terrain_map.c, src/terrain_map.h:
+       Added kern-terrain-map-blend
+
+       * src/kern.c, src/sprite.c, src/sprite.h:
+       Added ability to 'decorate' sprites with other sprites, making layered sprites
+
+       * worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm:
+       Blending shard and gregor's hut maps
+
+       * worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Added some shore sprites and shore terrains based on Kris Parker's work
+
+       * worlds/haxima-1.002/newterrain.png:
+       Terrain pieces
+
+2006-02-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS, BUGS, ChangeLog, INSTALL, NEWS, configure.ac, scripts/RELEASE_CHECKOFF:
+       Preparing for 0.5.3 release
+
+       * INSTALL:
+       Updated instructions on running the game
+
+       * doc/USERS_GUIDE:
+       Updated for new install
+
+       * src/combat.c, src/kern.c, src/place.c, src/place.h, src/session.c, src/terrain_map.c, src/terrain_map.h:
+       Added ref counting for terrain maps
+
+       * src/kern.c, src/place.c, src/place.h:
+       Added kern-place-set/get-terrain-map
+
+       * worlds/haxima-1.002/Makefile.am:
+       Wrong filename
+
+       * worlds/haxima-1.002/effects.scm:
+       Bugfix from Bernhard Link: faction-wood-spider is nowehere defined, use faction-spider
+
+2006-02-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/player.cpp, src/player.h:
+       Bugfix: if the script called kern-char-unready on a PC it would mess up the player party inventory counts, could cause an assert in status.c
+
+       * worlds/haxima-1.002/Makefile.am, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/tower.png:
+       Added Kris Parker's new tower sprite and the activated altar sprite
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       Bugfix: hydra's weren't appearing on wilderness combat maps
+
+       * worlds/haxima-1.002/arms.scm:
+       Balance: fireballs no longer drop fire fields where they hit
+
+       * worlds/haxima-1.002/engineer.scm:
+       Fixed typo
+
+       * worlds/haxima-1.002/newmonst.png, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprites.scm:
+       Added Kris Parker's new gint mage sprite
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm:
+       Fixed dragons, hydras and lichs to drop blood using normal drop; prevents them from dropping on the wilderness
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Kris Parker's change: add loot to accursed npc types
+
+       * worlds/haxima-1.002/shard.scm:
+       Changed Fens to use shallow water to keep out the pirate ships from getting spawned
+
+2006-02-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/nazghul.c:
+       Added -I and -G to the command-line help
+
+       * src/nazghul.c, worlds/haxima-1.002/Makefile.am:
+       Removed hard-coded haxima.scm from the kernel. It now assumes the more generic start-new-game.scm is the file to load to start a new game
+
+       * worlds/haxima-1.002/Attic/haxima.scm:
+       Moved from here
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Accursed Templar should use human knight sprite
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spider.scm:
+       o Spiders were still dropping loot in wilderness, converted them to use
+         standard loot-drop which fixes this
+       o Fire slimes were supposed to drop flaming oils as loot, fixed that
+
+       * worlds/haxima-1.002/start-new-game.scm:
+       Replacement for haxima.scm
+
+       * worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/zones.scm:
+       Fixed Gregor and Tooth's sleeping locations
+
+2006-02-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS, BUGS, ChangeLog, NEWS:
+       *** empty log message ***
+
+       * Makefile.am, Attic/PRESS_RELEASE, m4/Makefile.am, src/Makefile.am, worlds/Makefile.am, worlds/haxima-1.002/Makefile.am:
+       Bernhard Link's patch to add maintainer-clean as a target to the makefiles
+
+       * autogen.sh, configure.ac:
+       Bernhard Link's configure patch
+
+       * nazghul.nsi:
+       Windows installer will bundle .bat files
+
+       * scripts/RELEASE_CHECKOFF:
+       Updates made on last release
+
+       * src/cmdwin.c, src/console.c, src/nazghul.c:
+       Bernhard Link's debug patch to create .console and .cmdwin iff DEBUG is defined
+
+       * src/common.c, src/common.h, src/images.c, src/nazghul.c, src/scheme.c, src/session.c, src/sound.c, worlds/haxima-1.002/Makefile.am:
+       Bernhard Link's patch to add -I and -G options
+
+       * src/nazghul.c:
+       Bernhard Link's usage patch
+
+       * src/play.c, src/sky.c:
+       Last submit broke new game startup; also previous eclipse code made new game startup all dark (which looks really cool, but was wrong)
+
+       * src/play.c:
+       Bugfix: nazghul junk (where junk was not a valid load file) caused a segfault
+
+       * worlds/haxima-1.002/Makefile.am:
+       Install newfolks.png
+
+       * worlds/haxima-1.002/Makefile.am:
+       Bernhard Link's patch: don't install Makefile.am, do install newmonst.png
+
+       * worlds/haxima-1.002/ability.scm:
+       Disarm now drops the target's weapon on the ground at his feet
+
+2006-02-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * nazghul.nsi:
+       Nullsoft installer script for windows
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/cmd.c, src/cmd.h, src/combat.c, src/ctrl.c, src/event.c, src/foogod.c, src/kern.c, src/nazghul.c, src/place.c, src/play.c, src/sky.c:
+       G)et now always scoops up everything
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/potions.scm:
+       Misc bugfixes
+
+       * worlds/haxima-1.002/newfolks.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       Adding Kris Parker's new player character sprites
+
+2006-01-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/kama.scm:
+       Bugfix: ask Kama to rejoin after he leaves and he just points at the door
+
+       * worlds/haxima-1.002/roland.scm:
+       Bugfix: after leaving, Roland couldn't rejoin
+
+2006-01-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS:
+       Recorded new sprites from Kris Parker
+
+       * worlds/haxima-1.002/arms.scm:
+       Tweaked armour defense
+
+       * worlds/haxima-1.002/chester.scm:
+       Bumped price of plate
+
+       * worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/newmonst.png, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       Added Kris Parker's new goblin sprites
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Bugfix: troll loot not using tags
+
+       * worlds/haxima-1.002/shroom.scm:
+       Typo in conv
+
+2006-01-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/object.c, src/object.h:
+       Adding better support for irregular plural names
+
+       * src/object.c:
+       Takes care of a few more plural name cases
+
+       * src/sky.c, src/sky.h:
+       Added eclipse
+
+       * worlds/haxima-1.002/food.scm:
+       Fixed plural food names
+
+       * worlds/haxima-1.002/Attic/haxima.scm:
+       Kris Parker's improved astronomy
+
+       * worlds/haxima-1.002/money.scm:
+       Using singular name for coin
+
+       * worlds/haxima-1.002/moons.png:
+       New transparent moon sprites
+
+       * worlds/haxima-1.002/naz.scm:
+       Drunken staggering checks for an occupant
+
+2006-01-27  Janne Johansson  <icepic@localhost.localdomain>
+
+       * src/terrain_map.c:
+       no sub-optimizations, just the fix. Sorry for borking my first few commits
+
+       * src/terrain_map.c:
+       merging two types of fixes isn't good. sorry for the bad commit
+
+       * src/terrain_map.c:
+       remove warning about possible use of h2,w2 initialized
+
+2006-01-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Attic/haxima.scm:
+       Implemented Kris Parker's recommended changes to the opening sequence in the moongate clearing
+
+       * worlds/haxima-1.002/moongate.scm:
+       Increasing the brightness of moongates
+
+       * worlds/haxima-1.002/roland.scm:
+       Roland now uses the human knight sprite
+
+2006-01-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * ChangeLog, NEWS, scripts/RELEASE_CHECKOFF:
+       *** empty log message ***
+
+       * src/nazghul.c:
+       Added Janne to the credits for his patches
+
+       * worlds/haxima-1.002/Makefile.am:
+       Added some missing files to the list
+
+2006-01-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS:
+       Updated AUTHORS to reflect recent submissions
+
+       * doc/USERS_GUIDE, src/cmd.c, src/cmd.h, src/ctrl.c, worlds/haxima-1.002/books.scm:
+       Applied patch from Tim Douglas to fix H)elp command; added ctrl-q)quit q/o saving at his suggestion
+
+       * src/terrain_map.c:
+       Applying patch from Janne Johansson for compiler warning
+
+       * worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/naz.scm:
+       Promoted some generally useful code from mouse.scm to naz.scm
+
+       * worlds/haxima-1.002/naz.scm:
+       Bugfix: purchasing a cure service from a healer didn't work
+
+2006-01-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac:
+       Patch from Janne Johansson
+
+       * src/character.cpp, src/map.c, src/scheme.c:
+       Adding casts to double for calls to pow() and sqrt()
+
+       * src/map.c, src/nazghul.c:
+       Got rid of getop_long and a few old options I don't want to support any more
+
+       * src/nazghul.c:
+       Patch from Janne Johansson for Sun compiler
+
+       * src/sprite.h:
+       Removed some obsolete code
+
+2006-01-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/screen.c:
+       Bugfix: when zoomed out, transparency shows up as magenta
+
+       * worlds/haxima-1.002/arms.scm:
+       Arms balance tweaking
+
+       * worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Reworked edge spawning to make it easier to tune
+
+       * worlds/haxima-1.002/species.scm:
+       Increased dragon HP
+
+2006-01-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp:
+       Bugfix (1411788): NPC parties getting into towns and dungeons
+
+       * src/ascii.c, src/ascii.h, src/screen.c:
+       Added support for colored console text; nothing using it yet but it does work
+
+       * src/character.cpp:
+       Doubled XP required for level advancement
+
+       * src/cmd.c:
+       Casting spells gives XP
+
+       * src/combat.c:
+       Bugfix: NPC attacks while on (but not aboard) ship
+
+       * src/ctrl.c, worlds/haxima-1.002/books.scm:
+       Changed quit-without-saving keybinding from ctrl-Q to ctrl-S
+
+       * src/nazghul.c:
+       Added Steve Riberty to art credits for new rune sprites
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/food.png, worlds/haxima-1.002/reagents.png, worlds/haxima-1.002/runestones.png, worlds/haxima-1.002/shapes.png, worlds/haxima-1.002/signs.png, worlds/haxima-1.002/special.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/tools.png:
+       Added transparency to all sprites
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/food.png, worlds/haxima-1.002/shapes.png:
+       From Kris, added transparency to some more sprites
+
+       * worlds/haxima-1.002/ai.scm:
+       Bugfix: use-ranged-spells not returning #f when it didn't cast anything, cause dryads to walk
+
+       * worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/town-entry.scm:
+       Bugfix: Bole's inn-room door was not being locked on town re-entry
+
+       * worlds/haxima-1.002/conv.scm:
+       Oparine townsfolk now give directions to Green Tower
+
+       * worlds/haxima-1.002/dank-cave.scm:
+       Bugfix: ladder up from Dank Cave led to wrong location
+
+       * worlds/haxima-1.002/enchanter.scm:
+       Enchanter was using generic response to ENCH keyword
+
+       * worlds/haxima-1.002/kathryn.scm:
+       Bugfix: Kathryn not giving player her Wis Quas scroll upon join
+
+       * worlds/haxima-1.002/monster-generator.scm:
+       Removed some obsolete code
+
+       * worlds/haxima-1.002/npc-types.scm:
+       Craven archers now armed with daggers for when they run out of ammo
+
+       * worlds/haxima-1.002/oparine.scm:
+       Fixed some signs and terrain
+
+       * worlds/haxima-1.002/palette.scm:
+       Bugfix: alchemy sign confused with arms shop sign
+
+       * worlds/haxima-1.002/scrolls.scm:
+       Canceling u)se scroll was using up scroll
+
+       * worlds/haxima-1.002/thiefs_den.scm:
+       Removing unthiefly treasure from Thief's Den
+
+       * worlds/haxima-1.002/traps_3.scm:
+       Bugfix: spawn points in Fun with Levers weren't getting triggered
+
+2006-01-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.h, src/combat.h, src/kern.c, src/object.h, src/play.c, src/player.h, src/status.c, src/status.h, src/tree.h:
+       Fixed all -pedantic warnings over which I have control (ie, not in SDL headers)
+
+       * src/cmd.c:
+       Fixing an access-after-deleted bug in mixing spells
+
+       * src/cmd.c:
+       Renamed getchar to cmd_getchar to avoid collision on openBSD
+
+       * worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/runestones.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm:
+       New rune stone sprites courtesy of Steve Riberdy
+
+2006-01-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Field.cpp, src/Makefile.am, src/astar.c, src/closure.c, src/cmd.c, src/combat.c, src/ctrl.c, src/dice.c, src/dtable.c, src/kern.c, src/map.c, src/object.c, src/place.c, src/scheme.c, src/session.c, src/sky.c, src/sound.c, src/species.c, src/terrain.c, src/vmask.c:
+       Kernel changes:
+       o Added -Wall for CFLAGS as well as CXXFLAGS
+       o Fixed all the -Wall compilation warnings
+       o Bugfix: when t)alking and a person was nearby, target origin started on
+         person instead of player
+
+       * src/ascii.c, src/character.cpp, src/event.c, src/nazghul.c, src/player.cpp, src/sprite.c:
+       Some -Wall compiler warning fixes
+
+       * src/cmd.c, src/ctrl.c:
+       Removed old Ctrl-S command to save terrain map; unnecessary now that terrain maps are saved along with the rest of the game, and harmful in that some distros don't have a writable /tmp/
+
+       * src/place.c:
+       Kernel changes:
+       o Bugfix: terrain effects (like fire) were being applied to monster generator
+         objects
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o New NPC type: fire slimes
+
+2006-01-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/conv.c:
+       Fix for assert in ascii.c
+
+2006-01-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/tooth.scm:
+       Misc. fixes provided by Roland Hautz
+
+       * worlds/haxima-1.002/npc-types.scm:
+       NPC's no longer drop loot on the wilderness map
+
+       * worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shapes.png, worlds/haxima-1.002/sprites.scm:
+       Added Kris Parker's human knight sprite
+
+2006-01-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/gen.scm:
+       Haxima changes:
+       o Gen needed some bufs since he can potentially become a player party member
+
+       * worlds/haxima-1.002/runes.scm:
+       Haxima changes:
+       o Bugfix: g)et didn't work with Runes on the ground
+
+2006-01-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c:
+       Kernel changes:
+       o asciiPaint() now maps unrecognized chars to '?' and bleats a warning. This is
+         to help debug the assert(c>=' ') in SF bug 1399049.
+
+       * src/cmd.c:
+       Kernel changes:
+       o Bugfix: SF 1114048: selling itesm - list updated improperly. Actually, list
+         was just getting built improperly from the get-go.
+
+2006-01-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/signs.png, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/trigrave.scm:
+       Haxima changes:
+       o Added some "sign" sprites
+
+2006-01-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF:
+       Added comment about windows text files
+
+       * worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/treasury.scm:
+       Haxima changes:
+       o Bugfix: auto-generated corpses were saving improperly, causing null objects
+         to be in them on reload
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/moongate-clearing.scm:
+       Haxima changes:
+       o Bugfix: old entrance to slimy cavern still in moongate clearing
+       o Bugfix: +4 iron helm stats were wrong
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Bugfix: kathryn's letter was defined in kathryn.scm, which might not be
+         loaded before the letter is referenced in the script.
+       o Bugfix: found a part of the wilderness map that was incorrectly impassable
+
+       * worlds/haxima-1.002/mouse.scm:
+       Haxima changes:
+       o Bugfix: if Kathrn in party but Thud alive and not in party, crash when player
+         encounters the Mouse
+
+       * worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Bugfix: some spells like In Ex Por would be consumed even if the player
+         aborted without selecting a target (In Sanct, Sanct and An Ex Por were also
+         affected)
+
+2006-01-08  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * configure.ac:
+       *** empty log message ***
+
+2006-01-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF, src/Party.cpp, worlds/haxima-1.002/edge-spawn.scm:
+       Making sure the last few fixes were committed
+
+       * src/Party.cpp, src/character.cpp, src/character.h, src/object.c, src/object.h, src/player.cpp, worlds/haxima-1.002/items.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/spider.scm:
+       Haxima changes:
+       o Bugfix: spider's sometimes dropped piles of spider silk with zero (0) objects
+         in them
+       o Bugfix: cannon-killing a large gint party cuases a crash. Someone in the
+         party was dropping a healing potion. When a healing potion execs it looks for
+         a nearby Being to put itself into its inventory. On the wilderness, it was
+         finding the gint party, and trying to call a Character method on a Party
+         object. Crash!
+
+       * src/character.cpp, src/player.cpp, src/player.h:
+       Kernel changes:
+       o Bugfix: if a party member died it's readied items were lost.
+
+       * worlds/haxima-1.002/luximene.scm:
+       Haxima changes:
+       o Bugfix: error in the script when the Necromancer summoned Luximene.
+       o Added more stuff to Luximene's conversation
+
+       * worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Bugfix: moongate near Glasdrin was positioned over an impassable mountain
+
+       * worlds/haxima-1.002/shroom.scm:
+       Bugfix: shroom's trade conv broken by typo
+
+2006-01-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp:
+       Kernel changes:
+       o Bugfix: Party::save() was not saving one of the arguments to
+         kern-party-set-vehicle, this caused a bad save file when the player saved
+         with pirates somewhere on the map
+
+2006-01-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE:
+       doc changes
+
+2006-01-04  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * worlds/haxima-1.002/Makefile.am:
+       Initial.
+
+2006-01-03  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * Makefile.am, configure.ac, src/Makefile.am, worlds/Makefile.am:
+       Added haxima to build system.
+
+2005-12-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE:
+       Minor edits to USERS_GUIDE
+
+       * worlds/haxima-1.002/lich-tomb.scm:
+       Fixed ladder up in Lich's Tomb, was referring to old Keep Crypt
+
+2005-12-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS, BUGS, Attic/Makefile.in, Attic/configure, doc/USERS_GUIDE, scripts/RELEASE_CHECKOFF, scripts/ghul-test-install, worlds/Makefile.am:
+       USERS_GUIDE, Makefile.in and misc other final tweaks
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/nazghul.c, src/player.cpp, src/vmask.c:
+       Kernel changes:
+       o Reduced action point cost for PC spell-casting by 1/2
+       o Changed the main menu order: Journey Onward is always first if it's
+         applicable
+       o If a party member dies it unreadies all of its arms
+       o The X)amine command shows the XY coords only in Developer Mode
+       o Turned off switching to round-robin mode on entrance to a hostile place. Just
+         feels weird during play.
+       o Added a user confirmation check before over-writing an existing saved game
+         when "Start New Game" is selected
+
+       * src/character.cpp, src/cmd.c, src/map.c, src/tick.c:
+       Kernel changes:
+       o Reduced action point cost for PC spell-casting by 1/2
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/eastpass.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/ilya.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/moongate.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/traps_2.scm, worlds/haxima-1.002/tutorial_town.scm, worlds/haxima-1.002/tutorial_wilderness.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Bugfix: various spells needed some maintenance
+       o Bugfix: scrolls misspelled in Lia's shop script
+       o Bugfix: queen spider's would cast web spew when out of range
+       o Tweaked some loot drops
+       o Increased starting player HP but reduced HP gain per level
+
+       * worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/moon.scm, worlds/haxima-1.002/moongate.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Bugfix: various spells needed some maintenance
+
+       * worlds/haxima-1.002/special.png:
+       A couple of new images I forgot to check in.
+
+       * worlds/haxima-1.002/thorald.scm:
+       Adding tutorial NPC to repository
+
+2005-12-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * INSTALL, README:
+       Updated the README and INSTALL files.
+
+       * src/Missile.cpp, src/Party.cpp, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/ctrl.c, src/effect.c, src/foogod.c, src/kern.c, src/list.h, src/map.c, src/nazghul.c, src/object.c, src/place.c, src/play.c, src/player.cpp, src/player.h, src/scheme.c, src/session.c, src/session.h, src/status.c, src/vmask.c, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/tutorial.scm, worlds/haxima-1.002/tutorial_cave.scm, worlds/haxima-1.002/tutorial_town.scm, worlds/haxima-1.002/tutorial_wilderness.scm:
+       Haxima changes:
+       o Finished the tutorial.
+       
+       Kernel changes:
+       o Reverted most of my last changes since they made reload unstable.
+       o Main menu does not loop (big memory leak if it does)
+
+       * src/ctrl.c, src/nazghul.c:
+       Kernel changes:
+       o Made the terraform and zoom commands available only with the --developer
+         option on the command line
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/zane.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Misc tweaks to the scripts
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/tutorial.scm, worlds/haxima-1.002/tutorial_town.scm:
+       Haxima changes:
+       o Conversation tweaks.
+
+       * worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Paved a road from Trigrave north to the Fen
+
+2005-12-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Missile.cpp, src/Party.cpp, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/ctrl.c, src/effect.c, src/foogod.c, src/kern.c, src/list.h, src/map.c, src/nazghul.c, src/object.c, src/place.c, src/play.c, src/player.cpp, src/player.h, src/scheme.c, src/session.c, src/session.h, src/status.c, src/vmask.c, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/tutorial.scm, worlds/haxima-1.002/tutorial_town.scm:
+       Haxima changes:
+       o Added tutorial.scm to provide a walkthrough of the basic commands (unfinished)
+       
+       Kernel changes:
+       o Added tutorial to the main menu
+       o Made the global player party into the session struct.
+       o Changed the way the player party is allocated/freed
+
+       * src/character.cpp, src/nazghul.c, src/play.c, src/session.h, src/status.c, src/status.h, worlds/haxima-1.002/main-menu.scm, worlds/haxima-1.002/slywan.scm:
+       Haxima changes:
+       o Added main-menu.scm to support main menu UI
+       
+       Kernel changes:
+       o Added main menu UI. If no load file is specified to nazghul it will show a
+         menu allowing the user to select a new game or to journey onward.
+       o Quit&Save now falls back to the main menu UI.
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/slywan.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/tetzl.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/tooth.scm, worlds/haxima-1.002/zones.scm, worlds/haxima-1.002/zones.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o More stuff in new town
+
+2005-12-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, src/map.c:
+       Kernel changes:
+       o Bugfix: projectile animation speed varied from host to host
+
+       * worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jake.scm, worlds/haxima-1.002/kun.scm, worlds/haxima-1.002/mesmeme.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added extra town & some NPCs
+
+       * worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/ilya.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/roland.scm:
+       Haxima changes:
+       o Tweaked Ilya's conv
+
+       * worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Reworked Oparine
+
+2005-12-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/vehicles.scm:
+       Haxima changes:
+       o Added some sprites for a couple of special items
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/prison.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/special.scm:
+       Haxima changes:
+       o Modified the wilderness map.
+
+       * worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added lava bridge combat map
+       o Added mountain combat map
+
+       * worlds/haxima-1.002/crypt.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Reworked Green Tower Lower
+
+       * worlds/haxima-1.002/dank-cave.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/step.scm:
+       Haxima changes:
+       o Populated Dank Cave
+       o Fixed In Quas Corp spell
+
+       * worlds/haxima-1.002/effects.scm:
+       Haxima changes:
+       o Bugfix: sleep effect did not wake up victim when it expired
+
+       * worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/prison.scm, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Reworked Glasdrin Prison.
+
+2005-12-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/character.cpp, src/character.h, src/kern.c:
+       Kernel changes:
+       o Bugfix: charm an NPC and try Z)tats on the NPC's turn => crash. I fixed this
+         by tearing out the kernel implementation of "charm" and replacing it with a
+         simple faction change. Finished implementing the notion of "current" vs
+         "base" faction.
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/dank-cave.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/nossifer.scm:
+       Haxima changes:
+       o Changed the way the charm effect is implemented.
+
+2005-12-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/kern.c:
+       Kernel changes:
+       o Bugfix: hang if a character joins the player when already in the player party
+
+       * src/character.cpp, src/ctrl.c, src/kern.c:
+       Kernel changes:
+       o Character::clone() now clones readied items, too
+
+       * src/kern.c, src/player.cpp, worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/kama.scm:
+       Haxima changes:
+       o NPC's who will join now check if they are already in player party when asked
+         to join again (safe if they don't this just fixes the messages)
+       o Added LEAVe to conversations so the player can dismiss party members if he
+         wants to.
+       
+       Kernel changes:
+       o Bugfix: if an npc left and rejoined the game would hang.
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/altar-room.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o bugfix: after loading a saved game, killing a wizard resulted in script
+         errors because the wizard loot list wasn't using tags
+       o Added summon-demon ability for warlocks
+       o Added turn-invisible ability for demons
+       o Populated Altar Room
+       o Fixed In Quas Xen spell
+
+       * worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/kalcifax.scm:
+       Haxima changes:
+       o NPC's who will join now check if they are already in player party when asked
+         to join again (safe if they don't this just fixes the messages)
+
+       * worlds/haxima-1.002/amy.scm, worlds/haxima-1.002/poor-house.scm:
+       Haxima changes:
+       o Added Amy
+
+       * worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/kama.scm:
+       Haxima changes:
+       o Changed Kama's occupations
+
+       * worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/slimy-cavern.scm:
+       Haxima changes:
+       o Moved slimy cave
+       o Altered Roland's conv
+
+2005-12-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/kern.c, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Added Wis Sanct, detect trap
+       o Added An Sanct Ylem, disarm trap
+       
+       Kernel changes:
+       o Added kern-obj-is-container?
+       o Added kern-obj-is-trapped?
+       o Added kern-obj-remove-trap
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/zane.scm:
+       Haxima changes:
+       o Added effects for potions of dragon's, hydra's and lich's blood
+       o Added a couple of new "hidden" spells
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrain-to-ptype.scm, worlds/haxima-1.002/vehicles.scm:
+       Haxima changes:
+       o Added pirate NPC parties
+       o Tuned ship cannon damage
+
+2005-12-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/place.c, src/place.h, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/town-entry.scm, worlds/haxima-1.002/Attic/trigrave-entry.scm, worlds/haxima-1.002/trigrave.scm:
+       Haxima changes:
+       o Fixed inn room doors in all the towns. On entry to a town all inn room doors
+         are locked.
+       
+       Kernel changes:
+       o Bugfix: NPC's with multi-place schedules might start in the wrong town.
+       o Previously a place's on-entry hook would only support one hook fx, now it
+         will support a list of them.
+
+       * src/kern.c, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/prison.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/town-entry.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Redid Glasdrin's map to reduce the size and number of guards.
+       
+       Kernel changes:
+       o Performance improvement: added kern-obj-is-field?. The is-field? procedure in
+         the script was the bottleneck causing too-frequent garbage collection cycles
+         in places with lots of combatant NPC's (like guards). This change reduces
+         gc frequency in Glasdrin by almost 300%.
+
+       * src/sprite.c, src/sprite.h, src/vehicle.cpp:
+       Kernel changes:
+       o Bugfix: if two ships were both visible, their sprites would always have the
+         same facing even if the ships didn't. The sprites were in lockstep.
+
+2005-12-22  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * ChangeLog, configure.ac:
+       configure.ac: test for SDL_image
+
+2005-12-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/object.c, src/session.h, worlds/haxima-1.002/abe.scm, worlds/haxima-1.002/jewelry.png, worlds/haxima-1.002/jewelry.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/runes.scm, worlds/haxima-1.002/thiefs_den.scm, worlds/haxima-1.002/traps_4.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Fixed a few NPC schedules
+       o Added some missing files
+       
+       Kernel changes:
+       o NPC's now kick the player out of their bed
+
+       * src/cmd.c, src/common.c, src/common.h, src/ctrl.c, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/Attic/haxima.scm:
+       Haxima changes:
+       o Restoring a few test values to real game values
+       
+       Kernel changes:
+       o Build error fix: renamed log2 to logBase2. Apparently log2 conflicts with
+         newer versions of math.h.
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o Converted all (pertinent) npc types to use the new treasure drop system.
+       o Changed price of morning stars in Trigrave.
+
+2005-12-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/object.c, src/object.h, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Added L1 nixies without ranged weapons
+       o Added a new treasure drop effect
+       
+       Kernel changes:
+       o Added a new on-death hook
+
+       * worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/parties.scm:
+       Haxima changes:
+       o Bugfix: npc party generation had a bug where it wouldn't generate rare party
+         types
+
+2005-12-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/place.c:
+       Kernel changes:
+       o Bugfix: if combat was initiated over a town, on exit the town would be
+         removed from the map. Of, if the player saved during that combat, the save
+         file would crash when loaded.
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Added some npc and npc party types
+
+2005-12-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Wilderness combat tuning
+       
+       Kernel changes:
+       o Advancement tuning
+
+2005-12-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/kern.c, src/player.cpp, src/player.h, worlds/haxima-1.002/ankh-shrine.scm, worlds/haxima-1.002/demon-gate.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/talking-ankh.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Fixed up end-game
+       
+       Kernel changes:
+       o Added kern-end-game to gracefully end the game when it is over
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/silas.scm:
+       Haxima changes:
+       o Altered Accursed NPC conversations to streamline the plot
+
+       * worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/joel.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm:
+       Haxima changes:
+       o Rearranged dungeons on road to absalot
+       o Added Joel, a shepherd
+       o Added Gate to Absalot on wilderness map
+       o Added a pick (new tool)
+
+       * worlds/haxima-1.002/combat-maps.scm:
+       Haxima changes:
+       o Fixed up bridge combat maps & camping map
+
+       * worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Improved the wilderness combat maps
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/Attic/haxima.scm:
+       Haxima changes:
+       o Updates to Enchanter's conv
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/tools.scm:
+       Haxima changes:
+       o Added Tower of Absalot
+
+2005-12-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/crypt.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/necromancers-lair.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Added Necromancer's cave to the map
+       o Moved Crypt from Keep to level below GTL
+
+       * worlds/haxima-1.002/ancient-derelict.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/special.scm:
+       Haxima changes:
+       o Added an ancient derelict
+
+       * worlds/haxima-1.002/chanticleer.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/crypt.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/the-man.scm:
+       Haxima changes:
+       o Moved the location of Lost Halls
+       o Tweaked some conversations
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/warritrix.scm:
+       Haxima changes:
+       o Added ghost of Warritrix
+       o Fixed randomly-generated corpses to use same argument scheme as containers
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/warritrix.scm:
+       Haxima changes:
+       o Added Bet Por (single-character teleport) and Vas Por (whole-party teleport)
+
+       * worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/road_to_absalot.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Moved Fire Sea to its own dungeon
+
+2005-12-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/moongate.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/void-temple.scm:
+       Haxima changes:
+       o Misc tweaks here and there
+
+2005-12-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/place.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/keep_crypt_mech.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Kama to GTL
+       o Tweaked Gen's conv
+       
+       Kernel changes:
+       o Bugfix: broke character saving when I added saving of the force-drop flag
+
+       * src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/shroom.scm:
+       Haxima changes:
+       o Changed Angriss to be L20
+       o Changed web-spew to use 1/2 level (not 100%)
+       
+       Kernel changes:
+       o Bugfix: misplace "g" in kern.c caused broke kern-map-repaint
+
+       * src/play.c, src/session.c, worlds/haxima-1.001/shard.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Added the moons & moongates
+       
+       Kernel changes:
+       o Bugfix: the sun and moon weren't appearing in the sky window when the game
+         first started. As soon as the player took a turn they would appear. Needed to
+         call sky_advance() as soon as the current Place was established to force a
+         repaint of the sky window.
+
+       * src/player.cpp, worlds/haxima-1.002/kraken-lakes.scm:
+       *** empty log message ***
+
+       * worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kalcifax.scm, worlds/haxima-1.002/kama.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Kalcifax, the wandering mage
+
+2005-12-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/kern.c, src/status.c, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/ghertie.scm:
+       Haxima changes:
+       o And more conversation tweaks
+       
+       Kernel changes:
+       o New feature: when buying/selling, the quantity the player currently owns is
+         shown in brackets.
+       o Annoyance fix: on reload, shopkeepers had to goto the top left corner of their
+         appointed area before they were done "commuting". Until then they would not buy
+         or sell.
+
+2005-12-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/chanticleer.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/spider.scm:
+       Haxima changes:
+       o More conversation tweaks
+       
+       Kernel changes:
+       o Player can now switch places with non-hostile non-party members (as well as
+         party members). This helps the "blocked in the hallway" syndrome.
+       o Bugfix: paralysis was having no effect on player character's in follow mode.
+
+       * src/cmd.c, src/ctrl.c, src/kern.c, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/the-man.scm:
+       Haxima changes:
+       o And more conversation tweaks
+       
+       Kernel changes:
+       o New feature: if a player character has no saved target, and the player gives
+         it the a)ttack command, the crosshair will start on the nearest hostile instead
+         of on the PC. This should somewhat reduce the risk of carpal tunnel.
+       o Did something similar for the t)alk command.
+       o Bugfix: kern_blit_map() was not flushing the vmask cache, causing LOS
+         problems when terrain-altering mechanisms were handled
+
+2005-12-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/character.cpp, src/place.c, src/place.h, worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Bugfix: the gate guard in Paladin's Hold wasn't getting cleaned up on
+         respawn, causing an ever-increasing population of gate guards cluttering up
+         the hallway
+       o Added ladder between Kraken Lakes and Fire Sea level
+       o Bugfix: species' on-death closures weren't getting registered
+       o Bugfix: the potion sprite set had a bug that made the newer potions have no
+         sprite
+       
+       Kernel changes:
+       o Bugfix: Character::save() was saving intelligence and dexterity as the return
+         values from getIntelligence() and getDexterity(), which add the species
+         values. This causes characters to grow in intelligence and dexterity with
+         each save/load cycle.
+       o Bugfix: circularly-connected places weren't saving their neighborliness
+         relationship correctly, resulting in some places getting isolated.
+
+2005-12-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/ctrl.c, worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/food.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/steward.scm:
+       Haxima changes:
+       o Tweaked the world map a bit so that Glasdrin may be reached by land.
+       o Added to some conversations
+       
+       Kernel changes:
+       o ui_trade() no longer automatically puts the bought item in inventory if the
+         item has a 'buy hook.
+       o Giving player characters a damage bonus.
+
+2005-12-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/cmd.c, src/combat.c, src/ctrl.c, src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/eastpass.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/reagents.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/traps_3.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/westpass.scm:
+       Doc changes:
+       o Added a list of the effect codes shown in the status window for party members
+         to the USERS GUISE
+       
+       Haxima changes:
+       o Minor bugfixes to scripts and maps
+       
+       Kernel changes:
+       o R)eady command now prompts for party member when in follow mode
+       o Added highlight boxes to X)amine command
+
+2005-12-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/kern.c:
+       Kernel changes:
+       o Moved the name member of the Character class up to the Being class and made
+         it private. Moved mut/acc up there as well so now the Party class can enjoy
+         all the benefits of having its very own name. Equality to all the classes!
+       o Added kern-being-set-name so the script can name parties
+
+       * src/Party.cpp, src/kern.c, src/map.c, src/object.c, src/object.h, src/place.c:
+       Kernel changes:
+       o Added optional time-to-live (TTL) count on objects. If set, the count
+         decrements every time the object gets a turn. When the count expires if the
+         player is not in LOS the object is removed from the game.
+       o Added kern-obj-set-ttl for the script
+
+       * src/Party.cpp, src/Party.h, src/ctrl.c, src/kern.c, src/object.c, src/player.cpp, src/player.h:
+       Kernel changes:
+       o Cleaned up NPC parties, eliminating the PartyType class and lots of other
+         useless leftovers. Will be much easier to make NPC parties now from the
+         script, more like making NPC characters now.
+
+       * src/cmd.c, src/combat.c, src/kern.c:
+       Kernel changes:
+       o Added kern-obj-set-conv
+
+       * src/combat.c, src/map.c, src/place.c, src/session.c:
+       Kernel changes:
+       o Finally fixed a noxious intermittent bug that's been haunting me for months:
+         LOS getting messed up. Turns out it would only happen with reloads, due to
+         map subplaces not getting deleted, resulting in player character's not
+         getting deleted and hence not removing their views before the next session
+         starts. Philosophically, this comes from mixing persistent state (internal to
+         map.c in this case) with per-session state. Learn from my mistakes, kiddies.
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/gregors-hut-zones.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/terrain-to-ptype.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added a bunch more wilderness party types
+       o Named all the wilderness party types
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Added Westpass, a ranger camp that guards a mountain pass
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/Attic/moongate-clearing-zones.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Miscellaneous stuff while testing early game playability.
+
+       * worlds/haxima-1.002/edge-spawn.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/step.scm, worlds/haxima-1.002/terrain-to-ptype.scm:
+       Haxima changes:
+       o Added new wilderness NPC party generator
+
+2005-12-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/ctrl.c, src/dtable.c, src/dtable.h, src/factions.h, src/place.c, src/screen.c, src/screen.h, src/session.h:
+       Kernel changes:
+       o Prompt player before attacking non-hostiles (already had this in party mode,
+         but looks like it was lost a while ago in town mode)
+       o The x)amine command now shows diplomacy status of other beings
+       o Commands that select characters on the map now show hostile's with a red box
+         around them, allies with green, and neutrals with yellow. Hopefully this and
+         the last change will keep newbies from trying to fist Gregor to death when
+         they start the game.
+
+       * src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       
+       o Populated Fire Sea with a dragon. One is probably enough.
+       
+       Kernel changes:
+       
+       o Bugfix: in a previous checkin I accidentally screwed up
+         kern-terrain-get-pclass; looks like I was trying to add
+         kern-terrain-blocks-los? or something and got them mixed up
+       
+       o Added kern-terrain-blocks-los? (since I already had an implementation)
+
+       * src/map.c, src/map.h, src/object.c, src/place.c, src/play.c, src/scheme-private.h, src/session.c, src/session.h:
+       Kernel changes:
+       o Added mapSetSelected() so that the currently selected player character will
+         show up brightly even in dark rooms (but will not light up its surroundings)
+       o If reload fails the console message reflects an error (it was always declaring
+         success)
+       o When the player changes places the turn is ended (the place_exec loop
+         exits). Otherwise, until the turn is over if somebody shoots an arrow or
+         takes damage the animations are shown in the viewer for the NEW place.
+
+       * worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/forsaken-prison.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added and populated Watchpoint dungeon room
+       o Moved ladder between first and second level of Kurpolis
+       o Populated Forsaken Prison dungeon room
+       o Tweaked some maps and convs
+
+2005-12-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Populated Fire Bridge
+       o Added enslave ability for gazers
+       o Added narcotize ability for gazers
+       o Tweaked tremor spell
+       o Added corrupted halberdier and crossbowman NPC types
+       o Added ladder to Absalot
+       
+       Kernel changes:
+       o Bugfix: charm was not working right
+
+2005-11-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/kern.c, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Populated Rivulets of Fire dungeon room
+       o Added telekinesis spell
+       
+       Kernel changes:
+       o Added kern-obj-is-mech? to support telekinesis spell
+
+2005-11-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/step.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added chomp-deck ability for krakens
+       o Added step spawn points (again... newer version)
+       o Finished adding monsters to the Deepness
+       o Fixed a bug in the acid effect
+       o Added kraken, sea serpent and hydra AI
+       
+       Kernel changes:
+       o When characters advance a level they get full hp and mana restoration
+       o Character::setLevel() also sets XP for that level
+
+2005-11-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/player.cpp, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/yellow-slime.scm:
+       Haxima changes:
+       o Added acid effect and acid bolt (untested)
+       o Finished Pools
+       
+       Kernel changes:
+       o Casting spells dec's action points
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/object.c, src/object.h, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lich-tomb.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added fire immunity
+       o Skeletons immune to fire and poison
+       o Finished Lich's Tomb
+       
+       Kernel changes:
+       o Added a nil hook for effects like fire immunity which don't do anything other
+         than exist
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm:
+       Haxima changes:
+       o Added Craven Archer NPC type
+       o Finished Death Knight Keep
+
+       * worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/treasury.scm:
+       Haxima changes:
+       o Added lost treasury
+
+2005-11-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/cmd.c, src/ctrl.c, src/kern.c, src/place.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Finished Great Hall
+       o Fixed Vas Flam and Grav Por spells
+       o Fixed player missile spells to go through the abilities layer once target
+         selected, makes missile spell code more common
+       
+       Kernel changes:
+       o kern_fire_missile was causing double hits
+       o Compressed some combat console verbage
+
+       * worlds/haxima-1.002/alex.scm, worlds/haxima-1.002/jones.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Finished Paladin's Hold
+
+2005-11-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/step.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Modified gate guards a bit
+       o Mostly finished up Paladin's Hold
+
+2005-11-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/common.h, src/place.c, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/old-mine.scm, worlds/haxima-1.002/tools.scm:
+       Haxima changes:
+       o Added some ghosts to the Old Mine
+       o Added wind traps which blow out torches
+       o Seperated torch-light effect from generic light effect
+       o Bugfix: effect removal procedures should not call kern-obj-remove-effect, or
+         endless recursion results.
+       
+       Kernel changes:
+       o Reduced MIN_PLAYER_LIGHT from 128 to 8, so that torches become a bit more important.
+
+       * worlds/haxima-1.002/food.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/old-mine.scm:
+       Haxima changes:
+       o Finished Old Mine
+
+2005-11-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/old-mine.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/troll.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Finished Goblin Kingdoms
+
+2005-11-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/ctrl.c, worlds/haxima-1.002/abandoned-cellar.scm, worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep_crypt_mech.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/slimy-cavern.scm:
+       Haxima changes:
+       o Added guard-pt, a special case of spawn-pt, for guards
+       o Changed re-spawn time from one hour and one minute to one day
+       
+       Kernel changes:
+       o Finally fixed the "FIXME: use Being::pathfindTo" messages coming from ctrl.c
+       o When the party leader switches from Follow mode to Round Robin mode he no
+         longer forfeits his own turn.
+
+       * src/cmd.c, worlds/haxima-1.002/abandoned-cellar.scm, worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/Attic/af-entry.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/Attic/slimy-cavern-entry.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm:
+       Haxima changes:
+       o All NPC types added
+       
+       Kernel changes:
+       o Bugfix: if a chest was on a mech which could not be opened, trying to open
+         the chest would have no effect.
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/anne.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/douglas.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Douglas and Anne to the Entrance to Kurpolis
+
+2005-11-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep_crypt_mech.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Converted/added ranger, skeletal spear-thrower and skeletal warrior types to
+         new npc format
+       o Bugfix: skeletons had no limbs
+       
+       Kernel changes:
+       o When NPC's are choosing arms they now consider the defense and to-hit
+         values. Attack, defense and armor are given more weight than to-hit.
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o Added the teleport ability for NPC's
+       o Added a cave goblin priest NPC type
+
+2005-11-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Split ork faction and species into cave goblin and forest goblin
+       o Converted some existing goblin npc types into forest goblin hunters and
+         stalkers, and cave goblin slingers and berserkers.
+       o Added an axe weapon type
+       o Modified most of the Goblin Kingdom dungeons to use the new monster spawning
+         method
+       
+       Kernel changes:
+       o Bugfix: crash in Character::setTarget(). Mis-handling the targets refcount in
+         a corner case.
+
+2005-11-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/clock.c, src/clock.h, src/ctrl.c, src/kern.c, src/place.c, src/player.cpp, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o Added the new monster-spawning system for dungeon rooms. This is much simpler
+         than the previous monster generator systems, at the cost of some features
+         which weren't much used.
+       
+       Kernel changes:
+       o Moved the place on-entry hook invocation to the place_enter() function
+       o kern-get-time now returns the year, month,  week and day as well as the hour
+         and minute
+
+2005-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/kobj.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/troll.scm:
+       Haxima changes:
+       o Started consolidating the NPC gobs
+
+2005-11-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/spider.scm:
+       Haxima changes:
+       o Added forest goblin shaman
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Made curried wrapper for kern-mk-species
+       o Reorg'd species.scm into table format like arms.scm (make balance easier)
+       o Made curried wrapper for kern-mk-occ
+       o Reorg'd occ.scm into table format (balancing easier)
+
+2005-10-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/altar-room.scm, worlds/haxima-1.002/dank-cave.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/lich-tomb.scm, worlds/haxima-1.002/old-mine.scm:
+       Haxima changes:
+       o Added Old Mine map
+       o Added Lich Tomb map
+       o Added Altar Room map
+       o Added Dank Cave map
+
+2005-10-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kraken-lakes.scm, worlds/haxima-1.002/tblit.scm:
+       Haxima changes:
+       o Added maps for 4th level of Kurpolis
+
+       * worlds/haxima-1.002/forsaken-prison.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/mans-hideout.scm:
+       Haxima changes:
+       o Added Forsaken Prison map
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kraken-lakes.scm:
+       Haxima changes:
+       o Added Kraken Lakes level & its maps
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm:
+       Haxima changes:
+       o Added Death Knight's Hold
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/tblit.scm:
+       Haxima changes:
+       o Added Treasury room
+
+2005-10-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Attic/goblin-battle.scm, worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/grey-goblin-village.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/kurpolis.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/Attic/troll-den.scm:
+       Haxima changes:
+       o Re-organized the source for the first level of Kurpolis
+       o Modifed the entrance to Kurpolis to be more entrance-y
+
+       * worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/Attic/keep_crypt.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Added Paladin's Hold
+
+       * worlds/haxima-1.002/goblin-kingdoms.scm, worlds/haxima-1.002/Attic/haxima.scm:
+       Haxima changes:
+       o Added Shaman's Grove map
+
+2005-10-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/nossifer.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/talking-ankh.scm:
+       Haxima changes:
+       o Added Nossifer
+
+2005-10-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ankh-shrine.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/talking-ankh.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added Ankh Shrine
+       o Added talking ankh
+
+2005-10-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/dennis.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/selene.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Selene
+       o Added Dennis
+
+2005-10-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/silas.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Silas
+
+2005-10-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/items.scm, worlds/haxima-1.002/luximene.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/necromancer.scm, worlds/haxima-1.002/necromancers-lair.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Necromancer
+       o Added Luximene
+
+2005-10-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jorn.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Jorn, Ghertie's first mate
+
+2005-10-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/kern.c, src/terrain_map.c, worlds/haxima-1.002/gholet.scm, worlds/haxima-1.002/prison.scm:
+       Haxima changes:
+       o Added NPC Gholet
+       
+       Kernel changes:
+       o Bugfix: if script called kern-obj-remove-from-inventory with a count arg
+         greater than the numer available to remove we'd assert in
+         Container::takeOut. Replaced the assert with return false and emit a warning
+         to the console.
+
+2005-10-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/prison.scm:
+       Haxima changes:
+       o Added Sam's Prison Chamber map as a prison below Glasdrin
+
+2005-10-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/meaney.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Meaney, one of Ghertie's ex-crew
+
+2005-10-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/poor-house.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Poor House
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Added Ghertie's Quest.
+
+2005-10-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/player.cpp, worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Tweaked the maps a bit around the Engineer's Hut
+       o A few fixes to the Engineer's conversation
+       
+       Kernel changes:
+       o Bugfix: if reloading a game saved while on board a vehicle, upon disembarking
+         the vehicle would be inadvertently destroyed. Needed to add a ref_inc on load
+         to prevent this.
+       o Characters that were sleeping due to a spell would still respond with a
+         conversation (unlike characters sleeping due to their schedule telling them
+         to). Since "sleep" is a concept known to the kernel I added a check for it.
+       o Bugfix: sleeping party members shouldn't be able to rendezvous
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/the-man.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added the MAN
+       o Tweaked Ghertie's conversation
+
+2005-10-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/engineer.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/vehicles.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added engineer
+       o Added voidship
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Put Lost Halls on the wilderness map
+
+       * worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Sprinkled lost halls with corpse loot
+       o Bugfix: wind spells were broken, calling kern-being-is-hostile? on non-being
+         objects; caused a crash
+
+2005-10-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/troll.scm:
+       Haxima changes:
+       o Bugfix: mongen2 exec was not evaluating kern-char-get-location, caused
+         monster generation to fail with a script error
+       o Bugfix: bog was poisoning non-being objects and emitting the noxious "Noxious
+         fumes!"  message
+       o Added Gint npc type
+       o Added monster generators to Lost Halls
+       
+       Kernel changes:
+       o Bugfix: kern_char_get_occ was not returning sc->NIL for null occs
+
+2005-10-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/common.c, src/common.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/objs.scm:
+       Haxima changes:
+       o Added searchable corpses with loot
+       
+       Kernel changes:
+       o Added a hook for 'search' on objects
+
+2005-10-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added Angriss and finished her lair
+       
+       Kernel changes:
+       o Added kern-conv-begin, so npc's can initiate conversation with the player
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Broke up the Lost Halls dungeon into dungeon rooms
+       o Added some procs to simplify dungeon room creation
+
+2005-10-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/angriss.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/ilya.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Almost done with Angriss lair
+       o Added Angriss; mostly done
+       o Implemented web-spew as an ability
+
+2005-10-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/angriss-lair.scm, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/special.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/step.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added most of Angriss's Lair
+
+2005-10-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/merciful-death.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/raise-merciful-death.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added the wreck of the Merciful Death
+       o Added Vas Uus Ylem spell
+       
+       Kernel changes:
+       o Added place-add-subplace
+       o Bugfix: if a spell closure returned no-effect cmdCastSpell would call
+         log_end() twice and assert in log.c
+
+2005-10-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/fire_sea.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added deep lava sprite and terrain type
+       o Added Rune of Wisdom
+       o Reverted boulders to being impassable
+
+       * worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/old-absalot.scm:
+       Haxima changes:
+       o Added permanent versions of all energy fields
+       o Dispell field spell will now worn on spider webs
+       o Added Rune of Skill
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/void-temple.scm:
+       Haxima changes:
+       o Added void temple
+       o Added Rune of Discretion
+
+2005-10-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/old-absalot.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Put Absalot on the main map
+       o Added mechs and... other stuff to Old Absalot
+
+       * worlds/haxima-1.002/absalot.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/old-absalot.scm:
+       Haxima changes:
+       o Added maps for Absalot and Old Absalot
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/engineers-hut.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/vehicles.scm:
+       Haxima changes:
+       o Added map and objects for the Engineer's Hut
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lever.scm, worlds/haxima-1.002/mans-hideout.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/tblit.scm:
+       Haxima changes:
+       o Added map and objects for the MAN's Hidedout
+
+       * worlds/haxima-1.002/earl.scm:
+       Haxima changes:
+       o Earl sells shovels
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/trigrave.scm:
+       Haxima changes:
+       o Added support for buried objects and a shovel
+       o Added Rune of Power
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/necromancers-lair.scm:
+       Haxima changes:
+       o Added map and objects for the Necromancers Lair
+
+2005-09-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/common.h, src/object.c, src/object.h, worlds/haxima-1.002/food.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/jeffreys.scm, worlds/haxima-1.002/jess.scm:
+       Haxima changes:
+       o Added Jeffries to Glasdrin
+       o Fixed buying alcohol to add drunkuness effect (previously picking up alcohol
+         from the ground would do this, but not buying it)
+       
+       Kernel changes:
+       o Cut back turns per hour from 60 to 20 so time will pass more quickly
+       o Added support for the 'buy hook to object types (to support alcohol
+         purchases)
+
+2005-09-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shapes.png, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added guard generators to Glasdrin
+
+       * worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/ini.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Ini, a paladin of Glasdrin
+
+2005-09-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/steward.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Victoria, ruler of Glasdrin
+       o Added a female ruler sprite
+
+2005-09-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/chester.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Chester, arms dealer, to Glasdrin
+
+2005-09-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, src/map.c, src/map.h, src/place.c, src/play.c, src/scheme-private.h:
+       Kernel changes:
+       o Increased scheme CELL_SEGSIZE from 5,000 to 40,000. This reduced the
+         frequency of garbage collection cycles and improves responsiveness. It also
+         dramatically improves the load time.
+       o Reduced scheme CELL_NSEGMENT from 20 to 10. Since the total size was
+         increased with the above change I'm reverting the change I made to this
+         earlier when scheme was running out of memory. It isn't necessary now.
+       o Added a REPAINT_IF_OLD flag to map updates made solely for animation
+         purposes. The intention is to cut back on unnecessary map repaints in cases
+         where the map was recently repainted due to player actions. Should also
+         eliminate the "dancing sprite" effect which occurs after animation repaints
+         are held off for short periods during special effects like map jitter or map
+         flash.
+
+       * worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/jess.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Jess, barkeep, to Glasdrin
+
+2005-09-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/kern.c, worlds/haxima-1.002/angela.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/patch.scm, worlds/haxima-1.002/prices.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/zones.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Map tweaks to Glasdrin
+       o Added doc Patch to Glasdrin
+       o Added npc healer scripts
+       
+       
+       Kernel changes:
+       o kern_ui_select_party_member now cleans up cmdwin
+
+2005-09-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/keep.scm, worlds/haxima-1.002/Attic/keep_crypt.scm, worlds/haxima-1.002/keep_crypt_mech.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/objs.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm:
+       Haxima changes:
+       o Added Crypt dungeon room
+
+2005-09-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/bart.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/prices.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Added Bart the shipwright to Oparine; player can now buy ships
+       o Bugfix: the dungeons kurpolis and mushroom cave needed to be designated by
+         tags, not raw variables, in their mk-dungeon calls
+       
+       Kernel changes:
+       o kern-place-get-vehicle
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Lia, reagent-seller of Oparine
+       o Added Fing, a nixie of Oparine
+
+       * worlds/haxima-1.002/fing.scm, worlds/haxima-1.002/ghertie.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/lia.scm, worlds/haxima-1.002/oparine.scm:
+       Haxima changes:
+       o Added Ghertie to Oparine
+
+2005-09-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/henry.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Henry the barkeep to Oparine
+
+       * worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/oscar.scm, worlds/haxima-1.002/prices.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added Oscar the Innkeeper to Oparine
+
+2005-09-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/alchemist.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/potions.png, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added the Alchemist
+       o Added three new (inert) potion types: dragon's blood, hydra's blood and
+         lich's blood
+
+2005-09-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added the Alchemist shop to Oparine
+       o Set zones for Oparine
+
+2005-09-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Added end of first quest and start of main quest to enchanter's conv
+       
+       Kernel changes:
+       o Added kern-char-add-experience
+
+2005-09-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, worlds/haxima-1.002/books.png, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/traps_1.scm:
+       Haxima changes:
+       o Finished testing/tweaks to Kathryn/Thud/Thief scenario
+       
+       Kernel changes:
+       o Added kern-char-force-drop and relevant support. With this, the scripter can
+         indicate that he wants a particular character to always drop their chest (as
+         opposed to dropping it based on a probability)
+
+2005-09-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/object.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/thud.scm:
+       Haxima changes:
+       o Bugfix: when warping in Thud and Kathryn their schedules are reset to null
+       o Added spell-sword-ai, Kathryn uses it
+       
+       Kernel changes:
+       o Added kern-char-set-schedule
+       o Bugfix: if a character is eating and the schedule is set to NULL then the
+         character will be stuck eating (and doing nothing else!).
+
+       * src/kern.c, src/player.cpp, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Bugfix: when losing gold or food console message said eg, "You lose -500
+         gold". Got rid of the negative sign in these messages.
+       
+       Kernel changes:
+       o Scaled back the thief's conversation in accordance with some plot changes
+       o Bugfix: kobj-get was printing eg, "Jack gets a beer" even when Jack didn't
+         really get the beer (because Jack lacked a container in which to put the
+         beer)
+
+2005-09-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/mouse.scm, worlds/haxima-1.002/naz.scm:
+       Haxima changes:
+       o Added Mouse, the Accursed Thief; not fully tested yet
+       o kobj-get checks if kern-obj-put-into succeeded (it won't for npc's with no container)
+       
+       Kernel changes:
+       o Added Character::leavePlayer() to remove player party members
+       o Added kern-char-leave-player
+       o kern-obj-remove uses Object::remove() now instead of place_remove_object()
+       o kern-obj-put-into now returns bool
+
+2005-09-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/object.c, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/food.scm, worlds/haxima-1.002/Attic/haxima.scm:
+       Haxima changes:
+       o Added Thief's Den
+       o Added rune types
+       
+       Kernel changes:
+       o Added simple critical hits: if (20 <= (1d20 + log2(lvl))) then the defender's
+         armor is ignored.
+       o Disarming traps is now (20 <= (1d20 + log2(dex) + log2(lvl)))
+
+       * src/cmd.c, src/common.c, src/common.h, src/ctrl.c, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/traps_1.scm, worlds/haxima-1.002/traps_2.scm, worlds/haxima-1.002/traps_3.scm:
+       Haxima changes:
+       o Added final trap level to Thief's ladder, it's quite evil IMHO
+       o Arranged riddles in first trap level to be serial and different
+       o Tweaked some armor/weapon values
+       
+       Kernel changes:
+       o Added simple critical hits: if (20 <= (1d20 + log2(lvl))) then the defender's
+         armor is ignored.
+       o Disarming traps is now (20 <= (1d20 + log2(dex) + log2(lvl)))
+
+2005-09-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/ctrl.c, src/ctrl.h, src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       
+       o Added mk-edge-gen, which creates a v2 monster generator that doesn't care if
+         the player is in LOS. Intended for edge-of-map or over-portal generators,
+         where it doesn't look odd for an npc to suddenly appear.
+       
+       o Bugfix: vampiric-touch might destroy it's victim then try to print its
+         name. Uses refcount now.
+       
+       Kernel changes:
+       
+       o Character level added as a bonus to to-hit and to-def
+       
+       o Bugfix: was not calculating attacker's to-hit penalty from armor
+       
+       o Bugfix: could h)andle invisible mechs when not revealed
+
+       * src/character.cpp, src/cmd.c, src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/items.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/potions.scm:
+       Haxima changes:
+       o vampiric touch damage limited to victim's hp
+       o Mana and healing potions on the ground will check for an adjacent npc that
+         wants them. If the npc does not have an action point debt it will
+         automatically get the potion, losing an action point in the process. This
+         idea comes from Ray Dillinger's discussion of "Displaced Actions". This way
+         npc's don't have to know about potions and search for them every turn. Since
+         potions are rarer than npc's and quickly picked up, it's more efficient to
+         have the potion search for npcs!
+       o bugfix: death knights of insufficient level were using disease touch
+       
+       Kernel changes:
+       o Bugfix: on reload a character's readied arms were also added to its
+         inventory, causing a double count of readied items.
+       o Bugfix: kern_obj_remove_from_inventory was doing nothing on
+         non-player-controlled characters (because Character::takeOut was doing
+         nothing)
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm:
+       Haxima changes:
+       o Added ability.scm for special NPC abilities
+       o Death knights use Disease Touch and Vampiric Touch
+       o Death knights drink mana potions
+       
+       Kernel changes:
+       o Added Character::setMana
+       o Added kern-char-get-max-mana
+       o Added kern-char-set-hp
+       o Added kern-char-set-mana
+       o Added kern-type-get-name
+       o Bugfix: kern_ui_select_party_member not printing a "-" in the cmdwin
+
+       * src/ctrl.c, src/kern.c, worlds/haxima-1.002/ability.scm, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm:
+       Haxima changes:
+       o Added disarm ability at L3
+       o Guard AI attempts to disarm foes
+       
+       Kernel changes:
+       o Added kern-char-get-readied-weapons
+       o Added kern-char-unready
+       o Added more verbose combat spewage
+
+2005-09-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o death-knight generator in great hall sets level to 1d8 (test of kernel
+         changes)
+       
+       Kernel changes:
+       o Added Character::setLevel
+       o Added kern-char-set-level
+       o Descriptions of characters via x)amine now show their level
+
+       * src/ctrl.c, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/Attic/slimy-cavern-entry.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/troll.scm, worlds/haxima-1.002/yellow-slime.scm:
+       Haxima changes:
+       o Added step version of mongen2
+       o Bugfix: where yellow slimes summoned green slimes I forgot to remove a
+         parameter passed to the spell, caused a crash
+       
+       Kernel changes:
+       o ctrl.c -- ctrl_idle() now checks return value of AI closure. The closure
+         should return true iff it handled the turn. If it returns false then control
+         falls through to the standard kernel AI. This allows magic users or creatures
+         with special ability to test if they want to do something unique, and if not
+         then to go ahead with the generic AI.
+
+       * src/kern.c, worlds/haxima-1.002/Attic/goblin-battle.scm, worlds/haxima-1.002/Attic/grey-goblin-village.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/Attic/troll-den.scm:
+       Haxima changes:
+       o Upgraded all monster generators to mongen2
+       o Upgraded mk-green-slime to be mk-gen-step
+       o Fixed torches
+       o With the kernel change below got rid of all the spurious "Noxious fumes!"
+         messages which occur in boggy places when slimes are around
+       
+       Kernel changes:
+       o kern_obj_add_effect propogates back the result of obj->addEffect() so the
+         script can check if the effect was actually applied
+
+2005-09-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.h, src/character.cpp, src/cmd.c, src/common.h, src/kern.c, src/map.c, src/map.h, src/object.c, src/place.c, src/session.c, src/session.h, worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/tblit.scm:
+       Haxima changes:
+       o Added dungeon room: Thief's Ladder III
+       o Added Death Knight npc type
+       o Added halberdier guard npc type
+       o Added crossbow guard npc type
+       
+       Kernel changes:
+       o Added hard-coded probabilities to drop items and chests instead of dropping
+         all the time. Less litter.
+       o When an object gets hit it flashes a damage sprite
+       o Bugfix: in the rare occasions when more than one being occupies the same tile
+         the X)amine command was only showing one of them
+
+2005-09-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/bim.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/lever.scm, worlds/haxima-1.002/traps_2.scm, worlds/haxima-1.002/traps_3.scm, worlds/haxima-1.002/traps_3_mechs.scm:
+       Haxima changes:
+       o Added dungeon room Thief's Ladder II
+
+2005-09-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/bim.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/traps_1.scm, worlds/haxima-1.002/traps_2.scm:
+       Haxima changes:
+       o Added dungeon room Thief's Ladder II
+
+2005-09-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/clock.c, src/clock.h, src/cmd.c, src/foogod.c, src/kern.c, src/object.c, worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/melvin.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/shroom.scm:
+       Haxima changes:
+       o Added Melvin of Bole
+       o Added Hackle of Bole
+       o Added Thief's Door (destination not correct yet)
+       
+       Kernel changes:
+       o Added kern-get-time to return time-of-day as (hours . minutes)
+       o Effects on generic objects now saved/loaded
+       o Bugfix: Reveal was not shown in status window
+
+       * worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/hackle.scm, worlds/haxima-1.002/Attic/haxima.scm:
+       Haxima changes:
+       o Map cleanup in Bole
+       o Conversation tweaks in Bole
+
+       * worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/traps_1.scm:
+       Haxima changes:
+       o Added dungeon room Thief's Ladder I
+       o Wired up Thief's Door destination
+       o Added riddle mechanism
+
+2005-09-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/chanticleer.scm, worlds/haxima-1.002/food.scm, worlds/haxima-1.002/miggs.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/trigrave.scm:
+       Haxima changes:
+       o Added Miggs, tavern-keeper of Trigrave
+       o Added a fat townswoman sprite
+
+2005-09-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/food.png, worlds/haxima-1.002/food.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added a "drunk" effect for alcoholic beverages
+
+2005-09-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/cmd.c, src/kern.c, worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/chanticleer.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/Attic/trigrave-zones.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Added a stun wand
+       o Maintenance on Trigrave conversations
+       o Added Earl's chest
+       
+       Kernel changes:
+       o Containers now save/reload effects on them
+       o The 'open' command no longer works on invisible containers and mechs (unless
+         Reveal is in effect)
+
+       * worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/trigrave.scm:
+       Haxima changes:
+       o Added a stun wand
+       o Maintenance on Trigrave conversations
+
+2005-08-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/zane.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Removed all the guards and mongens from Enchanter's Tower
+       o Added magically locked doors, treasure and beds to ET
+       o Added Enchanter to ET
+
+2005-08-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/ctrl.c, src/dtable.h, src/kern.c, src/object.c, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/zane.scm:
+       Kernel changes:
+       o Added kern-being-is-ally?
+       o Added kern-being-get-visible-allies
+       o Added kern-char-get-level
+       o Bugfix: dtable_are_allies() was referencing the value for hostiles, not
+         allies
+       o Tweaked XP needed for advancement down a little; level 2 now occurs at 32XP
+       o NPC's with ranged weapons will try and move away from foes who are blocking
+         them
+       
+       Haxima changes:
+       o Added slime and skeleton generators to enchanter's tower
+       o Enchanter's gate guards will summon rangers when they see hostiles
+       o Gate guards will also cast dispell undead if they see skeletons
+
+2005-08-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/gate-guard.scm:
+       Haxima changes:
+       o Gate guards now pathfind to their posts.
+
+2005-08-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * configure.ac, src/kern.c, src/nazghul.c, src/session.c, worlds/haxima-1.002/bim.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/kobj.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/Attic/spawnpoint.scm, worlds/haxima-1.002/splash.png, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/timer.scm:
+       Build changes:
+       o Bumped version to 0.5
+       
+       Kernel changes:
+       o Changed location where kernel looks for splash image to be the current
+         directory
+       o Erasing screen before painting frame for first time to get rid of residual
+         splash image
+       
+       Haxima changes:
+       o Minor conversation cleanup
+       o Added gate-guard.scm
+       o Added gate guards to enchanters tower
+       o Updated splash image
+       o Added a generic timer mech; originally I planned to use this with gate guards
+         but didn't need it. Since these will probably prove to be useful for other
+         things I'm adding the file to CVS (but not loading it on startup).
+
+       * src/character.cpp, src/kern.c, src/place.c, src/place.h:
+       Kernel changes:
+       o Bugfix: npc's no longer try to shoot at targets through walls. The
+         Character::canSee() method now checks LOS
+
+       * worlds/haxima-1.002/Attic/af-entry.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/Attic/slimy-cave-entry.scm, worlds/haxima-1.002/Attic/slimy-cavern-entry.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Consistently named all the "is-species?" type procedures
+
+       * worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/gate-guard.scm, worlds/haxima-1.002/Attic/haxima.scm:
+       Haxima changes:
+       o Added green slime generator to enchanter's tower
+       o Gate guards now close their gates when hostiles are visible
+
+2005-08-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/ctrl.c, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/ilya.scm, worlds/haxima-1.002/shard.scm:
+       Kernel changes:
+       o Bugfix: ctrl_do_attack() was referring to the target after it could have been
+         destroyed, causing an assert
+       
+       Haxima changes:
+       o Repositioned Gregor's Hut
+       o Repositioned Abandoned Farm
+       o Some conversation cleanup
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/oparine.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Added Oparine
+
+2005-08-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/glasdrin.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Added Glasdrin
+
+2005-08-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanters-tower.scm:
+       Haxima changes:
+       o Tweaks to enchtwr
+
+2005-08-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Reworked enchanter's tower into something smaller
+
+2005-08-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/npc-types.scm:
+       Haxima changes:
+       o Added Troll Den dungeon room
+       o Fixed troll boulder-throwing
+       o Tweaked troll npc type equipment
+
+       * worlds/haxima-1.002/bill.scm, worlds/haxima-1.002/bole.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/kathryn.scm, worlds/haxima-1.002/may.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/thud.scm, worlds/haxima-1.002/zones.scm:
+       Haxima changes:
+       o Ported Bole and existing occupants
+
+2005-08-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/scheme.c, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/Attic/goblin-battle.scm, worlds/haxima-1.002/Attic/grey-goblin-village.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/Attic/troll-den.scm, worlds/haxima-1.002/troll.scm:
+       Haxima changes:
+       o Added Troll Den dungeon room
+       o Fixed troll boulder-throwing
+
+2005-08-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/common.h, src/kern.c, src/place.c, src/place.h, worlds/haxima-1.001/enchanters-tower.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/Attic/grey-goblin-village.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/kurpolis.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/sprites.scm:
+       Kernel changes:
+       o At long last, after no end of polite requests from Sam, implemented u5-style
+         "adjacent" dungeon rooms, where stepping off the map edge of one dungeon will
+         land you in a neighboring room. It should work with towns and, for all I
+         know, wilderness zones, too (but stepping off the edge of a wilderness combat
+         map will still take you back to the wilderness).
+       
+       Haxima changes:
+       o Added two stub dungeon rooms
+       o Fixed the entrance to the mushroom cave to use an auto-entrance portal; this
+         is the recommended way for all wilderness dungeon entrances (at some point in
+         the past I must have removed the party E)nter command... don't recall when or
+         why)
+
+       * src/character.cpp, src/player.cpp, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/Attic/save.scm:
+       Kernel changes:
+       o Bugfix: with the recent multi-place schedule changes, when an NPC with a
+         schedule joins the player party it must be removed from the list of NPC's
+         with schedule, otherwise on entry to a town the kernel will try and move it
+         to its appointment, resulting in crashes or missing party members.
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/doris.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/sprites.scm:
+       Haxima changes:
+       o Added Doris to Green Tower
+       o Added a female townsman sprite
+
+       * worlds/haxima-1.002/deric.scm, worlds/haxima-1.002/green-tower.scm:
+       Haxima changes:
+       o Added Deric to Green Tower
+
+       * worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/goblin-battle.scm, worlds/haxima-1.002/Attic/grey-goblin-village.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/kurpolis.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/species.scm:
+       Haxima changes:
+       o Added dungeon room: Goblin Village
+       o Added dungeon room: Goblin Battle
+
+2005-08-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/place.c, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/mushroom-cave.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/reagents.png, worlds/haxima-1.002/reagents.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/species.scm:
+       Kernel changes:
+       o Bugfix: x)amine crashed when a monster generator was examined after loading a
+         saved game. Fix is a hack: objects w/o names are assumed to be intentionally
+         never-visible.
+       
+       Haxima changes:
+       o Ported mushroom cave from ghulscript
+       o Ported Shroom's mushroom quest from ghulscript
+
+       * src/place.c, worlds/haxima-1.002/green-tower-lower.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/Attic/save.scm:
+       Kernel changes:
+       
+       o Bugfix: if two chests were stacked on the same tile with nothing else then
+         x)amine would only report one; this was generally true of any objects that
+         had the same ObjectType
+       
+       Haxima changes:
+       o Mechanisms and other objects added to Green Tower
+       o Added Green Tower Lower and its mechanisms
+
+       * src/play.c, src/vmask.c, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/Attic/sched.scm, worlds/haxima-1.002/shroom.scm:
+       Kernel changes:
+       o Added call to vmask_flush_all in the reload function in an attempt to fix the
+         remembered-vmask problem on reload; had no visible effect but I think we need
+       
+       Haxima changes:
+       o Added Shroom to Green Tower
+
+       * worlds/haxima-1.002/books.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/save.scm:
+       Haxima changes:
+       o Added Gen to Green Tower
+
+2005-08-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/door.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/green-tower.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Added Green Tower; map is there but most objects and NPCs still have to be
+         ported from the old ghulscript
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Finished fining-in the wilderness map
+
+2005-08-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.002/addons.png, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/terrains.scm:
+       Haxima changes:
+       o Created a "stars" terrain type and sprite
+       o Filled in "void" part of wilderness map with stars
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o More work on the wilderness map
+
+       * worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Began to fine-in the area around the shrine
+
+       * worlds/haxima-1.002/shard.scm:
+       Haxima changes:
+       o Finished roughing out the wilderness map
+
+2005-08-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/kern.c, src/terrain_map.c, src/terrain_map.h, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm:
+       Kernel changes:
+       o Added composite maps
+       o Bugfix: failing to create characters in Party::createMembers() resulted in an
+         infinite loop. It now bails out gracefully if this fails.
+       
+       Haxima changes:
+       o Modified shard.scm to create a composite map for the wilderness
+       o Removed more references to deleted object types in npc-types.scm
+
+       * src/cmd.c, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/shard.scm:
+       Kernel changes:
+       o Bugfix: infinite loop in terrain-fill function if starting point has same
+         terrain type as the fill
+       
+       Haxima changes:
+       o Expanded shard map to 128x96, 60% roughed-in
+
+2005-08-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, src/Party.cpp, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/Attic/save.scm:
+       Bugfix: crash if an npc factory references an invalid object
+
+       * src/heap.h:
+       Cleaned up header
+
+2005-08-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/combat.c, src/common.h, src/ctrl.c, src/object.c, src/player.cpp, src/player.h:
+       Kernel changes:
+       o +5 XP to the whole party on combat victory
+       o Moved some of the AI stuff to prepare for more AI changes
+
+2005-07-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/status.c:
+       bugfix: spells without sprites would crash in ztats; now check for a null sprite. I'm not going to invest in sprites for spells since they never appear outside of inventory.
+
+       * worlds/haxima-1.002/abandoned-cellar.scm, worlds/haxima-1.002/abandoned-farm.scm, worlds/haxima-1.002/addons.png, worlds/haxima-1.002/Attic/af-entry.scm, worlds/haxima-1.002/ai.scm, worlds/haxima-1.002/arms.png, worlds/haxima-1.002/arms.scm, worlds/haxima-1.002/bakup.scm, worlds/haxima-1.002/beds.scm, worlds/haxima-1.002/bim.scm, worlds/haxima-1.002/books.png, worlds/haxima-1.002/books.scm, worlds/haxima-1.002/bridge.scm, worlds/haxima-1.002/camping-map.scm, worlds/haxima-1.002/cannon.wav, worlds/haxima-1.002/chanticleer.scm, worlds/haxima-1.002/charset.png, worlds/haxima-1.002/combat-maps.scm, worlds/haxima-1.002/containers.scm, worlds/haxima-1.002/conv.scm, worlds/haxima-1.002/damage.wav, worlds/haxima-1.002/door.scm, worlds/haxima-1.002/drawbridge.scm, worlds/haxima-1.002/earl.scm, worlds/haxima-1.002/effects.scm, worlds/haxima-1.002/enchanter.scm, worlds/haxima-1.002/enchanters-tower-zones.scm, worlds/haxima-1.002/enchanters-tower.scm, worlds/haxima-1.002/enter_moongate.wav, worlds/haxima-1.002/fields.scm, worlds/haxima-1.002/food.png, worlds/haxima-1.002/food.scm, worlds/haxima-1.002/frame.png, worlds/haxima-1.002/game.scm, worlds/haxima-1.002/gen.scm, worlds/haxima-1.002/generic-mech.scm, worlds/haxima-1.002/gregor.scm, worlds/haxima-1.002/Attic/gregors-hut-zones.scm, worlds/haxima-1.002/gregors-hut.scm, worlds/haxima-1.002/gwen.scm, worlds/haxima-1.002/Attic/haxima.scm, worlds/haxima-1.002/horse.wav, worlds/haxima-1.002/ifc.scm, worlds/haxima-1.002/ilya.scm, worlds/haxima-1.002/init.scm, worlds/haxima-1.002/items.scm, worlds/haxima-1.002/jim.scm, worlds/haxima-1.002/kobj.scm, worlds/haxima-1.002/lever.scm, worlds/haxima-1.002/loc.scm, worlds/haxima-1.002/lost-halls.scm, worlds/haxima-1.002/money.png, worlds/haxima-1.002/money.scm, worlds/haxima-1.002/monster-generator.scm, worlds/haxima-1.002/moon.scm, worlds/haxima-1.002/Attic/moongate-clearing-zones.scm, worlds/haxima-1.002/moongate-clearing.scm, worlds/haxima-1.002/moongate.scm, worlds/haxima-1.002/moons.png, worlds/haxima-1.002/naz.scm, worlds/haxima-1.002/npc-types.scm, worlds/haxima-1.002/objs.scm, worlds/haxima-1.002/occs.scm, worlds/haxima-1.002/palette.scm, worlds/haxima-1.002/parties.scm, worlds/haxima-1.002/Attic/player.scm, worlds/haxima-1.002/portals.scm, worlds/haxima-1.002/portcullis.scm, worlds/haxima-1.002/potions.png, worlds/haxima-1.002/potions.scm, worlds/haxima-1.002/pre-entry-hooks.scm, worlds/haxima-1.002/reagents.png, worlds/haxima-1.002/reagents.scm, worlds/haxima-1.002/roland.scm, worlds/haxima-1.002/rowing.wav, worlds/haxima-1.002/rune.png, worlds/haxima-1.002/Attic/save.scm, worlds/haxima-1.002/Attic/sched.scm, worlds/haxima-1.002/scrolls.png, worlds/haxima-1.002/scrolls.scm, worlds/haxima-1.002/shapes.png, worlds/haxima-1.002/shard.scm, worlds/haxima-1.002/shroom.scm, worlds/haxima-1.002/Attic/slimy-cave-entry.scm, worlds/haxima-1.002/Attic/slimy-cavern-entry.scm, worlds/haxima-1.002/slimy-cavern-zones.scm, worlds/haxima-1.002/slimy-cavern.scm, worlds/haxima-1.002/sounds.scm, worlds/haxima-1.002/Attic/spawnpoint.scm, worlds/haxima-1.002/species.scm, worlds/haxima-1.002/spells.scm, worlds/haxima-1.002/spider.scm, worlds/haxima-1.002/sprite-sets.scm, worlds/haxima-1.002/sprites.scm, worlds/haxima-1.002/tblit.scm, worlds/haxima-1.002/terrains.scm, worlds/haxima-1.002/tools.png, worlds/haxima-1.002/tools.scm, worlds/haxima-1.002/Attic/trigrave-entry.scm, worlds/haxima-1.002/Attic/trigrave-zones.scm, worlds/haxima-1.002/trigrave.scm, worlds/haxima-1.002/troll.scm, worlds/haxima-1.002/urt.scm, worlds/haxima-1.002/vehicles.scm, worlds/haxima-1.002/walk.wav, worlds/haxima-1.002/yellow-slime.scm, worlds/haxima-1.002/zane.scm:
+       New stripped-down haxima
+
+2005-05-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.h, src/cmd.c, src/cursor.cpp, src/cursor.h, src/map.c, src/place.c, src/place.h:
+       Kernel changes:
+       o The cursor feature now shades the region which is out of cursor range. I
+         believe this feature was originally suggested by Sam.
+       o Added a fast circle-drawing routine to map.c but decided not to use it for
+         now.
+
+2005-05-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, worlds/haxima-1.001/enchanters-tower-zones.scm, worlds/haxima-1.001/enchanters-tower.scm, worlds/haxima-1.001/gregor.scm, worlds/haxima-1.001/gregors-hut-zones.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/zane.scm:
+       Part 3 of changes to allow character schedules to span multiple places
+       
+       Kernel changes:
+       o Bugfixes
+       
+       Haxima changes:
+       o Gregors now splits his time between his hut and the moongate clearing (first
+         multi-place schedule)
+
+       * src/character.cpp, src/character.h, src/place.c, src/play.c, src/sched.c, src/sched.h, src/session.c, src/session.h:
+       Part 2 of changes to allow character schedules to span multiple places
+       
+       Kernel changes:
+       o Added a list for characters with schedules to the session struct
+       o Modified Character::setSchedule() to add itself to the list if the schedule
+         is not null
+       o Modified Character destructor to remove itself from the list if it was put on
+         it
+       o Added Character::introduce() method to drop an npc onto the map if it needs
+         to come in on the current hour. Currently it just drops the npc onto its
+         appointment.
+       o Modifed Character::commuting to handle off-place destinations as a special
+         case. Currently it just teleports them out to their destination.
+       o Modified the play loop to check for characters that need to be introduced on
+         the hour.
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/event.c, src/event.h:
+       Kernel changes:
+       o Consolidated some of the movecursor functions in cmd.c
+
+2005-05-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF, scripts/ghul-indent, src/character.cpp, src/kern.c, src/object.c, src/sched.c, src/sched.h, worlds/haxima-1.001/chanticleer.scm, worlds/haxima-1.001/enchanters-tower-zones.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gregors-hut-zones.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/trigrave-zones.scm:
+       Part 1 of changes to allow character schedules to span multiple places
+       
+       Kernel changes:
+       o Modified kern-mk-sched to specify a place for each schedule entry
+       o Added place_sym and place to struct appt (sched.h)
+       o Added sched_get_appointment(), passing in the time; this resolves the scheme
+         place varname to the kernel place structure
+       o Modified Character::synchronize() to use sched_get_appointment() and to get
+         the place from the appointment instead of itself
+       
+       Haxima changes:
+       o Modified all scheme appointments to specify the place
+
+2005-04-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c:
+       Bugfix: manually unreadying items readied by the agent
+
+2005-03-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h:
+       nazbot_br changes:
+       o Added type_is_usable()
+       o Added actor_use_item()
+       o Removed unimplemented function declarations from agent.h
+
+       * worlds/haxima-1.001/Attic/atf.scm, worlds/haxima-1.001/Attic/map-3.scm:
+       Changed map-3.scm to have the steal-item quest
+
+2005-03-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/nazghul.c, src/session.h, worlds/haxima-1.001/Attic/map-1.scm, worlds/haxima-1.001/Attic/map-2.scm, worlds/haxima-1.001/Attic/map-3.scm:
+       Kernel changes:
+       o agent_quit() requires the actor as an arg now (so it can evaluate the final
+         score)
+       o main() now returns the agent score if the agent accomplished the goal and
+         zero otherwise
+       o Added two new fields to the session struct for the agent score and success
+         flag
+       
+       Script changes:
+       o Added three new startup games for agent training: map-1.scm, map-2.scm and
+         map-3.scm. These are all 32x32 single-map games and re-use existing maps.
+
+       * worlds/haxima-1.001/Attic/atf.scm:
+       Added health and mana potions suitable for a bot (no selection ui)
+
+       * worlds/haxima-1.001/Attic/map-1.scm:
+       file map-1.scm was initially added on branch nazbot_br.
+
+       * worlds/haxima-1.001/Attic/map-2.scm:
+       file map-2.scm was initially added on branch nazbot_br.
+
+       * worlds/haxima-1.001/Attic/map-3.scm:
+       file map-3.scm was initially added on branch nazbot_br.
+
+2005-03-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/cmd.c, worlds/haxima-1.001/Attic/atf.scm:
+       Kernel changes:
+       o actor_readied() and actor_attack_being() account for the species weapon, if
+         any
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       Had to pull spell mixing back out -- spell casting is so interactive that this feature will probably have to wait until next time. Added functions to get current hit and mana points.
+
+       * src/Attic/beowulf.c, worlds/haxima-1.001/Attic/arena.scm, worlds/haxima-1.001/Attic/atf.scm:
+       Script changes:
+       o Added mk-map, a wrapper to simplify making places
+       
+       Kernel changes:
+       o Added beowulf_move to standardize the door-opening strategy for all movement
+
+2005-03-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, worlds/haxima-1.001/Attic/arena.scm:
+       Added actor_mix to the agent interface for mixing spells
+
+2005-03-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       Removed more functions from the agent interface
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       More cleanup of agent interface; removed some functions I decided I didn't want in the interface
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/kern.c:
+       More docs and cleanup to the agent interface
+
+2005-03-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/kern.c, worlds/haxima-1.001/Attic/arena.scm, worlds/haxima-1.001/Attic/atf.scm:
+       Kernel changes:
+       o Implemented goal-checking for KILL_ALL_MONSTERS
+       o Split actor_eval into actor_eval and actor_accomplished_goal
+
+       * src/Attic/agent.c, worlds/haxima-1.001/Attic/atf.scm:
+       Kernel changes:
+       o Implemented goal-checking for ESCAPE_DUNGEON
+
+       * src/Attic/agent.h:
+       nazbot_br changes:
+       o adding comments to document agent.h
+
+2005-02-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/kern.c, src/session.c, src/session.h, worlds/haxima-1.001/Attic/atf.scm, worlds/haxima-1.001/items.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/dgervais/dg_commodities.trans.png:
+       Kernel changes:
+       o Added kern_agent_set_goal
+       o Implemented goal-checking for GOAL_STEAL_ITEM
+       
+       Image changes:
+       o Modified a copy of dgervais glowing grail sprite to pulsate
+
+2005-02-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/closure.c, src/kern.c, src/session.h, worlds/haxima-1.001/Attic/arena.scm, worlds/haxima-1.001/Attic/atf.scm:
+       Kernel changes:
+       o Added actor_eval
+       o Added kern_set_agent_eval_weights
+       
+       Bot changes:
+       o Bugfix: beowulf_rearm did not clear the rearm flag when it had no arms,
+         causing it to get stuck trying to rearm
+       
+       Script changes:
+       o Added gold to arena.scm
+       o atf.scm calls kern-set-agent-eval-weights
+
+2005-02-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/beowulf.c:
+       ifdefined-out unfinished code
+
+       * worlds/haxima-1.001/Attic/arena.scm:
+       file arena.scm was initially added on branch nazbot_br.
+
+       * worlds/haxima-1.001/Attic/arena.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/enchanters-tower.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       making sure nazbot_br is checked in
+
+       * worlds/haxima-1.001/Attic/atf.scm:
+       file atf.scm was initially added on branch nazbot_br.
+
+       * worlds/haxima-1.001/Attic/atf.scm:
+       The agent training framework start file
+
+2005-02-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS, BUGS, ChangeLog, INSTALL, Attic/aclocal.m4, scripts/RELEASE_CHECKOFF, scripts/ghul-test-install, src/nazghul.c, src/play.c, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Kernel changes:
+       o using PACKAGE_VERSION from config.h now
+
+       * Attic/Makefile.in, Attic/configure, scripts/RELEASE_CHECKOFF, src/object.c:
+       Kernel changes:
+       o removed some noisy debug
+
+2005-02-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       nazbot_br changes:
+       o bot quits when nothing left to explore
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/character.cpp, src/knapsack.h:
+       nazbot_br changes:
+       o bot rearms itself when it gets some loot
+       o bot opens doors
+
+2005-02-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       nazbot_br changes:
+       o player bot opens chests and picks up items
+
+2005-02-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/character.cpp:
+       nazbot_br changes:
+       o player bot pursues and attacks hostiles in LOS
+
+2005-02-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       nazbot_br changes:
+       o agent keeps track of where it has seen hostiles, loot, or hazardous terrain
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/kern.c, src/map.c, src/object.c, src/place.c, src/place.h:
+       nazbot_br changes:
+       o agent will try and explore the entire map, keeping track of where it has been
+         and where it could not find a path to
+
+2005-02-06  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * configure.ac:
+       Sun Feb  6 12:23:20 CET 2005  Andreas Bauer  <baueran@in.tum.de>
+       
+        * configure.ac: AC_CONFIG_HEADERS, use [] around file name
+        * configure.ac: increase program version number to 0.4.0
+
+2005-02-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/Attic/beowulf.h, src/character.cpp, src/character.h, src/ctrl.c:
+       nazbot_br changes:
+       o agents can now keep state on their actors, one agent per actor
+       o characters now keep a pointer to their agent
+       o ctrl allocates an agent when needed
+       o characters destroy agents when they are destroyed
+       o beowulf agent ifc placed behind generic agent ifc
+
+       * src/Makefile.am, src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c, src/ctrl.c, src/ctrl.h, src/nazghul.c, src/play.c:
+       The ';' key now toggles the player bot on/off
+
+       * src/Attic/agent.c:
+       file agent.c was initially added on branch nazbot_br.
+
+       * src/Attic/agent.c, src/Attic/agent.h, src/Attic/beowulf.c:
+       nazbot_br changes:
+       o agent can move around randomly
+
+       * src/Attic/agent.h:
+       file agent.h was initially added on branch nazbot_br.
+
+       * src/Attic/beowulf.c:
+       file beowulf.c was initially added on branch nazbot_br.
+
+       * src/Attic/beowulf.h:
+       file beowulf.h was initially added on branch nazbot_br.
+
+       * src/nazghul.c:
+       Added --bot switch
+
+2005-02-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/nazghul.c, src/object.c:
+       Kernel changes:
+       o Bugfix: crash when printing the name of the player party's inventory
+       o Bugfix: crash when exiting a place after a player party member's last target
+         died due to extenuating circumstances (ie fire field)
+
+       * worlds/haxima-1.001/enchanters-tower.scm:
+       Added some missing script files
+
+2005-01-30  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * ChangeLog, Makefile.am, autogen.sh, configure.ac, m4/Makefile.am, m4/sdl.m4:
+       Sun Jan 30 17:50:58 CET 2005  Andreas Bauer <baueran@in.tum.de>
+       
+        * m4/sdl.m4: new
+        * configure.ac: modify check for SDL library
+
+2005-01-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS:
+       Filled out AUTHORS based on ChangeLog
+
+       * BUGS, ChangeLog, Attic/RELEASE_NOTES, Attic/configure, Attic/configure.in, doc/USERS_GUIDE, scripts/RELEASE_CHECKOFF, src/cmd.c, src/nazghul.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm:
+       Pre-release checkin:
+       o updated version number
+       o put startup scripts at defaults
+
+2005-01-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/chanticleer.scm, worlds/haxima-1.001/containers.scm, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/jim.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/trigrave.scm, worlds/haxima-1.001/images/mixed/mine-32x32.png:
+       Haxima changes
+       o Fixed some deficiencies in the Trigrave conversations.
+
+2005-01-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/astar.c, src/character.cpp, src/kern.c, src/place.c, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/enchanters-tower-zones.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/zane.scm:
+       Kernel changes:
+       o Increased max depth of pathfinding since it wasn't enough for the 65x65
+         Enchanter's Tower
+       o Fixed a lurking bug where we could overwrite an array boundary if an NPC had
+         over 100 items in their container
+       o Improved NPC self-arming alg by ignoring items with zero heuristic value
+       
+       Haxima changes:
+       o Added Zane, a ranger who hangs out at the Enchanter's Tower
+
+       * worlds/haxima-1.001/conv.scm, worlds/haxima-1.001/earl.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/zane.scm:
+       Haxima changes
+       o Zane trades in some reagents and potions
+       o Removed some reagents from Earl's shop
+       o Added the "Sanct Nox" spell which grants temporary immunity to poison
+
+2005-01-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Kernel changes:
+       o Implemented feature request [ 1071337 ] Rest until sunrise
+
+       * src/ctrl.c:
+       Kernel changes:
+       o Implemented feature request [ 1071364 ] Automatically open doors by walking
+         into them. Didn't implement auto-lockpicking since the kernel can't tell a
+         door from a lever (the kernel doesn't know what a door or a lockpick is, or
+         that they are related). Bummer.
+
+       * src/ctrl.c:
+       Kernel changes:
+       o Implemented feature request [ 1074366 ] Leave combat map with Esc after
+         victory
+
+       * src/status.c:
+       Kernel changes:
+       o Implemented feature request [ 1074387 ] Page up/down keys should always work
+         in item menus.
+
+       * worlds/haxima-1.001/earl.scm, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/jim.scm:
+       Haxima changes
+       o Modified the shopkeeper's dialogues to indicate what time they open, as per
+         feature request [ 1074389 ].
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/spells.scm:
+       Haxima changes
+       o Implemented feature request [ 1074364 ] Resurrected characters should be
+         asleep
+
+2005-01-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * ChangeLog, src/place.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/spider.scm:
+       Haxima changes:
+       o Rebalanced movement costs and speeds to improve performance in the Abandoned
+         Farm and the Lost Halls.
+       o Simplified spider egg execution to speedup performance
+
+       * ChangeLog, src/ctrl.c, src/dtable.c, src/dtable.h, src/effect.c, src/effect.h, src/factions.h, src/kern.c, src/object.c, worlds/haxima-1.001/Attic/class-bak.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/spells.scm:
+       Kernel changes:
+       o Fixed [ 1106462 ] An Xen Bet
+       o Changed diplomacy table from being stack-based to a simple
+         increment/decrement
+       o Added another function to effects: restart, to be used specifically when
+         restoring effects on a reload
+       
+       Haxima changes:
+       o Added the An Xen Bet spell as mentioned in Ilya's conv
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/npc-types.scm:
+       Haxima
+       o Refactored doors to make it easier to add new types.
+       o Added a windowed door to Roland's cell
+       o Added a few new keywords to Roland's conversation
+       o Added images and sprites for a windowed door
+
+       * worlds/haxima-1.001/haxima.scm:
+       Haxima changes
+       o More work on enchanter's tower
+
+       * worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Haxima changes
+       o More work on enchanter's tower
+       o Added a brazier sprite & terrain type
+
+2005-01-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Party.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/kern.c, src/object.c, src/object.h, src/place.c, src/play.c, src/player.cpp, src/player.h, src/session.c, worlds/haxima-1.001/abandoned-cellar.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/food.scm, worlds/haxima-1.001/gen.scm, worlds/haxima-1.001/ilya.scm, worlds/haxima-1.001/money.scm, worlds/haxima-1.001/moongate.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/spells.scm:
+       Kernel changes:
+       o obj_dec_ref now destroys an object at zero counts
+       o removed kern_obj_destroy
+       o added kern_obj_inc_ref & kern_obj_dec_ref
+       o most objects now destroyed by ref counts instead of explicit calls to delete
+       o fixed 1065888: "refcount targets"
+       
+       Haxima changes:
+       o More work on Enchanter's Tower
+       o changes on par with kern_* api changes
+
+       * src/Container.cpp, src/place.c:
+       Kernel changes:
+       o Fixed [ 1107183 ] get from top of stack
+
+       * src/character.cpp, src/kern.c:
+       Kernel changes:
+       o Fixed 1065895 "bow vanishes": NPC characters automatically unready their
+         weapons when they run out of ammo. But the weapon was not "mirrored" in the
+         NPC's inventory container. Now it is.
+
+       * worlds/haxima-1.001/door.scm:
+       Haxima changes:
+       o Added doors, minor tweaks to Enchanter's Tower
+
+2005-01-22  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * COPYING, ChangeLog:
+       Remove nazghul/examples/data/images/.xvpics.
+
+2005-01-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Kernel changes:
+       o Added a "fill" command to terrain editing mode
+       
+       Haxima changes:
+       o More work on Enchanter's Tower
+
+       * src/ctrl.c:
+       Bugfix: \n in cmdwin_print caused crash
+
+       * src/session.c, worlds/haxima-1.001/session.scm:
+       Kernel changes:
+       o Fixed 1067142 "Session->camping_proc corrupted"
+       
+       Haxima changes:
+       o Fixed crash when opening the troll corpse in abandoned cellar (it was created
+         as an object instead of a container)
+
+2005-01-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/terrain.c, src/terrain.h, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/road.scm, worlds/haxima-1.001/sprites.scm:
+       Kernel changes:
+       o In terraform mode, holding down CTRL while pressing the arrow keys paints
+         continuously.
+       o Also in terraform mode, pressing 'c' (for C)opy) will set the terrain "pen"
+         to be the terrain type beneath the cursor.
+       
+       Haxima changes:
+       o Second draft of Enchanter's Tower main floor map
+
+2005-01-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/player.cpp:
+       Fix for 1071359: "Camp: setting a watch means certain death". The guard was not
+       properly waking up companions, and not exiting guard mode, either. In unguarded
+       ambushes party members do wake up at random as intended so that should be good
+       as well.
+
+2005-01-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.h, src/ctrl.c, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/items.scm, worlds/haxima-1.001/money.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/shard.scm:
+       Fix for bug 1074739 "Spelling errors"
+
+       * src/kern.c, worlds/haxima-1.001/haxima.scm:
+       Fix for bug 1074360 "Crash when using picklocks on
+       objects". kern_type_get_gifc() was not checking for a NULL gifc before
+       dereferencing it.
+
+       * src/kern.c, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm:
+       Fix for bug 1074371 "Inn prices lower than advertised". Modified kern_conv_say
+       to take integer args as well as strings. Room price now single-sourced in a
+       scheme variable.
+
+       * worlds/haxima-1.001/door.scm:
+       Fix for bug 1074370 "Occupied doors should stay open". Modified the door-close
+       proc to check if the tile is occupied. If not, the door remains with a pending
+       timeout of 1, which will continue to try and close the door on consecutive exec
+       cycles.
+
+2005-01-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, src/cmd.c:
+       Fix for bug 1074739 "Spelling errors"
+
+2004-12-11  Andreas Bauer  <baueran@localhost.localdomain>
+
+       * AUTHORS, ChangeLog, Makefile.am, Attic/Makefile.in, NEWS, Attic/RELEASE_NOTES, Attic/acinclude.m4, Attic/aclocal.m4, autogen.sh, Attic/config.guess, Attic/config.sub, Attic/configure, configure.ac, Attic/configure.in, Attic/depcomp, Attic/install-sh, Attic/ltmain.sh, Attic/missing, Attic/mkinstalldirs, m4/ChangeLog, m4/Makefile.am, m4/acinclude.m4, src/Makefile.am, src/Attic/Makefile.in, worlds/Attic/Makefile.in:
+       Changed build system to GNU-compliant scheme.
+
+2004-12-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * AUTHORS:
+       file AUTHORS was initially added on branch gmcnutt_scheme.
+
+       * AUTHORS, ChangeLog, Attic/Makefile.in, Attic/aclocal.m4, Attic/configure, Attic/configure.in, src/Attic/Makefile.in, worlds/haxima-1.001/ilya.scm:
+       This incorporates Andreas Bauer's patch for configure.in. Developers should
+       probably upgrade their build tools to the latest versions:
+       
+       automake -- 1.7.9
+       aclocal -- 1.7.9
+       autoconf -- 2.59
+       
+       If you have trouble try this:
+       
+       aclocal
+       autoconf
+       ./configure
+       
+       And if you STILL have trouble try automake and repeat. After that I don't know
+       any more than you do.
+
+       * ChangeLog:
+       file ChangeLog was initially added on branch gmcnutt_scheme.
+
+2004-11-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/lost-halls.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/npc-types.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/troll.scm:
+       Haxima changes:
+       o Added more monster generators to Lost Halls
+       o Characters can now climb over boulders but they might slip and fall (with
+         damage)
+       
+       Kernel changes:
+       o Added kern-obj-get-dir
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/lost-halls.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/npc-types.scm:
+       Haxima changes:
+       o Added monster generators for dungeons/towns
+       o Put a troll generator in the lost halls
+
+2004-11-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/kern.c, worlds/haxima-1.001/chanticleer.scm, worlds/haxima-1.001/door.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/haxima.scm:
+       Haxima changes:
+       o Reduced destructiveness of flaming oil
+       o Filled in some holes in Chanticleer's conversation
+       
+       Kernel changes:
+       o Added kern-conv-get-amount
+
+       * worlds/haxima-1.001/door.scm, worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/slimy-cavern.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/mixed/mine-32x32.png:
+       Haxima
+       o Refactored doors to make it easier to add new types.
+       o Added a windowed door to Roland's cell
+       o Added a few new keywords to Roland's conversation
+       o Added images and sprites for a windowed door
+
+2004-11-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/closure.c, src/kern.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/roland.scm:
+       Haxima changes:
+       o Roland now greets the player as soon as he can see any player party members
+       
+       Kernel changes:
+       o Added kern-party-get-members
+
+2004-11-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, worlds/haxima-1.001/ai.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/npc-types.scm, worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/troll.scm:
+       Haxima changes:
+       o Fixed bandit taunts to run only once per bandit
+       o Added (lame) troll taunts
+       o Roland now offers to join more prominently
+       
+       Kernel changes:
+       o Moved mode-change commands above the check for action points (if the party
+         leader is paralyzed the player can exit Follow mode so the other party
+         members don't stand around like drooling idiots while they get whaled on)
+
+2004-11-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/character.cpp, src/character.h, src/kern.c, src/play.c, worlds/haxima-1.001/effects.scm:
+       More stuff to get NPC creation all in one sock.
+       
+       Haxima changes:
+       o Changed slime-split effect to use mk-green-slime instead of kern-obj-clone
+         and removed call to obsolete slime-init
+       
+       Kernel changes:
+       o Removed kern-init-stock-char from the API, only kern-mk-char should be used
+         from now on.
+       o Removed Character::initItems()
+       o Updated Character::initStock() in light of other changes
+
+       * src/kern.c, src/occ.c, src/occ.h, worlds/haxima-1.001/af-entry.scm, worlds/haxima-1.001/npc-types.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/troll.scm:
+       More stuff to get NPC creation all in one sock.
+       
+       Haxima changes:
+       o Bugfix: trolls didn't have their ai set and couldn't pick up rocks because
+         they had no container
+       o Updated all calls to kern-mk-occ to reflect changes in the occ struct.
+       
+       Kernel changes:
+       o Removed the container and item stuff from the occupation data structure;
+         character inventories are always initialized now via their script
+         constructors.
+       o Update kern-mk-occ to remove the obsolete arguments
+
+2004-11-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, src/Container.cpp, src/Party.cpp, src/Party.h, src/character.cpp, src/closure.c, src/kern.c, src/scheme.c, src/scheme.h, worlds/haxima-1.001/abandoned-cellar.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/containers.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gregors-hut-zones.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ilya.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/npc-types.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/parties.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       More refactoring for npc type cleanup.
+       
+       Haxima changes:
+       o Modify kern_mk_party_type: remove the occupation and ai and replace them with
+         a npc type factory closure
+       o Fixup all script references to kern-mk-party-type
+       o Convert all uses of kern-mk-stock-char to kern-mk-char (add npc type
+         factories)
+       
+       Kernel changes:
+       o Modify GroupInfo for PartyType: remove occ and ai and replace them with an
+         npc factory closure
+       o Modify PartyType::addGroup to reflect these changes
+       o Modify PartyType::~PartyType to reflect these changes
+       o Modify Party::createMembers to use the closure instead of calling
+       o Character::initStock()
+       o Modify closure_exec to return a foreign func as a void *
+
+2004-11-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/kern.c, src/scheme.c, src/session.c:
+       Step 1 1/2 of refactoring for new npc type factories
+
+2004-11-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/engine_extension_and_design/ENGINE_CLEANUP, doc/engine_extension_and_design/ENGINE_DESIGN_NOTES, src/Container.cpp, src/Party.cpp, src/character.cpp, src/closure.c, src/closure.h, src/kern.c, src/occ.c, src/occ.h, src/place.c, src/session.c, worlds/haxima-1.001/haxima.scm:
+       Fixed one nasty crash on reload; more still lurking
+
+2004-11-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/engine_extension_and_design/ENGINE_CLEANUP, doc/engine_extension_and_design/ENGINE_DESIGN_NOTES:
+       New doc files
+
+2004-11-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c, src/common.c, src/common.h, src/player.cpp, src/player.h, src/session.c, src/sound.c, src/sprite.c, src/sprite.h:
+       Removed some obsolete code; added call to SDL_CloseAudio on exit (when sound is used)
+
+       * src/object.c:
+       Bugfix: uninitialized string in ObjectType class caused intermittent crash on reload
+
+2004-10-28  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/images/dgervais/dg_weapons.trans.png:
+       Fixed the eldritch blade (left of the flaming sword).
+       The second animation frame was offset 1 pixel to the right.
+
+2004-10-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, Attic/configure.in, doc/USERS_GUIDE, src/character.cpp, src/nazghul.c, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/earl.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/scrolls.scm, worlds/haxima-1.001/slimy-cavern.scm, worlds/haxima-1.001/spells.scm:
+       Haxima changes:
+       o Roland now does a pathfinding test when asked to join
+       o Roland now (again) states his fealty to Lord Froederick when asked to join
+       o Added a resurrection scroll; put one in starter chest; can by more in trigrave
+       o Change Roland's level to 3
+       o Added equipment for Roland
+       o Reduced count of flaming oil for bandits
+       o Reduced range of xbow
+       o Roland mentions that he will JOIN
+       
+       Kernel changes:
+       o Special message now printed when a party member dies
+
+       * Attic/Makefile.in, Attic/configure, scripts/RELEASE_CHECKOFF, worlds/haxima-1.001/haxima.scm:
+       Final checkin before release
+
+2004-10-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/roland.scm:
+       Haxima changes:
+       o Roland now does a pathfinding test when asked to join
+       o Roland now (again) states his fealty to Lord Froederick when asked to join
+
+       * worlds/haxima-1.001/ai.scm, worlds/haxima-1.001/items.scm, worlds/haxima-1.001/scrolls.scm:
+       Adding a missed file
+
+       * worlds/haxima-1.001/combat-maps.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/images/mixed/mine-32x32.png:
+       Haxima changes:
+       o Added combat maps for east-west bridges and roads
+
+       * worlds/haxima-1.001/items.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       *** empty log message ***
+
+2004-10-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.cpp, src/character.h, src/kern.c, src/object.c, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/trigrave.scm:
+       Kernel changes:
+       o Bugfix: crash on reload due to double-deallocation of convs
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/play.c, worlds/haxima-1.001/haxima.scm:
+       Haxima changes:
+       o Added a hint about the shrine cave in the startup script.
+       
+       Kernel changes:
+       o Added a "help" command bound to '?'
+
+       * worlds/haxima-1.001/camping-map.scm, worlds/haxima-1.001/haxima.scm:
+       Haxima changes:
+       o Saved games now have wilderness ambushes
+
+       * worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/naz.scm:
+       Haxima changes:
+       o Removed the "L" from status for light effects
+
+       * worlds/haxima-1.001/game.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/parties.scm, worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/species.scm:
+       Haxima changes:
+       o Switched the bandits to use the generic script ai
+       o Added taunts to the generic ai
+
+2004-10-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/player.cpp:
+       Kernel changes:
+       o Fixed some bugs that appeared when an NPC joined the player party
+
+       * src/closure.c, worlds/haxima-1.001/camping-map.scm, worlds/haxima-1.001/earl.scm, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/occs.scm:
+       Haxima changes:
+       o Adde reagents and potions to the Trigrave Dry Goods store
+       o Added a chance of getting healing potions from bandits
+       
+       Kernel changes:
+       o Bugfix: broke entry to trigrave with recent changes
+
+2004-10-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/Container.cpp, src/Field.cpp, src/Party.cpp, src/character.cpp, src/character.h, src/closure.c, src/closure.h, src/ctrl.c, src/effect.c, src/kern.c, src/object.c, src/place.c, src/session.c, src/session.h, src/sky.c, src/terrain.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/kobj.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/slimy-cavern-zones.scm, worlds/haxima-1.001/slimy-cavern.scm:
+       Haxima changes:
+       o Modified pathfind to use the new kern-being-pathfind-to
+       o Added an ai for roland which will have him try to escape; once escaped it
+         reverts to the default kernel ai
+       
+       Kernel changes:
+       o Moved Character::pathfindTo up to Being::pathfindTo
+       o Added kern-being-pathfind-to
+       o Added kern-char-set-ai
+       o Changed all closure_del() to closure_unref(); closures must be destoryed via
+         ref counts (otherwise setting the closure to null from within the closure
+         might cause scheme to gc it before we can extract the return value in
+         closure_exec)
+
+       * src/kern.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/roland.scm:
+       Haxima changes:
+       o Roland will join the player once freed
+       
+       Kernel changes:
+       o Added kern-char-join-player (still has some bugs)
+
+       * worlds/haxima-1.001/roland.scm, worlds/haxima-1.001/slimy-cavern.scm:
+       Haxima changes:
+       o Started on Roland, a prisoner in the slime cave.
+
+2004-10-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/character.cpp, src/character.h, src/combat.c, src/combat.h, src/kern.c, src/play.c, src/player.cpp, src/session.c, src/session.h, worlds/haxima-1.001/af-entry.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/camping-map.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/spider.scm:
+       Haxima changes:
+       o Added the camping map
+       o Added a camping hook to generate ambushes while the player is camping in the
+         wilderness
+       
+       Kernel changes:
+       o Added kern-ambush-while-camping
+       o Changed kern-obj-is-char? to kern-obj-is-being?
+       o Changed kern-char-is-hostile? to kern-being-is-hostile?
+       o Added a camping_proc hook to the session
+       o Modified the main loop to invoke the session's camping_proc every turn when
+         the player is camping
+
+       * src/character.cpp, src/character.h, src/common.h, src/kern.c, src/player.cpp, src/status.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/scrolls.scm, worlds/haxima-1.001/session.scm:
+       Haxima changes:
+       o Parameters to kern-mk-player changed (due to removal of rest credits)
+       o Doubled the light per torch
+       
+       Kernel changes:
+       o Ripped out rest credits
+
+       * worlds/haxima-1.001/earl.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/lost-halls.scm, worlds/haxima-1.001/portals.scm, worlds/haxima-1.001/shard.scm:
+       Haxima changes:
+       o Added lost-halls.scm, a port of Sam's ork cave from the old ghulscript
+       o Added a mine entrance as an auto-portal
+
+2004-10-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/common.h, src/ctrl.c, src/kern.c, src/occ.h, src/species.h, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       These changes polish up the experience/advancement system a bit.
+       
+       Haxima changes:
+       o Set experience levels for all existing species and occs
+       
+       Kernel changes:
+       o Got rid of wasElevated and setElevated methods in Character class
+       o Added getExperienceValue method to Character class
+       o Added xpval fields to species and occ structs
+       o Removed addExperience in cmdOpen for traps
+       o Removed addExperience for attacks
+       o Added addExperience for kills
+       o Got rid of hard-coded XP values in common.h
+       o Added a console message when any Character gains a level
+       o Added a mapFlash when a player-controlled Character gains a level
+
+2004-10-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/object.c, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/jim.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/parties.scm, worlds/haxima-1.001/shard.scm:
+       Haxima changes:
+       o Added a bandit generator by the river
+       o Monster and ambush generators invisible
+       o Added a bandit occupation
+       o Added a bandit gang npc party type
+       
+       Kernel changes:
+       o kern-obj-set-visible now returns the object
+       o NPC parties were not wandering; fixed them
+
+       * src/place.c, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/slimy-cavern.scm, worlds/haxima-1.001/species.scm:
+       Haxima changes:
+       o Tweaked the moongate clearing map to make the northeast cave more obvious
+       o Added a bandit party waiting just outside the shrine
+       o Added some bandits to the back of the slimy cave
+       o Commented-out the "advanced items" chests
+       o Added a sling type and put one in the starter chest
+       o Gave the slime's acid spray a sprite
+       o Removed one slime generator from the Slimy Cave and moved the other; also
+         gave it a target location other than its own where slimes appear from
+       o Added a faction for outlaws (so they will fight with monsters)
+       o Rebalanced slime damage
+       o Reduced default movement speed to 1 to prevent NPCs from jumping around
+         erratically in town
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/earl.scm, worlds/haxima-1.001/trigrave-zones.scm, worlds/haxima-1.001/trigrave.scm:
+       Haxima changes:
+       o Added Earl, proprieter of the Trigrave general store
+
+       * worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/trigrave.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Changed Chanticleer's sprite
+
+2004-10-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, src/kern.c, worlds/haxima-1.001/monster-generator.scm:
+       Haxima changes:
+       o Made an ambush generator constructor
+       o Changed spider generators from party generators to ambush generators
+       
+       Kernel changes:
+       o Added kern-begin-combat to support ambushes
+
+       * src/kern.c, src/scheme.c, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/shard.scm:
+       Haxima changes:
+       o The ambush generators now monitor a region of the map
+       
+       Kernel changes:
+       o Added kern-get-player to return a reference to the player party
+       o kern-begin-combat now uses the correct orientation for ambushes
+
+       * src/kern.c, worlds/haxima-1.001/combat-maps.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/terrains.scm:
+       Haxima changes:
+       o Ported over the old ghulscript combat maps for grass, forest and hills
+       
+       Kernel changes:
+       o Added kern-terrain-set-combat-map
+
+       * src/sched.c, src/sched.h, worlds/haxima-1.001/chanticleer.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ifc.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/trigrave-zones.scm, worlds/haxima-1.001/trigrave.scm:
+       Haxima changes:
+       o Expanded Chanticleer's conversation and added him to trigrave
+       o Renamed the inn and tweaked some torch placement
+       o Added more beds
+       
+       Kernel changes:
+       o Added an activity for "drunk" (yes, I need to get these activities out of the
+         kernel...)
+
+       * worlds/haxima-1.001/shard.scm:
+       Haxima changes:
+       o Added roads (as terrains, not features) to the shard surface.
+
+2004-10-16  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/abandoned-cellar.scm, worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/bakup.scm, worlds/haxima-1.001/camping-map.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/slimy-cavern.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/trigrave.scm, worlds/haxima-1.001/vehicles.scm:
+       Palette cleanup.
+       Changing pal_expanded to have all glyphs be 2 characters wide.
+       Added non-LOS-blocking versions of various terrains.
+
+2004-10-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.c, src/astar.h, src/character.cpp, src/character.h, src/kern.c, src/player.cpp, worlds/haxima-1.001/door.scm, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ifc.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/trigrave-entry.scm, worlds/haxima-1.001/trigrave.scm:
+       o Bugfix: hard to get large parties through doors. Fixed this with two fairly
+         significant changes to character pathfinding. One change is that characters
+         now cache their paths so they can reuse them on subsequent turns if their
+         target destination has not changed. The second change is that by default they
+         pathfind through mechanisms. If they come to an impassable tile they check
+         for a mechanism and if it can be handled. If so, they handle it. This takes
+         care of doors. If the tile is still impassable they find a new path around
+         it.
+
+       * src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h, src/player.cpp, src/player.h, worlds/haxima-1.001/beds.scm, worlds/haxima-1.001/food.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/money.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/trigrave.scm:
+       Haxima changes:
+       o Added an object type for gold coins
+       o Fixed a bug in getting food (it was ignoring the object count)
+       o Gave the player some starting gold in the supplies chest
+       o Changed the innkeeper so that when she is eating she won't engage in business
+       
+       Engine changes:
+       o Added an addGold method analogous to the existing addFood methods
+
+       * src/kern.c, src/play.c, src/player.cpp, src/session.c, src/session.h:
+       Engine changes:
+       o Time runs faster when sleeping and camping
+
+       * worlds/haxima-1.001/spells.scm:
+       Haxima changes:
+       o Torches weren't getting removed from inventory when they were used.
+
+2004-10-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       o Bugfix: opening corpses on doors. Fixed this by adding a selection dialog to
+         cmdGet. Used whenever a container and a mech are found on the same
+         tile. We'll probably want to extend it to handle an arbitrary number of
+         targets but for now its fixed at just the two.
+
+       * worlds/haxima-1.001/chanticleer.scm:
+       Start of a new character
+
+       * worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       Eliminated the spider corpses
+
+       * worlds/haxima-1.001/troll.scm:
+       Bugfix: accidentally checked in a partial change
+
+2004-10-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/gwen.scm, worlds/haxima-1.001/trigrave-zones.scm, worlds/haxima-1.001/trigrave.scm:
+       Put the innkeeper into trigrave
+
+       * worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/trigrave.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Added a new sprite: gray-robed humanoid (for Gwen the Innkeeper of Trigrave)
+
+2004-10-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE, src/kern.c, worlds/haxima-1.001/spells.scm:
+       Bugfix: webs getting dropped on impassable terrain
+
+       * src/combat.c, src/kern.c, src/place.c, src/scheme.c, src/terrain_map.c, src/terrain_map.h:
+       Bugfix: ship maps getting saved multiple times
+
+       * src/scheme-private.h:
+       Increased memory for scheme allocator (running out when reloading in session.scm)
+
+       * worlds/haxima-1.001/camping-map.scm, worlds/haxima-1.001/session.scm:
+       Bugfix: broke save/reload in session.scm with my last map-saving fix; this fixes it
+
+       * worlds/haxima-1.001/gwen.scm:
+       Minor change to conv
+
+       * worlds/haxima-1.001/gwen.scm:
+       New character started
+
+2004-10-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * README:
+       Changed the reference to INSTALL and USERS_GUIDE to the top where people can find it easier
+
+       * worlds/haxima-1.001/jim.scm, worlds/haxima-1.001/Attic/john_iron.scm, worlds/haxima-1.001/trigrave-zones.scm, worlds/haxima-1.001/trigrave.scm:
+       Changed the blacksmith in trigrave
+
+2004-10-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp:
+       Bugfix: save/reload gives extra weapons. Readied items were being saved twice.
+
+       * worlds/haxima-1.001/Attic/john_iron.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/trigrave-zones.scm, worlds/haxima-1.001/trigrave.scm:
+       Added a blacksmith to trigrave
+
+       * worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/parties.scm, worlds/haxima-1.001/shard.scm:
+       Added some basic random encounter generators to the wilderness
+
+2004-10-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, INSTALL, Attic/Makefile.in, README, Attic/RELEASE_NOTES, Attic/configure, Attic/configure.in, doc/USERS_GUIDE, scripts/RELEASE_CHECKOFF, src/kern.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/trigrave.scm:
+       Added (unpopulated) town: Trigrave
+
+       * src/Attic/Makefile.in, src/nazghul.c, src/player.cpp:
+       Bugfix: segfault when saving games started with the --sound 0 option
+
+       * src/scheme.c:
+       Patch from Tim Douglas to fix compile error on Max OS X v10.3.5
+
+2004-10-09  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/moongate-clearing.scm:
+       Added many new arms and armor types, and added instances into the game.
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Removed _map (a test/example of some kind).
+
+       * worlds/haxima-1.001/moongate-clearing.scm:
+       Fixed up some width/alignment issues due to width-1 boulder glyphs within the map.
+
+       * worlds/haxima-1.001/objs.scm:
+       Added some new chest types.
+
+       * worlds/haxima-1.001/reagents.scm:
+       Fixed their order.  Commented out a 'bloodmoss' type which seemed to be a duplicate.
+
+2004-10-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/combat.c, src/event.c, src/kern.c, src/nazghul.c, src/object.c, src/object.h, src/player.cpp, src/player.h, src/sound.c, src/sound.h, src/species.c, src/species.h, src/vehicle.cpp, src/vehicle.h, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/sounds.scm:
+       o Sounds are now loaded as kernel objects. This change is intended to eliminate
+         the lag when playing sounds under windows.
+
+2004-10-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, src/Attic/Makefile.in:
+       Fixing a borken Makefile.in (hopefully)
+
+       * Attic/depcomp, src/Makefile.am, src/Attic/Makefile.in, src/nazghul.c, src/play.c, src/tick.c, src/tick.h:
+       o Bugfix: tick generation is paused while loading/reloading. In the process of
+         fixing this I tore the existing tick code out of nazghul.c and put it in its
+         own tick.c. Added routines to pause and resume tick generation.
+
+       * src/cmd.c, src/cmd.h:
+       Fixed the CTRL-<num> keys used by the T)erraform command to use UNICODE so it will work on non-US keyboards
+
+       * src/cmd.c, src/cmd.h, src/ctrl.c, src/event.h:
+       Karl Garrison's patch to dump terrain sprites as one BMP per frame
+
+       * worlds/haxima-1.001/sounds/cannon.wav, worlds/haxima-1.001/sounds/damage.wav, worlds/haxima-1.001/sounds/enter_moongate.wav, worlds/haxima-1.001/sounds/horse.wav, worlds/haxima-1.001/sounds/rowing.wav, worlds/haxima-1.001/sounds/walk.wav:
+       New sound files from Sam
+
+2004-10-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/player.cpp:
+       o Bugfix: N)ew Order when the leader is one member and a dead or incapacitated
+         member is the other would effectively hang the system when in follow
+         mode. With this change incapacitated members cannot be selected as the party
+         leader.
+
+       * src/cmd.c:
+       Fixed: opening a chest describes everything on the tile, not just the contents
+
+       * src/ctrl.c:
+       o UI change. If the player has just one party member and he uses the A)ttack
+         command the party will not switch out of follow mode. This way the camera
+         remains centered on the character.
+
+       * src/gob.c, src/object.c, src/scheme.c:
+       Fixed a memory leak. Wasn't freeing the hook entries on the hook lists maintained by objects.
+
+       * src/map.c, src/nazghul.c:
+       Bugfix: on some redhat systems we would crash on exit (even without sound enabled)
+
+       * src/sound.c:
+       Corrected the copyright notice at the top of this file
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/haxima.scm:
+       Rebalanced slimes
+
+       * worlds/haxima-1.001/terrains.scm:
+       Made bogs exude poisonous fumes again
+
+2004-10-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/event.c:
+       Removed #ifdefs for UNICODE
+
+       * src/event.c:
+       Bugfix: UNICODE changes broke Page Up/Down, now fixed for US keyboards (unsure about others)
+
+       * src/nazghul.c, src/Attic/splash.png:
+       Added splash screen on startup
+
+       * src/Attic/splash.png:
+       Removed extra copy of splash image file
+
+       * src/terrain_map.c:
+       o Bugfix: saving/reloading on win32. The problem was in terrain_map_save, where
+         the tiles were being saved as printf("%02s", tag). On windows it printed the
+         leading zero, on linux not. Removed the zero and all is well. Not sure why I
+         had a zero there to begin with.
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate.scm:
+       o Fixed the long delays in the opening cut scene. These were not unique to
+         win32. During the port I had to change usleep to SDL_Delay, which takes a
+         longer unit of time as an argument.
+
+       * worlds/haxima-1.001/images/gmcnutt/splash.png:
+       Adding splash image.
+
+2004-10-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, src/event.c, src/event.h:
+       o Converted to UNICODE for keypresses.
+
+       * src/ctrl.c, src/object.c, src/player.cpp, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/slimy-cavern.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm:
+       Added slime to the Slimy Cavern
+
+       * worlds/haxima-1.001/effects.scm:
+       Bugfix: when paralysis wore off it allowed the player to attack while ensnared
+
+       * worlds/haxima-1.001/slimy-cavern.scm:
+       Fixed load error in slimy-cave.scm due to a missing (unnecessary) file
+
+2004-10-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, Attic/configure, Attic/configure.in, Attic/depcomp, scripts/RELEASE_CHECKOFF, src/Party.cpp, src/character.cpp, src/cmd.c, src/common.c, src/ctrl.c, src/images.c, src/kern.c, src/map.c, src/nazghul.c, src/scheme.c, src/scheme.h, src/screen.c, src/session.c, src/wind.c:
+       Changes needed to compile and run under win32
+
+       * Attic/depcomp:
+       file depcomp was initially added on branch gmcnutt_scheme.
+
+       * worlds/haxima-1.001/abandoned-cellar.scm, worlds/haxima-1.001/bridge.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ilya.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/portals.scm, worlds/haxima-1.001/scrolls.scm, worlds/haxima-1.001/slimy-cavern.scm:
+       o Added a cave entrance to moongate-clearing
+       o Added torches to the warchest
+       o Added a troll and troll corpse to abandoned-cellar
+
+2004-10-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, COPYING, INSTALL, Attic/RELEASE_NOTES, Attic/configure, Attic/configure.in, doc/USERS_GUIDE, scripts/RELEASE_CHECKOFF, src/ctrl.c, src/nazghul.c, src/place.c, src/play.c, worlds/haxima-1.001/haxima.scm:
+       Last-minute tweaks for release
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/ilya.scm, worlds/haxima-1.001/pre-entry-hooks.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       o Bugfix: Entering green tower from session.scm was crashing due to an
+         out-of-date entry procedure.
+       o Bugfix: could not complete puska quest due to invalid scheme proc in ilya's
+         code
+
+2004-10-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/status.c:
+       o UI change: added a "Misc" pane to the inventory UI. Objects which don't fall
+         into any of the other categories (readyable, usable, mixable or castable) are
+         displayed here.
+
+       * worlds/haxima-1.001/abandoned-cellar.scm, worlds/haxima-1.001/ilya.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       o Finished implementing the puska quest
+
+2004-09-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * scripts/RELEASE_CHECKOFF, src/cmd.c, src/kern.c, src/place.c, src/play.c, src/player.cpp, src/scheme.c, src/session.h:
+       o Bugfix: LOS on reload was messed up. On reload, the current place was locked
+         so it did not get cleaned up => any objects in the place did not get cleaned
+         up => player characters did not get destroyed => they did not remove their
+         map views => in the new session, the old map views were still hanging around,
+         contributing to player LOS.
+
+       * src/character.cpp, src/place.c, src/scheme.c:
+       o Added an assert to ensure that the kernel has released all of its references
+         to scheme cells when we tear down the scheme session. This assert currently
+         fires on reload. That's because we tear down the scheme session before we
+         tear down the player's current place, and there are bound to be objects in
+         that place that still reference gobs. I'm checking this in so I can continue
+         to debug it on another machine.
+
+2004-09-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/scheme.c, src/scheme.h, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       o Added gc protection to various places in kern.c where it's necessary to
+         allocate more than one cell before returning to scheme. This fixes the
+         annoying "*** script error ***" messages that appeared intermittently.
+
+2004-09-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/abandoned-cellar.scm:
+       New place file
+
+2004-09-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, Attic/aclocal.m4, Attic/configure, src/Being.h, src/Party.h, src/cmd.c, src/kern.c, src/object.c, src/place.c, src/play.c, src/vmask.c, src/vmask.h, worlds/Attic/Makefile.in, worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/spider.scm:
+       o Bugfix: 'evade' now checks terrain for passability before trying to move
+         there. This prevents spiders from killing themselves on wall torches.
+       
+       o Performance: spider eggs now use kern-fold-rect when searching for
+         disturbances.
+       
+       o Bugfix: the vmask cache was not keeping count of its entries.
+       
+       o Added vmask_flush_all()
+       
+       o Bugfix: some destructors were not declared virtual as they should have been.
+
+2004-09-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/scheme.c, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/troll.scm:
+       Various experiments with improving AI performance
+
+2004-09-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/Party.cpp, src/character.cpp, src/combat.c, src/node.c, src/node.h, src/object.c, src/object.h, src/place.c, src/player.cpp:
+       o Converted the Party class's member list field from an embedded list to a
+         wrapper list; likewise for the hook in the Character class
+
+       * src/character.cpp, src/kern.c, src/map.c, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm, worlds/haxima-1.001/yellow-slime.scm:
+       o Fixed a couple of places where a callback function was not initialized
+         properly. This is a bug introduced *after* 0.3.0.
+       
+       o Various fixes to get session.scm working again.
+
+       * src/ctrl.c, src/event.c, src/kern.c, src/map.c, src/place.c:
+       Added kern_place_get_beings, a kernel filter for kern_place_get_objects, which speeds up the ai's noticeably
+
+       * src/kern.c, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       Improving performance. Added kern-being-get-visible-hostiles, which is a kernel
+       implementation of the all-visible-hostiles scheme procedure. The scheme version
+       ran in about 27 ms on my machine, the kernel version takes less than 1
+       ms. Virtually every AI uses this procedure on every turn.
+
+2004-09-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/event.c:
+       Numeric keypad now returns numbers when NUMLOCK enabled
+
+2004-09-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Makefile.am, Attic/Makefile.in:
+       Bugfix: removed examples as a source directory for make
+
+       * src/Field.cpp, src/Field.h, src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/combat.c, src/ctrl.c, src/node.c, src/node.h, src/object.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h:
+       Replaced embedded turn_list with wrapper node list
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/node.h, src/player.cpp:
+       o Converted the Party class's member list field from an embedded list to a
+         wrapper list; likewise for the hook in the Character class
+
+       * src/character.cpp, src/character.h:
+       Removed an obsolete list field from the Character class
+
+       * src/combat.c, src/ctrl.c, src/node.c, src/object.c, src/object.h, src/place.c, src/place.h:
+       o Fixed a few bugs in the new turn_list code and enabled it.
+
+       * src/place.c, src/place.h:
+       Removed some obsolete lists from the place structure
+
+       * worlds/haxima-1.001/spider.scm:
+       Turned off debug spew from spider.scm
+
+2004-09-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c, src/ctrl.c, src/node.c, src/node.h, src/place.c, src/place.h:
+       More invisible changes to fix the offset warnings
+
+       * src/combat.c:
+       Added yet more unused functions to combat (preparing to fix the list warnings)
+
+       * src/ctrl.c, src/event.c:
+       o Bugfix: NUMLOCK prevents ctrl key from working properly. This was due to use
+         of an '==' operator where an '&' operator belonged.
+       
+       o Added debug output to help debug problems with other people's keyboards.
+
+2004-09-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c:
+       Added new (unused) function
+
+       * src/list.h:
+       Removed some dead code
+
+       * src/object.c, src/object.h:
+       Removed the obsolete list field from the ObjectType class
+
+2004-09-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/spider.scm:
+       o Trolls now pick up boulder ammo dropped on the ground.
+       o Fixed a script error causing an invalid location.
+
+       * worlds/haxima-1.001/ilya.scm:
+       Fixed some minor bugs in Ilya's conversation.
+
+2004-09-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, scripts/RELEASE_CHECKOFF, src/character.cpp, src/kern.c, src/object.h, src/species.c, src/species.h, worlds/haxima-1.001/reagents.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/troll.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       o Added a field to species: on_death which is a script closure that expects the
+         character as a parm
+       o Fixued up kern_mk_species to expect the other parm.
+       o character::kill() calls the species on_death closure _before_ removing the
+         object (so the on-death proc can get the final coordinates of the character)
+       o Modified all the kern-mk-species calls to specify nil (by default) for their
+         death closure
+       o Createed an on-death proc for spiders which creates a corpse container and
+         puts a random amount of spider silk in it
+       o Modified the spider kern-mk-species call to specify the on-death proc
+       o Changed the sprites for the spider corpse and the spider silk reagent.
+
+       * src/kern.c, src/vmask.c, worlds/haxima-1.001/spells.scm:
+       o Bugfix: kern_in_los was computing the y-component of the vmask coordinates
+         incorrectly due to a typo.
+
+       * worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       o Queen spider animation fixed up a bit
+       o Added a queen spider corpse
+
+2004-09-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, INSTALL, Makefile.am, Attic/Makefile.in, Attic/RELEASE_NOTES, Attic/configure, Attic/configure.in, scripts/RELEASE_CHECKOFF, scripts/ghul-test-install, src/Makefile.am, src/Attic/Makefile.in, src/kern.c, src/nazghul.c, src/object.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Pre-release tweaks and changes
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Added a queen spider
+
+       * worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/naz.scm:
+       Paralysis prevents struggling against ensnare
+
+2004-09-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/object.c, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/spider.scm:
+       o Spiders now use a vampiric melee attack which drains hp from their targets
+         and heals them of damage.
+       o Added a web-spew skill for spiders. They can shoot webs similar to a wind
+         spell for a limited range. With these two changes spiders are almost an even
+         match for trolls.
+       o Bugfix: effects added to the keystroke-hook were not being removed properly
+         for NPC's.
+
+       * worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spider.scm:
+       Added a paralysis skill for spiders. Interaction with ensnare not optimal yet.
+
+2004-09-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/dtable.c, src/kern.c:
+       dtable defaults now set in dtable_new(), not kern_mk_dtable()
+
+       * src/effect.h, src/kern.c, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       o Added kern-obj-get-effects
+       o Spiders now attack foes that are disabled (sleeping or ensnared)
+
+       * worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/troll.scm:
+       Webs break when somebody struggles free
+
+2004-09-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/scrolls.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm:
+       o Spiders now immune to the ensnare effect (caused by webs)
+       o Using scrolls no longer consumes the scroll if the usage method
+         returns nil (so a user can ESC out of some usages)
+
+       * src/ctrl.c, src/kern.c, src/object.c, src/object.h, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/scrolls.scm, worlds/haxima-1.001/spider.scm:
+       o Added kern-obj-get-name
+       o Added a new hook that runs while processing a user keystroke in character
+         mode.
+       o Modified the web ensnare effect to use the keystroke hook. Now when a user
+         character is ensnared it works like Adom: the user has to keep hitting a key
+         to "struggle" against the web until he finally breaks free.
+
+       * src/kern.c, src/object.c, src/object.h, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/fields.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/reagents.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/troll.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Added spider webs
+
+2004-09-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Missile.cpp, src/kern.c, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/session.scm:
+       Kernel arms types no longer refer to field types. Cases where arms create fields are now all handled in the script.
+
+       * src/Missile.cpp, src/kern.c, src/object.c, src/object.h, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/items.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/scrolls.scm:
+       Changed missile interface
+
+       * src/ctrl.c:
+       Added base 1d20 for to-hit on all attacks (as per new combat system rules)
+
+       * src/map.c:
+       Bugfix: missiles with off-screen targets were animating wrong
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/troll.scm:
+       Bugfix for troll picking up boulder
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Added a sprite to distinguish between loose boulders (objects) and terrain boulders
+
+       * worlds/haxima-1.001/arms.scm:
+       Thrown boulders now convert back to boulder terrain when they hit
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ifc.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/scrolls.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/troll.scm, worlds/haxima-1.001/images/dgervais/dg_readable-32x32.png:
+       Added our first usable spell scroll and put a few in the startup warchest
+
+       * worlds/haxima-1.001/ifc.scm, worlds/haxima-1.001/scrolls.scm:
+       Cleanup of scroll code. Trivial now to add spell scrolls.
+
+       * worlds/haxima-1.001/troll.scm:
+       Trolls pay 2 turns worth of action points for ripping up boulders
+
+2004-09-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/troll.scm:
+       o More refactoring around the troll AI.
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/af-entry.scm, worlds/haxima-1.001/shard.scm:
+       Moved the abandoned farm
+
+       * worlds/haxima-1.001/af-entry.scm, worlds/haxima-1.001/naz.scm:
+       Changed spider spawn points in the abandoned farm
+
+2004-09-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/place.c, src/place.h:
+       o Fixed a bug related to NPC characters exiting the map via a kern-obj-move
+         call.
+
+       * worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/troll.scm:
+       o Trolls now pick up boulder ammo dropped on the ground.
+       o Fixed a script error causing an invalid location.
+
+2004-09-09  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/cmd.c, src/event.h:
+       Working on polish and new features for the Terraform UI.
+
+       * src/terrain.c:
+       Fixed palette_print() and palette_entry_print() to emit Scheme.
+       Also keeping track of palette->widest_glyph again.
+
+       * src/terrain.h:
+       Minor cleanup (removed some junk).
+
+       * src/terrain_map.c:
+       Changed terrain_map_print() to emit Scheme maps.
+
+       * src/terrain_map.c:
+       Fixed an ASCII diagram which got screwed up
+       by an automatic code indenter or similar.
+
+       * worlds/haxima-1.001/palette.scm:
+       Re-generated palette with palette_print().
+       Works great, with added comments.
+
+2004-09-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/character.cpp, src/character.h, src/kern.c, src/player.cpp:
+       Characters now save/load their personal containers
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/gregor.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       Trolls cannot evade diagonally now
+
+       * worlds/haxima-1.001/troll.scm:
+       Started a refactor of troll ammo-hunting alg to accomodate loose boulder objects lying on the ground (their fellow trolls usually drop a few when they die
+
+2004-09-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/character.cpp, src/character.h, src/kern.c, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/troll.scm:
+       o Created a specialized AI for trolls. This one prefers to fight at range and
+         will pick up nearby boulders and use them as ammo. It will also flee (using
+         the braindead legacy flee code in the kernel).
+
+2004-09-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h, src/player.cpp, src/player.h, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/troll.scm:
+       o Translated the original C combat AI into Scheme. Tested it with trolls. This
+         is supposed to offer a reasonable starting point for making custom combat
+         AI's in scheme.
+
+2004-09-02  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * doc/world_building/advancement.rogue.txt, doc/world_building/advancement.warrior.txt, doc/world_building/advancement.wizard.txt, doc/world_building/advancement.wright.txt, doc/world_building/being_tile_media.txt, doc/world_building/music_loop_media.txt, doc/world_building/sound_sample_media.txt, doc/world_building/town_scale_tile_media.txt, doc/world_building/wilderness_scale_tile_media.txt:
+       Transcribing various notes.
+
+2004-09-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ctrl.c, src/location.h, src/player.cpp, src/Attic/tile.c, src/Attic/tile.h, worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/af-entry.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spider.scm, worlds/haxima-1.001/troll.scm:
+       o Added a spider "class" in scheme
+       o Added a monster generator in the Abandoned Farm to keep it populated with
+         warring trolls and spiders
+
+2004-09-01  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * doc/world_building/being_tile_media.txt, doc/world_building/being_tile_media.txt, doc/world_building/music_loop_media.txt, doc/world_building/sound_sample_media.txt, doc/world_building/town_scale_tile_media.txt, doc/world_building/wilderness_scale_tile_media.txt:
+       Added some files.
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Added end-of-line comments to map lines with the Y coordinate.
+
+2004-09-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/player.cpp:
+       Forcing the player to follow mode when a single-member party wants to exit a small-scale place and it isn't in follow mode. Convenience feature.
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/shard.scm, worlds/haxima-1.001/sprites.scm:
+       Expanded world map to alpha release size
+
+       * worlds/haxima-1.001/shard.scm:
+       *** empty log message ***
+
+2004-08-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, src/Container.cpp, src/cmd.c, src/object.c, src/place.c, src/place.h:
+       o Bugfix: getting certain items like a poison bolt would lock/crash the engine
+       o Bugfix: getting piles of items was emitting one message per item in the pile
+
+2004-08-26  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/arms.scm:
+       Changed various sprites to new hi-res sprites.
+       Added some objects to the Terrain Test.
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/food.scm, worlds/haxima-1.001/objs.scm:
+       Replacing ss_angband sprites with the new higher resolution sprites.
+
+       * worlds/haxima-1.001/images/kgabbert/new_terrains.png:
+       Added a boulder-on-grass sprite (for use as a terrain)
+       in addition to the boulder sprite (with FF00FF for a terrain feature).
+
+2004-08-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/status.c, src/status.h:
+       Added kern-ui-select-from-list
+
+       * src/place.c:
+       Fixed some item count reporting when examing around
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/food.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/items.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/troll.scm:
+       Added more stuff to the start place
+
+       * worlds/haxima-1.001/gregor.scm:
+       Tweaked gregor's conv
+
+       * worlds/haxima-1.001/gregor.scm:
+       Fixed a bug in gregor's conv
+
+       * worlds/haxima-1.001/items.scm:
+       Added to the in-game user's manual
+
+       * worlds/haxima-1.001/session.scm:
+       Renamed a potion type
+
+2004-08-25  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm, worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/sprites.scm:
+       Added ss_kg_potions_1 and ss_kg_potions_2 to the Sprite Gallery.
+
+2004-08-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/common.h, src/play.c:
+       Reduced rate of time
+
+       * worlds/haxima-1.001/gregor.scm:
+       Added a bit more to Gregor's conversation
+
+       * worlds/haxima-1.001/gregor.scm:
+       New file
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/session.scm:
+       Added Gregor to the start place
+
+2004-08-24  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm, worlds/haxima-1.001/sprites.scm:
+       Added ss_dg_commodities to the sprite gallery.
+
+       * worlds/haxima-1.001/haxima.scm:
+       Added the Terrain Test and the Sprite Gallery to the shard surface
+       for test purposes.
+
+2004-08-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/haxima.scm:
+       Simplified startup script for development
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm:
+       More changes to moongate clearing
+
+       * worlds/haxima-1.001/images/sglasby/rune_font_8x16.png:
+       Fattening up the run sprites
+
+2004-08-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, examples/Makefile.in, examples/data/images/frame_pieces.png, src/kern.c, src/place.c, src/place.h, src/play.c, src/player.cpp, src/session.c, src/sprite.c, src/sprite.h, worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/session.scm:
+       You can now specify coordinates for edge entrances to places
+
+       * src/character.cpp, src/kern.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Tweaked the startup scene a bit
+
+       * src/character.cpp, src/kern.c, src/nazghul.c, src/play.c, src/player.cpp, src/session.c, src/session.h, src/sprite.c, src/terrain_map.c, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm:
+       Added a startup scene
+
+       * src/kern.c, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/play.c, src/play.h, src/player.cpp, src/player.h, src/session.c, src/session.h, src/wq.c, src/wq.h:
+       o Cleaned up the work queues a bit.
+
+       * worlds/haxima-1.001/haxima.scm:
+       Added an optional startup script
+
+       * worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/session.scm:
+       Polishing up the maps a bit
+
+       * worlds/haxima-1.001/moongate-clearing.scm:
+       Tweaks to Moongate Clearing map
+
+2004-08-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/log.c, src/log.h:
+       o Added log_flush()
+
+       * src/ctrl.c:
+       Setting Follow mode will not end the party leader's turn
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/troll.scm:
+       Added a basic no-frills troll
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/troll.scm:
+       o Increased troll vision radius
+       o Changed default action points required by weapons to be the number of action
+         points per turn for humans
+       o Bugfix: needed to kern-load ilya.scm from gregors-hut.scm
+
+2004-08-20  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm, worlds/haxima-1.001/sprites.scm:
+       Added sprites, scenery objects, and sprite gallery chambers for:
+       - ss_dg_tools
+       - ss_dg_readable
+
+2004-08-19  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm, worlds/haxima-1.001/sprites.scm:
+       Fixing some arrow/bolt sprites.
+       One arrow and two bolts are still glowing the wrong color
+       (plus wrong fletching)
+       Two bolts are moving 1 px Left/Right as they animate.
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm, worlds/haxima-1.001/sprites.scm:
+       Fixed numbering of some arrow/bolt sprites.
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm:
+       Added weapon sprites, put them in the Sprite Gallery.
+
+       * worlds/haxima-1.001/images/dgervais/dg_weapons.trans.png:
+       Fixed the top-left magic arrow (red glowing, was blue glowing)
+
+2004-08-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/kern.c, src/species.c, src/species.h, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/tests/basic-party.scm, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-enter.scm, worlds/haxima-1.001/tests/char-get.save.mstr, worlds/haxima-1.001/tests/char-get.scm, worlds/haxima-1.001/tests/char-handle.save.mstr, worlds/haxima-1.001/tests/char-handle.scm, worlds/haxima-1.001/tests/char-kamp.save.mstr, worlds/haxima-1.001/tests/char-kamp.scm, worlds/haxima-1.001/tests/char-new-order-1.save.mstr, worlds/haxima-1.001/tests/char-new-order-1.scm, worlds/haxima-1.001/tests/char-new-order-2.save.mstr, worlds/haxima-1.001/tests/char-new-order-2.scm, worlds/haxima-1.001/tests/char-new-order-3.save.mstr, worlds/haxima-1.001/tests/char-new-order-3.scm, worlds/haxima-1.001/tests/char-open.console.mstr, worlds/haxima-1.001/tests/char-open.save.mstr, worlds/haxima-1.001/tests/char-open.scm, worlds/haxima-1.001/tests/char-ready.save.mstr, worlds/haxima-1.001/tests/char-ready.scm, worlds/haxima-1.001/tests/char-search.console.mstr, worlds/haxima-1.001/tests/char-search.save.mstr, worlds/haxima-1.001/tests/char-search.scm, worlds/haxima-1.001/tests/char-talk.save.mstr, worlds/haxima-1.001/tests/char-talk.scm, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/char-use.scm, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.save.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.scm, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.console.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-cast.console.mstr, worlds/haxima-1.001/tests/console-party-cast.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-get.save.mstr, worlds/haxima-1.001/tests/console-party-handle.save.mstr, worlds/haxima-1.001/tests/console-party-mix.save.mstr, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.console.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/dtable-1.save.mstr, worlds/haxima-1.001/tests/dtable-1.scm, worlds/haxima-1.001/tests/dtable-2.save.mstr, worlds/haxima-1.001/tests/dtable-2.scm, worlds/haxima-1.001/tests/eternal-sleep.save.mstr, worlds/haxima-1.001/tests/eternal-sleep.scm, worlds/haxima-1.001/tests/factions-1.save.mstr, worlds/haxima-1.001/tests/factions-1.scm, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-1.scm, worlds/haxima-1.001/tests/mech-2.scm, worlds/haxima-1.001/tests/party-at.scm, worlds/haxima-1.001/tests/party-new-order-2.scm, worlds/haxima-1.001/tests/party-new-order-3.scm, worlds/haxima-1.001/tests/party-open.scm, worlds/haxima-1.001/tests/party-ready.scm, worlds/haxima-1.001/tests/party-search.scm, worlds/haxima-1.001/tests/party-talk.scm, worlds/haxima-1.001/tests/place-to-place-1.scm, worlds/haxima-1.001/tests/rendezvous-ap-lag.scm, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/test-map-1.scm, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/tfeat-1.scm, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       o Removed the damage, defend, armor and (I forgot the other one) mod fields in
+         the character class and species struct. They've never been used and I doubt
+         we'll miss them. Simplifies character and species creation to remove them.
+
+2004-08-18  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/sprites.scm:
+       Fixed some mis-numbered sprites in ss_dg_wearable.
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Some polish on the wearable items gallery.
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/scenery.scm:
+       Added scenery objects for all tiles in ss_dg_wearable
+       and placed them in a new chamber in the Sprite Gallery.
+
+       * worlds/haxima-1.001/moongate-clearing.scm:
+       Added a sprite for the moongate-clearing.
+
+       * worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/kgabbert/new_terrains.png:
+       Added new s_deep and s_shoals.
+
+2004-08-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/kern.c, src/log.c, worlds/haxima-1.001/ilya.scm:
+       o Added kern-conv-get-reply to directly query the player in a conversation.
+
+       * src/kern.c, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gregors-hut-zones.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ilya.scm, worlds/haxima-1.001/shroom.scm:
+       o kern-mk-sched now expects the "zone" rectangle of a schedule entry to be a
+         list.
+       o Gave Ilya a schedule that demonstrates how to use named zones to fill out the
+         place for a schedule entry. Reference gregors-hut-zones.scm.
+
+       * worlds/haxima-1.001/abandoned-farm.scm, worlds/haxima-1.001/haxima.scm:
+       Added Ilya's abandoned homestead
+
+2004-08-17  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/sprite-sets.scm:
+       Added various sprite sheets containing tiles
+       from David Gervais and Kevin Gabbert.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Added some notes (arrow/bolt tiles to fix)
+
+       * worlds/haxima-1.001/sprites.scm:
+       Finished ss_dg_weapons.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Fixed amulets
+
+       * worlds/haxima-1.001/sprites.scm:
+       Adding weapon sprites.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Adding sprites for ss_dg_weapons.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Added sprite bindings for ss_dg_wearable.
+
+2004-08-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/scheme-private.h, src/scheme.c, src/scheme.h, src/session.c:
+       Added file and line number reporting to scheme errors
+
+       * src/factions.h:
+       Added missing file.
+
+       * worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/ilya.scm:
+       Added Ilya to Gregor's Hut
+
+       * worlds/haxima-1.001/session.scm:
+       Removed references to Gregor's Hut.
+
+2004-08-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/game.scm, worlds/haxima-1.001/haxima.scm, worlds/haxima-1.001/moon.scm, worlds/haxima-1.001/moongate-clearing.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/pre-entry-hooks.scm, worlds/haxima-1.001/session.scm:
+       Added some script files for haxima
+
+2004-08-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/common.h, src/conv.c, src/conv.h, src/ctrl.c, src/dtable.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h, src/player.cpp, src/player.h, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/tests/basic-party.scm, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-enter.scm, worlds/haxima-1.001/tests/char-get.save.mstr, worlds/haxima-1.001/tests/char-get.scm, worlds/haxima-1.001/tests/char-handle.save.mstr, worlds/haxima-1.001/tests/char-handle.scm, worlds/haxima-1.001/tests/char-kamp.save.mstr, worlds/haxima-1.001/tests/char-kamp.scm, worlds/haxima-1.001/tests/char-new-order-1.save.mstr, worlds/haxima-1.001/tests/char-new-order-1.scm, worlds/haxima-1.001/tests/char-new-order-2.save.mstr, worlds/haxima-1.001/tests/char-new-order-2.scm, worlds/haxima-1.001/tests/char-new-order-3.save.mstr, worlds/haxima-1.001/tests/char-new-order-3.scm, worlds/haxima-1.001/tests/char-open.save.mstr, worlds/haxima-1.001/tests/char-open.scm, worlds/haxima-1.001/tests/char-ready.save.mstr, worlds/haxima-1.001/tests/char-ready.scm, worlds/haxima-1.001/tests/char-search.save.mstr, worlds/haxima-1.001/tests/char-search.scm, worlds/haxima-1.001/tests/char-talk.save.mstr, worlds/haxima-1.001/tests/char-talk.scm, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/char-use.scm, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.save.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.scm, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-cast.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-get.save.mstr, worlds/haxima-1.001/tests/console-party-handle.save.mstr, worlds/haxima-1.001/tests/console-party-kamp.save.mstr, worlds/haxima-1.001/tests/console-party-mix.save.mstr, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/dtable-1.save.mstr, worlds/haxima-1.001/tests/dtable-1.scm, worlds/haxima-1.001/tests/dtable-2.save.mstr, worlds/haxima-1.001/tests/dtable-2.scm, worlds/haxima-1.001/tests/empty-party.scm, worlds/haxima-1.001/tests/eternal-sleep.save.mstr, worlds/haxima-1.001/tests/eternal-sleep.scm, worlds/haxima-1.001/tests/factions-1.save.mstr, worlds/haxima-1.001/tests/factions-1.scm, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-1.scm, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/mech-2.scm, worlds/haxima-1.001/tests/party-at.save.mstr, worlds/haxima-1.001/tests/party-at.scm, worlds/haxima-1.001/tests/party-new-order-1.save.mstr, worlds/haxima-1.001/tests/party-new-order-1.scm, worlds/haxima-1.001/tests/party-new-order-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-2.scm, worlds/haxima-1.001/tests/party-new-order-3.save.mstr, worlds/haxima-1.001/tests/party-new-order-3.scm, worlds/haxima-1.001/tests/party-open.save.mstr, worlds/haxima-1.001/tests/party-open.scm, worlds/haxima-1.001/tests/party-ready.save.mstr, worlds/haxima-1.001/tests/party-ready.scm, worlds/haxima-1.001/tests/party-search.save.mstr, worlds/haxima-1.001/tests/party-search.scm, worlds/haxima-1.001/tests/party-talk.save.mstr, worlds/haxima-1.001/tests/party-talk.scm, worlds/haxima-1.001/tests/place-to-place-1.console.mstr, worlds/haxima-1.001/tests/place-to-place-1.save.mstr, worlds/haxima-1.001/tests/place-to-place-1.scm, worlds/haxima-1.001/tests/rendezvous-ap-lag.save.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.scm, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/tfeat-1.scm, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       
+       o Removed all references to the obsolete alignment system. Converted everything
+         to use factions.
+       
+       o Tore out all the faction stack stuff related to characters (if any managed to
+         get checked in). Parties have a base faction that is set when they are
+         created and never changed after that. Characters have a base faction and a
+         temporary faction which is used by the charm effect. It's very much the same
+         as before, but a bug was fixed where if a charm effect expired it would
+         remove a different, currently active charm effect.
+       
+       o Cleaned up old obsolete structures in conv.h
+       
+       o Character::useAmmo is now non-virtual and it takes the weapon as an
+         argument. Fixes a bug found when yellow slimes tried to use their acid spray.
+
+       * src/character.cpp, src/cmd.c, src/ctrl.c, src/kern.c, src/log.c, src/log.h, src/object.c, src/object.h, src/result.h, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/Attic/player.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm:
+       o Charm and confuse now seem to be functioning normally again. This concludes
+         the implementation of the new diplomacy system.
+
+       * worlds/haxima-1.001/session.scm:
+       Updated kern-mk-player to be compatible with recent changes
+
+2004-08-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/Party.cpp, src/character.cpp, src/common.h, src/kern.c, src/player.cpp, src/player.h, src/session.c, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/tests/basic-party.scm, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-enter.scm, worlds/haxima-1.001/tests/char-get.save.mstr, worlds/haxima-1.001/tests/char-get.scm, worlds/haxima-1.001/tests/char-handle.save.mstr, worlds/haxima-1.001/tests/char-handle.scm, worlds/haxima-1.001/tests/char-kamp.save.mstr, worlds/haxima-1.001/tests/char-kamp.scm, worlds/haxima-1.001/tests/char-new-order-1.save.mstr, worlds/haxima-1.001/tests/char-new-order-1.scm, worlds/haxima-1.001/tests/char-new-order-2.save.mstr, worlds/haxima-1.001/tests/char-new-order-2.scm, worlds/haxima-1.001/tests/char-new-order-3.save.mstr, worlds/haxima-1.001/tests/char-new-order-3.scm, worlds/haxima-1.001/tests/char-open.save.mstr, worlds/haxima-1.001/tests/char-open.scm, worlds/haxima-1.001/tests/char-ready.save.mstr, worlds/haxima-1.001/tests/char-ready.scm, worlds/haxima-1.001/tests/char-search.save.mstr, worlds/haxima-1.001/tests/char-search.scm, worlds/haxima-1.001/tests/char-talk.save.mstr, worlds/haxima-1.001/tests/char-talk.scm, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/char-use.scm, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.save.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.scm, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-cast.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-get.save.mstr, worlds/haxima-1.001/tests/console-party-handle.save.mstr, worlds/haxima-1.001/tests/console-party-kamp.save.mstr, worlds/haxima-1.001/tests/console-party-mix.save.mstr, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/dtable-1.save.mstr, worlds/haxima-1.001/tests/dtable-1.scm, worlds/haxima-1.001/tests/dtable-2.save.mstr, worlds/haxima-1.001/tests/dtable-2.scm, worlds/haxima-1.001/tests/eternal-sleep.save.mstr, worlds/haxima-1.001/tests/eternal-sleep.scm, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-1.scm, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/mech-2.scm, worlds/haxima-1.001/tests/party-at.save.mstr, worlds/haxima-1.001/tests/party-at.scm, worlds/haxima-1.001/tests/party-new-order-1.save.mstr, worlds/haxima-1.001/tests/party-new-order-1.scm, worlds/haxima-1.001/tests/party-new-order-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-2.scm, worlds/haxima-1.001/tests/party-new-order-3.save.mstr, worlds/haxima-1.001/tests/party-new-order-3.scm, worlds/haxima-1.001/tests/party-open.save.mstr, worlds/haxima-1.001/tests/party-open.scm, worlds/haxima-1.001/tests/party-ready.save.mstr, worlds/haxima-1.001/tests/party-ready.scm, worlds/haxima-1.001/tests/party-search.save.mstr, worlds/haxima-1.001/tests/party-search.scm, worlds/haxima-1.001/tests/party-talk.save.mstr, worlds/haxima-1.001/tests/party-talk.scm, worlds/haxima-1.001/tests/place-to-place-1.save.mstr, worlds/haxima-1.001/tests/place-to-place-1.scm, worlds/haxima-1.001/tests/rendezvous-ap-lag.save.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.scm, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/tfeat-1.scm, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       o Adding a new party member automatically pushes the party's faction onto the
+         new member's faction stack.
+       
+       o Added kern-party-add-member to the script API; in the initial load-file it's
+         best to use this instead of listing the members within the player party
+         declaration since it automatically updates each member's faction stack.
+
+       * src/common.h, src/kern.c, worlds/haxima-1.001/tests/factions-1.cmdwin.mstr, worlds/haxima-1.001/tests/factions-1.console.mstr, worlds/haxima-1.001/tests/factions-1.rec, worlds/haxima-1.001/tests/factions-1.save.mstr, worlds/haxima-1.001/tests/factions-1.scm, worlds/haxima-1.001/tests/list:
+       o Exported all the being faction methods to the script
+         (kern-being-push-faction, etc).
+
+2004-08-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Being.cpp, src/Being.h, src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Party.h, src/character.h, src/dtable.c, src/dtable.h, src/hstack.c, src/hstack.h, src/kern.c, src/session.c, src/session.h, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/tests/basic-time.scm, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-get.save.mstr, worlds/haxima-1.001/tests/char-handle.save.mstr, worlds/haxima-1.001/tests/char-kamp.save.mstr, worlds/haxima-1.001/tests/char-new-order-1.save.mstr, worlds/haxima-1.001/tests/char-new-order-2.save.mstr, worlds/haxima-1.001/tests/char-new-order-3.save.mstr, worlds/haxima-1.001/tests/char-open.save.mstr, worlds/haxima-1.001/tests/char-ready.save.mstr, worlds/haxima-1.001/tests/char-search.save.mstr, worlds/haxima-1.001/tests/char-talk.save.mstr, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.save.mstr, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-cast.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-get.save.mstr, worlds/haxima-1.001/tests/console-party-handle.save.mstr, worlds/haxima-1.001/tests/console-party-kamp.save.mstr, worlds/haxima-1.001/tests/console-party-mix.save.mstr, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/dtable-1.save.mstr, worlds/haxima-1.001/tests/dtable-1.scm, worlds/haxima-1.001/tests/dtable-2.save.mstr, worlds/haxima-1.001/tests/dtable-2.scm, worlds/haxima-1.001/tests/eternal-sleep.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/mech-2.scm, worlds/haxima-1.001/tests/party-at.save.mstr, worlds/haxima-1.001/tests/party-new-order-1.save.mstr, worlds/haxima-1.001/tests/party-new-order-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-3.save.mstr, worlds/haxima-1.001/tests/party-open.save.mstr, worlds/haxima-1.001/tests/party-ready.save.mstr, worlds/haxima-1.001/tests/party-search.save.mstr, worlds/haxima-1.001/tests/party-talk.save.mstr, worlds/haxima-1.001/tests/place-to-place-1.save.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.save.mstr, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/tfeat-1.scm, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       o Handles are now saved and loaded with elements of an hstack.
+
+2004-08-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/dtable.c, src/dtable.h, src/hstack.c, src/hstack.h, src/kern.c, src/macros.h, src/session.c, worlds/haxima-1.001/tests/dtable-1.save.mstr, worlds/haxima-1.001/tests/dtable-1.scm, worlds/haxima-1.001/tests/dtable-2.cmdwin.mstr, worlds/haxima-1.001/tests/dtable-2.console.mstr, worlds/haxima-1.001/tests/dtable-2.rec, worlds/haxima-1.001/tests/dtable-2.save.mstr, worlds/haxima-1.001/tests/dtable-2.scm:
+       o Saving/loading stack-based diplomacy table.
+       o Added kern_dtable_push/pop to the script API.
+       o Consolidated the kern_dtable_* functions into a common function to eliminate
+         redundant error-checking.
+
+2004-08-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/dtable.c, src/dtable.h, src/hstack.c, src/hstack.h:
+       Converted diplomacy table to be a table of stacks instead of a table of integers
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/dtable.c, src/dtable.h, src/kern.c, src/place.c, src/session.c, src/session.h, worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/scenery.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/tests/basic-time.scm, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-enter.scm, worlds/haxima-1.001/tests/char-get.save.mstr, worlds/haxima-1.001/tests/char-handle.save.mstr, worlds/haxima-1.001/tests/char-kamp.save.mstr, worlds/haxima-1.001/tests/char-new-order-1.save.mstr, worlds/haxima-1.001/tests/char-new-order-2.save.mstr, worlds/haxima-1.001/tests/char-new-order-3.save.mstr, worlds/haxima-1.001/tests/char-open.save.mstr, worlds/haxima-1.001/tests/char-ready.save.mstr, worlds/haxima-1.001/tests/char-search.save.mstr, worlds/haxima-1.001/tests/char-talk.save.mstr, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.save.mstr, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-cast.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-get.save.mstr, worlds/haxima-1.001/tests/console-party-handle.save.mstr, worlds/haxima-1.001/tests/console-party-kamp.save.mstr, worlds/haxima-1.001/tests/console-party-mix.save.mstr, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/eternal-sleep.save.mstr, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/mech-2.scm, worlds/haxima-1.001/tests/party-at.save.mstr, worlds/haxima-1.001/tests/party-new-order-1.save.mstr, worlds/haxima-1.001/tests/party-new-order-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-3.save.mstr, worlds/haxima-1.001/tests/party-open.save.mstr, worlds/haxima-1.001/tests/party-ready.save.mstr, worlds/haxima-1.001/tests/party-search.save.mstr, worlds/haxima-1.001/tests/party-talk.save.mstr, worlds/haxima-1.001/tests/place-to-place-1.cmdwin.mstr, worlds/haxima-1.001/tests/place-to-place-1.console.mstr, worlds/haxima-1.001/tests/place-to-place-1.rec, worlds/haxima-1.001/tests/place-to-place-1.save.mstr, worlds/haxima-1.001/tests/place-to-place-1.scm, worlds/haxima-1.001/tests/place-to-place-1.scm.cmdwin.mstr, worlds/haxima-1.001/tests/place-to-place-1.scm.console.mstr, worlds/haxima-1.001/tests/place-to-place-1.scm.rec, worlds/haxima-1.001/tests/place-to-place-1.scm.save.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.save.mstr, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/tfeat-1.scm, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       o Bugfix: in party mode exit to another small-scale place with no coordinates
+         matching those you just came from. Causes an assert. Problem was place_exec()
+         was assuming that if the object was still on-map after its turn it was on the
+         SAME map as before its turn. Removed the assumption, added a regression test
+         to catch this again (place-to-place-1).
+       o Added the new dtable (diplomacy table) implementation and the ability to
+         load/save it. Otherwise not used for anything yet.
+       o Moved the scenery definitions in P_terrain_test to a file loaded by
+         game.scm. Needed this to fix a save/reload problem.
+
+       * src/dtable.c, src/dtable.h, src/kern.c, worlds/haxima-1.001/tests/dtable-1.cmdwin.mstr, worlds/haxima-1.001/tests/dtable-1.console.mstr, worlds/haxima-1.001/tests/dtable-1.rec, worlds/haxima-1.001/tests/dtable-1.save.mstr, worlds/haxima-1.001/tests/dtable-1.scm, worlds/haxima-1.001/tests/list:
+       Exported dtable API to script and added tests
+
+2004-08-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c, src/vmask.h:
+       Bugfix: LOS in wilderness combat or zoom-in was sometimes wrong because of stale entries in the vmask cache. Solution was to invalidate all vmasks for the combat place upon exit from wilderness combat.
+
+       * src/object.c, src/object.h, src/player.cpp, src/vmask.c, worlds/haxima-1.001/tests/char-enter.console.mstr, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-party-kamp.console.mstr, worlds/haxima-1.001/tests/console-party-kamp.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/rendezvous-ap-lag.cmdwin.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.console.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.rec, worlds/haxima-1.001/tests/rendezvous-ap-lag.save.mstr, worlds/haxima-1.001/tests/rendezvous-ap-lag.scm:
+       o Bugfix: after a rendezvous exit party members would be immobile for a few
+         turns upon entry to another place. This was due to an action point debt
+         incurred during the rendezvous. Fixed this by zeroing out the action point
+         debt during a rendezvous so it doesn't carry over to new places.
+
+       * src/place.c, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/tests/eternal-sleep.cmdwin.mstr, worlds/haxima-1.001/tests/eternal-sleep.console.mstr, worlds/haxima-1.001/tests/eternal-sleep.rec, worlds/haxima-1.001/tests/eternal-sleep.save.mstr, worlds/haxima-1.001/tests/eternal-sleep.scm, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-2.save.mstr:
+       o Bugfix: if your only party member steps on a permanent sleep field at town
+         scale then they will never wake up. The fix was to apply per-tile effects to
+         objects _after_ they have a chance to take their turn.
+
+2004-08-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/cmd.h, src/ctrl.c, src/player.cpp, worlds/haxima-1.001/tests/char-kamp.cmdwin.mstr, worlds/haxima-1.001/tests/char-kamp.console.mstr, worlds/haxima-1.001/tests/char-kamp.rec, worlds/haxima-1.001/tests/char-kamp.save.mstr, worlds/haxima-1.001/tests/char-kamp.scm, worlds/haxima-1.001/tests/list:
+       o Added character-mode M)ix command
+       o Cleaned up console messages for character K)amp command
+       o Bugfix: party now wakes up in follow mode after kamping in town; must be in
+         follow mode before kamping.
+
+       * src/cmd.c, src/ctrl.c, src/player.h, worlds/haxima-1.001/tests/char-new-order-1.cmdwin.mstr, worlds/haxima-1.001/tests/char-new-order-1.console.mstr, worlds/haxima-1.001/tests/char-new-order-1.rec, worlds/haxima-1.001/tests/char-new-order-1.save.mstr, worlds/haxima-1.001/tests/char-new-order-1.scm, worlds/haxima-1.001/tests/char-new-order-2.cmdwin.mstr, worlds/haxima-1.001/tests/char-new-order-2.console.mstr, worlds/haxima-1.001/tests/char-new-order-2.rec, worlds/haxima-1.001/tests/char-new-order-2.save.mstr, worlds/haxima-1.001/tests/char-new-order-2.scm, worlds/haxima-1.001/tests/char-new-order-3.cmdwin.mstr, worlds/haxima-1.001/tests/char-new-order-3.console.mstr, worlds/haxima-1.001/tests/char-new-order-3.rec, worlds/haxima-1.001/tests/char-new-order-3.save.mstr, worlds/haxima-1.001/tests/char-new-order-3.scm, worlds/haxima-1.001/tests/char-use.scm, worlds/haxima-1.001/tests/list:
+       Added N)ew Order command to character mode
+
+       * src/cmd.c, src/ctrl.c, worlds/haxima-1.001/tests/char-open.cmdwin.mstr, worlds/haxima-1.001/tests/char-open.console.mstr, worlds/haxima-1.001/tests/char-open.rec, worlds/haxima-1.001/tests/char-open.save.mstr, worlds/haxima-1.001/tests/char-open.scm, worlds/haxima-1.001/tests/char-search.cmdwin.mstr, worlds/haxima-1.001/tests/char-search.console.mstr, worlds/haxima-1.001/tests/char-search.rec, worlds/haxima-1.001/tests/char-search.save.mstr, worlds/haxima-1.001/tests/char-search.scm, worlds/haxima-1.001/tests/char-talk.cmdwin.mstr, worlds/haxima-1.001/tests/char-talk.console.mstr, worlds/haxima-1.001/tests/char-talk.rec, worlds/haxima-1.001/tests/char-talk.save.mstr, worlds/haxima-1.001/tests/char-talk.scm, worlds/haxima-1.001/tests/char-use.cmdwin.mstr, worlds/haxima-1.001/tests/char-use.console.mstr, worlds/haxima-1.001/tests/char-use.rec, worlds/haxima-1.001/tests/char-use.save.mstr, worlds/haxima-1.001/tests/char-use.scm, worlds/haxima-1.001/tests/char-use.scm.cmdwin.mstr, worlds/haxima-1.001/tests/char-use.scm.console.mstr, worlds/haxima-1.001/tests/char-use.scm.rec, worlds/haxima-1.001/tests/list:
+       Cleaned up console messages for character search, talk, open and use commands
+
+2004-08-05  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * doc/engine_extension_and_design/README, doc/engine_extension_and_design/Attic/README~, doc/engine_extension_and_design/my_TODO.2004.05.05.txt:
+       Added a dir engine_extension_and_design.
+       Added a README for that dir.
+       Added some documents therein.
+
+       * doc/engine_extension_and_design/Attic/README~:
+       Backup file got added by mistake.
+
+       * worlds/haxima-1.001/terrains.scm:
+       Added a dir for world_building_notes.
+       Added a README in that directory.
+       Added various documents therein.
+
+       * worlds/haxima-1.001/world_building_notes/2004.02.19.design_notes.various.txt, worlds/haxima-1.001/world_building_notes/2004.03.28.character_advancement.txt, worlds/haxima-1.001/world_building_notes/2004.05.27.world_building.txt, worlds/haxima-1.001/world_building_notes/2004.06.02.world_building.txt, worlds/haxima-1.001/world_building_notes/2004.06.30.design_notes.conversations_and_NPCs.txt, worlds/haxima-1.001/world_building_notes/2004.07.08.design_notes.various.txt, worlds/haxima-1.001/world_building_notes/2004.07.08.terrain_palettes.txt:
+       Added variout files to world_building_notes/.
+
+       * worlds/haxima-1.001/world_building_notes/README:
+       Added a README for the world_building_notes dir.
+
+2004-08-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/cmd.c, src/conv.c, src/conv.h, src/ctrl.c, src/kern.c, src/object.c, src/object.h, src/status.c, src/status.h, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/party-talk.cmdwin.mstr, worlds/haxima-1.001/tests/party-talk.console.mstr, worlds/haxima-1.001/tests/party-talk.rec, worlds/haxima-1.001/tests/party-talk.save.mstr, worlds/haxima-1.001/tests/party-talk.scm, worlds/haxima-1.001/tests/party-talk.scm.cmdwin.mstr, worlds/haxima-1.001/tests/party-talk.scm.console.mstr, worlds/haxima-1.001/tests/party-talk.scm.rec, worlds/haxima-1.001/tests/party-talk.scm.save.mstr:
+       o Extended status api to support selecting from a generic list
+       o Rearranged the impl of conversation a bit
+       o Party::getConversation() now prompts the player with a list of members who
+         have conversations.
+       o Talking to a party in the wilderness now works with the above
+         changes. Currently, however, the only party with members who might have
+         conversations is the player's own party.
+
+       * src/character.cpp, src/cmd.c, src/ctrl.c, src/player.cpp, worlds/haxima-1.001/tests/char-enter.cmdwin.mstr, worlds/haxima-1.001/tests/char-enter.console.mstr, worlds/haxima-1.001/tests/char-enter.rec, worlds/haxima-1.001/tests/char-enter.save.mstr, worlds/haxima-1.001/tests/char-enter.scm, worlds/haxima-1.001/tests/char-get.cmdwin.mstr, worlds/haxima-1.001/tests/char-get.console.mstr, worlds/haxima-1.001/tests/char-get.rec, worlds/haxima-1.001/tests/char-get.save.mstr, worlds/haxima-1.001/tests/char-get.scm, worlds/haxima-1.001/tests/char-handle.cmdwin.mstr, worlds/haxima-1.001/tests/char-handle.console.mstr, worlds/haxima-1.001/tests/char-handle.rec, worlds/haxima-1.001/tests/char-handle.save.mstr, worlds/haxima-1.001/tests/char-handle.scm, worlds/haxima-1.001/tests/char-ready.cmdwin.mstr, worlds/haxima-1.001/tests/char-ready.console.mstr, worlds/haxima-1.001/tests/char-ready.rec, worlds/haxima-1.001/tests/char-ready.save.mstr, worlds/haxima-1.001/tests/char-ready.scm, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.cmdwin.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.console.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.rec, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.save.mstr, worlds/haxima-1.001/tests/char-xamine-ztats-at-pass.scm, worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/console-at.console.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-examine.console.mstr, worlds/haxima-1.001/tests/console-exit.console.mstr, worlds/haxima-1.001/tests/console-party-get.console.mstr, worlds/haxima-1.001/tests/console-party-kamp.console.mstr, worlds/haxima-1.001/tests/console-terraform.console.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.console.mstr, worlds/haxima-1.001/tests/mech-2.console.mstr, worlds/haxima-1.001/tests/tfeat-1.console.mstr:
+       Cleaned up console messages for a bunch of character commands
+
+       * src/cmd.c, src/status.c, worlds/haxima-1.001/tests/console-at.console.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/party-at.cmdwin.mstr, worlds/haxima-1.001/tests/party-at.console.mstr, worlds/haxima-1.001/tests/party-at.rec, worlds/haxima-1.001/tests/party-at.save.mstr, worlds/haxima-1.001/tests/party-at.scm:
+       Cleaned up console messages for party U)se and @ commands
+
+       * src/ctrl.c, worlds/haxima-1.001/tests/console-party-attack.console.mstr, worlds/haxima-1.001/tests/console-party-fire.console.mstr, worlds/haxima-1.001/tests/console-pass.console.mstr, worlds/haxima-1.001/tests/party-at.console.mstr:
+       Removed an extra EOL for the party Pass command
+
+2004-08-04  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/images.c:
+       Added improved error logging on IMG_Load() in response to a Mac OS X bug.
+
+       * worlds/haxima-1.001/images/kgabbert/kg_potions_1.trans.png, worlds/haxima-1.001/images/kgabbert/kg_potions_2.trans.png:
+       Added 2 tilesheets of potions from Kevin.
+       Potion artwork based on art from David Gervais.
+       Some arrangement by Sam Glasby.
+
+2004-08-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/cmd.c, src/kern.c, src/log.c, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/tests/console-party-get.console.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-1.save.mstr, worlds/haxima-1.001/tests/party-new-order-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-3.save.mstr, worlds/haxima-1.001/tests/party-open.cmdwin.mstr, worlds/haxima-1.001/tests/party-open.console.mstr, worlds/haxima-1.001/tests/party-open.rec, worlds/haxima-1.001/tests/party-open.save.mstr, worlds/haxima-1.001/tests/party-open.scm, worlds/haxima-1.001/tests/test-map-1.scm, worlds/haxima-1.001/tests/tfeat-1.console.mstr:
+       o Added kern-log-msg
+       o Cleaned up console output related to party mode O)pen command
+       o Revisited console output related to party mode G)et command and reduced the
+         verbosity
+
+       * src/Party.h, src/cmd.c, src/cmd.h, src/ctrl.c, src/status.c, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/party-open.console.mstr, worlds/haxima-1.001/tests/party-ready.cmdwin.mstr, worlds/haxima-1.001/tests/party-ready.console.mstr, worlds/haxima-1.001/tests/party-ready.rec, worlds/haxima-1.001/tests/party-ready.save.mstr, worlds/haxima-1.001/tests/party-ready.scm, worlds/haxima-1.001/tests/party-ready.scm.cmdwin.mstr, worlds/haxima-1.001/tests/party-ready.scm.console.mstr, worlds/haxima-1.001/tests/party-ready.scm.rec, worlds/haxima-1.001/tests/party-ready.scm.save.mstr:
+       o Bugfix: ready-arms stat window scrolled off-screen in some cases.
+       o Cleaned up console output related to party mode R)eady command
+
+       * src/cmd.c, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/party-search.cmdwin.mstr, worlds/haxima-1.001/tests/party-search.console.mstr, worlds/haxima-1.001/tests/party-search.rec, worlds/haxima-1.001/tests/party-search.save.mstr, worlds/haxima-1.001/tests/party-search.scm:
+       Cleaned up console messages related to the party S)earch command
+
+2004-08-03  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Tidied up the Sprite Gallery (chamber 1, missiles)
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/dgervais/dg_missiles.trans.png:
+       Arranged the arrows in ss_dg_missiles, added them all to the Sprite Gallery.
+
+       * worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/dgervais/dg_commodities.trans.png:
+       Added ss_dg_commodities.
+
+       * worlds/haxima-1.001/images/dgervais/dg_commodities.trans.png, worlds/haxima-1.001/images/dgervais/dg_missiles.trans.png, worlds/haxima-1.001/images/dgervais/dg_potions.trans.png, worlds/haxima-1.001/images/dgervais/dg_readable.trans.png, worlds/haxima-1.001/images/dgervais/dg_tools.trans.png, worlds/haxima-1.001/images/dgervais/dg_weapons.trans.png, worlds/haxima-1.001/images/dgervais/dg_wearable_items.trans.png:
+       Added various transparency-containing tile sheets.
+       Original tiles by David Gervais.
+       Tile sheet organization by Sam Glasby.
+       Transparency and animation frames by Kevin Gabbert.
+
+       * worlds/haxima-1.001/images/dgervais/dg_tools.trans.png:
+       Torches slightly misaligned, moved them into their frames.
+
+       * worlds/haxima-1.001/images/dgervais/dg_weapons.trans.png:
+       Added black to inside whip loop.
+
+2004-08-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/cmd.c, src/list.h, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/party-new-order-1.cmdwin.mstr, worlds/haxima-1.001/tests/party-new-order-1.console.mstr, worlds/haxima-1.001/tests/party-new-order-1.rec, worlds/haxima-1.001/tests/party-new-order-1.save.mstr, worlds/haxima-1.001/tests/party-new-order-1.scm, worlds/haxima-1.001/tests/party-new-order-2.cmdwin.mstr, worlds/haxima-1.001/tests/party-new-order-2.console.mstr, worlds/haxima-1.001/tests/party-new-order-2.rec, worlds/haxima-1.001/tests/party-new-order-2.save.mstr, worlds/haxima-1.001/tests/party-new-order-2.scm, worlds/haxima-1.001/tests/party-new-order-3.cmdwin.mstr, worlds/haxima-1.001/tests/party-new-order-3.console.mstr, worlds/haxima-1.001/tests/party-new-order-3.rec, worlds/haxima-1.001/tests/party-new-order-3.save.mstr, worlds/haxima-1.001/tests/party-new-order-3.scm:
+       o Bugfix: New Order didn't work for parties with more than 2 members
+       o Cleaned up console output related to party mode N)ew Order command.
+
+       * src/character.cpp, src/cmd.c, src/ctrl.c, worlds/haxima-1.001/tests/cmdwin-2.console.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-exit.console.mstr, worlds/haxima-1.001/tests/console-party-get.console.mstr, worlds/haxima-1.001/tests/console-party-kamp.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-kamp.console.mstr, worlds/haxima-1.001/tests/console-party-kamp.rec, worlds/haxima-1.001/tests/console-party-kamp.save.mstr, worlds/haxima-1.001/tests/console-party-kamp.scm, worlds/haxima-1.001/tests/console-party-kamp.scm.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-kamp.scm.console.mstr, worlds/haxima-1.001/tests/console-party-kamp.scm.rec, worlds/haxima-1.001/tests/console-party-kamp.scm.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.console.mstr, worlds/haxima-1.001/tests/mech-2.console.mstr, worlds/haxima-1.001/tests/tfeat-1.console.mstr:
+       Cleaned up console messages for party mode K)amp command
+
+       * src/cmd.c, worlds/haxima-1.001/tests/console-party-cast.console.mstr, worlds/haxima-1.001/tests/console-party-mix.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-mix.console.mstr, worlds/haxima-1.001/tests/console-party-mix.rec, worlds/haxima-1.001/tests/console-party-mix.save.mstr, worlds/haxima-1.001/tests/console-party-mix.scm, worlds/haxima-1.001/tests/list:
+       Cleaned up console messages for party mode M)ix command
+
+       * src/place.c, src/ptable.h, worlds/haxima-1.001/bim.scm, worlds/haxima-1.001/drawbridge.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/lever.scm, worlds/haxima-1.001/portcullis.scm, worlds/haxima-1.001/stone-lantern.scm, worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.console.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-handle.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-handle.console.mstr, worlds/haxima-1.001/tests/console-party-handle.rec, worlds/haxima-1.001/tests/console-party-handle.save.mstr, worlds/haxima-1.001/tests/console-party-handle.scm, worlds/haxima-1.001/tests/console-party-handle.scm.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-handle.scm.console.mstr, worlds/haxima-1.001/tests/console-party-handle.scm.rec, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/session.scm:
+       o Bugfix: the (new) drawbridge terrain feature was always passable.
+       o Cleaned up console output related to party mode H)andle command.
+
+       * worlds/haxima-1.001/tests/console-party-cast.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-cast.console.mstr, worlds/haxima-1.001/tests/console-party-cast.save.mstr, worlds/haxima-1.001/tests/console-party-cast.scm.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-cast.scm.console.mstr, worlds/haxima-1.001/tests/console-party-cast.scm.save.mstr, worlds/haxima-1.001/tests/console-party-get.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-get.console.mstr, worlds/haxima-1.001/tests/console-party-get.save.mstr:
+       Adding missing master files
+
+       * worlds/haxima-1.001/tests/console-party-cast.rec, worlds/haxima-1.001/tests/console-party-cast.scm, worlds/haxima-1.001/tests/console-party-get.rec, worlds/haxima-1.001/tests/console-party-get.scm, worlds/haxima-1.001/tests/test-map-1.scm:
+       More missing test files
+
+2004-08-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Party.h, src/Attic/Portal.cpp, src/Attic/Portal.h, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/ctrl.c, src/kern.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h, src/session.c:
+       o Removed the obsolete Portal class.
+       o Removed the E)nter command in party mode because
+         1. It's implementation was obsolete
+         2. It's usefulness is questionable
+         3. It will be easy to add back when we need it
+
+       * src/Party.cpp, src/cmd.c, worlds/haxima-1.001/tests/console-party-fire.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-fire.console.mstr, worlds/haxima-1.001/tests/console-party-fire.rec, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-party-fire.scm, worlds/haxima-1.001/tests/list:
+       Cleaned up the F)ire command
+
+       * src/cmd.c, src/player.cpp, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-fire.save.mstr, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/session.scm:
+       Cleaned up console messages for party G)et command
+
+2004-08-01  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Rearranged some missiles.
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Added all missile sprites to the Sprite Gallery.
+
+       * worlds/haxima-1.001/images/dgervais/dg_commodities-32x32.png, worlds/haxima-1.001/images/dgervais/dg_readable-32x32.png, worlds/haxima-1.001/images/dgervais/dg_tools-32x32.png, worlds/haxima-1.001/images/dgervais/dg_weapons-32x32.png:
+       Various reorganizations, etc.
+
+       * worlds/haxima-1.001/images/dgervais/dg_potions-32x32.png:
+       Fixed a draggo.
+
+       * worlds/haxima-1.001/images/dgervais/dg_weapons-32x32.png:
+       Added a blank tile for the "magic mace with red glow" animation frame.
+
+2004-08-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/ctrl.c, src/magic.c, src/magic.h, src/player.cpp, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.console.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.console.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-board.cmdwin.mstr, worlds/haxima-1.001/tests/console-board.console.mstr, worlds/haxima-1.001/tests/console-board.rec, worlds/haxima-1.001/tests/console-board.save.mstr, worlds/haxima-1.001/tests/console-board.scm, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-exit.console.mstr, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-party-attack.cmdwin.mstr, worlds/haxima-1.001/tests/console-party-attack.console.mstr, worlds/haxima-1.001/tests/console-party-attack.rec, worlds/haxima-1.001/tests/console-party-attack.save.mstr, worlds/haxima-1.001/tests/console-party-attack.scm, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       Updated console messages on all party spells up through C)ast
+
+       * src/log.h:
+       Adding missing file
+
+2004-07-31  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Added a Sprite Gallery place, accessible via a portal
+       in the Terrain Test.
+
+       * worlds/haxima-1.001/portals.scm:
+       Revised some documentation.
+       Added a new portal type t_perm_gate and a constructor mk-perm-gate.
+
+       * worlds/haxima-1.001/portals.scm:
+       Added documentation.
+
+       * worlds/haxima-1.001/portals.scm:
+       Indentation.
+
+       * worlds/haxima-1.001/sprite-sets.scm:
+       Added ss_dg_missiles.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Temporarily changed multi-facing missiles to multi-frame,
+       so that the graphics can be seen in context in the sprite gallery.
+
+       * worlds/haxima-1.001/images/dgervais/dg_commodities-32x32.png, worlds/haxima-1.001/images/dgervais/dg_missiles-32x32.png, worlds/haxima-1.001/images/dgervais/dg_potions-32x32.png, worlds/haxima-1.001/images/dgervais/dg_readable-32x32.png, worlds/haxima-1.001/images/dgervais/dg_tools-32x32.png, worlds/haxima-1.001/images/dgervais/dg_weapons-32x32.png:
+       Adding various tilesheets (tiles courtesy of David Gervais).
+
+       * worlds/haxima-1.001/images/dgervais/dg_missiles-32x32.png:
+       Re-arranged the arrows slightly.
+
+       * worlds/haxima-1.001/images/dgervais/dg_missiles-32x32.png:
+       Re-organized, added animation frames.
+
+2004-07-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/character.cpp, src/cmd.c, src/cmdwin.c, src/ctrl.c, src/log.c, src/nazghul.c, src/object.c, src/place.c, src/player.cpp, src/sky.h, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/tests/cmdwin-1.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/cmdwin-2.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-2.console.mstr, worlds/haxima-1.001/tests/cmdwin-3.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-3.console.mstr, worlds/haxima-1.001/tests/console-at.cmdwin.mstr, worlds/haxima-1.001/tests/console-at.console.mstr, worlds/haxima-1.001/tests/console-at.rec, worlds/haxima-1.001/tests/console-at.save.mstr, worlds/haxima-1.001/tests/console-at.scm, worlds/haxima-1.001/tests/console-attack.cmdwin.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-attack.rec, worlds/haxima-1.001/tests/console-attack.save.mstr, worlds/haxima-1.001/tests/console-attack.scm, worlds/haxima-1.001/tests/console-attack.scm.cmdwin.mstr, worlds/haxima-1.001/tests/console-attack.scm.console.mstr, worlds/haxima-1.001/tests/console-attack.scm.rec, worlds/haxima-1.001/tests/console-examine.cmdwin.mstr, worlds/haxima-1.001/tests/console-examine.console.mstr, worlds/haxima-1.001/tests/console-examine.rec, worlds/haxima-1.001/tests/console-examine.save.mstr, worlds/haxima-1.001/tests/console-examine.scm, worlds/haxima-1.001/tests/console-exit.cmdwin.mstr, worlds/haxima-1.001/tests/console-exit.console.mstr, worlds/haxima-1.001/tests/console-exit.rec, worlds/haxima-1.001/tests/console-exit.save.mstr, worlds/haxima-1.001/tests/console-exit.scm, worlds/haxima-1.001/tests/console-pass.cmdwin.mstr, worlds/haxima-1.001/tests/console-pass.console.mstr, worlds/haxima-1.001/tests/console-pass.rec, worlds/haxima-1.001/tests/console-pass.save.mstr, worlds/haxima-1.001/tests/console-pass.scm, worlds/haxima-1.001/tests/console-terraform.cmdwin.mstr, worlds/haxima-1.001/tests/console-terraform.console.mstr, worlds/haxima-1.001/tests/console-terraform.rec, worlds/haxima-1.001/tests/console-terraform.save.mstr, worlds/haxima-1.001/tests/console-terraform.scm, worlds/haxima-1.001/tests/console-terraform.scm.cmdwin.mstr, worlds/haxima-1.001/tests/console-terraform.scm.console.mstr, worlds/haxima-1.001/tests/console-terraform.scm.rec, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.console.mstr, worlds/haxima-1.001/tests/mech-2.console.mstr, worlds/haxima-1.001/tests/runall, worlds/haxima-1.001/tests/testexec, worlds/haxima-1.001/tests/tfeat-1.console.mstr, worlds/haxima-1.001/tests/wrap-1.cmdwin.mstr, worlds/haxima-1.001/tests/wrap-1.console.mstr, worlds/haxima-1.001/tests/wrap-2.cmdwin.mstr, worlds/haxima-1.001/tests/wrap-2.console.mstr:
+       Console rework started
+
+       * src/cmd.c, src/console.c, src/log.c, src/play.c, src/player.cpp, worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/cmdwin-2.console.mstr, worlds/haxima-1.001/tests/cmdwin-3.console.mstr, worlds/haxima-1.001/tests/console-at.console.mstr, worlds/haxima-1.001/tests/console-attack.console.mstr, worlds/haxima-1.001/tests/console-examine.console.mstr, worlds/haxima-1.001/tests/console-exit.console.mstr, worlds/haxima-1.001/tests/console-pass.console.mstr, worlds/haxima-1.001/tests/console-terraform.console.mstr, worlds/haxima-1.001/tests/mech-1.console.mstr, worlds/haxima-1.001/tests/mech-2.console.mstr, worlds/haxima-1.001/tests/tfeat-1.console.mstr, worlds/haxima-1.001/tests/wrap-1.console.mstr, worlds/haxima-1.001/tests/wrap-2.console.mstr:
+       o Cleaned up entrance messages
+       o Cleaned up saving/reloading messages in party mode
+
+2004-07-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/stone-lantern.scm:
+       Added a missing file
+
+2004-07-29  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/sprite-sets.scm:
+       Added ss_dg_wearable tilesheet.
+
+       * worlds/haxima-1.001/images/dgervais/dg_angband_enhanced-32x32.png:
+       Added the David Gervais enhanced 32x32 Angband tileset.
+
+       * worlds/haxima-1.001/images/dgervais/dg_wearable_items-32x32.png:
+       A tile sheet containing tiles for wearable items:
+       - Hats, helms, crown
+       - Amulets
+       - Rings
+       - Cloaks
+       - Robes
+       - Shields
+       - Armor (leather, chain, plate)
+
+2004-07-28  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/P_terrain_test.scm:
+       Terrain test pattern for screenshots, etc.
+
+       * worlds/haxima-1.001/P_terrain_test.scm, worlds/haxima-1.001/session.scm:
+       Added the Terrain Test place, preparatory for terrain/palette work.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Added sprites from ss_kg_terrain and ss_kg_roads.
+       Fixed some typos.
+
+2004-07-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/Makefile.am:
+       Adding missing file
+
+2004-07-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.c, src/astar.h, src/ctrl.c, src/place.c, src/player.cpp:
+       o Fixed one bug related to death-in-ship-by-cannon.
+       
+       o Worked around another bug hiding behind it. I didn't root cause it, and
+         suspect it's related to double-deallocation or overwriting an allocated
+         buffer, because it asserts in malloc(). But I don't see any immediate cause
+         and don't want to spend a lot of time on it at this point.
+
+       * worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr:
+       Remastered some tests to reflect a change in a sprite name
+
+2004-07-26  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/cmd.c:
+       Fixed a SIGSEGV on invocation of cmdTerraform().
+       I think we fixed this one before.  It must not have made it to CVS.
+
+       * src/common.h:
+       Removed a duplicate #define for PLACE_ID.
+
+       * worlds/haxima-1.001/sprite-sets.scm:
+       Added the kgabbert/ roads and terrains sprite sheets.
+       Added formatting + comments.
+
+       * worlds/haxima-1.001/sprites.scm:
+       Updated formatting, added comments.
+       Merged with Gordon's new feature tiles and bridge re-labeling.
+
+       * worlds/haxima-1.001/images/kgabbert/Attic/new_roads..png:
+       This should have been checked in as new_roads.png
+       but it was checked in as new_roads..png
+       which is one too many dots.
+
+       * worlds/haxima-1.001/images/kgabbert/Attic/new_roads..png, worlds/haxima-1.001/images/kgabbert/new_terrains.png:
+       Added the new roads and terrains tile sheets.
+
+       * worlds/haxima-1.001/images/kgabbert/new_roads.png:
+       Aarrgghh....  Checked this file in as new_roads..png
+       which is one too many dots.
+
+2004-07-25  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * worlds/haxima-1.001/images/gmcnutt/frame_pieces.16x16.plain_blue_bars.png:
+       Added the reorganized frames tile sheet.
+
+2004-07-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features.png:
+       Added a new hut sprite
+
+       * worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/images/gmcnutt/features.png:
+       Added a mine and cave entrance sprite
+
+2004-07-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, COPYING, INSTALL, Makefile.am, Attic/Makefile.in, Attic/RELEASE_NOTES, Attic/configure, Attic/configure.in, doc/USERS_GUIDE, examples/Makefile.in, scripts/RELEASE_CHECKOFF, src/clock.c, src/cmd.c, src/Attic/game.h, src/play.c, src/sky.c:
+       Various fixups to make the release work
+
+       * Attic/RELEASE_NOTES, src/object.h, src/place.c, src/place.h, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/session.scm, worlds/haxima-1.001/tests/tfeat-1.cmdwin.mstr, worlds/haxima-1.001/tests/tfeat-1.console.mstr, worlds/haxima-1.001/tests/tfeat-1.rec, worlds/haxima-1.001/tests/tfeat-1.save.mstr, worlds/haxima-1.001/tests/tfeat-1.scm, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-1.scm:
+       o Added a layer for terrain features
+       
+       o Modified passability, movement cost and terrain effects to check for terrain
+         features. Terrain features always override terrain movement and hazard
+         effects.
+       
+       o Updated the scripts accordingly, added a bridge terrain feature as an
+         example. One may be found in Gregor's hut.
+       
+       o Added a test for terrain feature passability and hazard overrides.
+
+       * src/character.cpp, src/ctrl.c, src/player.cpp:
+       Some initial console/cmdwin cleanup
+
+       * src/cmd.c, src/map.c, worlds/haxima-1.001/bim.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/lever.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/portcullis.scm, worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/images/gmcnutt/features.png, worlds/haxima-1.001/tests/basic-night-time.scm, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/mech-1.cmdwin.mstr, worlds/haxima-1.001/tests/mech-1.console.mstr, worlds/haxima-1.001/tests/mech-1.rec, worlds/haxima-1.001/tests/mech-1.save.mstr, worlds/haxima-1.001/tests/mech-1.scm, worlds/haxima-1.001/tests/mech-1.scm.cmdwin.mstr, worlds/haxima-1.001/tests/mech-1.scm.console.mstr, worlds/haxima-1.001/tests/mech-1.scm.rec, worlds/haxima-1.001/tests/mech-1.scm.save.mstr, worlds/haxima-1.001/tests/mech-2.cmdwin.mstr, worlds/haxima-1.001/tests/mech-2.console.mstr, worlds/haxima-1.001/tests/mech-2.rec, worlds/haxima-1.001/tests/mech-2.save.mstr, worlds/haxima-1.001/tests/mech-2.scm, worlds/haxima-1.001/tests/tfeat-1.console.mstr, worlds/haxima-1.001/tests/tfeat-1.save.mstr:
+       o Modified bim.scm to expect a light value as part of the gob state for a
+         binary mechanism.
+       o Added stone-lantern.scm, our first new light-switch-style mechanism.
+       o I think there was a kernel bugfix in here but I forgot what it was.
+
+       * worlds/Attic/Makefile.in:
+       *** empty log message ***
+
+       * worlds/haxima-1.001/bridge.scm:
+       Forgot to add the new bridge file in my last checkin
+
+       * worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/road.scm, worlds/haxima-1.001/session.scm:
+       Added road.scm, which includes a feature map translation function as an example of how to do that sort of thing
+
+       * worlds/haxima-1.001/session.scm, worlds/haxima-1.001/Attic/test.scm:
+       Cleanup
+
+       * worlds/haxima-1.001/tests/basic-party.scm, worlds/haxima-1.001/tests/basic-time.scm, worlds/haxima-1.001/tests/basic-wilderness-map.scm, worlds/haxima-1.001/tests/cmdwin-2.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-2.console.mstr, worlds/haxima-1.001/tests/wrap-1.cmdwin.mstr, worlds/haxima-1.001/tests/wrap-1.console.mstr, worlds/haxima-1.001/tests/wrap-2.cmdwin.mstr, worlds/haxima-1.001/tests/wrap-2.console.mstr:
+       Updated some test files
+
+2004-07-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * worlds/haxima-1.001/images/gmcnutt/features.png, worlds/haxima-1.001/images/gmcnutt/features2.png:
+       Added two more image sheets
+
+2004-07-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmdwin.c, src/cmdwin.h, src/ctrl.c, src/player.cpp:
+       o Added a cmdwin log, .cmdwin, for regression testing.
+       
+       o Added cmdwin_flush() which writes to the cmdwin log, writes to the console,
+         clears the cmdwin and repaints it for another prompt.
+       
+       o Top of player party key handle uses cmdwin_flush() now.
+
+       * src/common.h, src/screen.c, src/session.c:
+       Removed (faulty) timestamp from save files
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/terrains.scm:
+       Filled out a bit more of Gregor's hut
+
+       * worlds/haxima-1.001/tests/DESCRIPTIONS.TXT, worlds/haxima-1.001/tests/clean, worlds/haxima-1.001/tests/cmdwin-1.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-1.console.mstr, worlds/haxima-1.001/tests/cmdwin-1.rec, worlds/haxima-1.001/tests/cmdwin-1.save.mstr, worlds/haxima-1.001/tests/cmdwin-1.scm, worlds/haxima-1.001/tests/cmdwin-2.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-2.console.mstr, worlds/haxima-1.001/tests/cmdwin-2.rec, worlds/haxima-1.001/tests/cmdwin-2.save.mstr, worlds/haxima-1.001/tests/cmdwin-2.scm, worlds/haxima-1.001/tests/cmdwin-3.cmdwin.mstr, worlds/haxima-1.001/tests/cmdwin-3.console.mstr, worlds/haxima-1.001/tests/cmdwin-3.rec, worlds/haxima-1.001/tests/cmdwin-3.save.mstr, worlds/haxima-1.001/tests/cmdwin-3.scm, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/master, worlds/haxima-1.001/tests/remaster, worlds/haxima-1.001/tests/runall, worlds/haxima-1.001/tests/testexec, worlds/haxima-1.001/tests/wrap-1.rec, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-1.scm, worlds/haxima-1.001/tests/wrap-2.scm:
+       Added some cmdwin tests
+
+       * worlds/haxima-1.001/tests/clean, worlds/haxima-1.001/tests/list, worlds/haxima-1.001/tests/master, worlds/haxima-1.001/tests/remaster, worlds/haxima-1.001/tests/testexec, worlds/haxima-1.001/tests/wrap-1.rec, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-1.scm, worlds/haxima-1.001/tests/wrap-2.rec, worlds/haxima-1.001/tests/wrap-2.save.mstr, worlds/haxima-1.001/tests/wrap-2.scm:
+       Adding regression test framework
+
+       * worlds/haxima-1.001/tests/session.scm:
+       Made a copy of session.scm to insulate regression tests from world changes
+
+       * worlds/haxima-1.001/tests/testexec, worlds/haxima-1.001/tests/wrap-1.save.mstr, worlds/haxima-1.001/tests/wrap-2.save.mstr:
+       Removed timestamps from master files; reduced playback delay
+
+2004-07-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c:
+       Refixed the terraform bug
+
+       * src/map.c, src/place.c, src/screen.c:
+       o Bugfix: when zoomed out in a small-scale place, the selected character's
+         sprite would sometimes flash full-size at some place on the screen. This was
+         a bug in mapUpdateTile(), which didn't handle zoom-out properly.
+       
+       o Bugfix: when zoomed out and standing at the edge of a small-scale,
+         non-wrapping place the highlight box was painted wrong. Again, a bug (this
+         time in screenHighlight()) where the code was not written to handle zoom-out
+         properly.
+
+       * src/place.c:
+       Bugfix: couldn't board a ship
+
+       * worlds/haxima-1.001/gregors-hut.scm, worlds/haxima-1.001/session.scm:
+       Added initial hack at Gregor the Charcoal Burner's Hut
+
+2004-07-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h, src/player.cpp, src/scheme.c, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/portals.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/yellow-slime.scm:
+       o Places now take an optional closure which is run when the party tries to
+         enter them as a subplace. As an example, I added one to GreenTower which
+         prompts the player if he wants to enter or not.
+       
+       o Fixed several bugs in the code which distributes party members. This was
+         visible if you tried to enter a place that didn't have any safe locations.
+       
+       o Not sure if I changed any kernel code for this, but I added an example of a
+         portal that prompts the player when he tries to step through. The prompt
+         occurs after the player is on the portal, which is not exactly what we
+         want. The example prompts and rechecks to make sure the player really wants
+         to step through the portal. If he says no he'll end up on top of the portal
+         without teleporting.
+
+2004-07-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Field.cpp, src/Field.h, src/Party.cpp, src/character.cpp, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h, src/player.cpp, src/terrain.c, src/terrain.h, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/fields.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/ifc.scm:
+       o Attempting to enter impassable but hazardous terrain now applies the
+         hazard. For example, attempting to enter lava (impassable to most) will burn
+         you. This reuses the existing terrain "effect" which is applied when a
+         terrain is stepped on. I could have added another effect just for this
+         feature, but for all the realistic terrains I can think of the effects of
+         entering and failing to enter would be the same, so until an important
+         counterexample surfaces I'll not pollute my data structures with more NULL
+         pointers.
+       
+       o Attempting to enter a tile with a blocking but dangerous object will apply
+         damage. For example, attempting to enter an energy field will shock you. This
+         uses a new well-known signal called "bump", as in you bumped into something
+         that didn't give way. The optional bump handler is in the script for an
+         object.
+
+2004-07-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/closure.c, src/kern.c, src/mmode.c, src/mmode.h, src/object.c, src/object.h, src/place.c, src/place.h, src/player.cpp, src/player.h, src/ptable.c, src/ptable.h, src/session.c, src/session.h, src/species.c, src/species.h, src/status.c, src/terrain.c, src/terrain.h, src/vehicle.cpp, src/vehicle.h, worlds/haxima-1.001/bim.scm, worlds/haxima-1.001/door.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/portcullis.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/vehicles.scm:
+       o Replaced pmasks with movement modes and passability classes.
+
+2004-07-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/ctrl.c, src/kern.c, src/object.c, src/pinfo.h, src/place.c, src/place.h, src/player.cpp, src/terrain.c, src/terrain.h:
+       o Replaced pmask argument to place_is_passable with the object trying to pass.
+       o Removed pmask argument to place_find_path (object seeking a path is already
+         passed in).
+
+       * src/closure.c, src/cmd.c, src/cmd.h, src/ctrl.c, src/event.h, src/kern.c, src/place.c, src/place.h, src/terrain.c, src/terrain.h:
+       o Modified closure_exec to return integers as well as bools from scripts calls.
+       o Removed all the old placeFoo() functions that used the global Place variable
+         internally. Replaced them as necessary with place_foo(), which takes the
+         place as an argument.
+
+       * src/closure.c, src/combat.c, src/nazghul.c, src/place.c, src/terrain.c, src/terrain.h:
+       o Removed the obsolete 'effects' bitmask from terrains
+       o Corrected some places to use 'effect' instead of 'effects'; this fixes some
+         of the party-member-walking-on-campfire bugs Sam pointed out.
+
+       * worlds/haxima-1.001/game.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/terrains.scm:
+       Changed some hard-coded numeric values for pmasks to symbols
+
+       * worlds/haxima-1.001/game.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/images/dbailey/lost_dragon.png, worlds/haxima-1.001/images/dgervais/angband-32x32.png, worlds/haxima-1.001/images/gmcnutt/frame_pieces.png, worlds/haxima-1.001/images/gmcnutt/moons-16x16.png, worlds/haxima-1.001/images/jsteele/charset-8x16.png, worlds/haxima-1.001/images/jsteele/shapes-32x32.png, worlds/haxima-1.001/images/mixed/mine-32x32.png, worlds/haxima-1.001/images/sglasby/mechanisms.png, worlds/haxima-1.001/images/sglasby/rune_font_32x32.png, worlds/haxima-1.001/images/sglasby/rune_font_8x16.png:
+       Populated sound and image directories
+
+2004-07-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Container.cpp, src/Container.h, src/Field.cpp, src/Field.h, src/Attic/Item.cpp, src/Attic/Item.h, src/Attic/Loader.cpp, src/Attic/Loader.h, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Missile.cpp, src/Missile.h, src/Party.cpp, src/Party.h, src/Attic/Portal.cpp, src/Attic/Portal.h, src/Reagent.cpp, src/Reagent.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/Attic/Trap.cpp, src/Attic/Trap.h, src/ascii.c, src/ascii.h, src/astar.c, src/character.cpp, src/character.h, src/clock.c, src/clock.h, src/closure.c, src/closure.h, src/cmd.c, src/cmd.h, src/cmdwin.c, src/combat.c, src/combat.h, src/common.c, src/common.h, src/conv.c, src/conv.h, src/ctrl.c, src/ctrl.h, src/cursor.cpp, src/cursor.h, src/debug.c, src/debug.h, src/dice.c, src/dice.h, src/effect.c, src/effect.h, src/event.c, src/event.h, src/foogod.c, src/foogod.h, src/Attic/game.c, src/gob.c, src/gob.h, src/hash.c, src/images.c, src/images.h, src/kern.c, src/kern.h, src/Attic/lexer.c, src/Attic/lexer.h, src/list.h, src/macros.h, src/magic.c, src/magic.h, src/map.c, src/map.h, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/object.c, src/object.h, src/occ.c, src/occ.h, src/olist.c, src/opdefines.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h, src/Attic/portal.h, src/sched.c, src/sched.h, src/scheme-private.h, src/scheme.c, src/scheme.h, src/screen.c, src/screen.h, src/session.c, src/session.h, src/sky.c, src/sky.h, src/species.c, src/species.h, src/sprite.c, src/sprite.h, src/status.c, src/status.h, src/terrain.c, src/terrain.h, src/terrain_map.c, src/terrain_map.h, src/Attic/util.c, src/Attic/util.h, src/vehicle.cpp, src/vehicle.h, src/vmask.c, src/vmask.h, src/wind.c, src/wq.c, src/wq.h:
+       Merged from branch gmcnutt_scheme
+
+       * worlds/haxima-1.001/arms.scm, worlds/haxima-1.001/bakup.scm, worlds/haxima-1.001/bim.scm, worlds/haxima-1.001/Attic/class-bak.scm, worlds/haxima-1.001/class.scm, worlds/haxima-1.001/conv.scm, worlds/haxima-1.001/door.scm, worlds/haxima-1.001/effects.scm, worlds/haxima-1.001/fields.scm, worlds/haxima-1.001/food.scm, worlds/haxima-1.001/game.scm, worlds/haxima-1.001/gen.scm, worlds/haxima-1.001/generic-mech.scm, worlds/haxima-1.001/ifc.scm, worlds/haxima-1.001/init.scm, worlds/haxima-1.001/items.scm, worlds/haxima-1.001/kobj.scm, worlds/haxima-1.001/lever.scm, worlds/haxima-1.001/loc.scm, worlds/haxima-1.001/monster-generator.scm, worlds/haxima-1.001/moon.scm, worlds/haxima-1.001/moongate.scm, worlds/haxima-1.001/naz.scm, worlds/haxima-1.001/objs.scm, worlds/haxima-1.001/occs.scm, worlds/haxima-1.001/palette.scm, worlds/haxima-1.001/parties.scm, worlds/haxima-1.001/Attic/player.scm, worlds/haxima-1.001/portals.scm, worlds/haxima-1.001/portcullis.scm, worlds/haxima-1.001/reagents.scm, worlds/haxima-1.001/sched.scm, worlds/haxima-1.001/search.scm, worlds/haxima-1.001/session.scm, worlds/haxima-1.001/shroom.scm, worlds/haxima-1.001/species.scm, worlds/haxima-1.001/spells.scm, worlds/haxima-1.001/sprite-sets.scm, worlds/haxima-1.001/sprites.scm, worlds/haxima-1.001/tblit.scm, worlds/haxima-1.001/terrains.scm, worlds/haxima-1.001/Attic/test.scm, worlds/haxima-1.001/vehicles.scm, worlds/haxima-1.001/yellow-slime.scm:
+       Added all the new scripts
+
+       * worlds/haxima-1.001/sounds/cannon.wav, worlds/haxima-1.001/sounds/damage.wav, worlds/haxima-1.001/sounds/enter_moongate.wav, worlds/haxima-1.001/sounds/horse.wav, worlds/haxima-1.001/sounds/rowing.wav, worlds/haxima-1.001/sounds/walk.wav:
+       Populated sounds subdir
+
+2004-07-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/cmd.h, src/conv.c, src/ctrl.c, src/event.h, src/kern.c, src/status.h:
+       o Implemented kern-ui-handle-events but changed my mind about using it so it
+         remains untested (and unavailable to the script).
+       o Added kern-obj-remove-from-inventory & kern-obj-add-to-inventory.
+       o Added kern-ui-page-text for displaying scrolls and books in the status window.
+       o Modified cmdUse to NOT automatically remove items from inventory after they
+         are used. Instead items now remove themselves if they are consumable.
+
+2004-07-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/character.cpp, src/cmd.c, src/conv.c, src/kern.c, src/nazghul.c, src/play.c, src/session.c:
+       o Tried to eliminate conv.[ch], but we still use a few things in there. Cleaned
+         it up quite a bit, though, deleting 700 lines of code.
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/conv.c, src/kern.c, src/Attic/lexer.c, src/Attic/lexer.h, src/nazghul.c, src/session.c, src/terrain.c:
+       o Eliminated lexer.[ch]
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/cmd.c, src/hash.c, src/images.c, src/kern.c, src/nazghul.c, src/object.c, src/olist.c, src/place.c, src/play.c, src/session.c, src/terrain.c, src/terrain_map.c, src/Attic/util.c, src/Attic/util.h, src/wq.c:
+       o Modified the interpreter to fix the script->kernel->script recursion
+         issue. Limited testing so far, but no problems noted yet.
+
+       * src/conv.c, src/kern.c:
+       o Modified kern_conv_say to take a list of messages. This way we can break up
+         long strings in the script if we want to for easier-to-read formatting.
+       o Modified the kernel to always truncate player queries to the first four
+         characters. Conversation scripts should expect this, and only use keywords of
+         one to four characters. Because keywords are signal names they must match
+         exactly between kernel and script. The user can type extra, of course, but
+         only the first four characters will be used to make the signal name.
+
+2004-07-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/opdefines.h, src/scheme.c, src/scheme.h:
+       o Modified the interpreter to fix the script->kernel->script recursion
+         issue. Limited testing so far, but no problems noted yet.
+
+2004-07-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/ctrl.c, src/ctrl.h, src/kern.c:
+       o Added kern-char-get-mana
+       o Added kern-char-dec-mana
+       o Added kern-obj-dec-ap
+       o Added kern-obj-wander
+       o Added kern-char-attack
+       o Added kern-get-distance
+       o Added kern-in-los?
+       o Modified characters to have an optional "ai" closure, which runs when they
+         are idle in automatic mode. The kern api calls which make characters
+         (including kern-mk-char, kern-mk-stock-char and kern-mk-party-type) all take
+         an additional parameter for the ai.
+
+2004-07-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/cmd.h, src/ctrl.c, src/kern.c, src/object.c, src/object.h, src/scheme.c, src/species.c, src/species.h, src/status.c:
+       o Bugfix: needed to set the protection counter on sc->NIL, T and F to
+         zero. These special scheme cells are not obtained in the usual way, so
+         they're pref got out of synch and caused an assert when the invisibility
+         spell expired.
+       o Removed the startup closures from the kernel species struct and all related
+         code. These weren't working out with summoned creatures due to the SKS
+         recursion issue. Instead the equivalent thing is now done in the script.
+
+2004-07-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/effect.c, src/effect.h, src/gob.c, src/gob.h, src/kern.c, src/object.c, src/object.h:
+       o Bugfix: step on the sleep field then camp => crash in scheme. The problem is
+         using a NULL gob wrapper for NIL gobs (a recent change): if scheme needs to
+         run a garbage collection cycle with that NULL passed in as an arg it
+         crashes. The fix was to always use a non-NULL wrapper, even for NIL
+         gobs. Along with this I added ref-counting for gobs used in effects. The old
+         randomly-expiring protection spell showed that this is necessary for effects
+         applied to the entire party.
+       
+       o Bugfix: same steps to reproduce, once the above if fixed there was an assert
+         in Character::exec() because a resting character was not asleep as expected
+         (because the sleep effect wore off and woke him up). Fixed this by changing
+         Character::awaken() to not wake up resting characters.
+
+       * src/clock.c, src/clock.h, src/cmd.c, src/kern.c, src/sky.c, src/sky.h:
+       o Put astronomy info back into the AT command.
+       o Added names for moon phases, now reported by AT.
+
+       * src/effect.c, src/effect.h, src/kern.c, src/object.c, src/status.c:
+       o Added an optional "on-removal" procedure to effects so they can clean up
+         after themselves when they expire.
+       o Added a guard flag to prevent recursive status repaints
+
+       * src/kern.c, src/map.c, src/nazghul.c, src/sky.c, src/vmask.c, src/vmask.h:
+       o Bugfix: option-parsing wasn't working with options passed-in. Not sure why,
+         though this used to work. Added another option_index separate from optind as
+         indicated by the example in the man page.
+       o Bugfix: strange LOS artifacts. This happened because the lightmap was
+         operating directly on the cached vmask, which should only be altered by
+         vmask_los(). The fix was to use a temporary lightmap buffer instead.
+
+       * src/kern.c, src/object.c:
+       Bugfix: crash when "In Sanct" wears off the second party member. Problem was
+       double-deallocation of a kernel gob wrapper. Fixed this for this case by
+       getting rid of nil gobs. If it's common for a gob to be shared by an effect
+       applied to multiple party members then we'll need to add ref-counting to the
+       kernel gob wrapper.
+
+2004-07-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/clock.h, src/effect.h, src/kern.c, src/object.c, src/object.h:
+       o Added a duration field to effects. duration <= 0 means "forever"
+       o Added an expiration alarm to the effect entry struct. When a new entry is
+         created, if the effect has a finite duration this alarm is set. When the alarm
+         expires the effect is automatically removed.
+
+       * src/sprite.c:
+       o Bugfix: unmanned ship turns itself when hostile ship near. The cause of this
+         was an improper value for the "facing" when the vehicle was created. The
+         script was using 0, but it should have used a valid direction code like
+         "north". As a result, wheneve the ship with the bad facing tried to set the
+         srprite facing it silently failed, and thereby inherited the last valid
+         facing, which was set by the NPC ship underway. Added a debug warning in case
+         this ever happens again.
+
+2004-06-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/combat.c, src/place.c, src/place.h, src/player.h:
+       o Finally fixed all the gate spell scenarios I can test with current scripts.
+
+2004-06-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c, src/combat.h, src/player.cpp:
+       o Backing out recent changes. Need to try something else.
+
+2004-06-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/Spell.cpp, src/Attic/Spell.h, src/character.cpp, src/combat.c, src/ctrl.c, src/kern.c, src/nazghul.c, src/play.c, src/session.c, src/status.c:
+       o Removed Spell.h & Spell.cpp
+
+       * src/combat.c, src/combat.h, src/player.cpp:
+       o Removed combatAddParty
+       o Bugfix: wilderness combat cleans up properly now the player exits via a gate
+         spell (the shipboard case still handled improperly, though)
+
+2004-06-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/dice.c, src/kern.c:
+       o Bugfix: dice_valid should have checked for a null format pointer
+       o Bugfix: character destructor needed to remove char from party
+       o Bugfix: Party::createMembers() needed to use addMember() to inc ref count
+       o Added kern-char-kill
+       o Added kern-char-resurrect
+       o Added kern-obj-clone
+
+       * src/kern.c, src/object.c, src/place.c, src/sky.c, src/sky.h:
+       o Bugfix: putOnMap was not using the "no-step-signal" flag when calling
+         relocate(), causing some mild moongate recursion.
+
+       * src/kern.c, src/map.c:
+       o Added kern-map-set-peering
+       o Added kern-ui-waitkey
+
+       * src/kern.c:
+       o Added kern-place-get-width
+       o Added kern-place-get-height
+
+       * src/place.c, src/player.cpp, src/player.h:
+       o Bugfixes for time stop.
+
+2004-06-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/common.c, src/kern.c:
+       o Added kern-char-is-asleep?
+       o Added kern-map-set-jitter (for tremor/earthquake effects)
+
+       * src/kern.c:
+       o Added kern-char-set-alignment
+
+2004-06-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/cmd.c, src/gob.c, src/gob.h, src/kern.c, src/object.c, src/object.h, src/scheme-private.h, src/scheme.c:
+       o Added kern-add-xray-vision
+       o Added a "reveal all" status character to the foogod window
+       o Bugfix: foogod wasn't updating status for "quicken" & friends in a timely
+         manner.
+       o Added gobs to effects
+
+2004-06-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/foogod.c, src/kern.c, src/map.c, src/play.c, src/session.c, src/session.h:
+       o Added kern-add-xray-vision
+       o Added a "reveal all" status character to the foogod window
+       o Bugfix: foogod wasn't updating status for "quicken" & friends in a timely
+         manner.
+
+       * src/dice.c, src/kern.c:
+       o Added kern-char-is-hostile
+       o Bugfix: dice_parse missing a 'break' statement in a switch, caused an assert
+         on some valid dice expressions like "2d20+20"
+
+2004-06-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/closure.c, src/kern.c, src/object.c, src/object.h:
+       o Added kern-char-get-party
+       o Added kern-char-add-defense to change the defense bonus by an integral amount
+
+       * src/Attic/Spell.cpp, src/common.c, src/common.h, src/foogod.c, src/kern.c, src/magic.h, src/object.c, src/play.c, src/player.cpp, src/session.c, src/session.h:
+       o Moved the old global Reveal, Quicken, TimeStop and MagicNegated flags into
+         the session structure so they can be more conveniently saved/loaded
+       o Added kern-add-reveal, kern-add-quicken, kern-add-time-stop and
+         kern-add-magic-negated
+
+2004-06-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c, src/place.c:
+       o Modified kern-mk-place to expect a list of neighboring places. Currently only
+         above and below places are supported.
+       o Added kern-place-get-neighbor to lookup the neighboring place in a given
+         direction
+
+2004-06-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h, src/species.c, src/species.h:
+       o Modified kern-mk-arms-type to use the same gifc solution as
+         kern-mk-obj-type. It now expects a gifc cap as well as the gifc.
+       o Modified kern-fire-missile to check the missile for an 'exec' handler and to
+         run it on the target when it scores a hit
+       o Bugfix: status not being reflected immediately when an effect takes hold; was
+         waiting for next animation cycle.
+       o species now have a list of startup procedures
+       o Modified Character::start() to run all the species startup closures on the
+         character
+
+       * src/foogod.c, src/kern.c, src/wind.c:
+       o Added kern-set-wind to set the wind direction and minimal duration
+       o Added kern-ui-direction to prompt the player for a direction
+       o Bugfix: ship's hull hp not being painted in the correct place
+
+2004-06-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/character.cpp, src/kern.c:
+       o Added kern-mk-stock-char
+       o Added kern-place-is-passable
+       o Bugfix: if a character had a null tag in the script, it's kernel object tag
+         was not initialized, sometimes causing a crash on the subsequent save.
+       o Bugfix: if a character did not have an occupation the game would crash while
+         saving the character.
+       o Bugfix: npc parties were being saved with random alignment, causing them to
+         appear non-hostile on reload.
+       o Bugfix: the speed for ship types was not being loaded properly. This caused
+         the infinite loop when the npc ship attacks the player with cannons.
+
+       * src/character.cpp, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h:
+       o Added kern-obj-set-temporary
+       o Added Object::setTemporary() and Object::isTemporary()
+       o Added place_exit() which destroys all temporary objects in the place
+       o Modified Character::groupExitTo() to call place_exit() as the party leaves a
+         place
+
+2004-06-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/kern.c:
+       o Added kern-place-get-objects to return a list of all objects in a place.
+       o Added kern-char-set-fleeing to make a character flee from combat.
+       o Added kern-char-get-species to return the species of a character.
+
+2004-06-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/effect.c, src/effect.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/session.c, src/session.h:
+       o Added a "start" method for places, Objects and effects. The specific purpose
+         was so that the luminance effect imparted by "In Lor" would properly
+         initialize the effected object's luminosity at start-of-session. I expect the
+         support added will come in handy for other things as well later on.
+
+       * src/kern.c, src/place.c, src/place.h:
+       o Added kern-obj-is-char? to test if an object is a character
+       o Added kern-get-objects-at to return a list of objects at a location
+       o Added kern-obj-heal to heal hit points
+       o These new calls allowed me to implement a "Mani" spell which targets party
+         members from a list in the wilderness and characters on a tile in town
+
+2004-06-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Missile.cpp, src/Missile.h, src/kern.c, src/object.c:
+       o Added kern-ui-target and kern-fire-missile to support the Grav Por (magic
+         missile) spell.
+
+       * src/effect.h, src/kern.c, src/object.c:
+       o Added a cumulative flag to the effects structure. Only cumulative effects may
+         be attached more than once to an object.
+
+2004-06-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Field.cpp, src/Field.h, src/magic.c, src/object.c:
+       o A duration of < 0 on the field type makes it permanent
+       o Bugfix in spell tree
+       o An Zu now works
+
+2004-06-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/closure.c, src/effect.c, src/effect.h, src/kern.c, src/macros.h, src/object.c, src/object.h, src/scheme-private.h, src/scheme.c, src/session.c:
+       o Changed effects, fixed some nasty bugs and some minor ones.
+
+       * src/effect.c:
+       file effect.c was initially added on branch gmcnutt_scheme.
+
+       * src/effect.h:
+       file effect.h was initially added on branch gmcnutt_scheme.
+
+2004-06-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/Spell.cpp, src/Attic/Spell.h, src/cmd.c, src/kern.c, src/magic.c, src/magic.h, src/object.c, src/session.c, src/session.h:
+       o Added kern-set-magic-words
+       
+       o Added kern-add-spell
+       
+       o Added files magic.[ch]. These will replace Spell.[hcpp] which is being phased
+         out.
+       
+       o Moved spell words and spell tree out of Spell.h/Spell.cpp into the new
+         magic.h/magic.c
+       
+       o At this point I can mix an "An Nox" but I can't cast it yet.
+
+       * src/Party.cpp, src/Party.h, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/cmd.c, src/conv.c, src/kern.c, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       o Removed all traces of the old poison effect from the kernel.
+
+       * src/Attic/Spell.cpp, src/character.cpp, src/cmd.c, src/common.h, src/ctrl.c, src/kern.c, src/magic.c, src/magic.h, src/object.c, src/object.h, src/player.cpp, src/species.c, src/species.h:
+       o Added more fields to the spell structure so that I can reuse more of the
+         existing kernel code related to spellcasting.
+       
+       o The "an nox" test spell now works.
+
+       * src/magic.c:
+       file magic.c was initially added on branch gmcnutt_scheme.
+
+       * src/magic.h:
+       file magic.h was initially added on branch gmcnutt_scheme.
+
+2004-06-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Attic/Spell.cpp, src/cmd.c, src/combat.c, src/ctrl.c, src/player.cpp, src/player.h:
+       o Fixed the crash when sinking an NPC ship.
+       
+       o Fixed wilderness combat to always exit back to the player party's location
+         (found a case where it exited to the NPC party location, which I don't want
+         to allow).
+
+2004-05-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Field.cpp, src/kern.c, src/place.c, src/player.cpp, src/vehicle.cpp, src/vehicle.h:
+       o Added vehicles (wilderness only). Tested with a ship. Cannons not working
+         yet.
+
+       * src/Party.cpp, src/Party.h, src/kern.c, src/session.c:
+       o Fixed the bug that crashed when firing a cannon.
+       
+       o Added support for NPC's in ships (it crashes when you sink them with you
+         cannon's, though)
+
+2004-05-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/closure.c, src/cursor.cpp, src/cursor.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/place.h, src/player.h, src/wq.c:
+       o Moongates now show their closing/operning animations when the player steps
+         through.
+
+       * src/character.cpp, src/kern.c, src/map.c, src/map.h, src/sky.c, src/sky.h:
+       o Tweaked the map viewer to recenter on character's off-screen in round-robin
+         mode. Could still use a few more enhancements, but somewhat better now.
+
+       * src/ctrl.c, src/event.c, src/kern.c, src/play.c, src/session.c, src/terrain_map.c, src/terrain_map.h, src/wq.c:
+       o Fixed a very worrisome bug related to memory corruption.
+
+2004-05-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Party.h, src/clock.c, src/cmd.c, src/kern.c, src/nazghul.c, src/place.c, src/play.c, src/player.cpp, src/session.c, src/sky.c, src/sky.h:
+       o Astronomy partly working. Got a sun up. Not saving yet.
+
+       * src/kern.c, src/sky.c, src/sky.h:
+       o Added a distance to astral bodies to make the rendering order always
+         correct. So now the moons always pass before the sun, etc.
+
+       * src/kern.c, src/map.c, src/nazghul.c, src/play.c, src/player.cpp, src/session.c, src/session.h, src/sky.c, src/sky.h:
+       o Sky now associated with the session so it can save/load.
+
+2004-05-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/play.c, src/sky.c, src/sky.h:
+       More preliminary changes to astronomy.
+
+       * src/sky.c:
+       o Started in on the astronomy system. Half-torn apart right now but I need to
+         switch machines so I'm checking in.
+
+2004-05-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/wq.c, src/wq.h:
+       o Added most of the support needed for rudimentary moongates.
+
+       * src/gob.c:
+       file gob.c was initially added on branch gmcnutt_scheme.
+
+       * src/gob.c, src/gob.h:
+       Added missing files.
+
+       * src/gob.h:
+       file gob.h was initially added on branch gmcnutt_scheme.
+
+       * src/place.c:
+       o Bugfix: infrequent crash caused by not locking a tile in
+         place_for_each_tile().
+
+2004-05-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/Attic/Portal.cpp, src/Attic/Portal.h, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/ctrl.c, src/cursor.cpp, src/cursor.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/player.cpp, src/player.h:
+       o Implemented portals as mechs. Tested on a ladder and a trap door.
+
+2004-05-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/character.cpp, src/object.h, src/place.c, src/place.h, src/session.c, src/session.h, src/terrain_map.c, src/terrain_map.h:
+       o Bugfix: saving twice without an intervening reload was hitting an assert.
+
+2004-05-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/cmd.h, src/conv.c, src/conv.h, src/ctrl.c, src/kern.c, src/object.c, src/object.h, src/player.cpp, src/session.c, src/status.h:
+       o Fixed a few things to support character gobs.
+
+2004-05-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Party.cpp, src/Attic/Spell.cpp, src/character.cpp, src/clock.c, src/cmd.c, src/combat.c, src/conv.c, src/conv.h, src/ctrl.c, src/kern.c, src/object.c, src/object.h, src/place.c, src/play.c, src/player.cpp, src/session.c, src/sky.c:
+       o Removed the Mech C++ class. No longer needed now that mechs are completely
+         implemented in the script.
+
+       * src/Party.cpp, src/character.cpp, src/character.h, src/cmd.c, src/common.h, src/ctrl.c, src/kern.c, src/occ.c, src/occ.h, src/sched.c, src/sched.h, src/session.c:
+       o Added character schedules.
+
+       * src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h, src/place.c:
+       o Added support for terrain-blitting mechs.
+
+2004-05-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/cmd.c, src/kern.c, src/object.c, src/object.h, src/scheme.c, src/session.c, src/session.h:
+       o Added support for connecting mechs. Tested with basic
+         lever-and-portculis. Saving them works, too.
+
+       * src/kern.c, src/session.c, src/session.h:
+       o Eliminated kern-connect (no longer necessary with saved tags)
+
+       * src/scheme.c:
+       o Symbols now saved; might make "kern-connect" obsolete.
+
+2004-05-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/closure.c, src/cmd.c, src/kern.c, src/object.c, src/object.h, src/scheme.c, src/scheme.h:
+       o Added gob.c and gob.h to encapsulate gobs. Gobs now stored in a struct with
+         their corresponding scheme pointer. Automatically protected/unprotected on
+         creation/deletion, and they appear to correctly save
+         themselves and reinitialize their kernel objects on load.
+
+       * src/debug.c, src/kern.c, src/object.c, src/object.h, src/session.c:
+       o Cleaned up kobj initialization by adding a procedure to bind kobjs to gobs.
+
+2004-05-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/ctrl.c, src/kern.c, src/map.c, src/object.c, src/object.h, src/place.c, src/scheme-private.h, src/scheme.c, src/scheme.h:
+       o Got enough support in to make a door mech work. Saving them doesn't work yet.
+
+2004-05-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/closure.c, src/closure.h, src/cmd.c, src/kern.c, src/object.c, src/object.h, src/scheme.c, src/scheme.h:
+       o Implemented support for ghulscript-interfaces (gifcs), which are bound to
+         kernel ObjectTypes. This has been tested with the existing types, excluding
+         ArmsTypes.
+       
+       o Added support for ghulscript-objects (gobs), which are bounded to kernel
+         Objects. Not tested yet.
+
+2004-05-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/closure.c, src/kern.c, src/object.c, src/object.h:
+       o Added a monster-generator but now what I've been waiting for has come to
+         pass: the interpreter appears to be gc'ing a pointer referenced by the
+         kernel. Not immediately obvious why. Probably have to dig into the gc code.
+
+       * src/closure.c, src/closure.h, src/kern.c:
+       o Closures can now be either symbolic or raw procedures. Object type handlers
+         are now of the latter type since they never need to be saved.
+
+       * src/kern.c, src/object.c, src/object.h:
+       o Added an exec-handler to the ObjectType class.
+
+2004-05-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/character.cpp, src/character.h, src/cmd.c, src/conv.c, src/kern.c, src/object.c, src/object.h, src/occ.h, src/player.cpp, src/player.h, src/species.h:
+       o Pulled some of the Container methods (add, takeOut) and one of the Character
+         methods (addFood) up to the Object base class. Now, kern-obj-put-into and
+         kern-obj-add-food are safe on any object type.
+
+       * src/Container.cpp, src/Container.h, src/character.cpp, src/character.h, src/cmd.c, src/conv.c, src/kern.c, src/object.c, src/object.h, src/player.cpp, src/player.h, src/status.c:
+       o Pulled use_handler up from ItemType to base ObjectType (next step will be to
+         get rid of ItemType)
+       
+       o Changed the player_party inventory from a bare linked list to a
+         Container. For some reason this was necessary to the previous step, but I've
+         lost track of why by now.
+       
+       o Changed status viewer code appropriately.
+       
+       o Enhanced Container class with new methods to make it "browsable" by the
+         status viewer.
+
+       * src/Attic/Item.cpp, src/Attic/Item.h, src/Makefile.am, src/Attic/Makefile.in, src/character.cpp, src/cmd.c, src/conv.c, src/kern.c, src/play.c, src/player.cpp, src/player.h, src/session.c, src/status.c:
+       o Got rid of the ItemType subclass.
+       
+       o Bugfix: had to make the player_party's Container inventory be a pointer to
+         allow saving/loading using existing Container save/load code.
+
+2004-05-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Attic/Loader.cpp, src/Attic/Loader.h, src/Attic/Makefile.in, src/Party.cpp, src/Reagent.cpp, src/character.cpp, src/character.h, src/conv.c, src/images.c, src/kern.c, src/object.c, src/sched.c, src/screen.c, src/session.c, src/sprite.c:
+       o Removed obsolete Loader class
+
+       * src/Container.cpp, src/Container.h, src/character.cpp, src/closure.c, src/closure.h, src/cmd.c, src/kern.c, src/occ.c:
+       o Container traps now script procedures.
+       o Containers save themselves (including traps and contents)
+       o Added kern-mk-container
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/Trap.cpp, src/Attic/Trap.h, src/character.cpp, src/cmd.c, src/combat.c, src/kern.c, src/play.c, src/session.c:
+       o Removed obsolete Trap class
+
+       * src/character.cpp, src/character.h, src/cmd.c, src/kern.c, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       o Added a get-handler for all object types.
+       o Implemented food via the get-handler.
+
+       * src/occ.h:
+       o Changed container traps to be script procedures.
+       o Containers now saved (including traps and contents)
+       o Added kern-mk-container to load saved containers
+
+2004-05-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Field.cpp, src/Missile.cpp, src/kern.c, src/object.c, src/occ.c, src/terrain.h:
+       o Bugfix: fields left by missiles (like flaming oil) did not have their initial
+         duration setup right
+       
+       o Added/debugged container types in occupations
+
+       * src/kern.c:
+       o Bugfix: sleep sprites not properly setup in the species
+       
+       o Added new parm to kern-mk-terrain: the effect procedure (nil for none). This
+         replaces the original, ambiguous kern-attach-script as a way to create
+         effects for terrains.
+       
+       o Eliminated obsolete kern-attach-script
+
+2004-05-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/combat.c, src/kern.c, src/object.c:
+       o Changed kern-mk-party to kern-mk-party-type
+       o Added kern-mk-party
+       o A coupld of bugfixes related to NPC parties
+
+       * src/character.cpp, src/character.h, src/kern.c:
+       
+       o Bugfix: when saving in combat character alignments were not getting saved, so
+         on reload the npc's would attack each other
+
+       * src/combat.c, src/kern.c:
+       
+       o Added checks when positioning characters in combat to see if the terrain is
+         hazardous or if the tile contains a field.
+
+2004-05-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/kern.c:
+       Added kern-mk-party for prefab npc party types.
+
+       * src/kern.c, src/object.c, src/object.h:
+       Bugfix: objects were not saving their count.
+       
+       Cleanup: removed obsolete kern-mk-wilderness-combat
+
+2004-05-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Makefile.am, src/Attic/Makefile.in, src/character.cpp, src/combat.c, src/common.c, src/common.h, src/ctrl.c, src/dice.c, src/dice.h, src/kern.c:
+       Added support for dice-roll notation in the script. Updated existing armament
+       type declarations to use it.
+
+       * src/dice.c:
+       file dice.c was initially added on branch gmcnutt_scheme.
+
+       * src/dice.h:
+       file dice.h was initially added on branch gmcnutt_scheme.
+
+2004-05-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp:
+       Bugfix: thrown weapon types not initialized properly, caused a crash when used.
+
+       * src/Arms.cpp, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/cmd.c, src/kern.c, src/object.c, src/object.h, src/place.c, src/player.cpp, src/player.h:
+       Added a count parameter to kern-mk-obj. This allows you to make a batch of
+       objects with one call. The count is stored in the object itself, so it only
+       creates one object in memory, but that object represents a "pile" of objects of
+       the same type. (Note: this does not affect how objects are stored in inventory,
+       that will require more significant changes later).
+
+       * src/kern.c:
+       Bugfix: natural weapons weren't being setup properly in the species structure.
+
+2004-05-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/kern.c, src/object.c, src/object.h, src/status.c:
+       Poison now shows up in character stats. Changed the way stats are reported.
+
+       * src/kern.c, src/list.h:
+       Damage effects now print console messages if the damaged object is
+       player-controlled.
+       
+       Fixed a bug in changing party order.
+
+2004-05-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/species.c, src/species.h:
+       Added simple immunity to damage types. Currently only the species can specify
+       any type of immunity. Added kern-obj-get-immunities so the script can check for
+       immunities.
+
+2004-04-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Field.cpp, src/Field.h, src/kern.c, src/object.c:
+       o Changed kern-mk-obj to use the type as a factory, so not it will work for any
+         object with a type.
+       
+       o Added a duration parameter to kern-mk-field.
+
+       * src/Attic/Item.cpp, src/Attic/Item.h, src/closure.c, src/closure.h, src/kern.c, src/object.c, src/object.h, src/terrain.c:
+       o Added kern-ui-select-party-member. Scripts can now prompt the player to
+         select a party member.
+       
+       o Added kern-obj-remove-hook to remove effects like poison.
+       
+       o Added kern-mk-usable-item-type to create objects that can be (u)sed.
+       
+       o With these new commands I created and tested a cure-poison potion.
+
+2004-04-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Field.cpp, src/Field.h:
+       Field class needed to override the save() method to generate kern-mk-field
+       instead of kern-mk-obj.
+
+       * src/Field.cpp, src/Attic/Mech.cpp, src/Party.cpp, src/kern.c, src/object.c, src/object.h, src/player.cpp:
+       Started adding a poison field. Currently it poisons the party. This is the
+       initial checkin: it does not poison member, there is no way to cure the poison,
+       and the poisoned state is not saved.
+       
+       Added kern-obj-add-hook, which can be used to attach a closure to an object
+       when a specific hook fires. Currently the only hook is start-of-turn, which
+       runs at the start of the object's turn right after its assigned its action
+       points. The hook closure takes the object as its only parameter.
+
+       * src/Field.cpp, src/Field.h, src/kern.c:
+       Added kern-mk-field for instantiating Field objects.
+
+       * src/Field.cpp, src/Field.h, src/Attic/Spell.cpp, src/closure.c, src/kern.c, src/object.c, src/session.c, src/terrain.c:
+       Added saving/loading of field types. The new FieldType constructor takes a
+       closure as an argument and uses this to apply the effects of objects which are
+       placed on the field. This replaces the old effect-mask technique as it applied
+       to fields.
+       
+       Field objects currently have a bug in that they do not expire. I'll attempt to
+       fix this with my next checking.
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       Poison applied to the party is now applied to its members instead.
+       
+       Removed obsolete applyExistingEffects() methods. This has been replaced by the
+       start-of-turn hook.
+
+       * src/character.cpp, src/closure.c, src/closure.h, src/kern.c, src/object.c, src/object.h, src/place.c, src/scheme.c:
+       Added ability to save hooks attached to objects.
+
+       * src/character.h:
+       Removed some commented-out code.
+
+       * src/combat.c:
+       Removed some dead code.
+
+       * src/kern.c:
+       file kern.c was initially added on branch gmcnutt_scheme.
+
+       * src/kern.c:
+       New file.
+
+       * src/kern.h:
+       file kern.h was initially added on branch gmcnutt_scheme.
+
+       * src/kern.h:
+       New files.
+
+2004-04-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am:
+       Pulled the kernel API out of session.c to the new kern.c.
+
+       * src/Attic/Makefile.in:
+       Added kern.c.
+
+       * src/object.c:
+       Bugfix: Object constructor needed to set it's container link key to its object
+       type layer. It was defaulting to the null layer.
+
+       * src/player.cpp:
+       Bugfix: items in player inventory that were also readied by party members were
+       being saved twice.
+
+       * src/session.c:
+       Pulled kernel API out of session.c to the new kern.c.
+
+       * src/session.c:
+       Removed dead code.
+
+       * src/session.h:
+       Pulled kernel API implementation out of session.c over to kern.c.
+
+2004-03-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/object.c, src/object.h, src/place.c, src/player.cpp, src/session.c:
+       o All containers now recursively remove and destroy their contents on session
+         teardown.
+       
+       o Added ref-counting to avoid double-deletion of party members during session
+         teardown.
+
+       * src/character.cpp, src/cmd.c, src/cmd.h, src/ctrl.c, src/place.c, src/play.c, src/player.cpp, src/session.c, src/session.h:
+       o Added CTRL-Q)uicksave and CTRL-R)eload. Quicksave saves the current session
+         but does not quit the game. Reload reloads the session from the save file
+         while the game is still running.
+
+2004-03-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Container.cpp, src/Container.h, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Party.cpp, src/Party.h, src/Attic/Portal.cpp, src/Reagent.cpp, src/Reagent.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/character.cpp, src/character.h, src/object.c, src/object.h, src/place.c, src/player.cpp, src/player.h, src/session.c, src/vehicle.cpp, src/vehicle.h:
+       
+       o The player is now loaded like any other object. When starting from the
+         wilderness, the player party is loaded as an object in the wilderness. When
+         starting in non-wilderness, the party members are loaded as objects; then,
+         after loading but before starting the session, the starting place is
+         determined by checking the location of the party members.
+
+       * src/combat.c, src/place.c, src/place.h:
+       
+       o When saving in combat the combat place is saved recursively in the wilderness
+         place. This gets rid of the special-case hacks necessary to make saving in
+         combat work.
+
+2004-03-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/Mech.cpp, src/Attic/Mech.h, src/session.c:
+       o All of the kern_mk functions now return a pointer to the defined scheme
+         object (or nil if an error occurred)
+       
+       o Consolidated some of the scm_define macros
+
+       * src/Attic/Portal.cpp, src/cmd.c, src/combat.c, src/common.h, src/place.c, src/place.h, src/player.cpp, src/player.h, src/session.c, src/terrain_map.c:
+       o Places can now contain subplaces, which are saved recursively within them.
+       
+       o Saving in combat temporarily broken in conjunction with the above.
+
+       * src/combat.c, src/combat.h, src/place.c, src/place.h, src/session.c, src/session.h, src/terrain_map.c, src/terrain_map.h:
+       o Added a 'struct save' which is passed to all the saving routines. It includes
+         a callback table for writing out save code that is reasonably indented.
+
+       * src/place.c, src/session.c, src/terrain_map.c, src/terrain_map.h:
+       o Terrain maps associated with places are now saved recursively within
+         them. Terrain maps not associated with places (combat and overlay maps) are
+         still saved standalone.
+
+2004-03-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.c, src/object.h, src/session.c:
+       o kern-mk-place now looks for an optional list of contents. Each entry in the
+         list is an object followed by its x, y coordinates in the place. Content
+         lists are not yet saved. That's next, and it will require fiddling with how I
+         load/save the player party.
+       
+       o Added kern-mk-obj for creating simple objects.
+       
+       o Added kern-put-obj for locating objects that aren't created as part of a
+         place.
+
+2004-03-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/object.c, src/scheme.c, src/scheme.h, src/session.c, src/terrain.c, src/terrain.h:
+       o Added burning effect to lava terrain.
+
+       * src/closure.c:
+       file closure.c was initially added on branch gmcnutt_scheme.
+
+       * src/closure.c, src/closure.h, src/object.c:
+       o Invoking scheme closures from C now uses varargs (like printf).
+
+       * src/closure.c, src/closure.h:
+       Two files that belonged in the last checkin
+
+       * src/closure.h:
+       file closure.h was initially added on branch gmcnutt_scheme.
+
+2004-03-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/combat.c, src/session.c:
+       o Bugfix: save in combat, reload, save again without leaving combat => crash
+         because Combat.place not set. Relying on Place->is_wilderness_combat now
+         instead.
+
+       * src/nazghul.c:
+       o The command-line now expects the load file as a non-option argument (it used
+         to be the --file option).
+
+2004-03-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.c, src/character.cpp, src/combat.c, src/combat.h, src/list.h, src/place.c, src/place.h, src/player.cpp, src/session.c, src/session.h, src/terrain_map.c, src/terrain_map.h:
+       Almost saving/loading from combat
+
+       * src/combat.c, src/place.h, src/session.c, src/terrain_map.h:
+       o Can save/load from the temporary wilderness combat place now. Surprisingly
+         difficult, required some hacks which can hopefully be removed once places
+         save/load their own contents.
+
+2004-03-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/combat.c, src/object.c, src/object.h, src/player.cpp, src/player.h, src/session.c:
+       o At last saving/loading from towns works.
+
+2004-03-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/object.c, src/place.c, src/play.c, src/player.cpp, src/session.c:
+       o The player party constructor now relocates the party if the place is not
+         null.
+       
+       o Bugfix: object relocate() always called updateView(), even if the object was
+         removed from the map during relocation.
+       
+       o Bugfix: place destructor would assert if any objects were still sitting on
+         any tiles. Added a call to remove all objects before proceeding to tile
+         destruction.
+
+       * src/foogod.c, src/foogod.h, src/map.c, src/Attic/moongate.c, src/nazghul.c, src/object.c, src/play.c, src/player.cpp, src/session.c, src/session.h, src/sky.c, src/sky.h, src/status.c, src/status.h:
+       o Cleaned up the startup code a bit. Moved most of the game start code to
+         nazghul.c and the session start code to session.c.
+       
+       o Hacked ambient light to be a fixed value until I can reorg the astronomy
+         stuff.
+
+       * src/session.c, src/sky.c:
+       o More changes related to getting the game to save/reload in a town.
+
+2004-03-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Party.cpp, src/Attic/Portal.cpp, src/Attic/Portal.h, src/character.cpp, src/cmd.c, src/combat.c, src/ctrl.c, src/Attic/game.c, src/place.c, src/play.c, src/player.cpp, src/Attic/portal.h, src/session.c:
+       o Changed 'portal.h' to Portal.h, added Portal.cpp and cleaned up the .h file.
+
+       * src/Attic/Portal.cpp:
+       file Portal.cpp was initially added on branch gmcnutt_scheme.
+
+       * src/Attic/Portal.cpp, src/Attic/Portal.h, src/object.c, src/object.h, src/session.c:
+       o More cleanup in Poral.
+       
+       o Added a new object constructor similar to the new one for object types. All
+         the other constructors and the init() routines are now obsolescent and need
+         to be phased out.
+       
+       o Noticed a new bug: saving in towns records the player party coordinates, not
+         the party member coordinates. So reloading after saving in towns is not
+         correct.
+
+       * src/Attic/Portal.h:
+       file Portal.h was initially added on branch gmcnutt_scheme.
+
+       * src/cmd.c, src/terrain.c:
+       o Bugfix: terrain_new not properly zeroing out its structure, caused obsolete
+         'effects' field to be uninitialized, so crossing a bridge might burn and
+         poison the party!
+       
+       o Loading the wilderness map (sans all the towns) with the expanded palette. No
+         other issues found.
+
+       * src/cmd.c, src/images.c, src/images.h, src/session.c:
+       o Save/restore of limited games now works. At long, long last. Much still to be
+         done to get the full complement of features loading and saving, however.
+
+       * src/place.c, src/place.h, src/Attic/portal.h, src/session.c:
+       o Added 'kern-mk-town' procedure. This replaces the old "inference" technique
+         where the loader would make a place a town by inferring this from certain
+         fields.
+       
+       o You can now enter GreenTower from the Wild. Saving in GreenTower and
+         reloading works fine.
+
+2004-03-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/ascii.c, src/ascii.h, src/cmd.c, src/cmdwin.c, src/combat.c, src/common.h, src/cursor.cpp, src/cursor.h, src/map.c, src/play.c, src/screen.c, src/screen.h, src/session.c, src/session.h:
+       o Can now walk around. Sprites are mismatched, not sure what else is wrong yet.
+       
+       o Consolidated some globals into a new Session global.
+       
+       o Set NUM_MOONS to zero to turn off the moons until I can rewrite the MoonInfo
+         cruft - I don't want to propogate that any more if I can help it.
+
+       * src/character.cpp, src/clock.c, src/clock.h, src/cmd.c, src/combat.c, src/session.c, src/session.h, src/sky.c, src/sky.h:
+       o The LOS screw-up was more errors in script translation. It's just fine now.
+       
+       o Fixed some stuff related to the global clock. Decided it's reasonable to
+         require a clock in every game.
+       
+       o Fixed a bug where we crash if we have no Sun (don't see why a sun should be
+         required).
+
+       * src/sprite.c, src/sprite.h:
+       o Sprites have been fixed, this was a script-upgrade error.
+       
+       o Sprite animation needed to be reworked. The loader no longer pushes sprites
+         onto a list in the sprite lib, so I can't advance frames by incrementing each
+         individual sprite's frame counter anymore. Instead I use a single static
+         sprite_tick counter in the sprite lib and have all sprites % off of
+         that. This is more efficient anyway, as now I no longer have to walk the
+         sprite list touching every multi-frame sprite every animation tick, and I no
+         longer have to keep a per-sprite frame or wavecrest. The counter is an
+         unsigned int so rollover should happen naturally.
+       
+       o LOS is totally hosed, but other than that I've found no other problems so
+         far.
+
+2004-03-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/session.c:
+       o Loading and saving CHARs.
+
+       * src/player.cpp, src/player.h, src/session.c:
+       o Loading and saving the player party. Not actually walking around yet - that
+         will be next.
+
+       * src/session.c:
+       o Discovered that with -O2 turned on the c++ compiler appears to incorrectly
+         handle some cases of call-by-reference. That's it. No more c++. All new code
+         is hereby forbidden to make use of ANY c++ features. It must be phased out.
+       
+       o Ripped out all the unpack_<foo> functions (which were using the cursed
+         call-by-reference) and replaced them with a scanf-like unpacker which uses
+         explicit pointers as its args. Cleans up a lot of boilerplate, too.
+
+2004-03-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Arms.h, src/Container.cpp, src/Field.cpp, src/Field.h, src/Reagent.cpp, src/Reagent.h, src/Attic/Trap.cpp, src/Attic/Trap.h, src/Attic/moongate.c, src/Attic/moongate.h, src/object.c, src/object.h, src/occ.c, src/occ.h, src/session.c, src/vehicle.cpp, src/vehicle.h:
+       o Loading arms types
+
+       * src/character.cpp, src/character.h, src/session.c, src/species.c, src/species.h:
+       o Loading species
+
+       * src/occ.c, src/occ.h, src/session.c:
+       o Loading occupation types
+
+2004-03-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/combat.c, src/Attic/load.c, src/Attic/load.h, src/map.h, src/place.c, src/play.c, src/session.c, src/session.h, src/terrain_map.c, src/terrain_map.h:
+       o Moved loading code to session.c and got rid of load.[ch].
+       
+       o Added loading of terrain maps.
+
+       * src/Makefile.am, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Makefile.in, src/astar.c, src/conv.c, src/debug.c, src/debug.h, src/Attic/game.c, src/images.c, src/images.h, src/Attic/load.c, src/Attic/load.h, src/macros.h, src/opdefines.h, src/play.c, src/play.c, src/scheme-private.h, src/scheme.c, src/scheme.h, src/session.c, src/session.h, src/sky.c:
+       *** empty log message ***
+
+       * src/Party.cpp, src/cmd.c, src/combat.c, src/place.c, src/place.h, src/play.c, src/player.cpp, src/session.c:
+       o Loading and saving simple places (no objects in them yet).
+
+       * src/combat.c, src/play.c, src/session.c, src/session.h, src/terrain_map.c, src/terrain_map.h:
+       o Added a 'kern-include' proc. This is so the engine can save the session such
+         that when the save-file is reloaded all the necessary "include" files are
+         loaded with it.
+       
+       o Added saving of maps in the session file.
+
+       * src/Attic/load.c:
+       file load.c was initially added on branch gmcnutt_scheme.
+
+       * src/Attic/load.c, src/play.c, src/terrain.c, src/terrain.h, src/terrain_map.c:
+       Loading palettes
+
+       * src/Attic/load.c, src/place.c, src/scheme.c, src/scheme.h, src/sprite.c, src/sprite.h, src/terrain.c, src/terrain.h, src/terrain_map.c, src/terrain_map.h:
+       Terrain loading
+
+       * src/Attic/load.c, src/session.c, src/session.h:
+       Made the interpreter part of the session
+
+       * src/Attic/load.h:
+       file load.h was initially added on branch gmcnutt_scheme.
+
+       * src/opdefines.h:
+       file opdefines.h was initially added on branch gmcnutt_scheme.
+
+       * src/scheme-private.h:
+       file scheme-private.h was initially added on branch gmcnutt_scheme.
+
+       * src/scheme.c:
+       file scheme.c was initially added on branch gmcnutt_scheme.
+
+       * src/scheme.h:
+       file scheme.h was initially added on branch gmcnutt_scheme.
+
+       * src/session.c:
+       file session.c was initially added on branch gmcnutt_scheme.
+
+       * src/session.c, src/session.h:
+       o Include files now treated like regular session objects instead of a special
+         case. Cleans things up a bit.
+
+       * src/session.h:
+       file session.h was initially added on branch gmcnutt_scheme.
+
+2004-03-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/loader.cpp, src/Attic/loader.h, src/species.c, src/species.h:
+       o Loading SPECIES.
+
+2004-03-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/loader.cpp, src/Attic/loader.h, src/occ.c, src/occ.h:
+       o Loading OCCs now.
+       
+       o Added a templates for binding lists of tags into arrays of pointers.
+       
+       o Added a template to bind a single tag to a pointer.
+
+2004-03-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Reagent.cpp, src/Reagent.h, src/Attic/loader.cpp, src/Attic/loader.h:
+       o Loading REAGENTS
+
+       * src/Attic/Spell.cpp, src/Attic/Spell.h, src/Attic/loader.cpp, src/Attic/loader.h:
+       o Loading SPELLS
+       
+       o Fixed a nasty bug related to double-deallocating a string in the parsed
+         sprite destructor.
+
+       * src/Attic/loader.cpp, src/Attic/loader.h:
+       o Loading MAGIC WORDS.
+
+2004-03-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/def_macros.ghul, examples/data/types.ghul, examples/data/player/party.ghul, examples/data/types/chest_traps.ghul, examples/data/types/furniture.ghul, examples/data/types/magical_fields.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/portal_types.ghul, examples/data/types/useable_items.ghul, examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/world/characters/Gen.ghul, src/Arms.cpp, src/Arms.h, src/Container.cpp, src/Field.cpp, src/Field.h, src/Attic/Item.cpp, src/Attic/Item.h, src/Reagent.cpp, src/Attic/Trap.cpp, src/Attic/Trap.h, src/Attic/lexer.c, src/Attic/lexer.l, src/Attic/loader.cpp, src/Attic/loader.h, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/object.c, src/object.h, src/occ.c, src/Attic/parser.y, src/Attic/parser_cb.h, src/terrain.c, src/vehicle.cpp, src/vehicle.h:
+       o Loading objects types.
+       
+       o Split object types into OBJ_TYPE, TRAP_TYPE, FIELD_TYPE, ITEM_TYPE,
+         MOONGATE_TYPE and ARMS_TYPE.
+       
+       o Added new constructor calls to object type classes as necessary.
+
+2004-02-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/loader.cpp:
+       More formatting changes
+
+       * src/Attic/loader.cpp:
+       Formatting changes
+
+       * src/Attic/loader.cpp, src/Attic/loader.cpp, src/terrain.c:
+       *** empty log message ***
+
+2004-02-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/loader.c, src/Attic/loader.cpp:
+       Moved loader.c to loader.cpp
+
+       * src/Attic/loader.cpp:
+       file loader.cpp was initially added on branch gmcnutt_loader.
+
+       * src/Attic/loader.cpp, src/Attic/loader.cpp, src/Attic/loader.cpp, src/Attic/loader.cpp, src/Attic/loader.cpp:
+       *** empty log message ***
+
+2004-02-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/loader.c, src/Attic/loader.h, src/terrain.c, src/terrain.h, src/terrain_map.c:
+       o Loading PALETTE constructs now.
+
+2004-02-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world.ghul, examples/data/types/terrains.ghul, src/Attic/lexer.c, src/Attic/lexer.l, src/Attic/loader.c, src/Attic/parser.y, src/Attic/parser_cb.h, src/terrain.c, src/terrain.h, src/terrain_map.h:
+       o Converted all the loader errors to warnings so that the game continues on a
+         load error. I forgot that errors would exit the program.
+       
+       o Eliminated the old 'combat_map' construct and replaced it with a field in the
+         terrain construct for specifying a map. In the old system this was impossible
+         because tags usually had to be resolved right away at parse time, so maps and
+         terrains had a chicken-and-egg problem. With the new loader binding is done
+         as a second pass so this is no longer an issue. Right now terrains with no
+         defined combat map emit a warning at bind time.
+
+2004-02-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/Makefile.am, examples/Makefile.in, examples/data/Makefile, examples/data/def_constants.ghul, examples/data/def_macros.ghul, examples/data/types.ghul, examples/data/world.ghul, examples/data/types/portal_types.ghul, examples/data/types/readable_items.ghul, src/Attic/lexer.c, src/Attic/lexer.l, src/Attic/loader.c, src/Attic/loader.h, src/Attic/parser.y, src/play.c:
+       o Split the load file into two files: a game file (examples/game.ghul) and a
+         session file (examples/mapfile). The game file contains read-only game data
+         (or it will when all is said and done) and the session file contains all the
+         data used to save the state of a game (again, eventually). Right now the two
+         are fairly well split but lots of crossover still exists. This will be sorted
+         out in checking to follow.
+       
+       o Added the new GAME keyword to the script. This keyword goes in the saved
+         session file and specified the file from which to load the read-only game
+         data.
+       
+       o The loader now returns a session data structure which contains all the
+         per-session data and a pointer to the read-only game data. When a new session
+         is loaded the loader will attempt to reuse the existing game data unless the
+         session specifies it wants to use a different game file than the old
+         session. A session MUST specify a game file via the new GAME keyword or the
+         loader will abort.
+       
+       o When a session fails to load the loader will return the old session if it
+         exists or NULL otherwise.
+
+       * examples/data/types.ghul, examples/data/world.ghul, src/Attic/game.c, src/Attic/lexer.c, src/Attic/lexer.l, src/Attic/loader.c, src/Attic/loader.h, src/Attic/parser.y, src/Attic/parser_cb.h:
+       o Congregated the CURSOR and CROSSHAIR constructs into a MISC construct which
+         has them as fields.
+       
+       o Added file-name information to the parsing structures so that error messages
+         can show the file as well as the line (game file vs session file).
+
+       * src/ascii.c, src/ascii.h, src/Attic/loader.c, src/Attic/loader.h, src/play.c, src/screen.c, src/screen.h:
+       o Trivial change to the way I set the frame sprites and ascii sprite
+         to make things simpler to load.
+       
+       o Loading is now a separate step from actually changing the game state. The
+         loader returns - on success - a completely parsed and loaded structure which
+         the caller will then use to update the game state. This way we don't get
+         partway through changing the game state before we encounter a bind error, for
+         instance, which would cause the operation to fail.
+
+       * src/cmd.c, src/Attic/loader.c, src/sprite.c, src/sprite.h, src/terrain.c, src/terrain.h:
+       o Reverted terrain and sprite permanent structures to remember their
+         tags. Although I don't need them for lookups with the new loader, I will need
+         them for saving some objects to the session file (e.g., altered MAPS).
+
+       * src/cmd.c, src/combat.c, src/conv.c, src/Attic/game.c, src/Attic/loader.c, src/Attic/loader.h, src/Attic/parser.y, src/Attic/parser_cb.h, src/place.c, src/place.h, src/terrain.c, src/terrain.h:
+       o Parsing & loading terrains.
+
+       * src/Attic/loader.c:
+       o The loader now blows away its temporary data structures prior to
+         exit. This addresses the inefficiency problem I noted in an earlier checkin.
+
+       * src/Attic/parser_cb.h:
+       file parser_cb.h was initially added on branch gmcnutt_loader.
+
+2004-02-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/Mech.cpp, src/astar.c, src/debug.h, src/Attic/game.c, src/images.c, src/images.h, src/Attic/loader.c, src/play.c, src/sprite.c, src/sprite.h:
+       o Loading FRAME and ASCII constructs.
+       
+       o Removed tags from sprite and image structs. These tags are only required
+         while loading and it is sufficient to store them in the temporary data
+         structures used by the loader.
+       
+       o Currently the temporary loader structures will remain until a reload, at
+         which point everything will be torn down. Although convenient, this is
+         wasteful. I'll try to address this in my next checkin.
+
+       * src/Attic/game.c, src/images.c, src/Attic/loader.c, src/screen.c, src/screen.h, src/sprite.c:
+       Added loading and binding of frame elements
+
+       * src/Attic/game.c, src/images.c, src/images.h, src/Attic/lexer.c, src/Attic/loader.c, src/Attic/loader.h, src/Attic/parser.y, src/sprite.c, src/sprite.h:
+       Loading of sprites, binding implemented but untested
+
+       * src/Attic/loader.c, src/sprite.c, src/sprite.h:
+       Added an allocation pass and a binding pass to the loader
+
+2004-02-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/debug.c, src/debug.h, src/Attic/game.c, src/Attic/lexer.c, src/Attic/loader.c, src/Attic/mmap.c, src/Attic/mmap.h, src/nazghul.c, src/Attic/util.c, src/Attic/util.h:
+       o Moved the mmap utility wrappers from util.h/c to mmap.h/c. The problem with
+         util.h is that it includes common.h, which is too much for some clients. I'm
+         going to try a finer-grained approach with these little utility functions.
+       
+       o Converted the old (broken) debug macros to functions and put them in the new
+         debug.c.
+
+       * src/debug.c:
+       file debug.c was initially added on branch gmcnutt_loader.
+
+       * src/Attic/lexer.c, src/Attic/lexer.l, src/macros.h, src/Attic/parser.y, src/Attic/util.h:
+       Added macros.h for generic, c-safe macros. Cleaned up lexer.l and parser.y with this change.
+
+       * src/macros.h:
+       file macros.h was initially added on branch gmcnutt_loader.
+
+       * src/Attic/mmap.c:
+       file mmap.c was initially added on branch gmcnutt_loader.
+
+       * src/Attic/mmap.h:
+       file mmap.h was initially added on branch gmcnutt_loader.
+
+2004-02-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/lexer.h:
+       file lexer.h was initially added on branch gmcnutt_loader.
+
+       * Attic/lexer.h, examples/data/def_macros.ghul, examples/data/world.ghul, examples/data/player/party.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/occupations.ghul, examples/data/types/portal_types.ghul, examples/data/types/readable_items.ghul, examples/data/types/species.ghul, examples/data/types/useable_items.ghul, examples/data/types/vehicles.ghul, examples/data/world/characters/BlackBart_the_Shipwright.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/characters/Doris.ghul, examples/data/world/characters/Gen.ghul, examples/data/world/characters/Olin_the_Ghast.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/characters/party_members.ghul, examples/data/world/conversations/C_green_tower.ghul, examples/data/world/conversations/C_misc_npcs.ghul, examples/data/world/conversations/conversations.ghul, examples/data/world/places/Glasdrin.ghul, examples/data/world/places/GoblinCaves.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/GreenTowerLower.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, examples/data/world/places/P_rom_camp.ghul, examples/data/world/places/P_slime_cave.ghul, examples/data/world/places/P_terrain_test.ghul, examples/data/world/places/P_wilderness.ghul, src/Makefile.am, src/Attic/Makefile.in, src/Attic/lexer.c, src/Attic/lexer.l, src/Attic/loader.c, src/Attic/loader.h, src/Attic/parser.y, src/play.c, src/Attic/util.c, src/Attic/util.h:
+       o parser.o and lexer.o must be compiled using gcc (instead of g++) or I get
+         parser stack overflows. No idea why.
+       
+       o Updated the scripts to reflect some tweaks I made to the syntax while writing
+         the new parser.
+
+       * src/play.c:
+       Removed the obolete 'play' struct in play.c
+
+2004-02-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, Attic/configure, Attic/configure.in, examples/Makefile.in, src/Makefile.am, src/Attic/Makefile.in, src/Attic/lexer.c, src/Attic/lexer.h, src/Attic/lexer.l, src/Attic/loader.c, src/Attic/loader.h, src/Attic/old_lexer.c, src/Attic/parser.y, src/Attic/util.h:
+       o Brought in new flex/bison parser and got it to build.
+
+       * src/Attic/lexer.h:
+       Adding back in the old lexer.h (for now)
+
+       * src/Attic/lexer.l:
+       file lexer.l was initially added on branch gmcnutt_loader.
+
+       * src/Attic/loader.c:
+       file loader.c was initially added on branch gmcnutt_loader.
+
+       * src/Attic/loader.h:
+       file loader.h was initially added on branch gmcnutt_loader.
+
+       * src/Attic/old_lexer.c:
+       file old_lexer.c was initially added on branch gmcnutt_loader.
+
+       * src/Attic/parser.y:
+       file parser.y was initially added on branch gmcnutt_loader.
+
+2003-11-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/player.cpp, src/player.h:
+       Factored out the private try_to_enter_portal method in the player class
+
+2003-11-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/foogod.c, src/player.cpp, src/player.h:
+       Removed the turn counter.
+
+2003-11-07  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/common.h, src/console.c, src/foogod.c, src/screen.c, src/status.c:
+       new feature: resizing status window -- DANGER: known to be broken right now.
+
+       * src/object.c:
+       Fixed a crash bug upon entering a place with at least one object stack
+       created via the multiple-objects construct, such as:
+           t_arrow  2 27 50;
+       
+       Apparently, the place field was not being initialized, and when
+       the game loop checked for effects (such as fire) on the (place,x,y)
+       of these objects, a SIGSEGV was thrown.
+
+2003-11-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/types/vehicles.ghul, examples/data/world/places/P_wilderness.ghul, src/Arms.cpp, src/Party.cpp, src/Party.h, src/player.cpp, src/player.h, src/vehicle.cpp, src/vehicle.h:
+       Bugfix: sinking a horse killed the party
+
+       * src/console.c, src/console.h, src/foogod.c, src/foogod.h, src/status.c:
+       Bugfix: console/foogod clobbering each other
+
+2003-11-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/combat.c, src/ctrl.c, src/ctrl.h, src/player.cpp, src/player.h:
+       Moved most remaining fields exclusive to player over to Party; noticed that S)witch command causes a hang
+
+       * src/Party.cpp, src/common.h, src/list.h, src/player.cpp, src/player.h:
+       Removed duplicate applyExistingEffects code between player and Party classes
+
+2003-11-04  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/world/characters/party_members.ghul:
+       Added new party members, the better to examine UI issues with party sizes greater than 3.
+
+2003-11-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Party.h, src/cmd.c, src/combat.c, src/ctrl.c, src/Attic/game.c, src/player.cpp, src/player.h, src/status.c:
+       Moved more fields from player to Party, removed more duplicates
+
+       * src/Party.h, src/player.h:
+       Removed redundant 'vehicle' field in player class
+
+       * src/Party.h, src/player.h, src/screen.c:
+       Moved 'gold' from player to Party class
+
+       * src/player.cpp, src/player.h:
+       Removed obsolete 'turns' field from player class
+
+       * src/screen.c:
+       Bugfix: highlighting box rendered improperly in zoom mode
+
+2003-11-03  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/world/mechanisms/all_mechanisms.ghul, src/Attic/Mech.cpp, src/Attic/Mech.h:
+       Added support for any_event_among keyword in transitions {} block for MECH_TYPE.
+
+       * src/Attic/Mech.cpp, src/Attic/Mech.h, src/conv.c, src/conv.h:
+       Added functions/methods to dump state for Mech objects and structs, and for struct response.
+
+2003-11-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/Attic/formation.ghul, examples/data/types/npc_party_defs.ghul, examples/data/world/places/P_wilderness.ghul, src/Party.cpp, src/Party.h, src/combat.c, src/Attic/game.c, src/player.cpp, src/player.h:
+       More work towards integrating the player and Party class.
+       o Moved some fields from the player class to the PartyType class.
+       o Moved some fields from the player ghulscript construct to be optional fields
+         in the PARTY construct.
+
+       * examples/data/types/Attic/formation.ghul:
+       file formation.ghul was initially added on branch gmcnutt_party2_br.
+
+2003-11-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world/places/Glasdrin.ghul, examples/data/world/places/GoblinCaves.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_rom_camp.ghul, examples/data/world/places/P_wilderness.ghul, src/Party.cpp, src/Attic/game.c:
+       Eliminated the 'home' field in the ghulscript npc constructor
+
+       * src/Party.cpp, src/Party.h, src/character.cpp, src/character.h, src/cmd.c, src/conv.c, src/Attic/game.c, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       Moved the inventory from the player_party class to its parent Party class
+
+2003-11-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Missile.cpp, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Party.cpp, src/Party.h, src/Attic/Spell.cpp, src/astar.c, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/combat.h, src/common.h, src/conv.c, src/ctrl.c, src/ctrl.h, src/cursor.cpp, src/cursor.h, src/Attic/game.c, src/list.h, src/object.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h, src/status.c:
+       Cleaned up Party.h
+
+       * src/Party.cpp, src/Party.h, src/place.c, src/player.h:
+       Got rid of two obsolete methods in Party.h
+
+       * src/Party.cpp, src/Party.h, src/combat.c:
+       Made all Party.h members protected
+
+2003-10-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Party.cpp, src/Attic/Spell.cpp, src/astar.c, src/character.cpp, src/cmd.c, src/ctrl.c, src/place.c, src/player.cpp, src/player.h:
+       Bugfix: corner-case hang in pathfinding code
+
+2003-10-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Missile.cpp, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Party.cpp, src/Party.h, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/combat.h, src/common.h, src/conv.c, src/ctrl.c, src/ctrl.h, src/Attic/game.c, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h:
+       Renamed NpcParty as Party to prepare for merging player party code with npc party code
+
+       * src/Party.cpp:
+       file Party.cpp was initially added on branch gmcnutt_ctrl_br.
+
+       * src/Party.cpp, src/Party.h, src/Attic/Spell.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/conv.c, src/ctrl.c, src/list.h, src/player.cpp, src/player.h, src/status.c:
+       Made player party a subclass of Party, got rid of fixed-size pc array
+
+       * src/Party.h:
+       file Party.h was initially added on branch gmcnutt_ctrl_br.
+
+2003-10-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/ctrl.c, src/cursor.cpp, src/cursor.h, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       Hooked up all the controllers
+
+       * src/character.cpp, src/ctrl.c:
+       Partly hooked up character ai contrroller
+
+2003-10-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/NpcParty.h, src/character.h, src/ctrl.c, src/ctrl.h, src/player.cpp, src/player.h:
+       Hooked up player party ui controller
+
+       * src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/cmd.c, src/ctrl.c, src/object.c, src/object.h, src/player.h:
+       Hooked up ai party controller
+
+       * src/character.cpp, src/ctrl.c:
+       Hooked up character ui controller
+
+       * src/ctrl.c:
+       file ctrl.c was initially added on branch gmcnutt_ctrl_br.
+
+       * src/ctrl.h:
+       file ctrl.h was initially added on branch gmcnutt_ctrl_br.
+
+2003-10-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/AiPartyController.cpp:
+       file AiPartyController.cpp was initially added on branch gmcnutt_controller_br.
+
+       * src/Attic/AiPartyController.cpp, src/Attic/AiPartyController.h, src/Makefile.am, src/Attic/Makefile.in, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/cmd.c, src/object.c, src/object.h, src/player.h:
+       Added the AiPartyController
+
+       * src/Attic/AiPartyController.h:
+       file AiPartyController.h was initially added on branch gmcnutt_controller_br.
+
+       * src/Attic/Controller.h:
+       file Controller.h was initially added on branch gmcnutt_controller_br.
+
+       * src/Attic/Controller.h, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/Attic/UiPartyController.cpp, src/Attic/UiPartyController.h, src/character.cpp, src/character.h, src/cmd.c, src/cursor.cpp, src/cursor.h, src/object.c, src/object.h, src/place.c, src/player.cpp, src/player.h:
+       Added the UiPartyController
+
+       * src/Attic/UiPartyController.cpp:
+       file UiPartyController.cpp was initially added on branch gmcnutt_controller_br.
+
+       * src/Attic/UiPartyController.h:
+       file UiPartyController.h was initially added on branch gmcnutt_controller_br.
+
+2003-10-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, Attic/aclocal.m4, Attic/config.guess, Attic/config.sub, Attic/configure, Attic/install-sh, Attic/ltmain.sh, Attic/missing, Attic/mkinstalldirs, examples/Makefile.in, src/Attic/Makefile.in, src/los.c:
+       Build changes for RedHat
+
+       * Attic/Makefile.in, Attic/acinclude.m4, Attic/aclocal.m4, Attic/config.guess, Attic/config.sub, Attic/configure, Attic/install-sh, Attic/ltmain.sh, Attic/missing, Attic/mkinstalldirs, examples/Makefile.in, src/Attic/Makefile.in, src/los.c:
+       Knoppix build changes
+
+       * Attic/Makefile.in, Attic/PRESS_RELEASE, Attic/RELEASE_NOTES, Attic/acinclude.m4, Attic/aclocal.m4, Attic/config.guess, Attic/config.sub, Attic/configure, Attic/configure.in, Attic/ltconfig, Attic/missing, Attic/mkinstalldirs, examples/Makefile.in, scripts/ghul-test-install, src/Attic/Makefile.in:
+       More build config changes
+
+       * Attic/configure.in:
+       Changed required SDL version from 1.2.4 back to 1.2.3.
+
+2003-10-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/play.c, src/player.cpp:
+       o Bugfix: with animation off, npc's sometimes appeared to "jump" a
+         space. Needed to add conditional repaints of the map before prompting the
+         user for input, this way the user is always looking at an up-to-date map when
+         they decide what to do next.
+
+       * src/combat.c:
+       o Bugfix: with animation off, after fleeing from wilderness combat the screen
+         remained blank until the user pressed a key to cause a map repaint. (Thanks
+         to Sam for finding this).
+
+       * src/combat.c:
+       o Bugfix: with animation off, on entry to wilderness combat the map was not
+         being updated properly.
+
+       * src/place.c:
+       o Bugfix: with animation off, in Character Mode, if the current character quits
+         the game then in some cases the game will not quit, and will prompt the
+         player to move the next character, until the turn is over.
+
+2003-10-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, INSTALL, README, doc/USERS_GUIDE, src/nazghul.c:
+       o Updated some of the docs
+
+       * Attic/Makefile.in, Attic/configure, Attic/configure.in, Attic/ltconfig, examples/Makefile.in, src/Attic/Makefile.in:
+       Fixed the LIBTOOL problem
+
+       * Attic/PRESS_RELEASE, Attic/RELEASE_NOTES, scripts/ghul-test-install:
+       Added a PRESS_RELEASE file
+
+       * Attic/configure, Attic/configure.in, examples/data/world/places/Glasdrin.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/NpcParty.cpp, src/character.cpp, src/nazghul.c, src/place.c:
+       o Bugfix: stepping on a tile that contained an inactive moongate would invoke
+         the moongate in town.
+       o Tweeks to the sample world
+
+       * Attic/ltmain.sh:
+       Added ltmain.sh
+
+       * examples/data/player/party.ghul, examples/data/world/astronomy.ghul, examples/data/world/places/P_wilderness.ghul, src/player.cpp:
+       Removed some printf dbg
+
+       * examples/data/player/party.ghul, src/character.cpp, src/cmd.c, src/place.c, src/play.c:
+       Party can enter moongates in town (or dungeons) now
+
+       * examples/data/world/characters/Doris.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/conversations/conversations.ghul:
+       Added some dialog
+
+       * examples/data/world/characters/Doris.ghul, examples/data/world/characters/Attic/char_doris.ghul, examples/data/world/places/GreenTower.ghul:
+       Changed char_doris.ghul to Doris.ghul
+
+2003-10-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/astar.c:
+       Pathfinding now aborts immediately if the target destination is invalid. This helps when you're in a ship in a wilderness with hostile npc's and your machine is slow.
+
+       * src/cmd.c, src/vmask.c:
+       Bugfix: vmask_invalidate was calculating the wrong region on wrapping maps
+
+2003-10-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/event.c, src/map.c, src/play.c:
+       More profiling
+
+2003-09-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/event.c, src/map.c, src/play.c, src/player.cpp:
+       Replaced the pseudo-fps counter with a latency and turnaround indicator. They're still a little quirky for the first turn or two but after that they seem ok (I haven't tested them a whole lot, though)
+
+       * src/event.c, src/map.c:
+       Mouse events can no longer cause a repaint.
+
+2003-09-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, Attic/aclocal.m4, Attic/configure, examples/Makefile.in, examples/data/player/party.ghul, examples/data/world/astronomy.ghul, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/astar.c, src/character.cpp, src/character.h, src/cmd.c, src/conv.c, src/map.c, src/map.h, src/nazghul.c, src/object.c, src/terrain_map.c, src/tree.c, src/tree.h, src/vmask.c, src/vmask.h:
+       Merged over vmask changes
+
+       * src/character.cpp, src/character.h, src/map.c, src/object.c, src/vmask.c:
+       o Bugfix: selecteed character was sometimes blacked out near map edges
+       o Bugfix: town npc's were not properly going to sleep when they were scheduled
+         to.
+       o Bugfix: igniting a torch did not always take immediate affect in combat
+       o Bugfix: when a character exited combat it's sprite did not immediately
+         disappear
+
+       * src/cmd.c, src/map.c, src/map.h, src/object.c:
+       Added mapUpdateTile to repaint a single tile. Used in Object::select()
+
+       * src/map.c, src/vmask.c:
+       Bugfix: scrolling the camera was showing places that should have been masked out by the vmask.
+
+       * src/vmask.c:
+       Bugfix: opening/closing doors now affects line-of-sight like it should again
+
+2003-09-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/object.c:
+       Changed the forced update in Object::select() to a mapSetDirty
+
+2003-09-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/astar.c, src/character.cpp, src/conv.c, src/map.c, src/nazghul.c, src/object.c, src/terrain_map.c, src/tree.c, src/tree.h, src/vmask.c, src/vmask.h:
+       Added vmask caching
+
+       * src/vmask.c:
+       file vmask.c was initially added on branch gmcnutt_vmask_br.
+
+       * src/vmask.h:
+       file vmask.h was initially added on branch gmcnutt_vmask_br.
+
+2003-09-21  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Attic/Makefile.in, src/Attic/Spell.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/map.c, src/nazghul.c, src/play.c, src/player.cpp:
+       Made some speedup modifications.
+       o In full sunlight we no longer need to build the lightmap, which otherwise
+         takes about 1/3 of the time spent rendering on my slow box.
+       o Replaced a lot of forced screen updates with a call to mark the screen as
+         dirty.
+       o If the user specifies --tick -1 then animation is disabled.
+       
+       With these changes, and by using the --bpp 8 option my slow box is playable in
+       the outdoors during the day... if there aren't too many npc's around. More
+       improvements to come.
+
+       * src/map.c:
+       Modified mapMergeLightSource to only check tiles that are within the radius of
+       the light source. Doesn't seem to make any difference on my fast box, but it
+       might help on the slow box.
+
+2003-09-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/map.c:
+       o Performance: missiles that are out of the player's LOS are no longer
+         painted. The game play pauses as each animation runs, and they run
+         much faster when they don't actually have to update the
+         display. Rendering them only when they are in the player's view speeds
+         things up in Glasdrin when things lots of skeletons and guards are
+         firing at each other.
+       
+       o Bugfix: yet another bug in the projectile animation. Firing arrows
+         at column zero of the display would make them fly in the opposite
+         direction.
+
+2003-09-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/Makefile.in, Attic/acinclude.m4, Attic/aclocal.m4, Attic/configure, examples/Makefile.in, src/Attic/Makefile.in, src/ascii.c, src/ascii.h, src/character.cpp, src/common.h, src/Attic/game.c, src/images.c, src/images.h, src/map.c, src/nazghul.c, src/place.h, src/screen.c, src/screen.h, src/sprite.h:
+       Some changes to make it compile on Knoppix
+
+       * examples/data/def_constants.ghul, examples/data/images/mine-32x32.png, examples/data/player/party.ghul, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/species.ghul, examples/data/types/spells.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/world/astronomy.ghul, examples/data/world/portals.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/characters/Gen.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/characters/Attic/char_doris.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/places/Glasdrin.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_rom_camp.ghul, examples/data/world/places/P_terrain_test.ghul, examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul, src/Arms.cpp, src/Arms.h, src/Field.cpp, src/Field.h, src/Attic/Item.cpp, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/astar.c, src/astar.h, src/character.cpp, src/character.h, src/clock.c, src/clock.h, src/cmd.c, src/cmd.h, src/combat.c, src/combat.h, src/common.c, src/common.h, src/console.c, src/console.h, src/conv.c, src/event.c, src/event.h, src/foogod.c, src/formation.c, src/formation.h, src/Attic/game.c, src/map.c, src/map.h, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/object.c, src/object.h, src/pinfo.h, src/place.c, src/place.h, src/play.c, src/play.h, src/player.cpp, src/player.h, src/sched.c, src/screen.c, src/screen.h, src/sky.c, src/sky.h, src/sprite.c, src/sprite.h, src/vehicle.cpp, src/vehicle.h, src/wind.c, src/wind.h, src/wq.c, src/wq.h:
+       Merged in changes from gmcnutt-newcombat-br
+
+2003-09-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/world/places/Glasdrin.ghul, src/character.cpp, src/map.c:
+       Added a monster generator and lots of guards in Glasdrin. I love trouble. Fixed a few bugs that were flushed out with this.
+
+       * examples/data/player/party.ghul, examples/data/world/astronomy.ghul, src/Attic/NpcParty.cpp, src/Attic/Spell.cpp, src/astar.c, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/Attic/game.c, src/map.c, src/map.h, src/Attic/moongate.c, src/nazghul.c, src/object.c, src/object.h, src/play.c, src/player.cpp, src/player.h, src/sky.c:
+       Widespread changes because I decided to consolidate all the view-handling code
+       to the routines which place and remove objects from the map. A lot of #if 0's
+       remain to be cleaned up, but things appear to be working pretty smoothly
+       now. All the u5 spells have been tested (and work) at least in town. Some still
+       need to be tested in the wilderness.
+       
+       Numerous changes have been made while testing and debugging. The ones I can
+       remember include:
+       
+       o The party formation is now used only in wilderness combat. On entrance to
+         towns they just kind of pour out from the entrance point. This should fix
+         those odd remaining cases where one party member could be put on the other
+         side of a wall via a long path from the party's main position.
+       
+       o Gate travel now works again and damn is it slick. I added a full complement
+         of gates so now you can always cast Vas Rel Por and go somewhere.
+       
+       o Charmed npc's in town will be automatically uncharmed when the player exits.
+
+       * src/character.cpp:
+       Npc's now avoid hazardous terrain while commuting and wandering.
+
+       * src/console.c, src/nazghul.c, src/screen.h:
+       Removed obsolete references to SDL_ttf
+
+2003-09-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/Spell.cpp:
+       Clone and Invisibility now update the map more snappily to show their effects. I tried to have clone put the clone under player control but this causes issues in town. Need to make clone nicer later when I redo spells and effects.
+
+       * src/Attic/Spell.cpp, src/object.c, src/play.c, src/play.h:
+       Fixed Rel Tym and An Tym
+
+       * src/character.cpp, src/object.c, src/object.h, src/place.c:
+       o Added a new placement algorithm for dropping characters on a map within a
+         specified area. So far I've only modified resurrection to use it. Later I'll
+         probably modify some of the other summoning spells (including clone) and
+         possibly general combat placement to use it.
+
+       * src/character.cpp, src/foogod.c, src/play.c:
+       Fixed In An and added indicatord to the foogod window for the Time Stop, Quickness and Negate Magic global effects
+
+2003-09-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Bugfix: npc's were not waking up when put to sleep with In Zu
+
+2003-09-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world/characters/inhabitants_of_britain.ghul:
+       Bugfix: Hawknoz schedule had an out-of-order entry
+
+       * src/cmd.c:
+       Bugfix: dead/sleeping members could cast spells in party mode
+
+       * src/event.c:
+       Bugfix: playback mode was not working
+
+2003-09-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/combat.c, src/object.c:
+       o Walking off the edge of a combat map no longer requires the party to be in
+         Follow Mode. This will allow the one character to escape without the
+         others. Exiting towns still requires follow mode.
+
+       * src/character.cpp, src/character.h:
+       o Join: have Olin join, have him exits a town/dungeon through a wall, leaving
+         the other party members stranded.
+
+2003-09-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/spells.ghul, examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul, src/Attic/Spell.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/combat.h, src/conv.c, src/Attic/game.c, src/map.c, src/object.c, src/place.c, src/player.cpp, src/player.h:
+       o Bugfixes: Misc stuff related to spellcasting. First three levels now tested
+         and working in town/dungeon.
+
+       * src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/character.cpp, src/character.h, src/Attic/game.c, src/player.cpp, src/player.h:
+       o Bugfix: "Join" now works again.
+
+       * src/place.c, src/screen.c, src/screen.h:
+       Made the highlighting rectangle a rectangle (it was an upside-down L)
+
+2003-09-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/spells.ghul, examples/data/world/places/P_empire_city.ghul, src/cmd.c, src/common.h:
+       o Bugfix: Cast In Mani Corp (resurrect) in combat - you get a crosshair to
+         select the target. But, uh, the target is dead, so it's not on the map...
+         I fixed this by adding a new spell target type: SPELL_TARGET_PARTY_MEMBER.
+
+       * src/Attic/Spell.cpp, src/character.cpp:
+       o Bugfix: Cast Uus Por in Green Tower Lower - looks like we hang.
+
+       * src/character.cpp, src/Attic/game.c, src/play.c:
+       --Fixed a crash that occurred on startup if the --sound 0 option was
+         specified.
+
+       * src/combat.c:
+       o Bugfix: attack a ship to the east - gangplanks don't meet the shore.
+
+       * src/Attic/game.c:
+       o Bugfix: cannot board a ship in town. This is not a bugfix, but rather a
+         temporary workaround: I (mostly) disallow vehicles in town. See the
+         development log for my reasoning.
+
+2003-09-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/cmd.c, src/cmd.h, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       o Bugfix: Cannot rest in town (no (k)amp command in character mode).
+
+       * src/character.cpp, src/cmd.c, src/combat.c, src/player.cpp:
+       o Bugfix: Camping in the wilderness is fixed again.
+       
+       o Bugfix: attacking in the wilderness was leaving the player party on the
+         enemy's tile after combat.
+
+       * src/cmd.c:
+       o Pending a better policy on the issue of containers, I made all containers
+         delete themselves on open.
+       
+       o Fixed a bug in casting "An Sanct" in which the cursor did not appear. Tweaked
+         a few of the other spell-targeting routines to reflect changes made on the
+         branch.
+
+2003-09-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/Spell.cpp, src/character.cpp, src/place.c:
+       Fixed two bugs relating to castin In Por (blink) which were reported by Sam.
+       
+       o The Spell::teleport_horizontally() code was using some old idioms, include
+         the global Place. I replaced this with a simple call to caster->move(), which
+         handles the details of deciding to move a single member or the entire party,
+         depending on what mode we're in. This also required adding some view/los
+         updating code to character::relocate(), which probably needed to be there
+         anyway. This fixed the In Por in the Slime Cave.
+       
+       o For the In Por bug on the map edge, what was happening is that the caster
+         ended up teleporting to his current square. Fine, the character::move() code
+         discovers that someone from the caster's party is already there (the caster)
+         and tried to "bump" them. But the real bug is in place_move_object(), which
+         would crash anytime you tried to move an object to it's current
+         location. That's because it looked up both source and destination tiles, then
+         removed the object from the source tile. If this was the only object on the
+         tile then it destroys the source tile. But that means we just destroyed the
+         destination tile, and we'are about to put something on it... easy fix once
+         found.
+
+       * src/character.cpp:
+       o When synchronizing character schedules upon entry to a small-scale place, the
+         code now drops the character in the upper left corner of the roaming region
+         specified in the scheduled appointment. Before it would drop them in the
+         center. I decided that the corner was better because the engine makes no test
+         for passability, so it's up to the schedule designer, and since they have to
+         specify the ULC in the schedule it should make it more obvious when they are
+         specifying an impassable "drop point". Perhaps in the future I'll have the
+         engine do something smarter to avoid these kind of mistakes.
+
+2003-09-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/world/portals.ghul, src/character.cpp, src/player.cpp:
+       o Consolidated some code in the player_party class when I noticed that
+         relocate() seemed to deal with place-to-place movement correctly.
+       
+       o Fixed a bug where changing places in the middle of a place_exec() loop caused
+         a crash for commuting NPC's.
+       
+       o Fixed a bug in un-charming a fellow party member with the charm spell. The
+         target was uncharmed but remained in auto mode. Kind of cool but not exactly
+         what the user would expect.
+       
+       o Reconnected the portals between Empire City, the dungeon and the dark
+         passage.
+
+       * src/character.cpp:
+       Fixed a bug where town npc's would just wander off the edge of the map. Can't have that :-)
+
+       * src/object.c:
+       Fixed a bug that cause the coordinate display to vanish after walking around a bit in Empire City
+
+2003-09-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world/places/GoblinCaves.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_rom_camp.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/NpcParty.cpp, src/character.cpp, src/character.h, src/cmd.c, src/conv.c, src/Attic/game.c, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       Guards can now speak again, and you can provoke them to a fight.
+
+       * examples/data/world/places/P_empire_city.ghul:
+       Made the nixie and water elemental in Empire City both be aligned to the town. Otherwise they either attack each other or the townspeople, and they usually lose :-).
+
+       * src/Attic/NpcParty.cpp, src/astar.h, src/character.cpp, src/character.h, src/combat.c, src/object.c, src/object.h, src/place.c, src/place.h:
+       Party members now pathfind through other members in follow mode.
+
+       * src/console.c, src/console.h, src/nazghul.c, src/object.c, src/object.h, src/play.c:
+       Bugfix: destroying npc parties with ship cannons no longer makes them frop corpse loot.
+
+2003-09-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/terrains.ghul:
+       Changed all fast terrain to be medium.
+
+       * src/character.cpp, src/character.h, src/combat.c, src/combat.h, src/map.c, src/map.h, src/object.c, src/object.h, src/player.cpp, src/player.h:
+       More changes to support the unified game loop.
+       
+       o The player party can now exit from a town again.
+
+       * src/formation.c:
+       file formation.c was initially added on branch gmcnutt-newcombat-br.
+
+       * src/formation.c:
+       Adding formation.c
+
+2003-08-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/world/places/GoblinCaves.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_rom_camp.ghul, examples/data/world/places/P_wilderness.ghul, src/Makefile.am, src/Attic/Makefile.in, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/character.cpp, src/character.h, src/combat.c, src/combat.h, src/common.c, src/common.h, src/conv.c, src/formation.h, src/Attic/game.c, src/map.c, src/nazghul.c, src/object.c, src/pinfo.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/screen.c, src/screen.h, src/sprite.c, src/sprite.h, src/wind.c, src/wind.h, src/wq.c, src/wq.h:
+       More changes to support the unified game loop.
+       
+       o Moved conversations and schedules from the NpcParty class to the Character
+         class. Added an activity member and an appt member to the Character class to
+         support schedules.
+       
+       o When the loader puts a party in a non-wilderness place it automatically
+         distributes the party members.
+       
+       o Fixed a handful of minor bugs related to the above changes, as well as some
+         related to earlier changes in the way the party leader is managed.
+
+       * src/Attic/NpcParty.cpp, src/player.cpp, src/player.h:
+       More changes to support the unified game loop.
+       
+       o The player party now breaks out into party mode on entrance to a town.
+       
+       o Bugfix: entering a ladder from a town or dungeon was throwing us back into
+         party mode.
+
+2003-08-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/player.cpp:
+       Ok, now you can exit dungeons. But still no fighting\!
+
+       * src/combat.c, src/combat.h, src/player.cpp, src/player.h:
+       Player can now enter a dungeon again. Combat is broken there, and so is exiting, but there you go.
+
+2003-08-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/NpcParty.cpp, src/Attic/Spell.cpp, src/character.cpp, src/cmd.c, src/combat.c, src/combat.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h:
+       Combat loop eliminated, looks like most entry/exit situations functional. Dungeons are, no doubt, seriously broken right now, though.
+
+2003-08-21  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/common.h, src/nazghul.c, src/play.c:
+       Change nazghul version number printing.
+
+2003-08-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/foogod.c, src/object.c, src/object.h, src/vehicle.cpp, src/vehicle.h:
+       Fixed vehicle repair during camping
+
+2003-08-16  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/NpcParty.cpp, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/player.cpp, src/player.h:
+       Most camping problems now fixed
+
+       * src/combat.c:
+       Cleaned up some unused things in combat.c
+
+2003-08-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/cmd.c, src/cmd.h, src/combat.c, src/combat.h, src/common.h, src/foogod.c, src/nazghul.c, src/object.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h:
+       Bugfixes
+
+       * src/character.cpp, src/play.c, src/player.cpp:
+       Fixed death, added sleep to charm recovery
+
+2003-08-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES:
+       Updated
+
+       * Attic/configure, Attic/configure.in, scripts/RELEASE_CHECKOFF, scripts/ghul-test-install, src/nazghul.c:
+       Notes & such made while creating the 0.1.3 release
+
+       * examples/data/world/places/all_places.ghul:
+       Re-inserted the "Terrain Test" map to aid novice map hackers
+       for a SourceForge file release.
+
+2003-08-13  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * INSTALL:
+       Added some notes to INSTALL about PATH settings needed.
+
+2003-08-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Arms.cpp, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/object.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp:
+       Combat now lets place_exec run the npc character AI's
+
+2003-08-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world/astronomy.ghul, examples/data/world/characters/Attic/char_doris.ghul:
+       Script changes mandated by engine changes
+
+       * src/clock.c, src/clock.h, src/combat.c, src/foogod.c, src/play.c, src/player.cpp, src/player.h:
+       Time moves at wilderness scale in the wilderness once more
+
+       * src/place.c, src/place.h:
+       Bufgix: program hanging in place_exec due to removing objects
+
+2003-08-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Makefile.am, src/Attic/Makefile.in, src/clock.c, src/clock.h, src/player.h, src/sky.c, src/sky.h:
+       Moved clock routines from sky.[ch] to clock.[ch]
+
+       * src/clock.c:
+       file clock.c was initially added on branch gmcnutt-newcombat-br.
+
+       * src/clock.c, src/clock.h, src/Attic/game.c, src/sky.c:
+       Added TIME to ghulscript, removed arc from same, sun initial position now derived from time
+
+       * src/clock.c, src/clock.h, src/combat.c, src/common.h, src/event.c, src/event.h, src/Attic/moongate.c, src/Attic/moongate.h, src/play.c, src/sched.c, src/sky.c, src/sky.h:
+       Fixed the hang while repeatedly sleeping in the inn
+
+       * src/clock.c, src/clock.h, src/combat.c, src/play.c:
+       Changed the way time keeps track of the clock
+
+       * src/clock.c, src/clock.h, src/player.cpp, src/player.h:
+       Changed the way clock alarms work
+
+       * src/clock.h:
+       file clock.h was initially added on branch gmcnutt-newcombat-br.
+
+       * src/common.h, src/place.c, src/place.h, src/play.c:
+       Time goes by faster in the wilderness now
+
+2003-08-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/def_constants.ghul, examples/data/types/species.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/world/places/P_wilderness.ghul, src/Arms.cpp, src/Arms.h, src/Attic/NpcParty.cpp, src/cmd.c, src/common.h, src/Attic/game.c, src/object.c, src/object.h, src/vehicle.cpp, src/vehicle.h:
+       Moved some action point values which were hard-coded in the game to the load file
+
+       * src/cmd.c:
+       Bugfix: opening a closed door was printing 'Open an open door' as a console message
+
+2003-08-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/def_constants.ghul, examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/terrains.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/NpcParty.cpp, src/astar.c:
+       Added trails to Green Tower and the wilderness
+
+       * src/Attic/NpcParty.cpp, src/common.h, src/player.cpp, src/player.h:
+       Bugfix: members were getting an hour of rest every turn while sleeping
+
+2003-08-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/def_constants.ghul, examples/data/player/party.ghul, examples/data/types/species.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/characters/Gen.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/common.h, src/foogod.c, src/Attic/game.c, src/object.c, src/object.h, src/player.cpp, src/player.h, src/vehicle.cpp, src/vehicle.h:
+       Action points now distributed based on speed; updated all the speeds and passability costs in the example game
+
+       * src/Attic/NpcParty.cpp, src/astar.c, src/astar.h, src/place.c:
+       Bugfix: characters don't seem to be taking optimal path through/around forest
+
+       * src/combat.c:
+       Bugfix: party was placed off-center on the camping map
+
+2003-08-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/Attic/NpcParty.cpp, src/combat.c, src/object.c, src/place.c, src/place.h, src/play.c, src/vehicle.cpp:
+       o Bugfix: characters seemed to be getting more than one turn. Problem was the
+         turn_list order depended on object locations. Moving an object could change
+         its turn list order.
+       
+         The turn list is now no longer built during every place_exec(). Instead it is
+         maintained by place_add_object() and place_remove_object(). I also added a
+         new place_move_object() which moves an object without removing it and
+         replacing it in the turn list, so objects which move keep the same turn list
+         order.
+
+2003-08-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world/astronomy.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/characters/Gen.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/astar.c, src/cmd.c, src/common.h, src/object.c, src/object.h, src/place.c, src/player.cpp, src/player.h, src/sky.c, src/sky.h:
+       o Bugfix: in pathfinding, the heuristic was not assigning enough of a handicap
+         to tiles with hazards on them, and the npc party refused to move on a tile
+         with  hazard. This resulted in npc party's failing to commute. One fix was to
+         assign enough of a handicap so that the path would prefer to route around the
+         hazard. Another fix was to only avoid hazards when wandering. When
+         pathfinding it is sometimes necessary to cross hazardous terrain.
+       
+       o Bugfix: furthermore, the pathfinding alg had a bug in it where a shorter but
+         inferior path could be chosen over a longer but superior path.
+
+       * src/Arms.cpp, src/Field.cpp, src/Field.h, src/Attic/Item.cpp, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/astar.c, src/character.cpp, src/character.h, src/cmd.c, src/combat.c, src/common.h, src/conv.c, src/object.c, src/object.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h:
+       Changed top-level loop. Party-mode keyhandler now runs when it's the player party's turn in the place_exec() loop for the current place.
+
+       * src/Field.cpp:
+       file Field.cpp was initially added on branch gmcnutt-newcombat-br.
+
+       * src/Attic/NpcParty.cpp, src/astar.c, src/character.cpp, src/common.h, src/map.c, src/object.c, src/object.h, src/place.c, src/place.h, src/player.cpp:
+       --Fixed a crash that occurred on startup if the --sound 0 option was
+         specified.
+
+2003-08-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/map.c:
+       Bugfix: when zoomed out x)amine was reporting everything out-of-los.
+
+2003-07-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/terrains.ghul, examples/data/world/places/GreenTower.ghul:
+       Added a window terrain
+
+       * examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/terrains.ghul, examples/data/world/astronomy.ghul, examples/data/world/places/GreenTower.ghul:
+       Added arrow slits
+
+       * examples/data/world/astronomy.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/NpcParty.cpp, src/astar.c, src/combat.c, src/map.c, src/place.c, src/player.cpp, src/terrain_map.c:
+       o Bugfix: random crash due to overwriting an array during map
+         blitting. Probably introduced when we reduced the combat map size to 19x19.
+       
+       o Bugfix: crash when sinking an npc ship. The tile was being freed twice: once
+         for the ship and once for the npc party.
+       
+       o Bugfix: cannons sometimes not animated. Another map-wrapping problem.
+       
+       o Bugfix: cannons sometimes hitting the ship that fired them. Yet another
+         map-wrapping problem.
+
+2003-07-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/def_constants.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/characters/Attic/char_doris.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/character.cpp, src/character.h, src/cmd.c, src/cmd.h, src/combat.c, src/common.h, src/conv.c, src/conv.h, src/object.c, src/object.h, src/play.c:
+       Added T)alk command to combat
+
+       * examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/world/places/P_wilderness.ghul, src/Arms.cpp, src/Arms.h, src/Missile.cpp, src/Missile.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/combat.c, src/common.h, src/Attic/game.c, src/map.c, src/map.h, src/object.c, src/object.h, src/player.cpp, src/player.h, src/vehicle.cpp, src/vehicle.h:
+       Removed the OrdnanceType class, rewriting most of the cannon-firing code in the process
+
+       * examples/data/world/places/all_places.ghul:
+       Put back some of the old test places
+
+2003-07-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/GoblinCaves.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul:
+       Upgraded the door sprites.
+
+       * src/Attic/Item.cpp, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Spell.cpp, src/cmd.c, src/cmd.h, src/combat.c, src/console.c, src/conv.c, src/map.c, src/play.c, src/play.h, src/player.cpp:
+       Moved all the common command-handling code from play.c to the new cmd.c
+
+2003-07-27  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/species.ghul, examples/data/types/weapons.ghul, examples/data/world/places/P_wilderness.ghul:
+       Rebalanced vision radii a bit
+
+       * examples/data/world/astronomy.ghul, src/map.c, src/place.c:
+       Changed lighting to use raycasting.
+
+       * src/Arms.cpp, src/character.cpp, src/character.h, src/combat.c, src/common.c, src/common.h:
+       Extended max vision radius to 19; you need a character in your party who can see that far in order to take advantage of it
+
+       * src/Missile.cpp:
+       Bugfix: missiles were not doing damage due to recent changes
+
+       * src/combat.c:
+       Bugfix: if a charmed party members was the only one left in combat then combat would never exit.
+
+       * src/map.c:
+       Bugfix: --ShowAllTerrain was not painting objects
+
+2003-07-26  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp:
+       Bugfix: resting was resurrecting dead party members
+
+       * src/combat.c, src/play.c:
+       More console msg cleanup
+
+       * src/combat.c:
+       Bugfix: combat place needed to inherit 'underground' from town or wilderness place
+
+       * src/player.cpp:
+       Bugfix: npc parties might visibly 'warp' on entrance to a town because I was painting the scene before synchronizing their schedules
+
+2003-07-25  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world.ghul, examples/data/world/maps/terrain_combat_maps.ghul:
+       Added a combat map for hilly terrain
+
+       * examples/data/player/party.ghul, examples/data/world/characters/party_members.ghul, src/Missile.cpp, src/Missile.h, src/map.c, src/map.h, src/screen.c:
+       Bugfix: missiles were not animated right when zoomed out
+
+       * examples/data/types/terrains.ghul, src/combat.c, src/map.c, src/place.c, src/place.h:
+       Light sources are now raytraced. Solves the light-shining-through-wall problem.
+
+2003-07-24  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * src/character.cpp, src/character.h, src/combat.c, src/place.h:
+       If a place has no parent, characters cannot exit off map edges. Solves the problem where Olin exits in a direction the other characters cannot follow due to passability.
+
+       * src/combat.h, src/map.c:
+       Fixed map 'peer' mode to recenter correctly in combat/dungeons
+
+       * src/map.c, src/place.c, src/place.h:
+       Extended line-of-sight to radius 19.
+
+2003-07-23  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/weapons.ghul, src/character.cpp, src/character.h, src/combat.c, src/common.h:
+       o Bugfix: premature victory in combat in slime cave. Npc's were not being added
+         properly to the combat npc array when they were introduced after start of
+         combat. The array elements were getting overwritten and the max used index
+         was not updated right. Fixed additions and got rid of the max-used index.
+       
+       o Bugfix: hitting the '<' key in dungeons caused a crash. Disabled this command
+         in dungeons.
+
+       * src/combat.c:
+       Combat re-enters the FIGHTING state if hostile npc's added in a non-FIGHTING state
+
+2003-07-22  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/types/npc_party_defs.ghul, examples/data/types/readable_items.ghul, src/Attic/Spell.cpp, src/combat.c, src/console.c, src/play.c, src/play.h:
+       Misc small changes; console msg cleanup/polishing
+
+2003-07-20  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/def_macros.ghul, examples/data/types/occupations.ghul, examples/data/world/characters/BlackBart_the_Shipwright.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/characters/Gen.ghul, examples/data/world/characters/Olin_the_Ghast.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/characters/Attic/char_doris.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/characters/party_members.ghul, src/Arms.cpp, src/character.cpp, src/character.h, src/combat.c, src/play.c:
+       Some of the new balancing changes are in place now
+
+2003-07-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/types/species.ghul, src/species.c, src/species.h:
+       Eliminated the unused 'occs' fields from species
+
+       * examples/data/world.ghul, examples/data/types/species.ghul, src/species.c, src/species.h:
+       Added some (yet unused) fields to species
+
+       * examples/data/types/occupations.ghul, examples/data/types/species.ghul, src/occ.c, src/occ.h:
+       Added combat modifier fields to occ's
+
+       * examples/data/types/species.ghul:
+       Adjusted some species attributes
+
+       * src/Arms.cpp, src/Arms.h:
+       Added methods to access the hit, defend and damage and armor ranges
+
+       * src/status.c:
+       For arms, print weight on same line as name
+
+2003-07-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/configure, src/Arms.cpp, src/Arms.h, src/Makefile.am, src/Attic/Makefile.in, src/Missile.cpp, src/Missile.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/character.cpp, src/player.cpp:
+       Moved the Missile class out of the Arms files into Missile.h and Missile.cpp
+
+       * examples/data/types.ghul, examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/types/projectiles.ghul, examples/data/types/spells.ghul, examples/data/types/weapons.ghul, examples/data/types/worn_items.ghul, src/Arms.cpp, src/Arms.h, src/combat.c:
+       o Changed the damage and armor fields of ARMS to be a range of integers. This
+         simulates a single dice with a modifier. Currently only the max end of the
+         range is actually used by the engine.
+
+       * examples/data/types.ghul, src/Arms.cpp, src/Arms.h, src/Attic/game.c:
+       o Changed the way Ghulscript describes and the game parses armament
+         types. These now have their own keyword: 'ARMS', and are parsed similar to
+         they way Characters, NpcPartys and other types are parsed. They must no
+         longer be in the 'object_types' block.
+
+       * examples/data/types.ghul, examples/data/types/projectiles.ghul, examples/data/types/weapons.ghul, src/Arms.cpp, src/Arms.h, src/Attic/game.c:
+       o For arms, renamed 'attackValue' as 'damage' and 'defendValue' as 'armor'.
+       
+       o Cleaned up Arms.h/Arms.cpp a bit.
+
+       * src/Arms.cpp, src/Arms.h, src/character.cpp, src/common.h, src/Attic/game.c, src/player.cpp, src/status.c:
+       Got rid of the AmmoType class (looks like it isn't used anywher)
+
+2003-07-17  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/world.ghul, examples/data/world/maps/terrain_combat_maps.ghul:
+       Working on 19x19 combat maps.
+
+       * examples/data/world/maps/M_blank_19x19.ghul:
+       Added a new blank map template, sized for use in combat maps (19x19).
+
+2003-07-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/world.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/occupations.ghul, examples/data/types/readable_items.ghul, examples/data/types/species.ghul, examples/data/world/portals.ghul, examples/data/world/characters/Deric.ghul, examples/data/world/conversations/conversations.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/GoblinCaves.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/GreenTowerLower_Map.ghul, examples/data/world/places/MidWorld.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, examples/data/world/places/all_places.ghul, src/Attic/Mech.cpp, src/character.cpp, src/combat.c, src/combat.h, src/map.c, src/object.c, src/place.c, src/play.c:
+       New scripts; removed some engine debug and the aborted no-los-in-combat attempt
+
+       * src/play.c:
+       Added ability to (x)amine terrain visible via xray
+
+2003-07-16  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/images/mine-32x32.png:
+       Added a water elemental sprite, species, and npc party.
+       I also added one to Empire City.
+
+       * examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/species.ghul, examples/data/world/places/P_empire_city.ghul:
+       Added a water elemental sprite, species, and npc party.
+       Also added one to Empire City.
+
+       * examples/data/world/conversations/C_misc_npcs.ghul:
+       Added a new file for conversations with misc NPCs.
+
+       * examples/data/world/conversations/conversations.ghul:
+       Added a new file ./C_misc_npcs.ghul
+
+       * examples/data/world/places/P_empire_city.ghul:
+       Added a conversation to the water elemental.
+
+2003-07-15  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/images/mechanisms.png, examples/data/images/rune_font_32x32.png:
+       Fixed some errant pixels.
+
+2003-07-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/types.ghul, examples/data/types/furniture.ghul, examples/data/world/places/GreenTower.ghul, src/place.c, src/play.c:
+       Added a dresser container and a chair
+
+       * examples/data/images/lost_dragon.png, examples/data/sprite_sets/lost_dragon.ghul:
+       Added lost_dragon sprite set and images
+
+2003-07-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/data/images/mine-32x32.png, examples/data/sprite_sets/mechanism_sprites.ghul, examples/data/types/projectiles.ghul, src/Arms.cpp, src/Attic/Spell.cpp:
+       Prettied-up the portcullis sprite; fixed the assert if missiles have no sprite; fixed the return value for spells that only cast missiles from 'no effect' to 'success'
+
+       * examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/projectiles.ghul, examples/data/types/terrains.ghul, examples/data/world/places/Glasdrin.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/GreenTowerLower.ghul, examples/data/world/places/GreenTowerLower_Map.ghul:
+       Added wall torches, fixed some script bugs
+
+2003-07-13  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/projectiles.ghul, examples/data/types/spells.ghul:
+       Added a new light spell.
+
+       * examples/data/types/magical_fields.ghul:
+       Added a short-duration "magical illumination" field for a new minor light spell.
+
+       * examples/data/types/projectiles.ghul:
+       Added a new projectile for a new light spell.
+
+       * examples/data/types/spells.ghul:
+       Changed BET LOR to use EFFECT_NONE, as it should be.
+
+       * examples/data/types/spells.ghul:
+       Added comments to the BET LOR (minor light) spell.
+
+2003-07-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, examples/data/types.ghul, src/play.c:
+       o [engine] Fixed TARGET_SPELL_LOCATION for wilderness/town mode.
+
+       * Attic/RELEASE_NOTES, examples/dup_constants.h, examples/data/player/party.ghul, examples/data/types/occupations.ghul, examples/data/types/useable_items.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/characters/party_members.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_terrain_test.ghul, src/Attic/Item.cpp, src/Attic/Item.h, src/Attic/Spell.cpp, src/character.cpp, src/character.h, src/common.h, src/dup_constants.h, src/Attic/game.c:
+       o [engine] Added EFFECT_RESTORE to support mana restoration potions. Had to
+         sacrifice EFFECT_NATURAL because the effects bitmask is out of bits. Turns
+         out bit 31 does not work right because of an issue with atoi interpreting it
+         as an overflow. This will be addressed in the 0.3.x line with the new effects
+         system.
+
+       * examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/types/chest_traps.ghul, examples/data/types/weapons.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_terrain_test.ghul, src/Container.cpp, src/play.c:
+       Added a way to add traps to chests declared in places
+
+       * examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/types/containers.ghul, examples/data/types/occupations.ghul, examples/data/types/projectiles.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_terrain_test.ghul, examples/data/world/places/P_wilderness.ghul, src/place.c, src/place.h, src/play.c:
+       Opening chests now described contents again; modified describe to optionally describe the terrain
+
+       * examples/data/types/furniture.ghul:
+       Added furniture.ghul
+
+2003-07-12  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/types/readable_items.ghul:
+       Minor reformatting of a document.
+
+       * examples/data/types/weapons.ghul:
+       Minor reformatting.
+
+       * src/Attic/game.c:
+       Added minor comments.
+
+2003-07-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/world/places/P_terrain_test.ghul, src/Container.cpp, src/Container.h:
+       o [engine] When you declare a container on a map you now must provide a list of
+         contents. For example:
+       
+         t_chest 10 10 { }  // an empty chest
+         t_barrel 5 10 { t_sword 5 t_arrow 50 } // a barrel with a sword and arrows
+
+       * Attic/RELEASE_NOTES, examples/data/world.ghul, examples/data/world/characters/Gen.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/conversations/conversations.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_wilderness.ghul, src/character.cpp, src/common.h, src/conv.c:
+       o [daghul] Added an enhanced conversation tree for NPC character Gen and put
+         him in Green Tower. He can teach the player the rudiments of the goblin
+         language.
+
+       * examples/data/world.ghul, examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/types/useable_items.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/maps/M_slime_cave.ghul, examples/data/world/places/P_slime_cave.ghul:
+       o [daghul] Added the first real mini-quest.
+
+       * examples/data/world/characters/Gen.ghul:
+       Bugfix to Gen's conversation
+
+       * examples/data/world/characters/Gen.ghul, examples/data/world/places/GreenTower.ghul, src/console.c:
+       o [daghul] Gave Gen a schedule; modified the Green Tower map a bit.
+
+2003-07-11  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/Attic/Item.cpp:
+       Improved UI prompting for "read a document" mode.
+
+       * src/play.c:
+       Improved a failure message for teleport spells.
+
+2003-07-10  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/world/conversations/conversations.ghul, src/conv.c, src/conv.h:
+       o CHECK_ITEM takes a number and an operator. It compares the number of such
+         items in the player's inventory against the given value. Sliwan's
+         conversation updated to provide an example.
+
+       * Attic/RELEASE_NOTES, doc/USERS_GUIDE, examples/data/types/readable_items.ghul, src/play.c:
+       o Added a S)earch command which will reveal things on adjacent tiles that are
+         normally only visible with a Reveal spell
+       
+       o Reformatted the in-game users guide for better readability and use of screen
+         space
+
+       * Attic/RELEASE_NOTES, examples/data/world/places/P_terrain_test.ghul, src/Attic/game.c, src/object.c, src/object.h:
+       o Added a quantity field for placed items. The arrows, bolts and rocks in the
+         terrain test map provide a sample usage.
+
+       * examples/data/world/portals.ghul, examples/data/world/places/ForestCave.ghul, examples/data/world/places/P_slime_cave.ghul, examples/data/world/places/all_places.ghul:
+       Added a new dungeon map called Forest Cave
+
+       * examples/data/world/places/Glasdrin.ghul, examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul:
+       Added a new castle-town called Glasdrin
+
+2003-07-09  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/world.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/GreenTowerLower.ghul, src/Attic/Mech.cpp, src/conv.c, src/conv.h, src/Attic/game.c:
+       o The blit_map api call now works on places besides the one the mech is located
+         in. Previously it took a place parm but ignored it, defaulting to the current
+         place. Now it works as originally intended.
+       
+       o The CONNECT construct can now be used outside of the object {} block of a
+         PLACE definition, allowing mechs in different places to be more easily wired
+         together.
+       
+       o Mostly for demonstration purposes I added two levers in the middle of Green
+         Tower. One lever activates a portcullis in Green Tower Lower (the
+         underground, a different place) by means of the new global CONNECT
+         construct. The other lever activates a drawbridge in Green Tower Lower by
+         means of the newly corrected 'place' parm of blit map.
+
+2003-07-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/dup_constants.h, examples/data/world/astronomy.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_wilderness.ghul, src/dup_constants.h, src/Attic/game.c, src/Attic/game.h, src/sky.c:
+       o Added a mandrake patch to the wilderness. This required a fair amount of new,
+         special-case engine support, which annoys me: a MECH_FULL_MOON signal is
+         supported by the engine and delivered to every mech in the game whenever
+         either moon hits phase 0 (which the engine assumes to be full... see what I
+         mean? warty).
+
+       * Attic/RELEASE_NOTES, examples/dup_constants.h, examples/data/images/mine-32x32.png, examples/data/player/party.ghul, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/sprite_sets/ultima_IV_sprite_set.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/species.ghul, examples/data/types/spells.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_slime_cave.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/Spell.cpp, src/character.cpp, src/combat.c, src/common.h, src/conv.c, src/conv.h, src/dup_constants.h, src/play.c, src/play.h:
+       o Added the create_object api call for mech and conversations scriptlets. This
+         creates a simple object like an armament or item.
+       
+       o Added the create_npc_party api call for same. This creates npc parties and
+         adds them to the specified place (haven't tested created them in other
+         places, but the support is all there). Works in combat (dungeon rooms), too.
+       
+       o Added a new engine-supported mech signal: MECH_TURN, which is delivered every
+         turn to every mechanism within the player's current place.
+       
+       o Added some new mechanism macros in the examples to test the new
+         constructs. See the wilderness, the slime cave and Green Tower for example
+         usage.
+
+2003-07-03  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/play.c:
+       Increased cursor range for Xamine and Terraform to take advantage
+       of Zoom mode.
+
+2003-07-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, src/map.c, src/map.h, src/play.c:
+       --Added a ^z for map editing. This toggles map zooming.
+
+2003-07-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/def_constants.ghul, examples/data/images/mine-32x32.png, examples/data/player/party.ghul, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/world/astronomy.ghul, examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/characters/Attic/char_doris.ghul, examples/data/world/conversations/C_green_tower.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/GreenTower.ghul, src/conv.c, src/player.cpp:
+       --Created a simple inn where the player can check out a room to sleep
+         in. Haven't perfected the logic behind locking the player back out when he's
+         done, or kicking him out if he sleeps too long, etc. I wanted to this
+         completely with mechs, and I think it can be done (except for the kicking out
+         of bed part). Maybe Sam can figure out a nice way to do inns, it seems like
+         his kind of puzzle.
+
+       * Attic/RELEASE_NOTES, src/Attic/NpcParty.cpp, src/player.cpp, src/player.h:
+       --Npc parties now wake up the player if he is sleeping in their bed. They don't
+         throw him out like they do in u5, but they will keep waking the player up
+         until he moves and let's them get into bed.
+
+       * Attic/RELEASE_NOTES, examples/data/world/characters/Shroom_the_Hag.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/game.c:
+       --When npc parties are asleep they show a different sprite (if any species in
+         the party has a 'sleep_sprite' specified)
+
+2003-07-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/def_constants.ghul, examples/data/types.ghul, examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/world/places/GreenTower.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/map.c, src/map.h, src/object.h, src/place.c, src/play.c, src/player.cpp, src/player.h:
+       CHECKIN_NOTES
+
+       * examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/sprite_sets/ultima_IV_sprite_set.ghul:
+       ../CHECKIN_NOTES
+
+2003-06-30  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/readable_items.ghul:
+       Added a Map Editors guide document in-game.
+
+       * examples/data/types/readable_items.ghul:
+       Added more info to the Map Editors Guide document.
+
+2003-06-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, Attic/configure, doc/GHULSCRIPT, examples/data/types/npc_party_defs.ghul, examples/data/types/species.ghul, examples/data/types/weapons.ghul, examples/data/world/characters/party_members.ghul, examples/data/world/maps/M_slime_cave.ghul, examples/data/world/places/P_slime_cave.ghul, examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul, src/Attic/NpcParty.cpp, src/character.cpp, src/character.h, src/combat.c, src/place.c, src/species.c, src/species.h:
+       CHECKIN_NOTES
+
+2003-06-29  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/types.ghul, examples/data/types/spells.ghul:
+       Removed the unused REAGENT_TYPE() macro.
+
+       * examples/data/types.ghul, examples/data/types/useable_items.ghul:
+       Moved the ITEM_TYPE() macro.  Reformatting.  Added POTION_TYPE() macro. Increased torch duration from 1000 to 5000.
+
+       * examples/data/types.ghul, examples/data/types/projectiles.ghul:
+       Moved the (unused?) AMMO_TYPE() macro.
+
+       * examples/data/types.ghul, examples/data/types/weapons.ghul:
+       Moved the ARMS_TYPE() macro and went over weapons macros by type.
+
+       * examples/data/types.ghul, examples/data/types/chest_traps.ghul:
+       Moved the TRAP_TYPE() macro to where it is used.
+
+       * examples/data/types.ghul, examples/data/types/magical_fields.ghul:
+       Moved the FIELD_TYPE() macro to where it is used.
+
+       * examples/data/player/party.ghul, examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/types/worn_items.ghul:
+       Macro-ized worn items.  Added some new types of helm, body armor, boots.
+
+       * examples/data/types/projectiles.ghul:
+       Changed projectiles to use a PROJECTILE_TYPE() macro.
+
+       * examples/data/types/readable_items.ghul:
+       Added DOCUMENT_TYPE() macro.
+
+       * src/combat.c:
+       Added display of range/reach for ranged/melee attacks to the
+       UI prompt when making an attack.
+
+       * src/common.h:
+       Removed a kludge #ifdef block.
+
+2003-06-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, Attic/RELEASE_NOTES, Attic/RELEASE_NOTES, Attic/RELEASE_NOTES, examples/data/types/vehicles.ghul, examples/data/world/places/P_terrain_test.ghul, src/combat.c, src/common.c, src/common.h, src/cursor.cpp, src/cursor.h, src/Attic/game.c, src/map.c, src/place.c, src/play.c, src/player.cpp, src/player.h:
+       CHECKIN_NOTES
+
+2003-06-28  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/readable_items.ghul, examples/data/types/worn_items.ghul, examples/data/world/places/P_terrain_test.ghul:
+       Added a couple items.  Added placed objects to p_terrain_test.  Minor formatting, a couple of spelling fixes.
+
+       * examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_terrain_test.ghul:
+       Added a invisible lever mechanism and an example of its use.
+
+       * examples/data/world/mechanisms/all_mechanisms.ghul:
+       Minor formatting.
+
+       * examples/data/world/mechanisms/all_mechanisms.ghul:
+       Converted all door-like mechanisms to use the MAKE_DOORLIKE_MECH() macro.
+
+       * examples/data/world/places/P_rom_camp.ghul:
+       Corrected a comment.
+
+       * src/play.c:
+       Added notes to detailed_examine_XY() for future implementation.
+
+2003-06-27  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES:
+       Updated RELEASE_NOTES with info on the palette+map saving command.
+
+       * examples/data/types/npc_party_defs.ghul, examples/data/types/species.ghul, examples/data/types/weapons.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_rom_camp.ghul:
+       Added horses to the gypsy camp, and a new doorlike mechanism for a fence gate.
+
+       * examples/data/types/portal_types.ghul, examples/data/world/portals.ghul, examples/data/world/places/P_cavernous_troll_deeps.ghul, examples/data/world/places/all_places.ghul:
+       Created a new dungeon.
+
+       * examples/data/types/portal_types.ghul:
+       Added a new portal type t_standing_portal.
+
+       * examples/data/world/maps/M_blank_16x16.ghul:
+       Added a new map template of size 16x16.
+
+       * examples/data/world/maps/M_blank_32x32.ghul, examples/data/world/maps/M_blank_64x64.ghul:
+       Fixed palette name
+
+       * examples/data/world/maps/M_blank_32x32.ghul, examples/data/world/maps/M_blank_64x64.ghul:
+       Added a couple of blank map templates.
+
+       * examples/data/world/places/P_rom_camp.ghul, examples/data/world/places/all_places.ghul:
+       Added a gypsy (Rom) camp.
+
+       * src/common.h, src/cursor.cpp, src/play.c:
+       Some polish on cursor range things.
+
+       * src/play.c:
+       Polish and messages for Save Map command.
+
+       * src/play.c, src/terrain.c, src/terrain_map.c, src/terrain_map.h:
+       Added a map- and palette-saving command which saves the current map and palette to files as GhulScript.
+
+2003-06-26  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * src/cursor.cpp, src/cursor.h, src/map.c, src/map.h, src/play.c:
+       Added mapTileIsWithinViewport() and Cursor::setViewportBounded().
+       Changed Cursor::move() and the Xamine and Terraform commands to make
+       use of these.
+       
+       The Xamine and Terraform commands now have a cursor range which allows
+       for the viewing/alteration of any tile on the viewport.
+
+       * src/play.c, src/play.h, src/terrain.c, src/terrain.h:
+       Simplified and improved the terrain_palette API.
+       Improved the UI of Terraform (Home/End, quick terrain get/set)
+
+       * src/terrain.h:
+       Simplified the internals of quick_terrain in terrain palettes.
+
+2003-06-25  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/data/types/terrains.ghul, src/event.h, src/play.c, src/terrain.c, src/terrain.h:
+       Implemented actual terrain editing in the (^T)erraform command.
+       The command is bound to CONTROL-T, and invokes a UI cursoring mode
+       in which PageUp/PageDown cycle through terrain to draw with (in the
+       current terrain_palette) and (SPACE | ENTER | RETURN) alters terrain.
+       
+       The next step is more UI refinements, and command which saves the
+       current map and palette.
+
+       * examples/data/player/party.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/maps/M_dark_passage.ghul, examples/data/world/maps/M_secret_shrine.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/DarkPassage.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/GreenTowerLower_Map.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, examples/data/world/places/P_terrain_test.ghul, examples/data/world/places/P_wilderness.ghul, src/combat.c, src/common.h, src/Attic/game.c, src/terrain_map.c:
+       PALETTE is now a top-level keyword,
+       and the palette {} blocks in MAP {} have been
+       replaced with a palette field taking a palette tag.
+       
+       Also, terrain_map_clone() finally properly fixed,
+       and all maps and palettes in examples/data/ changed
+       to match the new GhulScript syntax.
+
+       * src/combat.c, src/conv.c, src/event.c, src/event.h, src/play.c, src/play.h:
+       Added keymod support to KeyHandler struct and functions.
+       
+       Added a skeletal (^T)erraform command, bound to CONTROL-T.
+       Currently it only prints messages and does not alter terrain.
+       Checking it in becaues the KeyHandler support touched several files.
+       The next checkin should add actual editing of terrain.
+
+       * src/combat.c:
+       Commented out some debugging output.
+
+       * src/combat.c, src/play.c:
+       Improvements to messages for enter/exit zoom-in maps.  Remapped the < and \ keys to > and < for consistency with roguelikes.
+
+       * src/event.c:
+       Minor change in eventHandler().
+
+       * src/play.c:
+       More tweaking of zoom-in messages.
+
+       * src/play.c:
+       Minor improvements to the Xamine and AT commands:
+       
+       Xamine now looks at the party / invoking character tile
+       before any cursor movement is done.
+       
+       AT now prints blank seperator lines above and below
+       its main output.
+
+       * src/terrain_map.c:
+       Fixed up terrain_map_print() somewhat.
+
+2003-06-23  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/types/terrains.ghul, src/Attic/game.c:
+       Added a new top-level keyword PALETTE.
+       This keyword is not used yet (coming next checkin)
+       but will replace the per-map palettes currently used.
+
+2003-06-21  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * scripts/run_nazghul:
+       Added information to the comment header.
+
+       * scripts/timesort_data, scripts/timesort_src, scripts/touch_all_src:
+       Added scripts which use (touch, ls -tr, find) to help know which files you have modified during a hacking session.
+
+       * src/terrain_map.c:
+       Fixed a picky, anal, pedantic C++ typecast on malloc().
+       Curse you C++, curse you...
+
+       * src/terrain_map.c:
+       Fixed a bug with terrain_map_clone().
+       A cloned terrain_map should be given a tag, to facilitate later saving.
+       Tags should be unique(ish) however.
+       This change gives a clone of a map with tag "foo" a new tag "foo_c".
+
+       * src/terrain_map.c:
+       Added some notes about terrains with "facing"
+       (such as diagonal wall corner pieces)
+       which we may desire to support in future.
+
+2003-06-20  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/world/places/P_wilderness.ghul, src/combat.c, src/common.c, src/common.h, src/Attic/game.c, src/terrain.c, src/terrain.h, src/terrain_map.c:
+       Added a 'palette' field to terrain_map, for saving same.
+       
+       Changes which ensure that every terrain_map has a palette.
+       Currently this is a best-effort solution; there exists at
+       least one case (merging two maps such as terrain combat map
+       + vehicle map, that is done by overlay_map() I believe;
+       terrain-blitting mechs could do this also, I think.)
+       where, due to terrain being blitted from a map with another
+       palette (said terrain not present in the main map palette),
+       terrain can exist on a map which is not present in the palette.
+       
+       In such cases, I soft-fail when writing the MAP {},
+       using ? or ?? or the like for any not-in-palette
+       terrain and adding a comment in the generated GhulScript
+       which notes that this was done.  This will not be sufficient
+       for the needs of 'save game', but is still very useful for
+       a map editor, where human hands can fix up the palette afterwards.
+       
+       As to how to implement the Right Thing (TM), this brings up
+       some design questions.  Once terrain palettes are globally
+       scoped entities, rather than being defined for each MAP {},
+       there is no truly compelling reason to have more than one
+       palette; or at least one palette per glyph-width.  On the
+       other hand, there is no truly compelling reason to rip out
+       multiple palette functionality right now.  In the near future
+       (0.3.x branch), we should decide what is best.  Multiple palettes
+       would require palette-merging of moderate sophistication.
+       Such code is easy enough to write, but the requirement that it
+       never fail or generate an invalid palette is rather taxing.
+       
+       In any event, here is one more step towards a map editor in-game.
+
+       * scripts/ghul-indent:
+       Read the manpage, added some whitespace-modifying items,
+       and the "no tabs, use spaces instead" option.
+       Changed to using long-form options.
+       Un-cuddled '} else'
+
+2003-06-19  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, src/Attic/game.c, src/terrain.c, src/terrain.h, src/terrain_map.c, src/terrain_map.h:
+       Added a map-printing function terrain_map_print() which can output
+         GhulScript for a MAP.  Work remains to be done, including making
+         sure that every terrain_map has its' palette field properly filled
+         out, and connecting the palette_print() function.  (Or better yet,
+         making palettes globally-scoped entities rather than per-map.)
+
+       * Attic/RELEASE_NOTES, examples/data/player/party.ghul, examples/data/types/vehicles.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/GreenTowerLower_Map.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_wilderness.ghul, src/Attic/game.c, src/terrain.h:
+       Finished converting game_load_ascii_terrain_map() to use
+         string-oriented terrain {} block parsing rather than
+         Loader::getRaw().
+       
+         Now, both compact one_char_per_tile maps and single/multi-byte
+         palette non-compact maps work alike.  That is, each line is a quoted
+         string.
+
+       * src/character.cpp:
+       Added \n to a debug message.
+
+       * src/terrain_map.c:
+       Un-snarled a diagram in a comment illustrating map rotation.
+
+2003-06-19  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/configure:
+       One more update to BUGS
+
+       * BUGS, INSTALL, Attic/RELEASE_NOTES:
+       Updated INSTALL and BUGS
+
+       * Attic/configure.in, src/nazghul.c:
+       Updated version number to 0.1.2
+
+2003-06-18  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/maps/M_dark_passage.ghul, examples/data/world/maps/M_secret_shrine.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/DarkPassage.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, examples/data/world/places/P_terrain_test.ghul, src/Attic/game.c, src/terrain.c, src/terrain.h:
+       Changed terrain palettes and terrain blocks in MAP constructs
+       (when multi-byte map is specified) to use different parsing code.
+       The new parsing code uses getString() rather than getRaw().
+       
+       This fixes several bugs pertaining to palette and map loading.
+       
+       TODO: Fix single-byte (compact) maps to work in the same way,
+             and the *.ghul that define such maps to match.
+
+       * src/common.h:
+       This belongs with the previous commit,
+       with the parsing changes for terrain palette and terarin blocks.
+       
+       The only change in this file is a small hack workaround for
+       a global terrain palette, which I am going to remove in the
+       very near future.  I am only checking this in for completeness,
+       my tests showed that CVS built and ran OK without this.
+
+2003-06-18  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, src/map.c:
+       --Added support for the sleep effect to items (previously only spells).
+       
+       --Party leader is now reevaluated every time some part of the code asks about
+         it (I use to try to cache the leader, but this makes things too
+         complicated). Also, if the leader falls asleep the next in command takes
+         over.
+       
+       --Fixed sleep fields in combat. Looks they were never processed
+         correctly.
+       
+       --Removed the 'find party' and 'find edge' requirements in combat
+         placement. Not sure if this will break something or not, but I decided to do
+         this when I found that nixies could not get distributed on a bridge combat
+         map. That's just silly, and most of that placement code was written back in
+         the day when I wanted the engine to do more ass-covering for map hackers. So
+         I removed it. We'll see what happens.
+       
+       --Fixed the "In Lor" spell by making the caster the default spell
+         target. Apparently I commented that line of code out for some reason but I
+         don't know why. Should have left a note. This time, I did.
+       
+       --Bugfix: the character describe method assumed the character had an
+         occupation. Some npc characters in the example game don't have an
+         occupation. For example, insects in a swarm.
+       
+       --Bugfix: charmed opponents continued to attack the party. This was a bug
+         introduced some time ago when I had characters remember their previous
+         targets so that stepping out of LOS would not make them start to wander
+         aimlessly. We needed to check if we were still hostile to these remembered
+         targets.
+       
+       --Bugfix: npcs standing on los-blocking terrain in combat no longer blind
+       
+       --Bugfix: wave sprites now rendered properly when peering (zoomed out by a
+         factor of two). There were several bugs contributing to this.
+       
+       --Added a level beneath Green Tower (to test some spells, but I think I'll keep
+         it).
+       
+       --Fixed map-wrapping bug in vehicle weapon firing.
+       
+       --Removed derived objects examples/mapfile and examples/data/mapfile from CVS.
+       
+       --Bugfix: x)amine los-checking did not work across map boundaries.
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/images/mine-32x32.png, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/places/GreenTower.ghul, src/vehicle.cpp, src/vehicle.h:
+       --Added support for the sleep effect to items (previously only spells).
+       
+       --Party leader is now reevaluated every time some part of the code asks about
+         it (I use to try to cache the leader, but this makes things too
+         complicated). Also, if the leader falls asleep the next in command takes
+         over.
+       
+       --Fixed sleep fields in combat. Looks they were never processed
+         correctly.
+       
+       --Removed the 'find party' and 'find edge' requirements in combat
+         placement. Not sure if this will break something or not, but I decided to do
+         this when I found that nixies could not get distributed on a bridge combat
+         map. That's just silly, and most of that placement code was written back in
+         the day when I wanted the engine to do more ass-covering for map hackers. So
+         I removed it. We'll see what happens.
+       
+       --Fixed the "In Lor" spell by making the caster the default spell
+         target. Apparently I commented that line of code out for some reason but I
+         don't know why. Should have left a note. This time, I did.
+       
+       --Bugfix: the character describe method assumed the character had an
+         occupation. Some npc characters in the example game don't have an
+         occupation. For example, insects in a swarm.
+       
+       --Bugfix: charmed opponents continued to attack the party. This was a bug
+         introduced some time ago when I had characters remember their previous
+         targets so that stepping out of LOS would not make them start to wander
+         aimlessly. We needed to check if we were still hostile to these remembered
+         targets.
+       
+       --Bugfix: npcs standing on los-blocking terrain in combat no longer blind
+       
+       --Bugfix: wave sprites now rendered properly when peering (zoomed out by a
+         factor of two). There were several bugs contributing to this.
+       
+       --Added a level beneath Green Tower (to test some spells, but I think I'll keep
+         it).
+       
+       --Fixed map-wrapping bug in vehicle weapon firing.
+       
+       --Removed derived objects examples/mapfile and examples/data/mapfile from CVS.
+
+       * examples/data/world/characters/Shroom_the_Hag.ghul, examples/data/world/places/GreenTowerLower.ghul, examples/data/world/places/GreenTowerLower_Map.ghul:
+       Forgotten files
+
+       * scripts/run_nazghul:
+       Adding Sam's run script
+
+2003-06-17  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/types/species.ghul, examples/data/types/spells.ghul, examples/data/types/useable_items.ghul, examples/data/world/astronomy.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul, src/Attic/Item.cpp, src/Attic/NpcParty.cpp, src/character.cpp, src/combat.c, src/map.c, src/play.c, src/player.cpp, src/screen.c, src/sky.c, src/sprite.c, src/sprite.h:
+       --Added support for the sleep effect to items (previously only spells).
+       
+       --Party leader is now reevaluated every time some part of the code asks about
+         it (I use to try to cache the leader, but this makes things too
+         complicated). Also, if the leader falls asleep the next in command takes
+         over.
+       
+       --Fixed sleep fields in combat. Looks they were never processed
+         correctly.
+       
+       --Removed the 'find party' and 'find edge' requirements in combat
+         placement. Not sure if this will break something or not, but I decided to do
+         this when I found that nixies could not get distributed on a bridge combat
+         map. That's just silly, and most of that placement code was written back in
+         the day when I wanted the engine to do more ass-covering for map hackers. So
+         I removed it. We'll see what happens.
+       
+       --Fixed the "In Lor" spell by making the caster the default spell
+         target. Apparently I commented that line of code out for some reason but I
+         don't know why. Should have left a note. This time, I did.
+       
+       --Bugfix: the character describe method assumed the character had an
+         occupation. Some npc characters in the example game don't have an
+         occupation. For example, insects in a swarm.
+       
+       --Bugfix: charmed opponents continued to attack the party. This was a bug
+         introduced some time ago when I had characters remember their previous
+         targets so that stepping out of LOS would not make them start to wander
+         aimlessly. We needed to check if we were still hostile to these remembered
+         targets.
+       
+       --Bugfix: npcs standing on los-blocking terrain in combat no longer blind
+       
+       --Bugfix: wave sprites now rendered properly when peering (zoomed out by a
+         factor of two). There were several bugs contributing to this.
+       
+       --Added a level beneath Green Tower (to test some spells, but I think I'll keep
+         it).
+
+2003-06-15  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, src/Attic/Mech.cpp, src/Attic/Mech.h:
+       --Bugfix: circular mech activation now has some crude
+         (over)protection. Connecting two lights spaceship-style in no longer causes
+         the engine to crash on stack overflow.
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, src/play.c:
+       --Bugfix: combat resulting from a conversation was not placing the opponent on
+         the combat map. This broke when I made towns function in party mode like the
+         wildernesses. Before that change combat just occurred in town so I didn't
+         need to setup the npc party in the combat map.
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/types/occupations.ghul, src/Attic/NpcParty.cpp, src/place.c, src/place.h:
+       --Added a druid class.
+       
+       --Npc parties in wander mode no longer walk over hazardous terrain. I was
+         getting concerned about Shroom walking around in the firepit at the White
+         Stag Lodge. :-)
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/world/places/GreenTower.ghul, src/Attic/NpcParty.cpp, src/conv.c:
+       --Added a new character to Green Tower. Shroom the Hag owns the reagent shop.
+
+       * Attic/RELEASE_NOTES, src/cmdwin.c, src/console.c, src/play.c, src/player.cpp:
+       --New feature in the console. If a message is a repeat of the last one then
+         instead of printing it again the console will print a notice of how many time
+         the message has repeated so far. Also changed the way "slow progress" and
+         friends are reported so that it takes advantage of this feature.
+
+       * Attic/RELEASE_NOTES, src/cmdwin.c, src/cmdwin.h, src/combat.c, src/play.c:
+       --The final contents of the cmdwin are now shown on the main console.
+
+2003-06-14  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/player/party.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/maps/M_secret_shrine.ghul, examples/data/world/places/P_empire_city.ghul, src/Attic/game.c, src/terrain.c, src/terrain.h:
+       Changed the implementation of terrain palettes.
+       Added print functionality for terrain palettes and
+       for terrain palette entries.
+       Got rid of the glyph field of terrains
+       Palettes now have a palette tag
+       Changed world data to match
+       (all map palettes are now named, no glyph field in TERRAIN() macro.)
+
+2003-06-14  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/sprite_sets/moons_sprite_set.ghul, examples/data/sprite_sets/ultima_IV_font_sprite_set.ghul, examples/data/world/astronomy.ghul, src/Attic/Mech.cpp, src/common.h, src/Attic/game.c, src/play.c, src/player.cpp, src/sky.c, src/sky.h, src/terrain.c, src/terrain.h:
+       --Fixed some issues with sunrise/sunset. The sun now begins to appear in the
+         sky window at sunrise, and is completely gone by sunset. The light fades in
+         and out over the space of the first hour after sunrise and before sunset,
+         respectively. The code to calculate sunlight now uses a single consistent
+         forumula, and does so for the moons as well as the sun (more on that below).
+       
+       --The moons now provide light depending on their arc and phase. They can
+         provide at most 128 light units, whereas the sun can provide 255 (max is 255
+         due to the way the lightmap gets built in map.c). So even with a full moon
+         things are a bit dim.
+       
+       --Replaced the u4 moon sprites with my own, since mine are 16x16 and u4 is
+         only 8x16. Makes the full moons look full.
+
+       * BUGS, Attic/RELEASE_NOTES, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/play.c:
+       --If the player attacks a non-hostile npc party then the target's alignment
+         bits are cleared from the player's alignment bits. In other words, the npc
+         party and all of its allies are now the player's enemies. If you attack a
+         townsperson all the other townspeople and the guards will attack you if they
+         can. Note that they still aren't smart enough to pathfind through impassable
+         mechanisms, so a door is enough to hold them off.
+
+       * BUGS, Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, src/play.c:
+       --Added the (a)ttack command for towns and wilderness. If the target is
+         non-hostile it prompts the player for confirmation.
+
+2003-06-13  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/types/terrains.ghul, src/Attic/game.c, src/terrain.c, src/terrain.h:
+       Obsoleted the 'glyph' field in 'struct terrain'
+       Moved 'struct terrain_palette' to terrain.h
+       Some notes and such.
+
+       * examples/data/world/astronomy.ghul:
+       Added some notes on the value of arc for the sun.
+
+       * src/Attic/game.c:
+       Added some notes prior to implementing NULL terrain support
+       for (terrain, terrain_palette, terrain_map).
+
+       * src/play.c:
+       Polished the use of mapTileIsVisible() in cmdXamine().
+
+       * src/terrain.c:
+       Added some notes where the 'struct terrain' API seemed inconsistent.
+
+       * src/terrain.h:
+       Notes and formatting
+
+       * src/Attic/util.h:
+       The removal of #include "common.h" from this file
+       prevented compilation.  Perhaps it is better for the other
+       files which want common.h to #include it themselves
+       (hash.c, others) but for now I desire that CVS compile.
+
+2003-06-13  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/world/astronomy.ghul, examples/data/world/places/GreenTower.ghul, examples/data/world/places/all_places.ghul, src/Attic/util.h:
+       --Added start of a new town: Green Tower
+
+       * examples/data/world/places/GreenTower.ghul:
+       Map upgrade.
+
+2003-06-12  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/def_constants.ghul, examples/data/types/terrains.ghul:
+       Moved all the Terrain stuff into terrains.ghul except pmask macros, which are used elsewhere
+
+       * examples/data/def_constants.ghul, examples/data/types.ghul, examples/data/sprite_sets/rune_font_sprite_set_32x32.ghul, examples/data/sprite_sets/ultima_IV_sprite_set.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_terrain_test.ghul, examples/data/world/places/all_places.ghul:
+       Much work on terrain types.  Macro-ization, rearrangement,
+       improved ship combat map, made a new STD_EXPANDED_PALETTE,
+       and added a new place P_terrain_test
+
+       * examples/data/def_macros.ghul, examples/data/types.ghul:
+       Moved macros to where they were used.
+
+       * examples/data/types.ghul:
+       Formatting improvements for internal documentation.
+
+       * examples/data/sprite_sets/rune_font_sprite_set_8x16.ghul:
+       Fixed the path to the image file from "images/" to "data/images/"
+
+       * src/Attic/Mech.cpp:
+       Turned off some verbose debug output.
+
+2003-06-12  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, doc/GHULSCRIPT, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/types/terrains.ghul, examples/data/world/astronomy.ghul, examples/data/world/places/P_wilderness.ghul, src/angband.c, src/map.c, src/map.h, src/play.c, src/sky.c:
+       --Added a campsite map, campsite formation and party formation to the examples
+         file. Increased the light from a fireplace, too.
+       
+       --Added a new function in map: mapTileIsVisible checks if a tile is visible
+         under the LOS rules.
+
+2003-06-11  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/types/readable_items.ghul:
+       Added Xamine and AT commands to the "Users Guide to Nazghul"
+
+       * src/character.cpp, src/character.h, src/combat.c, src/play.c, src/status.c:
+       // Added pmask to Ztats display
+       // Added ammo display to Attack prompt
+       // Require confirmation for attack self
+       // (and attack ally, in near future)
+       // Changed the key to exit combat from ESCAPE to '\'
+       // Improved a few prompts
+
+       * src/combat.c, src/common.h, src/map.c, src/map.h, src/play.c, src/play.h, src/sky.c, src/sky.h:
+       New command AT which displays party-centric information.  Lots of astronomy functions stuff related to this as well.
+
+       * src/combat.c, src/event.h, src/play.c:
+       Refactored the Xamine command to un-munge struct KeyHandler for future expansions
+
+       * src/play.c:
+       Look, Xamine, Ztats, AT take zero turns, improved some prompts
+
+2003-06-11  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS, Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world/places/P_wilderness.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Attic/Spell.cpp, src/combat.c, src/Attic/game.c, src/map.c, src/object.c, src/play.c:
+       --Fixed a memory leak. NpcParty objects were not being deleted after combat
+         except in the case where the NpcParty initiated combat. Added a new flag to
+         the NpcParty class: 'destroy_on_combat_exit'. By default it is true. In the
+         case where the NpcParty initiates combat it sets it to false before entering
+         combat. After combat the NpcParty will be deleted once it returns to the code
+         in place.c which updates objects every turn.
+
+       * Attic/RELEASE_NOTES, doc/GHULSCRIPT, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world/astronomy.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_wilderness.ghul, src/play.c, src/sound.c:
+       --Fixed a crash that occurred on startup if the --sound 0 option was
+         specified.
+
+2003-06-08  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world.ghul, src/Attic/NpcParty.cpp, src/combat.c, src/combat.h, src/common.h, src/Attic/game.c, src/vehicle.cpp:
+       --Added a COMBAT section to the script. Currently this is only used to declare
+         the sound files used in combat for events like entry, defeat and victory.
+       
+       --Fixed a bug introduced when I fixed cannons firing in town. The npc code was
+         not properly incrementing turns when it fired cannons.
+       
+       --When npc vehicle weapons hit an npc party it was printing "You hit ", as if
+         the player was doing the firing. Changed the message from "you" to whatever
+         the name of the weapon being fired.
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/types/species.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/character.cpp, src/character.h, src/combat.c, src/map.c, src/map.h, src/object.c, src/object.h, src/place.h, src/play.c, src/player.cpp, src/sound.c, src/sound.h, src/species.c, src/species.h, src/vehicle.cpp:
+       --Added sound attenuation with distance (hearing the nixies splash around gets
+         really annoying when you can't get away from it - need to find some better
+         sounds). I only made it apply in party mode because in combat mode it's a bit
+         trickier for the code that's playing the sound to figure out which party
+         member it needs to calculate the distance from. Since dungeons are not party
+         mode I'll probably want to reconsider how to do that.
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/types/species.ghul, examples/data/world/characters/Olin_the_Ghast.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, src/Attic/Loader.cpp, src/Attic/Loader.h, src/character.cpp, src/character.h, src/sound.c, src/species.c, src/species.h:
+       --Fixed bugs related to playing a sound when damage is inflicted. Previously it
+         was a hardcoded hack that broke a while back when we split the data files
+         into their own directory. The fix was to add an optional 'damage_sound' field
+         to both the SPECIES and CHAR declarations. When a character receives damage
+         it will first check if it has its own special damage sound to play, otherwise
+         it will check if its species has a damage sound to play, otherwise it doesn't
+         play anything. This works in the case of damaging npc parties, too (for
+         example with ship cannons) because npc party damage calls the character
+         damage routines. In the examples I modified all species to play the old
+         traditional damage sound.
+
+2003-06-07  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * BUGS:
+       Added a BUGS file for per-release bug info
+
+       * INSTALL, Attic/configure, Attic/configure.in, src/nazghul.c:
+       Updated INSTALL and configure.in in preparation for release 0.1.1
+
+       * Attic/RELEASE_NOTES, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/types.ghul, examples/data/types/projectiles.ghul, examples/data/types/vehicles.ghul, src/common.h, src/place.c, src/place.h, src/play.c, src/player.cpp, src/player.h, src/vehicle.cpp:
+       --Fixed the bug Sam reported about firing cannons in town. Whenever the cannon
+         was fired the turns were updates as if the party was in the wilderness, not
+         town. So about 64 turns passed, and if any hostiles happened to be nearby you
+         would immediately enter combat. Also spruced up the messages shown when
+         firing and fixed the cannonball sprite (finally :-)) in the examples.
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/types/readable_items.ghul:
+       Removed the old notes which referred to LB and SH
+
+2003-06-06  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, src/Attic/Mech.cpp, src/Attic/Mech.h, src/object.h, src/place.c:
+       --Changed the way mechs are described. From now on, the mech state name is an
+         adjective. This adjective is applied to the mech name when the mech is
+         described. For example, if a "door" mech is in a "closed" state then the
+         l)ook or x)amine commands will describe it as "a locked door" (the articles
+         'a' and 'an' are automatically derived by the engine's code for describing
+         objects). If the mech has no state, or if the state has no name, then simply
+         the mechanism name is used. E.g., "a door". I updated all the mechs in the
+         example game so that they are described nicely now.
+       
+       --I also added a new optional field to mechanism states: 'invisible'. By
+         default it is false. When true the mechanism is not shown on the map and it
+         is not described by l)ook or x)amine. However, if Reveal is in effect (Wis
+         Quas in the current magic system), then the mechanism is described and - if a
+         sprite is available - rendered.
+       
+       --Closed moongates are not described by l)ook or x)amine unless Reveal is in
+         effect.
+
+2003-06-05  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/places/P_wilderness.ghul:
+       --Created a combat map for east-west bridges (combat looks kind of funny when
+         half the map has been terrain-filled with bridge icons ;)).
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/cursor.cpp, src/place.c:
+       --Sam found some bugs in cursor movement related to map-wrapping. Fixed those
+         and added a regression test for this case.
+       
+       --If an npc party is in a vehicle, the l)ook and x)amine commands will now say
+         so.
+
+       * examples/Attic/mapfile, examples/data/def_constants.ghul, examples/data/Attic/mapfile, examples/data/types/portal_types.ghul, examples/data/world/portals.ghul, examples/data/world/places/DarkPassage.ghul, src/character.cpp, src/combat.c:
+       --Previously party members could switch places if one bumped another one on the
+         map. But if passability constraints didn't permit the switch then the move
+         simply failed. In order to get us out of some corner cases I modified this so
+         that if passability checks fail then the move succeeds and the mover is
+         simply stacked on the same tile as the other member. We already stack to
+         solve passability problems on dungeon entrance, so this just extends the
+         scope of that compromise.
+       
+       --Implemented the new dungeon exit rules regarding portal entry: the party must
+         be in party mode, all members must be able to rendezvous at the portal, and
+         the exit takes effect atomically (i.e., everybody exits at once via the
+         portal or nobody at all gets to go through the portal). This concludes the
+         new player movement algorithm. And that calls for a beer.
+
+       * src/character.cpp, src/character.h, src/object.c, src/object.h, src/place.c, src/play.c, src/player.cpp, src/player.h, src/vehicle.cpp:
+       --Fixed the L)ook and X)amine output to be for the most part correct. We still
+         need to make up our minds on what to print for mechanisms, but other than
+         that the output should be correct.
+       
+       --Also resynched the layer enumeration in object.h and the LAYER_* #defines in
+         examples/data/def_constants.ghul (we really need to fix this dependency). I
+         did this so that the cursor would not be described by the l)ook or x)amine
+         commands. Note that if they get out of synch again we might see the cursor
+         being described and things kept at a nother layer NOT described, so watch for
+         this.
+
+2003-06-04  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/sprite_sets/misc_added_sprite_set.ghul:
+       Minor formatting fix (removed duplicate ;;)
+
+       * examples/data/world/maps/terrain_combat_maps.ghul:
+       Changed the m_water_combat map to 32x32 to match the rest.
+
+       * examples/data/world/places/P_empire_city.ghul:
+       Changed the castle_bay_portcullis lever's initial state
+       to match the terrain initial state.  (Minor tweak)
+
+       * src/combat.c, src/cursor.cpp, src/event.h, src/play.c, src/play.h:
+       Added an (X)amine command, which is an extended (L)ook.  And some notes ton the Cursor API.
+
+2003-06-04  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world/places/P_empire_city.ghul, src/play.c, src/player.cpp, src/player.h:
+       --Added a minor hack to force the game into dungeon mode if it loads up with
+         the player party starting out in a dungeon. Previously the party would be in
+         the dungeon, but it would be in party mode. The new game rules forbid party
+         mode in a dungeon.
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/world/portals.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, src/combat.c, src/place.c:
+       --Discovered that "follow mode" did not work correctly when the party leader
+         moved north or east. Not sure how long that's been like that, but I fixed it
+         in place.c.
+       
+       --Fixed a crash when entering a dungeon from another dungeon. The combat code
+         was tring to derefence the party's current place to check for an unboarded
+         vehicle (this is necessary for town/wilderness combat), but the last dungeon
+         entry erased the current place. This seems to be the only place combat code
+         tries to find the party's current place without first checking that it is
+         town or wilderness combat. Fixed it by simply skipping the vehicle test if
+         the party's current place is null.
+       
+       --Added another dungeon, "Dark Passage", with links both to the Prison Chamber
+         and to the surface of Empire City. Tested moving between them all and
+         everything seems ok for the simple cases.
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world/characters/BlackBart_the_Shipwright.ghul, src/Attic/NpcParty.cpp, src/place.c, src/place.h:
+       This checkin fixes all known problems with creating temporary combat maps.
+       
+       --The combat algorith now always combines the map derived from the player
+         party's tile with the map derived from the npc party's tile. Before it only
+         did this when it was creating filled maps from the terrain, not it will use
+         the combat map specified for the terrain, too.
+       
+       --Terrain combat maps are now required to be at least COMBAT_MAP_W x
+         COMBAT_MAP_H in size (currently set to 32 x 32 in combat.h). The combat code
+         will assert if a map is too small, but before that happens the parser code
+         will catch it at load time.
+       
+       --Fixed the old combat maps for forest and grass to be 32 x 32 (didn't touch
+         Sam's new water map - he may want to make his own changes at this point).
+
+       * examples/data/world/places/DarkPassage.ghul:
+       Forgot to check this in
+
+       * src/character.cpp, src/character.h, src/combat.c:
+       --Changed combat party positioning code. When entering combat, if a party
+         member cannot find a safe position then it will default to the party's
+         "start" location. This means that party members can get stacked, and that
+         they can get stranded on combat maps. But it also means that entry to combat
+         or dungeons is guaranteed to work, and this simplifies the movement algorithm
+         tremendously.
+
+2003-06-03  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world.ghul, examples/data/player/party.ghul, examples/data/world/maps/terrain_combat_maps.ghul, src/combat.c, src/combat.h, src/Attic/game.c:
+       This checkin fixes all known problems with creating temporary combat maps.
+       
+       --The combat algorith now always combines the map derived from the player
+         party's tile with the map derived from the npc party's tile. Before it only
+         did this when it was creating filled maps from the terrain, not it will use
+         the combat map specified for the terrain, too.
+       
+       --Terrain combat maps are now required to be at least COMBAT_MAP_W x
+         COMBAT_MAP_H in size (currently set to 32 x 32 in combat.h). The combat code
+         will assert if a map is too small, but before that happens the parser code
+         will catch it at load time.
+       
+       --Fixed the old combat maps for forest and grass to be 32 x 32 (didn't touch
+         Sam's new water map - he may want to make his own changes at this point).
+
+2003-06-02  Sam Glasby  <sglasby@localhost.localdomain>
+
+       * examples/data/def_constants.ghul, examples/data/world.ghul, examples/data/sprite_sets/mechanism_sprites.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/occupations.ghul, examples/data/types/species.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_wilderness.ghul:
+       2003/06/01 -- map changes, nixies, mechanism macros and sprites
+
+2003-06-02  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/USERS_GUIDE:
+       Updated the section on magic in the USERS_GUIDE to match the current example game
+
+       * examples/Attic/mapfile, examples/data/def_constants.ghul, examples/data/Attic/mapfile, examples/data/player/party.ghul, src/Attic/Mech.cpp, src/place.c:
+       Fixed passability problems with mechs.
+
+       * src/combat.c, src/place.h, src/player.cpp, src/player.h:
+       --First pass at new dungeon support. Party correctly enters and exits an empty
+         dungeon with only one entrance. Haven't tested other cases yet.
+
+2003-06-01  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/Attic/GAME_DEVELOPERS_GUIDE, doc/MAP_HACKERS_GUIDE:
+       Moved a doc
+
+       * doc/USERS_GUIDE:
+       Updated for 0.2.0 release
+
+       * examples/Attic/mapfile, examples/data/def_constants.ghul, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/types/species.ghul, examples/data/types/terrains.ghul, examples/data/types/vehicles.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_empire_city.ghul:
+       --Added SOLID as a passability bit to the examples and modified most currently
+         impassable terrain and impassable mech states to use it. Also uodated all
+         literal constant passability masks to use macros.
+       
+       --Added pretty much all bits to the ghast passability mask. This allows them to
+         walk through walls, over water, etc.
+       
+       --Added Olin to Empire City and gave him a schedule and a conversation tree,
+         including an option to join the party.
+       
+       --Removed WATER from the gazer pmask (still has SHOALS, though)
+       
+       --Added a mortuary and crypt to Empire City.
+       
+       --Removed the pmask field in the player party definition. This field is now
+         obsolete - the engine will use the intersection of the party member's pmasks
+         to compute party passability.
+
+       * examples/data/def_constants.ghul, examples/data/def_macros.ghul, examples/data/main.ghul, examples/data/types.ghul, examples/data/world.ghul, examples/data/player/party.ghul, examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/sprite_sets/frame_sprite_set.ghul, examples/data/sprite_sets/mechanism_sprites.ghul, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/sprite_sets/moons_sprite_set.ghul, examples/data/sprite_sets/rune_font_sprite_set.ghul, examples/data/sprite_sets/rune_font_sprite_set_32x32.ghul, examples/data/sprite_sets/rune_font_sprite_set_8x16.ghul, examples/data/sprite_sets/sam_new_tiles_32x32.ghul, examples/data/sprite_sets/ultima_IV_font_sprite_set.ghul, examples/data/sprite_sets/ultima_IV_sprite_set.ghul, examples/data/types/chest_traps.ghul, examples/data/types/containers.ghul, examples/data/types/magical_fields.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/occupations.ghul, examples/data/types/portal_types.ghul, examples/data/types/projectiles.ghul, examples/data/types/readable_items.ghul, examples/data/types/species.ghul, examples/data/types/spells.ghul, examples/data/types/terrains.ghul, examples/data/types/useable_items.ghul, examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/types/worn_items.ghul, examples/data/world/astronomy.ghul, examples/data/world/portals.ghul, examples/data/world/characters/BlackBart_the_Shipwright.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/characters/party_members.ghul, examples/data/world/conversations/conversations.ghul, examples/data/world/maps/M_dark_passage.ghul, examples/data/world/maps/M_secret_shrine.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul, examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul, scripts/apply-license-header, scripts/ghul-indent, scripts/gpl.h, scripts/public-domain.h, scripts/remove-old-copyright-header, src/Arms.cpp, src/Arms.h, src/Container.cpp, src/Container.h, src/Field.h, src/Attic/Item.cpp, src/Attic/Item.h, src/Attic/Loader.cpp, src/Attic/Loader.h, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Reagent.cpp, src/Reagent.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/Attic/Trap.cpp, src/Attic/Trap.h, src/angband.c, src/ascii.c, src/ascii.h, src/astar.c, src/astar.h, src/character.cpp, src/character.h, src/cmdwin.c, src/cmdwin.h, src/combat.c, src/combat.h, src/common.c, src/common.h, src/console.c, src/console.h, src/constants.h, src/conv.c, src/conv.h, src/cursor.cpp, src/cursor.h, src/debug.h, src/dup_constants.h, src/event.c, src/event.h, src/floodfill.c, src/foogod.c, src/foogod.h, src/formation.h, src/Attic/game.c, src/Attic/game.h, src/hash.c, src/hash.h, src/heap.c, src/heap.h, src/images.c, src/images.h, src/knapsack.c, src/knapsack.h, src/Attic/lexer.c, src/Attic/lexer.h, src/list.h, src/los.c, src/los.h, src/map.c, src/map.h, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/object.c, src/object.h, src/occ.c, src/occ.h, src/olist.c, src/olist.h, src/pinfo.h, src/place.c, src/place.h, src/play.c, src/play.h, src/player.cpp, src/player.h, src/Attic/portal.h, src/sched.c, src/sched.h, src/screen.c, src/screen.h, src/sky.c, src/sky.h, src/sound.c, src/sound.h, src/species.c, src/species.h, src/sprite.c, src/sprite.h, src/status.c, src/status.h, src/terrain.c, src/terrain.h, src/terrain_map.c, src/terrain_map.h, src/tree.c, src/tree.h, src/Attic/util.c, src/Attic/util.h, src/vehicle.cpp, src/vehicle.h, src/wind.c, src/wind.h, src/wq.c, src/wq.h:
+       Added license headers to all source and example files
+
+       * examples/data/main.ghul, examples/data/types.ghul, examples/data/types/spells.ghul:
+       Cleaned up some obsolete references to u4/u5/u6
+
+       * examples/data/world/characters/Olin_the_Ghast.ghul:
+       Missed this file on an earlier commit
+
+       * src/Attic/NpcParty.cpp, src/Attic/game.c, src/player.cpp, src/player.h:
+       --Fixed a bug in NpcParty related to npc schedules. The engine was only
+         properly advancing turns for the known nps schedule activities. Activities
+         extended by the script were not updating the npc turn counter, resulting in
+         an infinite loop when the engine tried to update npc turns.
+       
+       --Removed the pmask field from the player party, both in the parsing code and
+         in the class definition. Player party pmask is now calculated on the fly from
+         the intersection of party member pmasks.
+       
+       --Modified the add_member routine in the player party to reject proposed
+         members which do not have a passability bit in common with the party
+         pmask. In the case of the first member added to the party this rule is
+         skipped.
+
+2003-05-31  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * Makefile.am, Attic/Makefile.in, Attic/configure, Attic/configure.in:
+       --Minor cleanup in configure.in (comments only)
+       
+       --Version number now 0.2.0 (configure.in)
+       
+       --If you build the distro tarball from the cvs tree the cvs directories are now
+         removed.
+
+       * autogen.sh, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/player/party.ghul, examples/data/world/characters/BlackBart_the_Shipwright.ghul, src/conv.c, src/place.c:
+       -- Fixed a bug in conversation parsing which did not properly chain
+          "send_signal" and "set_alarm", so if these were not last in the list of
+          responses they would not be executed.
+       
+       -- Fixed a crash when "blinking" across a wilderness map boundary. Some of the
+          public entry functions to place.c were not wrapping coordinates, resulting
+          in some bad tile lookups. Fixed all public functions to wrap when the map
+          supports it.
+       
+       -- Updated Black Bart's conversation to inherit from the generic orc
+          conversation, and edited it for consistency.
+
+       * Attic/configure.in:
+       Re-enabled the -O2 option
+
+       * examples/Makefile.am, examples/Makefile.in, examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world.ghul:
+       -- Fixed Makefile.am to generate a Makefile which always forces a rebuild of
+          the example mapfile.
+       -- Fixed a build error introduced when I removed a map in my previous checkin.
+
+       * examples/data/world/maps/Attic/M_prison_and_torture_chamber.ghul, examples/data/world/places/P_empire_city.ghul, examples/data/world/places/P_prison_and_torture_chamber.ghul:
+       -- Removed obsolete map files.
+       -- Added place file for empire city.
+
+       * src/Attic/Mech.cpp, src/Attic/Spell.cpp, src/Attic/game.c, src/play.c:
+          Fixed all the uninitialized variables that -Wall was warning about when
+       the -O2 option was enabled. That also seems to fix the runtime crashes that
+       occurred when -O2 was enabled.
+
+       * src/Attic/game.c:
+       Found another uninitialized variable that caused a crash during game load
+
+2003-05-30  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/GAME_RULES:
+       Modified some rules pertaining to party movement from town to world maps and through portals.
+
+       * doc/GAME_RULES:
+       Added GAME_RULES to capture the explanation and reasoning behind engine behaviour where it differs from u5
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world/characters/BlackBart_the_Shipwright.ghul, examples/data/world/mechanisms/all_mechanisms.ghul:
+       -- Added a shipwright to Empire City where the player can purchase a ship.
+
+       * examples/Attic/mapfile, examples/data/Attic/mapfile, examples/data/world/astronomy.ghul, examples/data/world/places/P_wilderness.ghul:
+       -- Improved terrain variety on the wilderness map.
+
+       * src/Attic/Makefile.in, src/Attic/NpcParty.cpp, src/player.cpp:
+       -- Portals and moongates now trump terrain passability in party movement. If a
+          tile has a portal, terrain passability is ignored.
+       
+       -- The engine no longer checks portals for destination passability. If the
+          party enters a portal, it's going to move through it regardless of what's on
+          the other side. This does not affect entering towns from a map edge,
+          however. In that case passability is still determined by the terrain at the
+          edge of the town map.
+       
+       -- When stepping through a portal the player now gets a quick look at what's
+          there before the party appears. This is to hopefully make things less
+          confusing when the party portals on top of a hostile npc party and combat
+          starts up.
+
+2003-05-29  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * doc/Attic/GAME_DEVELOPERS_GUIDE, src/Attic/game.c, src/play.c, src/player.cpp, src/player.h:
+       t
+
+       * examples/Makefile.am, examples/Makefile.in, examples/Attic/mapfile, examples/data/def_constants.ghul, examples/data/Attic/mapfile, examples/data/types.ghul, examples/data/world.ghul, examples/data/player/party.ghul, examples/data/sprite_sets/mechanism_sprites.ghul, examples/data/world/astronomy.ghul, examples/data/world/portals.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/all_places.ghul:
+       Tried to fix Makefile.am (didn't quite); imported empire city map; some new mech macros
+
+       * examples/data/world/places/P_wilderness.ghul, examples/data/world/places/all_places.ghul:
+       Added new simple wilderness
+
+2003-05-28  Gordon McNutt  <gmcnutt@localhost.localdomain>
+
+       * COPYING, INSTALL, Makefile.am, Attic/Makefile.in, README, Attic/aclocal.m4, Attic/config.guess, Attic/config.sub, Attic/configure, Attic/configure.in, Attic/install-sh, Attic/missing, Attic/mkinstalldirs, examples/Attic/.console, examples/Makefile.am, examples/Makefile.in, examples/dup_constants.h, examples/Attic/mapfile, examples/data/ALL_GHULFILES, examples/data/Makefile, examples/data/def_constants.ghul, examples/data/def_macros.ghul, examples/data/main.ghul, examples/data/Attic/mapfile, examples/data/types.ghul, examples/data/world.ghul, examples/data/images/angband-16x16.png, examples/data/images/angband-32x32.png, examples/data/images/charset-16x16.png, examples/data/images/charset-8x16.png, examples/data/images/charset-8x16_intra1.png, examples/data/images/charset-8x8.png, examples/data/images/frame.png, examples/data/images/frame_pieces.png, examples/data/images/frame_pieces_2-16x16.png, examples/data/images/images_35x24_intra1.png, examples/data/images/mechanisms.png, examples/data/images/mine-32x32.png, examples/data/images/moons-16x16.png, examples/data/images/rune_font_32x32.png, examples/data/images/rune_font_8x16.png, examples/data/images/sam_32x32_font_template.png, examples/data/images/sam_mechanisms_template.png, examples/data/images/sam_new_tiles_32x32_intra1.png, examples/data/images/shapes-16x16.png, examples/data/images/shapes-32x32.png, examples/data/images/shrine-32x32.png, examples/data/images/splash.png, examples/data/images/u4_enhanced_tiles_32x32.png, examples/data/images/u4_enhanced_tiles_32x32_intra_1.png, examples/data/player/party.ghul, examples/data/sounds/cannon.wav, examples/data/sounds/damage.wav, examples/data/sounds/drum_02.wav, examples/data/sounds/enter_moongate.wav, examples/data/sounds/fanfare5.wav, examples/data/sounds/fanfare7.wav, examples/data/sounds/footsteps_1.wav, examples/data/sounds/horse.wav, examples/data/sounds/rowing-old1.wav, examples/data/sounds/rowing.wav, examples/data/sounds/walk.wav, examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/sprite_sets/frame_sprite_set.ghul, examples/data/sprite_sets/mechanism_sprites.ghul, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/sprite_sets/moons_sprite_set.ghul, examples/data/sprite_sets/rune_font_sprite_set.ghul, examples/data/sprite_sets/rune_font_sprite_set_32x32.ghul, examples/data/sprite_sets/rune_font_sprite_set_8x16.ghul, examples/data/sprite_sets/sam_new_tiles_32x32.ghul, examples/data/sprite_sets/ultima_IV_font_sprite_set.ghul, examples/data/sprite_sets/ultima_IV_sprite_set.ghul, examples/data/tile_sheet_utils/TileSheet.pm, examples/data/tile_sheet_utils/reformat_tile_sheet.perl, examples/data/types/chest_traps.ghul, examples/data/types/containers.ghul, examples/data/types/magical_fields.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/occupations.ghul, examples/data/types/portal_types.ghul, examples/data/types/projectiles.ghul, examples/data/types/readable_items.ghul, examples/data/types/species.ghul, examples/data/types/spells.ghul, examples/data/types/terrains.ghul, examples/data/types/useable_items.ghul, examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/types/worn_items.ghul, examples/data/world/astronomy.ghul, examples/data/world/portals.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/characters/party_members.ghul, examples/data/world/conversations/conversations.ghul, examples/data/world/maps/M_dark_passage.ghul, examples/data/world/maps/Attic/M_prison_and_torture_chamber.ghul, examples/data/world/maps/M_secret_shrine.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/all_places.ghul, examples/data/world/sounds/cannon.wav, examples/data/world/sounds/damage.wav, examples/data/world/sounds/drum_02.wav, examples/data/world/sounds/enter_moongate.wav, examples/data/world/sounds/fanfare5.wav, examples/data/world/sounds/fanfare7.wav, examples/data/world/sounds/footsteps_1.wav, examples/data/world/sounds/horse.wav, examples/data/world/sounds/rowing-old1.wav, examples/data/world/sounds/rowing.wav, examples/data/world/sounds/walk.wav, src/Arms.cpp, src/Arms.h, src/Container.cpp, src/Container.h, src/Field.h, src/Attic/Item.cpp, src/Attic/Item.h, src/Attic/Loader.cpp, src/Attic/Loader.h, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Reagent.cpp, src/Reagent.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/Attic/Trap.cpp, src/Attic/Trap.h, src/angband.c, src/ascii.c, src/ascii.h, src/astar.c, src/astar.h, src/character.cpp, src/character.h, src/cmdwin.c, src/cmdwin.h, src/combat.c, src/combat.h, src/common.c, src/common.h, src/console.c, src/console.h, src/constants.h, src/conv.c, src/conv.h, src/cursor.cpp, src/cursor.h, src/debug.h, src/dup_constants.h, src/event.c, src/event.h, src/floodfill.c, src/foogod.c, src/foogod.h, src/formation.h, src/Attic/game.c, src/Attic/game.h, src/hash.c, src/hash.h, src/heap.c, src/heap.h, src/images.c, src/images.h, src/knapsack.c, src/knapsack.h, src/Attic/lexer.c, src/Attic/lexer.h, src/list.h, src/los.c, src/los.h, src/map.c, src/map.h, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/object.c, src/object.h, src/occ.c, src/occ.h, src/olist.c, src/olist.h, src/pinfo.h, src/place.c, src/place.h, src/play.c, src/play.h, src/player.cpp, src/player.h, src/Attic/portal.h, src/sched.c, src/sched.h, src/screen.c, src/screen.h, src/sky.c, src/sky.h, src/sound.c, src/sound.h, src/species.c, src/species.h, src/sprite.c, src/sprite.h, src/status.c, src/status.h, src/terrain.c, src/terrain.h, src/terrain_map.c, src/terrain_map.h, src/tree.c, src/tree.h, src/Attic/util.c, src/Attic/util.h, src/vehicle.cpp, src/vehicle.h, src/wind.c, src/wind.h, src/wq.c, src/wq.h:
+       Initial revision
+
+       * COPYING, INSTALL, Makefile.am, Attic/Makefile.in, README, Attic/aclocal.m4, Attic/config.guess, Attic/config.sub, Attic/configure, Attic/configure.in, Attic/install-sh, Attic/missing, Attic/mkinstalldirs, examples/Attic/.console, examples/Makefile.am, examples/Makefile.in, examples/dup_constants.h, examples/Attic/mapfile, examples/data/ALL_GHULFILES, examples/data/Makefile, examples/data/def_constants.ghul, examples/data/def_macros.ghul, examples/data/main.ghul, examples/data/Attic/mapfile, examples/data/types.ghul, examples/data/world.ghul, examples/data/images/angband-16x16.png, examples/data/images/angband-32x32.png, examples/data/images/charset-16x16.png, examples/data/images/charset-8x16.png, examples/data/images/charset-8x16_intra1.png, examples/data/images/charset-8x8.png, examples/data/images/frame.png, examples/data/images/frame_pieces.png, examples/data/images/frame_pieces_2-16x16.png, examples/data/images/images_35x24_intra1.png, examples/data/images/mechanisms.png, examples/data/images/mine-32x32.png, examples/data/images/moons-16x16.png, examples/data/images/rune_font_32x32.png, examples/data/images/rune_font_8x16.png, examples/data/images/sam_32x32_font_template.png, examples/data/images/sam_mechanisms_template.png, examples/data/images/sam_new_tiles_32x32_intra1.png, examples/data/images/shapes-16x16.png, examples/data/images/shapes-32x32.png, examples/data/images/shrine-32x32.png, examples/data/images/splash.png, examples/data/images/u4_enhanced_tiles_32x32.png, examples/data/images/u4_enhanced_tiles_32x32_intra_1.png, examples/data/player/party.ghul, examples/data/sounds/cannon.wav, examples/data/sounds/damage.wav, examples/data/sounds/drum_02.wav, examples/data/sounds/enter_moongate.wav, examples/data/sounds/fanfare5.wav, examples/data/sounds/fanfare7.wav, examples/data/sounds/footsteps_1.wav, examples/data/sounds/horse.wav, examples/data/sounds/rowing-old1.wav, examples/data/sounds/rowing.wav, examples/data/sounds/walk.wav, examples/data/sprite_sets/angband_sprite_set.ghul, examples/data/sprite_sets/frame_sprite_set.ghul, examples/data/sprite_sets/mechanism_sprites.ghul, examples/data/sprite_sets/misc_added_sprite_set.ghul, examples/data/sprite_sets/moons_sprite_set.ghul, examples/data/sprite_sets/rune_font_sprite_set.ghul, examples/data/sprite_sets/rune_font_sprite_set_32x32.ghul, examples/data/sprite_sets/rune_font_sprite_set_8x16.ghul, examples/data/sprite_sets/sam_new_tiles_32x32.ghul, examples/data/sprite_sets/ultima_IV_font_sprite_set.ghul, examples/data/sprite_sets/ultima_IV_sprite_set.ghul, examples/data/tile_sheet_utils/TileSheet.pm, examples/data/tile_sheet_utils/reformat_tile_sheet.perl, examples/data/types/chest_traps.ghul, examples/data/types/containers.ghul, examples/data/types/magical_fields.ghul, examples/data/types/npc_party_defs.ghul, examples/data/types/occupations.ghul, examples/data/types/portal_types.ghul, examples/data/types/projectiles.ghul, examples/data/types/readable_items.ghul, examples/data/types/species.ghul, examples/data/types/spells.ghul, examples/data/types/terrains.ghul, examples/data/types/useable_items.ghul, examples/data/types/vehicles.ghul, examples/data/types/weapons.ghul, examples/data/types/worn_items.ghul, examples/data/world/astronomy.ghul, examples/data/world/portals.ghul, examples/data/world/characters/inhabitants_of_britain.ghul, examples/data/world/characters/party_members.ghul, examples/data/world/conversations/conversations.ghul, examples/data/world/maps/M_dark_passage.ghul, examples/data/world/maps/Attic/M_prison_and_torture_chamber.ghul, examples/data/world/maps/M_secret_shrine.ghul, examples/data/world/maps/terrain_combat_maps.ghul, examples/data/world/mechanisms/all_mechanisms.ghul, examples/data/world/places/all_places.ghul, examples/data/world/sounds/cannon.wav, examples/data/world/sounds/damage.wav, examples/data/world/sounds/drum_02.wav, examples/data/world/sounds/enter_moongate.wav, examples/data/world/sounds/fanfare5.wav, examples/data/world/sounds/fanfare7.wav, examples/data/world/sounds/footsteps_1.wav, examples/data/world/sounds/horse.wav, examples/data/world/sounds/rowing-old1.wav, examples/data/world/sounds/rowing.wav, examples/data/world/sounds/walk.wav, src/Arms.cpp, src/Arms.h, src/Container.cpp, src/Container.h, src/Field.h, src/Attic/Item.cpp, src/Attic/Item.h, src/Attic/Loader.cpp, src/Attic/Loader.h, src/Makefile.am, src/Attic/Makefile.in, src/Attic/Mech.cpp, src/Attic/Mech.h, src/Attic/NpcParty.cpp, src/Attic/NpcParty.h, src/Reagent.cpp, src/Reagent.h, src/Attic/Spell.cpp, src/Attic/Spell.h, src/Attic/Trap.cpp, src/Attic/Trap.h, src/angband.c, src/ascii.c, src/ascii.h, src/astar.c, src/astar.h, src/character.cpp, src/character.h, src/cmdwin.c, src/cmdwin.h, src/combat.c, src/combat.h, src/common.c, src/common.h, src/console.c, src/console.h, src/constants.h, src/conv.c, src/conv.h, src/cursor.cpp, src/cursor.h, src/debug.h, src/dup_constants.h, src/event.c, src/event.h, src/floodfill.c, src/foogod.c, src/foogod.h, src/formation.h, src/Attic/game.c, src/Attic/game.h, src/hash.c, src/hash.h, src/heap.c, src/heap.h, src/images.c, src/images.h, src/knapsack.c, src/knapsack.h, src/Attic/lexer.c, src/Attic/lexer.h, src/list.h, src/los.c, src/los.h, src/map.c, src/map.h, src/Attic/moongate.c, src/Attic/moongate.h, src/nazghul.c, src/object.c, src/object.h, src/occ.c, src/occ.h, src/olist.c, src/olist.h, src/pinfo.h, src/place.c, src/place.h, src/play.c, src/play.h, src/player.cpp, src/player.h, src/Attic/portal.h, src/sched.c, src/sched.h, src/screen.c, src/screen.h, src/sky.c, src/sky.h, src/sound.c, src/sound.h, src/species.c, src/species.h, src/sprite.c, src/sprite.h, src/status.c, src/status.h, src/terrain.c, src/terrain.h, src/terrain_map.c, src/terrain_map.h, src/tree.c, src/tree.h, src/Attic/util.c, src/Attic/util.h, src/vehicle.cpp, src/vehicle.h, src/wind.c, src/wind.h, src/wq.c, src/wq.h:
+       Initial import
+
+       * Makefile.am, Attic/Makefile.in:
+       Fixed top-level Makefile.am to include the doc directory when building the distro tarball.
+
+       * doc/Attic/GAME_DEVELOPERS_GUIDE, doc/GHULSCRIPT, doc/USERS_GUIDE, examples/Attic/.console:
+       Added documentation.
+
+       * examples/Attic/.console:
+       Removed .console.
+
+       * src/play.c:
+       bugfix: mapInit() must go before placeEnter()
diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
index 0000000..f6ba1f3
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,54 @@
+BUILDING AND INSTALLING
+
+Nazghul requires the following libraries:
+
+        SDL-1.2............http://www.libsdl.org
+        libSDL_image-1.2...http://www.libsdl.org/projects/SDL_image/
+        libSDL_image-1.2...http://www.libsdl.org/projects/SDL_mixer/
+        libpng.............http://www.libpng.org/pub/png/libpng.html
+        zlib
+        
+UNIXy systems
+
+The libraries should be available as packages for most systems- you will
+need dev versions of the packages, eg SDL_dev-1.2.deb
+
+To compile and install nazghul from a tarball:
+
+        $ ./configure
+        $ make
+        $ make install
+    
+(If you don't want to install as root then use the --prefix option with
+configure. E.g., ./configure --prefix=$HOME)
+
+To compile and install from a CVS checkout rather than a milestone
+tarball:
+
+        $ ./autogen.sh
+        $ make
+        $ make install
+        
+The --prefix option may be applied to autogen in the same manner as
+configure.
+
+STARTING THE GAME
+
+To run haxima, the game that comes packaged with the engine:
+
+        $ haxima.sh
+
+WIN32
+
+The prebuilt installers should simply be a case of download and click.
+
+Setting up a compilation environment and libraries for a cvs build can
+be more tricky: Detailed instuctions are available in win32/readme.txt
+
+
+TROUBLESHOOTING
+
+Try one of the following resources:
+
+        http://myweb.cableone.net/gmcnutt/faq.html
+        nazghul-users@lists.sourceforge.net
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
new file mode 100644 (file)
index 0000000..d7dfa01
--- /dev/null
@@ -0,0 +1,30 @@
+AUTOMAKE_OPTIONS = dist-shar dist-zip dist-tarZ
+
+SUBDIRS = src worlds m4
+
+DIST_SUBDIRS = $(SUBDIRS)
+
+EXTRA_DIST = doc icons haxima.desktop
+
+ACLOCAL_AMFLAGS = -I m4
+
+@MAINT@alldist:
+@MAINT@        ${MAKE} distcheck
+@MAINT@        ${MAKE} dist-shar
+@MAINT@        ${MAKE} dist-zip
+@MAINT@        ${MAKE} dist-tarZ
+
+MAINTAINERCLEANFILES = configure Makefile.in aclocal.m4 config.h.in \
+               config.guess config.sub depcomp install-sh \
+               missing mkinstalldirs
+
+@MAINT@cvsclean: maintainer-clean
+@MAINT@        @-rm -f `find . -name Makefile.in`
+@MAINT@        @-rm -f libtool ltmain.sh acinclude.m4 */Makefile.in
+@MAINT@        @-rm -f configure aclocal.m4 config.h.in stamp-h.in depcomp ylwrap
+@MAINT@        @-rm -f config.guess config.sub config.cache config.log config.status
+@MAINT@        @-rm -f mkinstalldirs missing install-sh COPYING ABOUT-NLS config.rpath
+@MAINT@        @-rm -fr @PACKAGE@-@VERSION@* *~ */*~
+@MAINT@        @echo "================================================="
+@MAINT@        @echo "Don't forget your ChangeLog and NEWS entries ...."
+@MAINT@        @echo "================================================="
diff --git a/Makefile.in b/Makefile.in
new file mode 100644 (file)
index 0000000..48de57d
--- /dev/null
@@ -0,0 +1,726 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = .
+DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
+       $(srcdir)/Makefile.in $(srcdir)/config.h.in \
+       $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
+       config.guess config.sub depcomp install-sh missing
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
+ configure.lineno config.status.lineno
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-dvi-recursive install-exec-recursive \
+       install-html-recursive install-info-recursive \
+       install-pdf-recursive install-ps-recursive install-recursive \
+       installcheck-recursive installdirs-recursive pdf-recursive \
+       ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+       $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+       distdir dist dist-all distcheck
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+distdir = $(PACKAGE)-$(VERSION)
+top_distdir = $(distdir)
+am__remove_distdir = \
+  { test ! -d "$(distdir)" \
+    || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \
+         && rm -fr "$(distdir)"; }; }
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.Z $(distdir).shar.gz \
+       $(distdir).zip
+GZIP_ENV = --best
+distuninstallcheck_listfiles = find . -type f -print
+distcleancheck_listfiles = find . -type f -print
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AUTOMAKE_OPTIONS = dist-shar dist-zip dist-tarZ
+SUBDIRS = src worlds m4
+DIST_SUBDIRS = $(SUBDIRS)
+EXTRA_DIST = doc icons haxima.desktop
+ACLOCAL_AMFLAGS = -I m4
+MAINTAINERCLEANFILES = configure Makefile.in aclocal.m4 config.h.in \
+               config.guess config.sub depcomp install-sh \
+               missing mkinstalldirs
+
+all: config.h
+       $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+am--refresh:
+       @:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             echo ' cd $(srcdir) && $(AUTOMAKE) --gnu'; \
+             $(am__cd) $(srcdir) && $(AUTOMAKE) --gnu \
+               && exit 0; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           echo ' $(SHELL) ./config.status'; \
+           $(SHELL) ./config.status;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       $(SHELL) ./config.status --recheck
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       $(am__cd) $(srcdir) && $(AUTOCONF)
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+$(am__aclocal_m4_deps):
+
+config.h: stamp-h1
+       @if test ! -f $@; then \
+         rm -f stamp-h1; \
+         $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+       else :; fi
+
+stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
+       @rm -f stamp-h1
+       cd $(top_builddir) && $(SHELL) ./config.status config.h
+$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+       ($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+       rm -f stamp-h1
+       touch $@
+
+distclean-hdr:
+       -rm -f config.h stamp-h1
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @fail= failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+       @fail= failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       $(am__remove_distdir)
+       test -d "$(distdir)" || mkdir "$(distdir)"
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(MKDIR_P) "$(distdir)/$$subdir" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+           $(am__relativize); \
+           new_distdir=$$reldir; \
+           dir1=$$subdir; dir2="$(top_distdir)"; \
+           $(am__relativize); \
+           new_top_distdir=$$reldir; \
+           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+           ($(am__cd) $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$new_top_distdir" \
+               distdir="$$new_distdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               am__skip_mode_fix=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+       -test -n "$(am__skip_mode_fix)" \
+       || find "$(distdir)" -type d ! -perm -755 \
+               -exec chmod u+rwx,go+rx {} \; -o \
+         ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -400 -exec chmod a+r {} \; -o \
+         ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \
+       || chmod -R a+r "$(distdir)"
+dist-gzip: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       $(am__remove_distdir)
+
+dist-bzip2: distdir
+       tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2
+       $(am__remove_distdir)
+
+dist-lzma: distdir
+       tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma
+       $(am__remove_distdir)
+
+dist-xz: distdir
+       tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz
+       $(am__remove_distdir)
+dist-tarZ: distdir
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       $(am__remove_distdir)
+dist-shar: distdir
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       $(am__remove_distdir)
+dist-zip: distdir
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+dist dist-all: distdir
+       tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz
+       tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
+       shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
+       -rm -f $(distdir).zip
+       zip -rq $(distdir).zip $(distdir)
+       $(am__remove_distdir)
+
+# This target untars the dist file and tries a VPATH configuration.  Then
+# it guarantees that the distribution is self-contained by making another
+# tarfile.
+distcheck: dist
+       case '$(DIST_ARCHIVES)' in \
+       *.tar.gz*) \
+         GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\
+       *.tar.bz2*) \
+         bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\
+       *.tar.lzma*) \
+         lzma -dc $(distdir).tar.lzma | $(am__untar) ;;\
+       *.tar.xz*) \
+         xz -dc $(distdir).tar.xz | $(am__untar) ;;\
+       *.tar.Z*) \
+         uncompress -c $(distdir).tar.Z | $(am__untar) ;;\
+       *.shar.gz*) \
+         GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\
+       *.zip*) \
+         unzip $(distdir).zip ;;\
+       esac
+       chmod -R a-w $(distdir); chmod a+w $(distdir)
+       mkdir $(distdir)/_build
+       mkdir $(distdir)/_inst
+       chmod a-w $(distdir)
+       test -d $(distdir)/_build || exit 0; \
+       dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
+         && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+         && am__cwd=`pwd` \
+         && $(am__cd) $(distdir)/_build \
+         && ../configure --srcdir=.. --prefix="$$dc_install_base" \
+           $(DISTCHECK_CONFIGURE_FLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) \
+         && $(MAKE) $(AM_MAKEFLAGS) dvi \
+         && $(MAKE) $(AM_MAKEFLAGS) check \
+         && $(MAKE) $(AM_MAKEFLAGS) install \
+         && $(MAKE) $(AM_MAKEFLAGS) installcheck \
+         && $(MAKE) $(AM_MAKEFLAGS) uninstall \
+         && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \
+               distuninstallcheck \
+         && chmod -R a-w "$$dc_install_base" \
+         && ({ \
+              (cd ../.. && umask 077 && mkdir "$$dc_destdir") \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \
+              && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \
+                   distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \
+             } || { rm -rf "$$dc_destdir"; exit 1; }) \
+         && rm -rf "$$dc_destdir" \
+         && $(MAKE) $(AM_MAKEFLAGS) dist \
+         && rm -rf $(DIST_ARCHIVES) \
+         && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \
+         && cd "$$am__cwd" \
+         || exit 1
+       $(am__remove_distdir)
+       @(echo "$(distdir) archives ready for distribution: "; \
+         list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \
+         sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x'
+distuninstallcheck:
+       @$(am__cd) '$(distuninstallcheck_dir)' \
+       && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \
+          || { echo "ERROR: files left after uninstall:" ; \
+               if test -n "$(DESTDIR)"; then \
+                 echo "  (check DESTDIR support)"; \
+               fi ; \
+               $(distuninstallcheck_listfiles) ; \
+               exit 1; } >&2
+distcleancheck: distclean
+       @if test '$(srcdir)' = . ; then \
+         echo "ERROR: distcleancheck can only run from a VPATH build" ; \
+         exit 1 ; \
+       fi
+       @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \
+         || { echo "ERROR: files left in build directory after distclean:" ; \
+              $(distcleancheck_listfiles) ; \
+              exit 1; } >&2
+check-am: all-am
+check: check-recursive
+all-am: Makefile config.h
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-hdr distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f $(am__CONFIG_DISTCLEAN_FILES)
+       -rm -rf $(top_srcdir)/autom4te.cache
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all \
+       ctags-recursive install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+       all all-am am--refresh check check-am clean clean-generic \
+       ctags ctags-recursive dist dist-all dist-bzip2 dist-gzip \
+       dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \
+       distclean distclean-generic distclean-hdr distclean-tags \
+       distcleancheck distdir distuninstallcheck dvi dvi-am html \
+       html-am info info-am install install-am install-data \
+       install-data-am install-dvi install-dvi-am install-exec \
+       install-exec-am install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs installdirs-am maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+       pdf-am ps ps-am tags tags-recursive uninstall uninstall-am
+
+
+@MAINT@alldist:
+@MAINT@        ${MAKE} distcheck
+@MAINT@        ${MAKE} dist-shar
+@MAINT@        ${MAKE} dist-zip
+@MAINT@        ${MAKE} dist-tarZ
+
+@MAINT@cvsclean: maintainer-clean
+@MAINT@        @-rm -f `find . -name Makefile.in`
+@MAINT@        @-rm -f libtool ltmain.sh acinclude.m4 */Makefile.in
+@MAINT@        @-rm -f configure aclocal.m4 config.h.in stamp-h.in depcomp ylwrap
+@MAINT@        @-rm -f config.guess config.sub config.cache config.log config.status
+@MAINT@        @-rm -f mkinstalldirs missing install-sh COPYING ABOUT-NLS config.rpath
+@MAINT@        @-rm -fr @PACKAGE@-@VERSION@* *~ */*~
+@MAINT@        @echo "================================================="
+@MAINT@        @echo "Don't forget your ChangeLog and NEWS entries ...."
+@MAINT@        @echo "================================================="
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/NEWS b/NEWS
new file mode 100644 (file)
index 0000000..a86a5b4
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,257 @@
+Changes between 0.7.0 and 0.7.1
+o Fixed c++ compile warnings (g++ (GCC) 4.4.4 20100630 (Red Hat 4.4.4-10))
+o Fixed missing libpng DLL in win32 release
+Changes between 0.6.0 and 0.7.0
+Engine
+o Y)use command for skills
+o Quest log in the Z)stats pane
+o Intro scene
+o Misc bugfixes
+Haxima
+o Music
+o Warritrix quest resolved
+o Wilderness spawns slightly more challenging
+o Smoke bombs
+o Misc bugfixes
+Changes between 0.5.6 and 0.6.0
+Engine
+o Detailed speed handling added
+o Backend support for multiple actions per turn
+o Better support for diagonal movement
+o Terrains can now have partial opacity
+o Backend support for skills- wrogue skills added, but not enabled yet
+o Enhanced weapon callbacks and behaviour
+o Enhancements to the built in map editor
+o Better support for script/engine integration via script defined engine variables
+o Revisions to Zstats screens
+o Improved npc party behaviour when player is camping
+o Fixed: Memory leaks are hopefully all cleaned up now
+o New effects: smoke, beam attacks
+o Fixed: several crashes
+o Objects are not dropped on water or air
+Module
+o New spells
+o Random dungeon code generalized, new random dungeons added
+o More movement types added, to distinguish fast creatures from merely fast-moving ones
+o New items, weapons and shopping options
+o Equipment now affects character speed
+o Fixes and additions to conversations
+o Fixed: problems with porcullises not working
+o Visibly distinguishable moons
+o Burning glass maze fairer
+o Characters will no longer voluntarily walk off cliffs (chasm terrain now only selectively lethal))
+o Improved hidden map behaviour
+o Many spellbooks added and distributed
+o Several tweaks to combat balance
+o Fixed: problems entering places diagonally
+o More sprites
+o More hires terrains, directional 'natural rock' walls
+o First pass at a template for new games (now out of date already, sigh)
+o Vehicle combat maps upgraded
+o Various minor bugfixes
+
+Changes between nazghul 0.5.6 and 0.5.5:
+o Fixed: crash when dying upon exit from tutorial cave
+o Fixed: various minor bug-fixes
+
+Changes between nazghul 0.5.5 and 0.5.4:
+Kernel changes:
+o SAVED GAMES FROM PREVIOUS VERSIONS BROKEN! (sorry)
+o Support for smaller displays
+o Multiple saved games supported (with screenshots)
+o Colorized text
+o Character stats affect spell outcomes
+o Character stats have more effect on combat
+o Character and global effects now shown as icons instead of letter codes
+o U)sed and R)eadied items moved to top of list for quicker access next time
+o Mouse targeting
+o New settings menu to turn sound off and change the screen size
+o Better error handling if init script cannot be found
+o Missiles handle line-of-fire better when standing next to corners
+o Support for large icons on big critter (sorry, not multi-tile yet)
+o Disable '>' when standing over a town to prevent abuse
+o M)ix command now shows how many of that spell are already mixed
+o Spell inventory shows icons and stats about spell
+o Bugfixes
+Haxima changesL
+o Reduced most reagent and consumable prices
+o Undead immune to sleep and kill spells
+o Boss dude at end of game immune to charm
+o Some new spells
+o Some new quests and dungeons
+o Lots of new sprites
+o Simple character creation at start of game
+o New in-game objects: clocks, mirrors, watches, bookshelf, caltrops, viles of
+  slime (fun!) and a spell book
+o New NPCs: ratlings, sludge kraken, griffins and carybids
+o Better flee algorithm for NPCs who have had enough
+o Doors may be trapped like chests; multiple traps may be applied
+o S)earching chests or doors might detect a trap, or might set one off
+o Sextant and In Wis both report location as [x=<x> y=<y>]
+o When party members leave they U)nready their equipment and give it back
+o Mesmeme now has prismatic gaze, making him somewhat useful in combat
+o You can name your ships
+o Some new characters
+o Bugfixes
+
+Changes between nazghul 0.5.3 and nazghul 0.5.4:
+o Blended terrain [1]
+o Misc. improved sprites
+o Fixes for: spinning arrows on ground, S rune visibility, "dropped" key
+  presses, solo mode/rendezvous abuse, fire slimes dividing into green slimes,
+  immobile critters, misc. spelling/grammar, party mode + save game abuse, solo
+  moded + posession lockup, Alchemist's lich quest, invisibility scrolls not
+  getting consumed when used, extra ship on town entry bug, wind not updated on
+  load bug, t)alk targeting invisible people abuse, missing Abigail character
+  [1], misc. haxima plot fixes, misc. other
+o Minor limited tweaks to some weapon stats
+o Reagents a lot cheaper now
+o New bottom level of Kurpolis (warning: evil) [1]
+o Demons immune to kill spell
+o Improved pathfinding performance
+o Fixes for 64bit compilation
+o Added sextants
+[1] Changes not applicable with previous saved games
+
+
+Changes between nazghul 0.5.2 and nazghul 0.5.3:
+o Bugfix: assert in status.c after disarmed or acid dissolves readied 
+o New sprites: gint mage, tower, activated altar, PC's, goblins, transparent
+  moon sprites
+o Balance: fireballs no longer drop fire fields where they 
+o Bugfix: hydra's weren't appearing on wilderness combat maps
+o Bugfix: pirate ships spawning in Fens
+o Bugfix: dragons, hydras, lichs and spiders dropped some loot in wilderness
+o Accursed loot
+o Accursed Templar and Roland use human knight sprite
+o Fire slimes drop flaming oils
+o "Normal" UNIX-style installation for source distros
+o New commandline -I (game data dir) and -G (save game dir) options
+o Fixed Gregor and Tooth's sleeping locations
+o Disarm now drops the target's weapon on the ground at his feet
+o Bugfix: nazghul junk (where junk was not a valid load file) caused a segfault
+o G)et now always scoops up everything
+o Bugfix: after leaving, Roland and Kama couldn't rejoin
+o Tweaked armour defense, prices
+o Bugfix: troll loot not using 
+o Added eclipse and improved moon phases
+o Fixed many plural names
+o Drunken staggering doesn't swap
+o Opening sequence tweaks
+
+Changes between nazghul 0.5.1 and nazghul 0.5.2:
+o Bugfix: purchasing a cure service from a healer didn't work
+o Bugfix: when zoomed out, transparency shows up as magenta
+o Bugfix: spawn points in Fun with Levers weren't getting triggered
+o Bugfix: canceling u)se scroll was using up scroll
+o Bugfix  NPC parties getting into towns and dungeons
+o Bugfix: Kathryn not giving player her Wis Quas scroll upon join
+o Bugfix: ladder up from Dank Cave led to wrong location
+o Bugfix: Bole's inn-room door was not being locked on town re-entry
+o Bugfix: dryads in combat/town maps would walk
+o Bugfix: when t)alking and a person was nearby, target origin started on
+  person instead of player
+o Bugfix: g)et didn't work with Runes on the ground
+o Bugfix: selling itesm - list updated improperly. Actually, list was just
+  getting built improperly from the get-go.
+o Bugfix: kathryn's letter was defined in kathryn.scm, which might not be
+  loaded before the letter is referenced in the script.
+o Bugfix: found a part of the wilderness map that was incorrectly impassable
+o Bugfix: old entrance to slimy cavern still in moongate clearing
+o Bugfix: +4 iron helm stats were wrong
+o Ctrl-Q now means "quit without saving"
+o Ctrl-S now means "save without quitting"
+o Command-line options changed
+o Increased dragon HP
+o Changed quit-without-saving keybinding from ctrl-Q to ctrl-S
+o Casting spells now gives XP
+o Doubled XP required for level advancement
+o Removed unthiefly treasure from Thief's Den
+o New sprites: rune stones, human knight, shop signs
+o Added transparency to all sprites
+o New NPC type: fire slimes
+o NPC's no longer drop loot on the wilderness map
+o Gen buffed up
+
+Changes between nazghul 0.5.0 and 0.5.1:
+o Bugfix: some spells like In Ex Por would be
+  consumed even if the player aborted without
+  selecting a target (In Sanct, Sanct and An Ex
+  Por were also affected)
+o Bugfix: searching corpses from saved games
+  sometimes caused script errors
+o Bugfix: if Kathrn in party but Thud alive and
+  not in party, crash when player encounters the
+  Mouse
+o Bugfix: error in the script when the Necromancer
+  summoned Luximene.
+o Bugfix: if a party member died it's readied
+  items were lost.
+o Bugfix: moongate near Glasdrin was positioned
+  over an impassable mountain
+o Bugfix: spider's sometimes dropped piles of
+  spider silk with zero (0) objects in them
+o Bugfix: cannon-killing a large gint party cuased
+  a crash
+o Bugfix: shroom's trade conv broken
+o Bugfix: NPC pirates caused bad save file
+
+Major changes between nazghul 0.5.0 and 0.4.0:
+
+Haxima changes:
+o Haxima is now a complete game.
+o Wilderness map
+o Several towns
+o Several dungeons
+o A main quest which can be completed
+o Several side quests
+
+Kernel changes:
+o NPC target highlighting shows friends and foes
+o Attack command autotargets nearest foe
+o Talk command autotargets nearest object with a conversation
+o Main menu added
+
+Changes between nazghul 0.3.3 and 0.4.0:
+
+Haxima changes:
+o Fixed the sprite for the eldritch blade
+o Trolls can pick up boulders
+o Improved NPC taunts
+o Improved various NPC conversations
+o Rebalanced some weapons and armor
+o Improved performance in crowded places
+o Added monster generators in Lost Halls
+o Characters can climb over boulders at some 
+  risk of falling off
+o Bugfix: inn prices lower than advertised
+o Bugfix: occupied doors should stay open
+o Bugfix: opening troll corpse in Abandoned Cellar
+o Started a new town: the Enchanter's Tower
+o Added a few new spells (undocumented - talk to 
+  NPC's to discover them)
+o Feat request: Shopkeepers tell you what time 
+  they open
+o Feat request: ESC exits combat when done (note: 
+  '<' already did)
+o Feat request: resurrected characters should be 
+  asleep
+o Feat request: automatically open doors when 
+  walking into them
+o Misc new objects, terrains and the odd NPC 
+  character
+
+Kernel changes:
+o Fixed several crashes that occurred  on reload
+o Andreas Bauer improved the configure and build 
+  system(now GNU-compliant)
+o Bugfix: crash when using picklocks on objects
+o Bugfix: setting a watch in camp means certain 
+  death
+o Added "fill" command (f key) to terrain editor
+o Added "copy' command (c key) to terrain editor
+o Bugfix: camping procedure corrupted (crash)
+o Bugfix: crash when a Character's target is 
+  killed by someone else
+o Bugfix: NPC bow "vanishes" when they run out of
+  arrows
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..dfd826e
--- /dev/null
+++ b/README
@@ -0,0 +1,2 @@
+See INSTALL for instructions on building, installing and starting the game. See
+doc/USERS_GUIDE for detailed instructions on playing the game.
diff --git a/aclocal.m4 b/aclocal.m4
new file mode 100644 (file)
index 0000000..7c09da1
--- /dev/null
@@ -0,0 +1,1005 @@
+# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2007, 2008, 2009  Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.63],,
+[m4_warning([this file was generated for autoconf 2.63.
+You have another version of autoconf.  It may work, but is not guaranteed to.
+If you have problems, you may need to regenerate the build system entirely.
+To do so, use the procedure documented by the package, typically `autoreconf'.])])
+
+# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_AUTOMAKE_VERSION(VERSION)
+# ----------------------------
+# Automake X.Y traces this macro to ensure aclocal.m4 has been
+# generated from the m4 files accompanying Automake X.Y.
+# (This private macro should not be called outside this file.)
+AC_DEFUN([AM_AUTOMAKE_VERSION],
+[am__api_version='1.11'
+dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
+dnl require some minimum version.  Point them to the right macro.
+m4_if([$1], [1.11.1], [],
+      [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
+])
+
+# _AM_AUTOCONF_VERSION(VERSION)
+# -----------------------------
+# aclocal traces this macro to find the Autoconf version.
+# This is a private macro too.  Using m4_define simplifies
+# the logic in aclocal, which can simply ignore this definition.
+m4_define([_AM_AUTOCONF_VERSION], [])
+
+# AM_SET_CURRENT_AUTOMAKE_VERSION
+# -------------------------------
+# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
+# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
+AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
+[AM_AUTOMAKE_VERSION([1.11.1])dnl
+m4_ifndef([AC_AUTOCONF_VERSION],
+  [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
+_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
+
+# AM_AUX_DIR_EXPAND                                         -*- Autoconf -*-
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
+# $ac_aux_dir to `$srcdir/foo'.  In other projects, it is set to
+# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
+#
+# Of course, Automake must honor this variable whenever it calls a
+# tool from the auxiliary directory.  The problem is that $srcdir (and
+# therefore $ac_aux_dir as well) can be either absolute or relative,
+# depending on how configure is run.  This is pretty annoying, since
+# it makes $ac_aux_dir quite unusable in subdirectories: in the top
+# source directory, any form will work fine, but in subdirectories a
+# relative path needs to be adjusted first.
+#
+# $ac_aux_dir/missing
+#    fails when called from a subdirectory if $ac_aux_dir is relative
+# $top_srcdir/$ac_aux_dir/missing
+#    fails if $ac_aux_dir is absolute,
+#    fails when called from a subdirectory in a VPATH build with
+#          a relative $ac_aux_dir
+#
+# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
+# are both prefixed by $srcdir.  In an in-source build this is usually
+# harmless because $srcdir is `.', but things will broke when you
+# start a VPATH build or use an absolute $srcdir.
+#
+# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
+# iff we strip the leading $srcdir from $ac_aux_dir.  That would be:
+#   am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
+# and then we would define $MISSING as
+#   MISSING="\${SHELL} $am_aux_dir/missing"
+# This will work as long as MISSING is not called from configure, because
+# unfortunately $(top_srcdir) has no meaning in configure.
+# However there are other variables, like CC, which are often used in
+# configure, and could therefore not use this "fixed" $ac_aux_dir.
+#
+# Another solution, used here, is to always expand $ac_aux_dir to an
+# absolute PATH.  The drawback is that using absolute paths prevent a
+# configured tree to be moved without reconfiguration.
+
+AC_DEFUN([AM_AUX_DIR_EXPAND],
+[dnl Rely on autoconf to set up CDPATH properly.
+AC_PREREQ([2.50])dnl
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+])
+
+# AM_CONDITIONAL                                            -*- Autoconf -*-
+
+# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 9
+
+# AM_CONDITIONAL(NAME, SHELL-CONDITION)
+# -------------------------------------
+# Define a conditional.
+AC_DEFUN([AM_CONDITIONAL],
+[AC_PREREQ(2.52)dnl
+ ifelse([$1], [TRUE],  [AC_FATAL([$0: invalid condition: $1])],
+       [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
+AC_SUBST([$1_TRUE])dnl
+AC_SUBST([$1_FALSE])dnl
+_AM_SUBST_NOTMAKE([$1_TRUE])dnl
+_AM_SUBST_NOTMAKE([$1_FALSE])dnl
+m4_define([_AM_COND_VALUE_$1], [$2])dnl
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi
+AC_CONFIG_COMMANDS_PRE(
+[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
+  AC_MSG_ERROR([[conditional "$1" was never defined.
+Usually this means the macro was only invoked conditionally.]])
+fi])])
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 10
+
+# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be
+# written in clear, in which case automake, when reading aclocal.m4,
+# will think it sees a *use*, and therefore will trigger all it's
+# C support machinery.  Also note that it means that autoscan, seeing
+# CC etc. in the Makefile, will ask for an AC_PROG_CC use...
+
+
+# _AM_DEPENDENCIES(NAME)
+# ----------------------
+# See how the compiler implements dependency checking.
+# NAME is "CC", "CXX", "GCJ", or "OBJC".
+# We try a few techniques and use that to set a single cache variable.
+#
+# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was
+# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular
+# dependency, and given that the user is not expected to run this macro,
+# just rely on AC_PROG_CC.
+AC_DEFUN([_AM_DEPENDENCIES],
+[AC_REQUIRE([AM_SET_DEPDIR])dnl
+AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl
+AC_REQUIRE([AM_MAKE_INCLUDE])dnl
+AC_REQUIRE([AM_DEP_TRACK])dnl
+
+ifelse([$1], CC,   [depcc="$CC"   am_compiler_list=],
+       [$1], CXX,  [depcc="$CXX"  am_compiler_list=],
+       [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'],
+       [$1], UPC,  [depcc="$UPC"  am_compiler_list=],
+       [$1], GCJ,  [depcc="$GCJ"  am_compiler_list='gcc3 gcc'],
+                   [depcc="$$1"   am_compiler_list=])
+
+AC_CACHE_CHECK([dependency style of $depcc],
+               [am_cv_$1_dependencies_compiler_type],
+[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_$1_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp`
+  fi
+  am__universal=false
+  m4_case([$1], [CC],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac],
+    [CXX],
+    [case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac])
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_$1_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_$1_dependencies_compiler_type=none
+fi
+])
+AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type])
+AM_CONDITIONAL([am__fastdep$1], [
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_$1_dependencies_compiler_type" = gcc3])
+])
+
+
+# AM_SET_DEPDIR
+# -------------
+# Choose a directory name for dependency files.
+# This macro is AC_REQUIREd in _AM_DEPENDENCIES
+AC_DEFUN([AM_SET_DEPDIR],
+[AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl
+])
+
+
+# AM_DEP_TRACK
+# ------------
+AC_DEFUN([AM_DEP_TRACK],
+[AC_ARG_ENABLE(dependency-tracking,
+[  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors])
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno])
+AC_SUBST([AMDEPBACKSLASH])dnl
+_AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl
+])
+
+# Generate code to set up dependency tracking.              -*- Autoconf -*-
+
+# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+#serial 5
+
+# _AM_OUTPUT_DEPENDENCY_COMMANDS
+# ------------------------------
+AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS],
+[{
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`AS_DIRNAME("$mf")`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`AS_DIRNAME(["$file"])`
+      AS_MKDIR_P([$dirpart/$fdir])
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+])# _AM_OUTPUT_DEPENDENCY_COMMANDS
+
+
+# AM_OUTPUT_DEPENDENCY_COMMANDS
+# -----------------------------
+# This macro should only be invoked once -- use via AC_REQUIRE.
+#
+# This code is only required when automatic dependency tracking
+# is enabled.  FIXME.  This creates each `.P' file that we will
+# need in order to bootstrap the dependency handling code.
+AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS],
+[AC_CONFIG_COMMANDS([depfiles],
+     [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS],
+     [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"])
+])
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 8
+
+# AM_CONFIG_HEADER is obsolete.  It has been replaced by AC_CONFIG_HEADERS.
+AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)])
+
+# Do all the work for Automake.                             -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 16
+
+# This macro actually does too much.  Some checks are only needed if
+# your package does certain things.  But this isn't really a big deal.
+
+# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
+# AM_INIT_AUTOMAKE([OPTIONS])
+# -----------------------------------------------
+# The call with PACKAGE and VERSION arguments is the old style
+# call (pre autoconf-2.50), which is being phased out.  PACKAGE
+# and VERSION should now be passed to AC_INIT and removed from
+# the call to AM_INIT_AUTOMAKE.
+# We support both call styles for the transition.  After
+# the next Automake release, Autoconf can make the AC_INIT
+# arguments mandatory, and then we can depend on a new Autoconf
+# release and drop the old call support.
+AC_DEFUN([AM_INIT_AUTOMAKE],
+[AC_PREREQ([2.62])dnl
+dnl Autoconf wants to disallow AM_ names.  We explicitly allow
+dnl the ones we care about.
+m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
+AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
+AC_REQUIRE([AC_PROG_INSTALL])dnl
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+AC_SUBST([CYGPATH_W])
+
+# Define the identity of the package.
+dnl Distinguish between old-style and new-style calls.
+m4_ifval([$2],
+[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
+ AC_SUBST([PACKAGE], [$1])dnl
+ AC_SUBST([VERSION], [$2])],
+[_AM_SET_OPTIONS([$1])dnl
+dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
+m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
+  [m4_fatal([AC_INIT should be called with package and version arguments])])dnl
+ AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
+ AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
+
+_AM_IF_OPTION([no-define],,
+[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
+ AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
+
+# Some tools Automake needs.
+AC_REQUIRE([AM_SANITY_CHECK])dnl
+AC_REQUIRE([AC_ARG_PROGRAM])dnl
+AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
+AM_MISSING_PROG(AUTOCONF, autoconf)
+AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
+AM_MISSING_PROG(AUTOHEADER, autoheader)
+AM_MISSING_PROG(MAKEINFO, makeinfo)
+AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
+AC_REQUIRE([AM_PROG_MKDIR_P])dnl
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+AC_REQUIRE([AC_PROG_AWK])dnl
+AC_REQUIRE([AC_PROG_MAKE_SET])dnl
+AC_REQUIRE([AM_SET_LEADING_DOT])dnl
+_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
+             [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
+                            [_AM_PROG_TAR([v7])])])
+_AM_IF_OPTION([no-dependencies],,
+[AC_PROVIDE_IFELSE([AC_PROG_CC],
+                 [_AM_DEPENDENCIES(CC)],
+                 [define([AC_PROG_CC],
+                         defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_CXX],
+                 [_AM_DEPENDENCIES(CXX)],
+                 [define([AC_PROG_CXX],
+                         defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
+AC_PROVIDE_IFELSE([AC_PROG_OBJC],
+                 [_AM_DEPENDENCIES(OBJC)],
+                 [define([AC_PROG_OBJC],
+                         defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
+])
+_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
+dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
+dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This macro
+dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
+AC_CONFIG_COMMANDS_PRE(dnl
+[m4_provide_if([_AM_COMPILER_EXEEXT],
+  [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
+])
+
+dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
+dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
+dnl mangled by Autoconf and run in a shell conditional statement.
+m4_define([_AC_COMPILER_EXEEXT],
+m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
+
+
+# When config.status generates a header, we must update the stamp-h file.
+# This file resides in the same directory as the config header
+# that is generated.  The stamp files are numbered to have different names.
+
+# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
+# loop where config.status creates the headers, so we can generate
+# our stamp files there.
+AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
+[# Compute $1's index in $config_headers.
+_am_arg=$1
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
+
+# Copyright (C) 2001, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_SH
+# ------------------
+# Define $install_sh.
+AC_DEFUN([AM_PROG_INSTALL_SH],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+AC_SUBST(install_sh)])
+
+# Copyright (C) 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# Check whether the underlying file-system supports filenames
+# with a leading dot.  For instance MS-DOS doesn't.
+AC_DEFUN([AM_SET_LEADING_DOT],
+[rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+AC_SUBST([am__leading_dot])])
+
+# Add --enable-maintainer-mode option to configure.         -*- Autoconf -*-
+# From Jim Meyering
+
+# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_MAINTAINER_MODE([DEFAULT-MODE])
+# ----------------------------------
+# Control maintainer-specific portions of Makefiles.
+# Default is to disable them, unless `enable' is passed literally.
+# For symmetry, `disable' may be passed as well.  Anyway, the user
+# can override the default with the --enable/--disable switch.
+AC_DEFUN([AM_MAINTAINER_MODE],
+[m4_case(m4_default([$1], [disable]),
+       [enable], [m4_define([am_maintainer_other], [disable])],
+       [disable], [m4_define([am_maintainer_other], [enable])],
+       [m4_define([am_maintainer_other], [enable])
+        m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
+AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
+  dnl maintainer-mode's default is 'disable' unless 'enable' is passed
+  AC_ARG_ENABLE([maintainer-mode],
+[  --][am_maintainer_other][-maintainer-mode  am_maintainer_other make rules and dependencies not useful
+                         (and sometimes confusing) to the casual installer],
+      [USE_MAINTAINER_MODE=$enableval],
+      [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
+  AC_MSG_RESULT([$USE_MAINTAINER_MODE])
+  AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
+  MAINT=$MAINTAINER_MODE_TRUE
+  AC_SUBST([MAINT])dnl
+]
+)
+
+AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
+
+# Check to see how 'make' treats includes.                 -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2009  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# AM_MAKE_INCLUDE()
+# -----------------
+# Check to see how make treats includes.
+AC_DEFUN([AM_MAKE_INCLUDE],
+[am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+AC_MSG_CHECKING([for style of include used by $am_make])
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+AC_SUBST([am__include])
+AC_SUBST([am__quote])
+AC_MSG_RESULT([$_am_result])
+rm -f confinc confmf
+])
+
+# Fake the existence of programs that GNU maintainers use.  -*- Autoconf -*-
+
+# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 6
+
+# AM_MISSING_PROG(NAME, PROGRAM)
+# ------------------------------
+AC_DEFUN([AM_MISSING_PROG],
+[AC_REQUIRE([AM_MISSING_HAS_RUN])
+$1=${$1-"${am_missing_run}$2"}
+AC_SUBST($1)])
+
+
+# AM_MISSING_HAS_RUN
+# ------------------
+# Define MISSING if not defined so far and test if it supports --run.
+# If it does, set am_missing_run to use it, otherwise, to nothing.
+AC_DEFUN([AM_MISSING_HAS_RUN],
+[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
+AC_REQUIRE_AUX_FILE([missing])dnl
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  AC_MSG_WARN([`missing' script is too old or missing])
+fi
+])
+
+# Copyright (C) 2003, 2004, 2005, 2006  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_MKDIR_P
+# ---------------
+# Check for `mkdir -p'.
+AC_DEFUN([AM_PROG_MKDIR_P],
+[AC_PREREQ([2.60])dnl
+AC_REQUIRE([AC_PROG_MKDIR_P])dnl
+dnl Automake 1.8 to 1.9.6 used to define mkdir_p.  We now use MKDIR_P,
+dnl while keeping a definition of mkdir_p for backward compatibility.
+dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
+dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
+dnl Makefile.ins that do not define MKDIR_P, so we do our own
+dnl adjustment using top_builddir (which is defined more often than
+dnl MKDIR_P).
+AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
+case $mkdir_p in
+  [[\\/$]]* | ?:[[\\/]]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+])
+
+# Helper functions for option handling.                     -*- Autoconf -*-
+
+# Copyright (C) 2001, 2002, 2003, 2005, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 4
+
+# _AM_MANGLE_OPTION(NAME)
+# -----------------------
+AC_DEFUN([_AM_MANGLE_OPTION],
+[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
+
+# _AM_SET_OPTION(NAME)
+# ------------------------------
+# Set option NAME.  Presently that only means defining a flag for this option.
+AC_DEFUN([_AM_SET_OPTION],
+[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
+
+# _AM_SET_OPTIONS(OPTIONS)
+# ----------------------------------
+# OPTIONS is a space-separated list of Automake options.
+AC_DEFUN([_AM_SET_OPTIONS],
+[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
+
+# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
+# -------------------------------------------
+# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
+AC_DEFUN([_AM_IF_OPTION],
+[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
+
+# Check to make sure that the build environment is sane.    -*- Autoconf -*-
+
+# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
+# Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 5
+
+# AM_SANITY_CHECK
+# ---------------
+AC_DEFUN([AM_SANITY_CHECK],
+[AC_MSG_CHECKING([whether build environment is sane])
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[[\\\"\#\$\&\'\`$am_lf]]*)
+    AC_MSG_ERROR([unsafe absolute working directory name]);;
+esac
+case $srcdir in
+  *[[\\\"\#\$\&\'\`$am_lf\ \   ]]*)
+    AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$[*]" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$[*]" != "X $srcdir/configure conftest.file" \
+      && test "$[*]" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      AC_MSG_ERROR([ls -t appears to fail.  Make sure there is not a broken
+alias in your environment])
+   fi
+
+   test "$[2]" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   AC_MSG_ERROR([newly created file is older than distributed files!
+Check your system clock])
+fi
+AC_MSG_RESULT(yes)])
+
+# Copyright (C) 2001, 2003, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# AM_PROG_INSTALL_STRIP
+# ---------------------
+# One issue with vendor `install' (even GNU) is that you can't
+# specify the program used to strip binaries.  This is especially
+# annoying in cross-compiling environments, where the build's strip
+# is unlikely to handle the host's binaries.
+# Fortunately install-sh will honor a STRIPPROG variable, so we
+# always use install-sh in `make install-strip', and initialize
+# STRIPPROG with the value of the STRIP variable (set by the user).
+AC_DEFUN([AM_PROG_INSTALL_STRIP],
+[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
+if test "$cross_compiling" != no; then
+  AC_CHECK_TOOL([STRIP], [strip], :)
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+AC_SUBST([INSTALL_STRIP_PROGRAM])])
+
+# Copyright (C) 2006, 2008  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
+# This macro is traced by Automake.
+AC_DEFUN([_AM_SUBST_NOTMAKE])
+
+# AM_SUBST_NOTMAKE(VARIABLE)
+# ---------------------------
+# Public sister of _AM_SUBST_NOTMAKE.
+AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
+
+# Check how to create a tarball.                            -*- Autoconf -*-
+
+# Copyright (C) 2004, 2005  Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# serial 2
+
+# _AM_PROG_TAR(FORMAT)
+# --------------------
+# Check how to create a tarball in format FORMAT.
+# FORMAT should be one of `v7', `ustar', or `pax'.
+#
+# Substitute a variable $(am__tar) that is a command
+# writing to stdout a FORMAT-tarball containing the directory
+# $tardir.
+#     tardir=directory && $(am__tar) > result.tar
+#
+# Substitute a variable $(am__untar) that extract such
+# a tarball read from stdin.
+#     $(am__untar) < result.tar
+AC_DEFUN([_AM_PROG_TAR],
+[# Always define AMTAR for backward compatibility.
+AM_MISSING_PROG([AMTAR], [tar])
+m4_if([$1], [v7],
+     [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
+     [m4_case([$1], [ustar],, [pax],,
+              [m4_fatal([Unknown tar format])])
+AC_MSG_CHECKING([how to create a $1 tar archive])
+# Loop over all known methods to create a tar archive until one works.
+_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
+_am_tools=${am_cv_prog_tar_$1-$_am_tools}
+# Do not fold the above two line into one, because Tru64 sh and
+# Solaris sh will not grok spaces in the rhs of `-'.
+for _am_tool in $_am_tools
+do
+  case $_am_tool in
+  gnutar)
+    for _am_tar in tar gnutar gtar;
+    do
+      AM_RUN_LOG([$_am_tar --version]) && break
+    done
+    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
+    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
+    am__untar="$_am_tar -xf -"
+    ;;
+  plaintar)
+    # Must skip GNU tar: if it does not support --format= it doesn't create
+    # ustar tarball either.
+    (tar --version) >/dev/null 2>&1 && continue
+    am__tar='tar chf - "$$tardir"'
+    am__tar_='tar chf - "$tardir"'
+    am__untar='tar xf -'
+    ;;
+  pax)
+    am__tar='pax -L -x $1 -w "$$tardir"'
+    am__tar_='pax -L -x $1 -w "$tardir"'
+    am__untar='pax -r'
+    ;;
+  cpio)
+    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
+    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
+    am__untar='cpio -i -H $1 -d'
+    ;;
+  none)
+    am__tar=false
+    am__tar_=false
+    am__untar=false
+    ;;
+  esac
+
+  # If the value was cached, stop now.  We just wanted to have am__tar
+  # and am__untar set.
+  test -n "${am_cv_prog_tar_$1}" && break
+
+  # tar/untar a dummy directory, and stop if the command works
+  rm -rf conftest.dir
+  mkdir conftest.dir
+  echo GrepMe > conftest.dir/file
+  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
+  rm -rf conftest.dir
+  if test -s conftest.tar; then
+    AM_RUN_LOG([$am__untar <conftest.tar])
+    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
+  fi
+done
+rm -rf conftest.dir
+
+AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
+AC_MSG_RESULT([$am_cv_prog_tar_$1])])
+AC_SUBST([am__tar])
+AC_SUBST([am__untar])
+]) # _AM_PROG_TAR
+
+m4_include([m4/acinclude.m4])
+m4_include([m4/sdl.m4])
diff --git a/config.guess b/config.guess
new file mode 100644 (file)
index 0000000..dc84c68
--- /dev/null
@@ -0,0 +1,1501 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+#   Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Originally written by Per Bothner.  Please send patches (context
+# diff format) to <config-patches@gnu.org> and include a ChangeLog
+# entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub.  If it succeeds, it prints the system name on stdout, and
+# exits with 0.  Otherwise, it exits with 1.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+       for c in cc gcc c89 c99 ; do
+         if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+            CC_FOR_BUILD="$c"; break ;
+         fi ;
+       done ;
+       if test x"$CC_FOR_BUILD" = x ; then
+         CC_FOR_BUILD=no_compiler_found ;
+       fi
+       ;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+       PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+       # NetBSD (nbsd) targets should (where applicable) match one or
+       # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+       # *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+       # switched to ELF, *-*-netbsd* would select the old
+       # object file format.  This provides both forward
+       # compatibility and a consistent mechanism for selecting the
+       # object file format.
+       #
+       # Note: NetBSD doesn't particularly care about the vendor
+       # portion of the name.  We always set it to "unknown".
+       sysctl="sysctl -n hw.machine_arch"
+       UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+           /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+       case "${UNAME_MACHINE_ARCH}" in
+           armeb) machine=armeb-unknown ;;
+           arm*) machine=arm-unknown ;;
+           sh3el) machine=shl-unknown ;;
+           sh3eb) machine=sh-unknown ;;
+           sh5el) machine=sh5le-unknown ;;
+           *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+       esac
+       # The Operating System including object format, if it has switched
+       # to ELF recently, or will in the future.
+       case "${UNAME_MACHINE_ARCH}" in
+           arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+               eval $set_cc_for_build
+               if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+                       | grep -q __ELF__
+               then
+                   # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+                   # Return netbsd for either.  FIX?
+                   os=netbsd
+               else
+                   os=netbsdelf
+               fi
+               ;;
+           *)
+               os=netbsd
+               ;;
+       esac
+       # The OS release
+       # Debian GNU/NetBSD machines have a different userland, and
+       # thus, need a distinct triplet. However, they do not need
+       # kernel version information, so it can be replaced with a
+       # suitable tag, in the style of linux-gnu.
+       case "${UNAME_VERSION}" in
+           Debian*)
+               release='-gnu'
+               ;;
+           *)
+               release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+               ;;
+       esac
+       # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+       # contains redundant information, the shorter form:
+       # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+       echo "${machine}-${os}${release}"
+       exit ;;
+    *:OpenBSD:*:*)
+       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+       exit ;;
+    *:ekkoBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+       exit ;;
+    *:SolidBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+       exit ;;
+    macppc:MirBSD:*:*)
+       echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    *:MirBSD:*:*)
+       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+       exit ;;
+    alpha:OSF1:*:*)
+       case $UNAME_RELEASE in
+       *4.0)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+               ;;
+       *5.*)
+               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+               ;;
+       esac
+       # According to Compaq, /usr/sbin/psrinfo has been available on
+       # OSF/1 and Tru64 systems produced since 1995.  I hope that
+       # covers most systems running today.  This code pipes the CPU
+       # types through head -n 1, so we only detect the type of CPU 0.
+       ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+       case "$ALPHA_CPU_TYPE" in
+           "EV4 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "EV4.5 (21064)")
+               UNAME_MACHINE="alpha" ;;
+           "LCA4 (21066/21068)")
+               UNAME_MACHINE="alpha" ;;
+           "EV5 (21164)")
+               UNAME_MACHINE="alphaev5" ;;
+           "EV5.6 (21164A)")
+               UNAME_MACHINE="alphaev56" ;;
+           "EV5.6 (21164PC)")
+               UNAME_MACHINE="alphapca56" ;;
+           "EV5.7 (21164PC)")
+               UNAME_MACHINE="alphapca57" ;;
+           "EV6 (21264)")
+               UNAME_MACHINE="alphaev6" ;;
+           "EV6.7 (21264A)")
+               UNAME_MACHINE="alphaev67" ;;
+           "EV6.8CB (21264C)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8AL (21264B)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.8CX (21264D)")
+               UNAME_MACHINE="alphaev68" ;;
+           "EV6.9A (21264/EV69A)")
+               UNAME_MACHINE="alphaev69" ;;
+           "EV7 (21364)")
+               UNAME_MACHINE="alphaev7" ;;
+           "EV7.9 (21364A)")
+               UNAME_MACHINE="alphaev79" ;;
+       esac
+       # A Pn.n version is a patched version.
+       # A Vn.n version is a released version.
+       # A Tn.n version is a released field test version.
+       # A Xn.n version is an unreleased experimental baselevel.
+       # 1.2 uses "1.2" for uname -r.
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit ;;
+    Alpha\ *:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # Should we change UNAME_MACHINE based on the output of uname instead
+       # of the specific Alpha model?
+       echo alpha-pc-interix
+       exit ;;
+    21064:Windows_NT:50:3)
+       echo alpha-dec-winnt3.5
+       exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+       echo m68k-unknown-sysv4
+       exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-amigaos
+       exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+       echo ${UNAME_MACHINE}-unknown-morphos
+       exit ;;
+    *:OS/390:*:*)
+       echo i370-ibm-openedition
+       exit ;;
+    *:z/VM:*:*)
+       echo s390-ibm-zvmoe
+       exit ;;
+    *:OS400:*:*)
+        echo powerpc-ibm-os400
+       exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+       echo arm-acorn-riscix${UNAME_RELEASE}
+       exit ;;
+    arm:riscos:*:*|arm:RISCOS:*:*)
+       echo arm-unknown-riscos
+       exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+       echo hppa1.1-hitachi-hiuxmpp
+       exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+       # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+       if test "`(/bin/universe) 2>/dev/null`" = att ; then
+               echo pyramid-pyramid-sysv3
+       else
+               echo pyramid-pyramid-bsd
+       fi
+       exit ;;
+    NILE*:*:*:dcosx)
+       echo pyramid-pyramid-svr4
+       exit ;;
+    DRS?6000:unix:4.0:6*)
+       echo sparc-icl-nx6
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       case `/usr/bin/uname -p` in
+           sparc) echo sparc-icl-nx7; exit ;;
+       esac ;;
+    s390x:SunOS:*:*)
+       echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4H:SunOS:5.*:*)
+       echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+       echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+       echo i386-pc-auroraux${UNAME_RELEASE}
+       exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+       eval $set_cc_for_build
+       SUN_ARCH="i386"
+       # If there is a compiler, see if it is configured for 64-bit objects.
+       # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+       # This test works for both compilers.
+       if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+           if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+               (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+               grep IS_64BIT_ARCH >/dev/null
+           then
+               SUN_ARCH="x86_64"
+           fi
+       fi
+       echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:6*:*)
+       # According to config.sub, this is the proper way to canonicalize
+       # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+       # it's likely to be more like Solaris than SunOS4.
+       echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    sun4*:SunOS:*:*)
+       case "`/usr/bin/arch -k`" in
+           Series*|S4*)
+               UNAME_RELEASE=`uname -v`
+               ;;
+       esac
+       # Japanese Language versions have a version number like `4.1.3-JL'.
+       echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+       exit ;;
+    sun3*:SunOS:*:*)
+       echo m68k-sun-sunos${UNAME_RELEASE}
+       exit ;;
+    sun*:*:4.2BSD:*)
+       UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+       test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+       case "`/bin/arch`" in
+           sun3)
+               echo m68k-sun-sunos${UNAME_RELEASE}
+               ;;
+           sun4)
+               echo sparc-sun-sunos${UNAME_RELEASE}
+               ;;
+       esac
+       exit ;;
+    aushp:SunOS:*:*)
+       echo sparc-auspex-sunos${UNAME_RELEASE}
+       exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+       echo m68k-atari-mint${UNAME_RELEASE}
+        exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+        echo m68k-atari-mint${UNAME_RELEASE}
+       exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+        echo m68k-milan-mint${UNAME_RELEASE}
+        exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+        echo m68k-hades-mint${UNAME_RELEASE}
+        exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+        echo m68k-unknown-mint${UNAME_RELEASE}
+        exit ;;
+    m68k:machten:*:*)
+       echo m68k-apple-machten${UNAME_RELEASE}
+       exit ;;
+    powerpc:machten:*:*)
+       echo powerpc-apple-machten${UNAME_RELEASE}
+       exit ;;
+    RISC*:Mach:*:*)
+       echo mips-dec-mach_bsd4.3
+       exit ;;
+    RISC*:ULTRIX:*:*)
+       echo mips-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    VAX*:ULTRIX*:*:*)
+       echo vax-dec-ultrix${UNAME_RELEASE}
+       exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+       echo clipper-intergraph-clix${UNAME_RELEASE}
+       exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+       int main (int argc, char *argv[]) {
+#else
+       int main (argc, argv) int argc; char *argv[]; {
+#endif
+       #if defined (host_mips) && defined (MIPSEB)
+       #if defined (SYSTYPE_SYSV)
+         printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_SVR4)
+         printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+       #endif
+       #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+         printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+       #endif
+       #endif
+         exit (-1);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c &&
+         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+         SYSTEM_NAME=`$dummy $dummyarg` &&
+           { echo "$SYSTEM_NAME"; exit; }
+       echo mips-mips-riscos${UNAME_RELEASE}
+       exit ;;
+    Motorola:PowerMAX_OS:*:*)
+       echo powerpc-motorola-powermax
+       exit ;;
+    Motorola:*:4.3:PL8-*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+       echo powerpc-harris-powermax
+       exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+       echo powerpc-harris-powerunix
+       exit ;;
+    m88k:CX/UX:7*:*)
+       echo m88k-harris-cxux7
+       exit ;;
+    m88k:*:4*:R4*)
+       echo m88k-motorola-sysv4
+       exit ;;
+    m88k:*:3*:R3*)
+       echo m88k-motorola-sysv3
+       exit ;;
+    AViiON:dgux:*:*)
+        # DG/UX returns AViiON for all architectures
+        UNAME_PROCESSOR=`/usr/bin/uname -p`
+       if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+       then
+           if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+              [ ${TARGET_BINARY_INTERFACE}x = x ]
+           then
+               echo m88k-dg-dgux${UNAME_RELEASE}
+           else
+               echo m88k-dg-dguxbcs${UNAME_RELEASE}
+           fi
+       else
+           echo i586-dg-dgux${UNAME_RELEASE}
+       fi
+       exit ;;
+    M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
+       echo m88k-dolphin-sysv3
+       exit ;;
+    M88*:*:R3*:*)
+       # Delta 88k system running SVR3
+       echo m88k-motorola-sysv3
+       exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+       echo m88k-tektronix-sysv3
+       exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+       echo m68k-tektronix-bsd
+       exit ;;
+    *:IRIX*:*:*)
+       echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+       exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+       echo i386-ibm-aix
+       exit ;;
+    ia64:AIX:*:*)
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:2:3)
+       if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+               eval $set_cc_for_build
+               sed 's/^                //' << EOF >$dummy.c
+               #include <sys/systemcfg.h>
+
+               main()
+                       {
+                       if (!__power_pc())
+                               exit(1);
+                       puts("powerpc-ibm-aix3.2.5");
+                       exit(0);
+                       }
+EOF
+               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+               then
+                       echo "$SYSTEM_NAME"
+               else
+                       echo rs6000-ibm-aix3.2.5
+               fi
+       elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+               echo rs6000-ibm-aix3.2.4
+       else
+               echo rs6000-ibm-aix3.2
+       fi
+       exit ;;
+    *:AIX:*:[456])
+       IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+       if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+               IBM_ARCH=rs6000
+       else
+               IBM_ARCH=powerpc
+       fi
+       if [ -x /usr/bin/oslevel ] ; then
+               IBM_REV=`/usr/bin/oslevel`
+       else
+               IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+       fi
+       echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+       exit ;;
+    *:AIX:*:*)
+       echo rs6000-ibm-aix
+       exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+       echo romp-ibm-bsd4.4
+       exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+       echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+       exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+       echo rs6000-bull-bosx
+       exit ;;
+    DPX/2?00:B.O.S.:*:*)
+       echo m68k-bull-sysv3
+       exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+       echo m68k-hp-bsd
+       exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+       echo m68k-hp-bsd4.4
+       exit ;;
+    9000/[34678]??:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       case "${UNAME_MACHINE}" in
+           9000/31? )            HP_ARCH=m68000 ;;
+           9000/[34]?? )         HP_ARCH=m68k ;;
+           9000/[678][0-9][0-9])
+               if [ -x /usr/bin/getconf ]; then
+                   sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+                    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+                    case "${sc_cpu_version}" in
+                      523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+                      528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+                      532)                      # CPU_PA_RISC2_0
+                        case "${sc_kernel_bits}" in
+                          32) HP_ARCH="hppa2.0n" ;;
+                          64) HP_ARCH="hppa2.0w" ;;
+                         '') HP_ARCH="hppa2.0" ;;   # HP-UX 10.20
+                        esac ;;
+                    esac
+               fi
+               if [ "${HP_ARCH}" = "" ]; then
+                   eval $set_cc_for_build
+                   sed 's/^              //' << EOF >$dummy.c
+
+              #define _HPUX_SOURCE
+              #include <stdlib.h>
+              #include <unistd.h>
+
+              int main ()
+              {
+              #if defined(_SC_KERNEL_BITS)
+                  long bits = sysconf(_SC_KERNEL_BITS);
+              #endif
+                  long cpu  = sysconf (_SC_CPU_VERSION);
+
+                  switch (cpu)
+               {
+               case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+               case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+               case CPU_PA_RISC2_0:
+              #if defined(_SC_KERNEL_BITS)
+                   switch (bits)
+                       {
+                       case 64: puts ("hppa2.0w"); break;
+                       case 32: puts ("hppa2.0n"); break;
+                       default: puts ("hppa2.0"); break;
+                       } break;
+              #else  /* !defined(_SC_KERNEL_BITS) */
+                   puts ("hppa2.0"); break;
+              #endif
+               default: puts ("hppa1.0"); break;
+               }
+                  exit (0);
+              }
+EOF
+                   (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+                   test -z "$HP_ARCH" && HP_ARCH=hppa
+               fi ;;
+       esac
+       if [ ${HP_ARCH} = "hppa2.0w" ]
+       then
+           eval $set_cc_for_build
+
+           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+           # generating 64-bit code.  GNU and HP use different nomenclature:
+           #
+           # $ CC_FOR_BUILD=cc ./config.guess
+           # => hppa2.0w-hp-hpux11.23
+           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+           # => hppa64-hp-hpux11.23
+
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+               grep -q __LP64__
+           then
+               HP_ARCH="hppa2.0w"
+           else
+               HP_ARCH="hppa64"
+           fi
+       fi
+       echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+       exit ;;
+    ia64:HP-UX:*:*)
+       HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+       echo ia64-hp-hpux${HPUX_REV}
+       exit ;;
+    3050*:HI-UX:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <unistd.h>
+       int
+       main ()
+       {
+         long cpu = sysconf (_SC_CPU_VERSION);
+         /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+            true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+            results, however.  */
+         if (CPU_IS_PA_RISC (cpu))
+           {
+             switch (cpu)
+               {
+                 case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+                 case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+                 default: puts ("hppa-hitachi-hiuxwe2"); break;
+               }
+           }
+         else if (CPU_IS_HP_MC68K (cpu))
+           puts ("m68k-hitachi-hiuxwe2");
+         else puts ("unknown-hitachi-hiuxwe2");
+         exit (0);
+       }
+EOF
+       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+               { echo "$SYSTEM_NAME"; exit; }
+       echo unknown-hitachi-hiuxwe2
+       exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+       echo hppa1.1-hp-bsd
+       exit ;;
+    9000/8??:4.3bsd:*:*)
+       echo hppa1.0-hp-bsd
+       exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+       echo hppa1.0-hp-mpeix
+       exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+       echo hppa1.1-hp-osf
+       exit ;;
+    hp8??:OSF1:*:*)
+       echo hppa1.0-hp-osf
+       exit ;;
+    i*86:OSF1:*:*)
+       if [ -x /usr/sbin/sysversion ] ; then
+           echo ${UNAME_MACHINE}-unknown-osf1mk
+       else
+           echo ${UNAME_MACHINE}-unknown-osf1
+       fi
+       exit ;;
+    parisc*:Lites*:*:*)
+       echo hppa1.1-hp-lites
+       exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+       echo c1-convex-bsd
+        exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+        exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+       echo c34-convex-bsd
+        exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+       echo c38-convex-bsd
+        exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+       echo c4-convex-bsd
+        exit ;;
+    CRAY*Y-MP:*:*:*)
+       echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*[A-Z]90:*:*:*)
+       echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+       | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+             -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+             -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*TS:*:*:*)
+       echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*T3E:*:*:*)
+       echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    CRAY*SV1:*:*:*)
+       echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    *:UNICOS/mp:*:*)
+       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+       exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+       FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+        echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+        exit ;;
+    5000:UNIX_System_V:4.*:*)
+        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+       exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+       echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+       exit ;;
+    sparc*:BSD/OS:*:*)
+       echo sparc-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:BSD/OS:*:*)
+       echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+       exit ;;
+    *:FreeBSD:*:*)
+       case ${UNAME_MACHINE} in
+           pc98)
+               echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           amd64)
+               echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+           *)
+               echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+       esac
+       exit ;;
+    i*:CYGWIN*:*)
+       echo ${UNAME_MACHINE}-pc-cygwin
+       exit ;;
+    *:MINGW*:*)
+       echo ${UNAME_MACHINE}-pc-mingw32
+       exit ;;
+    i*:windows32*:*)
+       # uname -m includes "-pc" on this system.
+       echo ${UNAME_MACHINE}-mingw32
+       exit ;;
+    i*:PW*:*)
+       echo ${UNAME_MACHINE}-pc-pw32
+       exit ;;
+    *:Interix*:*)
+       case ${UNAME_MACHINE} in
+           x86)
+               echo i586-pc-interix${UNAME_RELEASE}
+               exit ;;
+           authenticamd | genuineintel | EM64T)
+               echo x86_64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+           IA64)
+               echo ia64-unknown-interix${UNAME_RELEASE}
+               exit ;;
+       esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+       echo i${UNAME_MACHINE}-pc-mks
+       exit ;;
+    8664:Windows_NT:*)
+       echo x86_64-pc-mks
+       exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+       # How do we know it's Interix rather than the generic POSIX subsystem?
+       # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+       # UNAME_MACHINE based on the output of uname instead of i386?
+       echo i586-pc-interix
+       exit ;;
+    i*:UWIN*:*)
+       echo ${UNAME_MACHINE}-pc-uwin
+       exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+       echo x86_64-unknown-cygwin
+       exit ;;
+    p*:CYGWIN*:*)
+       echo powerpcle-unknown-cygwin
+       exit ;;
+    prep*:SunOS:5.*:*)
+       echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+       exit ;;
+    *:GNU:*:*)
+       # the GNU system
+       echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+       exit ;;
+    *:GNU/*:*:*)
+       # other systems with GNU libc and userland
+       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
+       exit ;;
+    i*86:Minix:*:*)
+       echo ${UNAME_MACHINE}-pc-minix
+       exit ;;
+    alpha:Linux:*:*)
+       case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+         EV5)   UNAME_MACHINE=alphaev5 ;;
+         EV56)  UNAME_MACHINE=alphaev56 ;;
+         PCA56) UNAME_MACHINE=alphapca56 ;;
+         PCA57) UNAME_MACHINE=alphapca56 ;;
+         EV6)   UNAME_MACHINE=alphaev6 ;;
+         EV67)  UNAME_MACHINE=alphaev67 ;;
+         EV68*) UNAME_MACHINE=alphaev68 ;;
+        esac
+       objdump --private-headers /bin/sh | grep -q ld.so.1
+       if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+       echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+       exit ;;
+    arm*:Linux:*:*)
+       eval $set_cc_for_build
+       if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+           | grep -q __ARM_EABI__
+       then
+           echo ${UNAME_MACHINE}-unknown-linux-gnu
+       else
+           echo ${UNAME_MACHINE}-unknown-linux-gnueabi
+       fi
+       exit ;;
+    avr32*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    cris:Linux:*:*)
+       echo cris-axis-linux-gnu
+       exit ;;
+    crisv32:Linux:*:*)
+       echo crisv32-axis-linux-gnu
+       exit ;;
+    frv:Linux:*:*)
+       echo frv-unknown-linux-gnu
+       exit ;;
+    i*86:Linux:*:*)
+       LIBC=gnu
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #ifdef __dietlibc__
+       LIBC=dietlibc
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
+       echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
+       exit ;;
+    ia64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m32r*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    m68*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #undef CPU
+       #undef ${UNAME_MACHINE}
+       #undef ${UNAME_MACHINE}el
+       #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+       CPU=${UNAME_MACHINE}el
+       #else
+       #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+       CPU=${UNAME_MACHINE}
+       #else
+       CPU=
+       #endif
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       ;;
+    or32:Linux:*:*)
+       echo or32-unknown-linux-gnu
+       exit ;;
+    padre:Linux:*:*)
+       echo sparc-unknown-linux-gnu
+       exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+       echo hppa64-unknown-linux-gnu
+       exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+       # Look for CPU level
+       case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+         PA7*) echo hppa1.1-unknown-linux-gnu ;;
+         PA8*) echo hppa2.0-unknown-linux-gnu ;;
+         *)    echo hppa-unknown-linux-gnu ;;
+       esac
+       exit ;;
+    ppc64:Linux:*:*)
+       echo powerpc64-unknown-linux-gnu
+       exit ;;
+    ppc:Linux:*:*)
+       echo powerpc-unknown-linux-gnu
+       exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+       echo ${UNAME_MACHINE}-ibm-linux
+       exit ;;
+    sh64*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sh*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    vax:Linux:*:*)
+       echo ${UNAME_MACHINE}-dec-linux-gnu
+       exit ;;
+    x86_64:Linux:*:*)
+       echo x86_64-unknown-linux-gnu
+       exit ;;
+    xtensa*:Linux:*:*)
+       echo ${UNAME_MACHINE}-unknown-linux-gnu
+       exit ;;
+    i*86:DYNIX/ptx:4*:*)
+       # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+       # earlier versions are messed up and put the nodename in both
+       # sysname and nodename.
+       echo i386-sequent-sysv4
+       exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+        # Unixware is an offshoot of SVR4, but it has its own version
+        # number series starting with 2...
+        # I am not positive that other SVR4 systems won't match this,
+       # I just have to hope.  -- rms.
+        # Use sysv4.2uw... so that sysv4* matches it.
+       echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+       exit ;;
+    i*86:OS/2:*:*)
+       # If we were able to find `uname', then EMX Unix compatibility
+       # is probably installed.
+       echo ${UNAME_MACHINE}-pc-os2-emx
+       exit ;;
+    i*86:XTS-300:*:STOP)
+       echo ${UNAME_MACHINE}-unknown-stop
+       exit ;;
+    i*86:atheos:*:*)
+       echo ${UNAME_MACHINE}-unknown-atheos
+       exit ;;
+    i*86:syllable:*:*)
+       echo ${UNAME_MACHINE}-pc-syllable
+       exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+       echo i386-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    i*86:*DOS:*:*)
+       echo ${UNAME_MACHINE}-pc-msdosdjgpp
+       exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+       UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+       if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+               echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+       else
+               echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+       fi
+       exit ;;
+    i*86:*:5:[678]*)
+       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       case `/bin/uname -X | grep "^Machine"` in
+           *486*)           UNAME_MACHINE=i486 ;;
+           *Pentium)        UNAME_MACHINE=i586 ;;
+           *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+       esac
+       echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+       exit ;;
+    i*86:*:3.2:*)
+       if test -f /usr/options/cb.name; then
+               UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+               echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+       elif /bin/uname -X 2>/dev/null >/dev/null ; then
+               UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+               (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+               (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+                       && UNAME_MACHINE=i586
+               (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+                       && UNAME_MACHINE=i686
+               echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+       else
+               echo ${UNAME_MACHINE}-pc-sysv32
+       fi
+       exit ;;
+    pc:*:*:*)
+       # Left here for compatibility:
+        # uname -m prints for DJGPP always 'pc', but it prints nothing about
+        # the processor, so we play safe by assuming i586.
+       # Note: whatever this is, it MUST be the same as what config.sub
+       # prints for the "djgpp" host, or else GDB configury will decide that
+       # this is a cross-build.
+       echo i586-pc-msdosdjgpp
+        exit ;;
+    Intel:Mach:3*:*)
+       echo i386-pc-mach3
+       exit ;;
+    paragon:*:*:*)
+       echo i860-intel-osf1
+       exit ;;
+    i860:*:4.*:*) # i860-SVR4
+       if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+         echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+       else # Add other i860-SVR4 vendors below as they are discovered.
+         echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+       fi
+       exit ;;
+    mini*:CTIX:SYS*5:*)
+       # "miniframe"
+       echo m68010-convergent-sysv
+       exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+       echo m68k-convergent-sysv
+       exit ;;
+    M680?0:D-NIX:5.3:*)
+       echo m68k-diab-dnix
+       exit ;;
+    M68*:*:R3V[5678]*:*)
+       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       OS_REL=''
+       test -r /etc/.relid \
+       && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+          && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+       OS_REL='.3'
+       test -r /etc/.relid \
+           && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+       /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+           && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+       /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+           && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+       echo m68k-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+       echo m68k-atari-sysv4
+       exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+       echo sparc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    rs6000:LynxOS:2.*:*)
+       echo rs6000-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+       echo powerpc-unknown-lynxos${UNAME_RELEASE}
+       exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+       echo mips-dde-sysv${UNAME_RELEASE}
+       exit ;;
+    RM*:ReliantUNIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    RM*:SINIX-*:*:*)
+       echo mips-sni-sysv4
+       exit ;;
+    *:SINIX-*:*:*)
+       if uname -p 2>/dev/null >/dev/null ; then
+               UNAME_MACHINE=`(uname -p) 2>/dev/null`
+               echo ${UNAME_MACHINE}-sni-sysv4
+       else
+               echo ns32k-sni-sysv
+       fi
+       exit ;;
+    PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+                      # says <Richard.M.Bartel@ccMail.Census.GOV>
+        echo i586-unisys-sysv4
+        exit ;;
+    *:UNIX_System_V:4*:FTX*)
+       # From Gerald Hewes <hewes@openmarket.com>.
+       # How about differentiating between stratus architectures? -djm
+       echo hppa1.1-stratus-sysv4
+       exit ;;
+    *:*:*:FTX*)
+       # From seanf@swdc.stratus.com.
+       echo i860-stratus-sysv4
+       exit ;;
+    i*86:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo ${UNAME_MACHINE}-stratus-vos
+       exit ;;
+    *:VOS:*:*)
+       # From Paul.Green@stratus.com.
+       echo hppa1.1-stratus-vos
+       exit ;;
+    mc68*:A/UX:*:*)
+       echo m68k-apple-aux${UNAME_RELEASE}
+       exit ;;
+    news*:NEWS-OS:6*:*)
+       echo mips-sony-newsos6
+       exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+       if [ -d /usr/nec ]; then
+               echo mips-nec-sysv${UNAME_RELEASE}
+       else
+               echo mips-unknown-sysv${UNAME_RELEASE}
+       fi
+        exit ;;
+    BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
+       echo powerpc-be-beos
+       exit ;;
+    BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
+       echo powerpc-apple-beos
+       exit ;;
+    BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
+       echo i586-pc-beos
+       exit ;;
+    BePC:Haiku:*:*)    # Haiku running on Intel PC compatible.
+       echo i586-pc-haiku
+       exit ;;
+    SX-4:SUPER-UX:*:*)
+       echo sx4-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-5:SUPER-UX:*:*)
+       echo sx5-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-6:SUPER-UX:*:*)
+       echo sx6-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-7:SUPER-UX:*:*)
+       echo sx7-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8:SUPER-UX:*:*)
+       echo sx8-nec-superux${UNAME_RELEASE}
+       exit ;;
+    SX-8R:SUPER-UX:*:*)
+       echo sx8r-nec-superux${UNAME_RELEASE}
+       exit ;;
+    Power*:Rhapsody:*:*)
+       echo powerpc-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Rhapsody:*:*)
+       echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+       exit ;;
+    *:Darwin:*:*)
+       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+       case $UNAME_PROCESSOR in
+           i386)
+               eval $set_cc_for_build
+               if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+                 if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+                     (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+                     grep IS_64BIT_ARCH >/dev/null
+                 then
+                     UNAME_PROCESSOR="x86_64"
+                 fi
+               fi ;;
+           unknown) UNAME_PROCESSOR=powerpc ;;
+       esac
+       echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+       exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+       UNAME_PROCESSOR=`uname -p`
+       if test "$UNAME_PROCESSOR" = "x86"; then
+               UNAME_PROCESSOR=i386
+               UNAME_MACHINE=pc
+       fi
+       echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+       exit ;;
+    *:QNX:*:4*)
+       echo i386-pc-qnx
+       exit ;;
+    NSE-?:NONSTOP_KERNEL:*:*)
+       echo nse-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+       echo nsr-tandem-nsk${UNAME_RELEASE}
+       exit ;;
+    *:NonStop-UX:*:*)
+       echo mips-compaq-nonstopux
+       exit ;;
+    BS2000:POSIX*:*:*)
+       echo bs2000-siemens-sysv
+       exit ;;
+    DS/*:UNIX_System_V:*:*)
+       echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+       exit ;;
+    *:Plan9:*:*)
+       # "uname -m" is not consistent, so use $cputype instead. 386
+       # is converted to i386 for consistency with other x86
+       # operating systems.
+       if test "$cputype" = "386"; then
+           UNAME_MACHINE=i386
+       else
+           UNAME_MACHINE="$cputype"
+       fi
+       echo ${UNAME_MACHINE}-unknown-plan9
+       exit ;;
+    *:TOPS-10:*:*)
+       echo pdp10-unknown-tops10
+       exit ;;
+    *:TENEX:*:*)
+       echo pdp10-unknown-tenex
+       exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+       echo pdp10-dec-tops20
+       exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+       echo pdp10-xkl-tops20
+       exit ;;
+    *:TOPS-20:*:*)
+       echo pdp10-unknown-tops20
+       exit ;;
+    *:ITS:*:*)
+       echo pdp10-unknown-its
+       exit ;;
+    SEI:*:*:SEIUX)
+        echo mips-sei-seiux${UNAME_RELEASE}
+       exit ;;
+    *:DragonFly:*:*)
+       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+       exit ;;
+    *:*VMS:*:*)
+       UNAME_MACHINE=`(uname -p) 2>/dev/null`
+       case "${UNAME_MACHINE}" in
+           A*) echo alpha-dec-vms ; exit ;;
+           I*) echo ia64-dec-vms ; exit ;;
+           V*) echo vax-dec-vms ; exit ;;
+       esac ;;
+    *:XENIX:*:SysV)
+       echo i386-pc-xenix
+       exit ;;
+    i*86:skyos:*:*)
+       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+       exit ;;
+    i*86:rdos:*:*)
+       echo ${UNAME_MACHINE}-pc-rdos
+       exit ;;
+    i*86:AROS:*:*)
+       echo ${UNAME_MACHINE}-pc-aros
+       exit ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
+     I don't know....  */
+  printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+  printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+          "4"
+#else
+         ""
+#endif
+         ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+  printf ("arm-acorn-riscix\n"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+  printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+  int version;
+  version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+  if (version < 4)
+    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+  else
+    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+  exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+  printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+  printf ("ns32k-encore-mach\n"); exit (0);
+#else
+  printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+  printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+  printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+  printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+    struct utsname un;
+
+    uname(&un);
+
+    if (strncmp(un.version, "V2", 2) == 0) {
+       printf ("i386-sequent-ptx2\n"); exit (0);
+    }
+    if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+       printf ("i386-sequent-ptx1\n"); exit (0);
+    }
+    printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+#  include <sys/param.h>
+#  if defined (BSD)
+#   if BSD == 43
+      printf ("vax-dec-bsd4.3\n"); exit (0);
+#   else
+#    if BSD == 199006
+      printf ("vax-dec-bsd4.3reno\n"); exit (0);
+#    else
+      printf ("vax-dec-bsd\n"); exit (0);
+#    endif
+#   endif
+#  else
+    printf ("vax-dec-bsd\n"); exit (0);
+#  endif
+# else
+    printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+  printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+  exit (1);
+}
+EOF
+
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
+       { echo "$SYSTEM_NAME"; exit; }
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+    case `getsysinfo -f cpu_type` in
+    c1*)
+       echo c1-convex-bsd
+       exit ;;
+    c2*)
+       if getsysinfo -f scalar_acc
+       then echo c32-convex-bsd
+       else echo c2-convex-bsd
+       fi
+       exit ;;
+    c34*)
+       echo c34-convex-bsd
+       exit ;;
+    c38*)
+       echo c38-convex-bsd
+       exit ;;
+    c4*)
+       echo c4-convex-bsd
+       exit ;;
+    esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/config.h.in b/config.h.in
new file mode 100644 (file)
index 0000000..11fd56e
--- /dev/null
@@ -0,0 +1,149 @@
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the `atexit' function. */
+#undef HAVE_ATEXIT
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#undef HAVE_FCNTL_H
+
+/* Define to 1 if you have the <float.h> header file. */
+#undef HAVE_FLOAT_H
+
+/* Define to 1 if you have the `floor' function. */
+#undef HAVE_FLOOR
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `png' library (-lpng). */
+#undef HAVE_LIBPNG
+
+/* Define to 1 if you have the `SDL_image' library (-lSDL_image). */
+#undef HAVE_LIBSDL_IMAGE
+
+/* Define to 1 if you have the `SDL_mixer' library (-lSDL_mixer). */
+#undef HAVE_LIBSDL_MIXER
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the `malloc' function. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <malloc.h> header file. */
+#undef HAVE_MALLOC_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `realloc' function. */
+#undef HAVE_REALLOC
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `select_argtypes' function. */
+#undef HAVE_SELECT_ARGTYPES
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the `strchr' function. */
+#undef HAVE_STRCHR
+
+/* Define to 1 if you have the `strdup' function. */
+#undef HAVE_STRDUP
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strpbrk' function. */
+#undef HAVE_STRPBRK
+
+/* Define to 1 if you have the `strstr' function. */
+#undef HAVE_STRSTR
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vprintf' function. */
+#undef HAVE_VPRINTF
+
+/* Most likely your home directory is stored in $HOME. */
+#undef HOME_ENV
+
+/* Minimum supported script version */
+#undef MIN_SCRIPT_MAJOR
+
+/* Minimum supported script version */
+#undef MIN_SCRIPT_MINOR
+
+/* Minimum supported script version */
+#undef MIN_SCRIPT_RELEASE
+
+/* .nazghul is for Unix users. */
+#undef NAZGHUL_USER_DIR
+
+/* _nazghul is for Windows users. */
+#undef NAZGHUL_USER_DIR_WIN
+
+/* Name of package */
+#undef PACKAGE
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Enable quest log */
+#undef USE_QUESTS
+
+/* Enable Yuse command and skills */
+#undef USE_SKILLS
+
+/* Version number of package */
+#undef VERSION
+
+/* Define to empty if `const' does not conform to ANSI C. */
+#undef const
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+#undef volatile
diff --git a/config.sub b/config.sub
new file mode 100644 (file)
index 0000000..2a55a50
--- /dev/null
@@ -0,0 +1,1705 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+#   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+#   Free Software Foundation, Inc.
+
+timestamp='2009-11-20'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine.  It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+# 02110-1301, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+
+# Please send patches to <config-patches@gnu.org>.  Submit a context
+# diff and a properly formatted GNU ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#      CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#      CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+       $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )        # Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
+  uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+  kopensolaris*-gnu* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+       -sun*os*)
+               # Prevent following clause from handling this invalid input.
+               ;;
+       -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+       -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+       -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+       -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+       -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+       -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+       -apple | -axis | -knuth | -cray | -microblaze)
+               os=
+               basic_machine=$1
+               ;;
+        -bluegene*)
+               os=-cnk
+               ;;
+       -sim | -cisco | -oki | -wec | -winbond)
+               os=
+               basic_machine=$1
+               ;;
+       -scout)
+               ;;
+       -wrs)
+               os=-vxworks
+               basic_machine=$1
+               ;;
+       -chorusos*)
+               os=-chorusos
+               basic_machine=$1
+               ;;
+       -chorusrdb)
+               os=-chorusrdb
+               basic_machine=$1
+               ;;
+       -hiux*)
+               os=-hiuxwe2
+               ;;
+       -sco6)
+               os=-sco5v6
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5)
+               os=-sco3.2v5
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco4)
+               os=-sco3.2v4
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2.[4-9]*)
+               os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco3.2v[4-9]*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco5v6*)
+               # Don't forget version if it is 3.2v4 or newer.
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -sco*)
+               os=-sco3.2v2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -udk*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -isc)
+               os=-isc2.2
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -clix*)
+               basic_machine=clipper-intergraph
+               ;;
+       -isc*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+               ;;
+       -lynx*)
+               os=-lynxos
+               ;;
+       -ptx*)
+               basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+               ;;
+       -windowsnt*)
+               os=`echo $os | sed -e 's/windowsnt/winnt/'`
+               ;;
+       -psos*)
+               os=-psos
+               ;;
+       -mint | -mint[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+       # Recognize the basic CPU types without company name.
+       # Some are omitted here because they have special meanings below.
+       1750a | 580 \
+       | a29k \
+       | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+       | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+       | am33_2.0 \
+       | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
+       | bfin \
+       | c4x | clipper \
+       | d10v | d30v | dlx | dsp16xx \
+       | fido | fr30 | frv \
+       | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+       | i370 | i860 | i960 | ia64 \
+       | ip2k | iq2000 \
+       | lm32 \
+       | m32c | m32r | m32rle | m68000 | m68k | m88k \
+       | maxq | mb | microblaze | mcore | mep | metag \
+       | mips | mipsbe | mipseb | mipsel | mipsle \
+       | mips16 \
+       | mips64 | mips64el \
+       | mips64octeon | mips64octeonel \
+       | mips64orion | mips64orionel \
+       | mips64r5900 | mips64r5900el \
+       | mips64vr | mips64vrel \
+       | mips64vr4100 | mips64vr4100el \
+       | mips64vr4300 | mips64vr4300el \
+       | mips64vr5000 | mips64vr5000el \
+       | mips64vr5900 | mips64vr5900el \
+       | mipsisa32 | mipsisa32el \
+       | mipsisa32r2 | mipsisa32r2el \
+       | mipsisa64 | mipsisa64el \
+       | mipsisa64r2 | mipsisa64r2el \
+       | mipsisa64sb1 | mipsisa64sb1el \
+       | mipsisa64sr71k | mipsisa64sr71kel \
+       | mipstx39 | mipstx39el \
+       | mn10200 | mn10300 \
+       | moxie \
+       | mt \
+       | msp430 \
+       | nios | nios2 \
+       | ns16k | ns32k \
+       | or32 \
+       | pdp10 | pdp11 | pj | pjl \
+       | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+       | pyramid \
+       | rx \
+       | score \
+       | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+       | sh64 | sh64le \
+       | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+       | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+       | spu | strongarm \
+       | tahoe | thumb | tic4x | tic80 | tron \
+       | ubicom32 \
+       | v850 | v850e \
+       | we32k \
+       | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | z8k | z80)
+               basic_machine=$basic_machine-unknown
+               ;;
+       m6811 | m68hc11 | m6812 | m68hc12 | picochip)
+               # Motorola 68HC11/12.
+               basic_machine=$basic_machine-unknown
+               os=-none
+               ;;
+       m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+               ;;
+       ms1)
+               basic_machine=mt-unknown
+               ;;
+
+       # We use `pc' rather than `unknown'
+       # because (1) that's what they normally are, and
+       # (2) the word "unknown" tends to confuse beginning users.
+       i*86 | x86_64)
+         basic_machine=$basic_machine-pc
+         ;;
+       # Object if more than one company name word.
+       *-*-*)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+       # Recognize the basic CPU types with company name.
+       580-* \
+       | a29k-* \
+       | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+       | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+       | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+       | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+       | avr-* | avr32-* \
+       | bfin-* | bs2000-* \
+       | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
+       | clipper-* | craynv-* | cydra-* \
+       | d10v-* | d30v-* | dlx-* \
+       | elxsi-* \
+       | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+       | h8300-* | h8500-* \
+       | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+       | i*86-* | i860-* | i960-* | ia64-* \
+       | ip2k-* | iq2000-* \
+       | lm32-* \
+       | m32c-* | m32r-* | m32rle-* \
+       | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+       | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
+       | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+       | mips16-* \
+       | mips64-* | mips64el-* \
+       | mips64octeon-* | mips64octeonel-* \
+       | mips64orion-* | mips64orionel-* \
+       | mips64r5900-* | mips64r5900el-* \
+       | mips64vr-* | mips64vrel-* \
+       | mips64vr4100-* | mips64vr4100el-* \
+       | mips64vr4300-* | mips64vr4300el-* \
+       | mips64vr5000-* | mips64vr5000el-* \
+       | mips64vr5900-* | mips64vr5900el-* \
+       | mipsisa32-* | mipsisa32el-* \
+       | mipsisa32r2-* | mipsisa32r2el-* \
+       | mipsisa64-* | mipsisa64el-* \
+       | mipsisa64r2-* | mipsisa64r2el-* \
+       | mipsisa64sb1-* | mipsisa64sb1el-* \
+       | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+       | mipstx39-* | mipstx39el-* \
+       | mmix-* \
+       | mt-* \
+       | msp430-* \
+       | nios-* | nios2-* \
+       | none-* | np1-* | ns16k-* | ns32k-* \
+       | orion-* \
+       | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+       | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+       | pyramid-* \
+       | romp-* | rs6000-* | rx-* \
+       | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+       | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+       | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+       | sparclite-* \
+       | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
+       | tahoe-* | thumb-* \
+       | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \
+       | tron-* \
+       | ubicom32-* \
+       | v850-* | v850e-* | vax-* \
+       | we32k-* \
+       | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
+       | xstormy16-* | xtensa*-* \
+       | ymp-* \
+       | z8k-* | z80-*)
+               ;;
+       # Recognize the basic CPU types without company name, with glob match.
+       xtensa*)
+               basic_machine=$basic_machine-unknown
+               ;;
+       # Recognize the various machine names and aliases which stand
+       # for a CPU type and a company and sometimes even an OS.
+       386bsd)
+               basic_machine=i386-unknown
+               os=-bsd
+               ;;
+       3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+               basic_machine=m68000-att
+               ;;
+       3b*)
+               basic_machine=we32k-att
+               ;;
+       a29khif)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       abacus)
+               basic_machine=abacus-unknown
+               ;;
+       adobe68k)
+               basic_machine=m68010-adobe
+               os=-scout
+               ;;
+       alliant | fx80)
+               basic_machine=fx80-alliant
+               ;;
+       altos | altos3068)
+               basic_machine=m68k-altos
+               ;;
+       am29k)
+               basic_machine=a29k-none
+               os=-bsd
+               ;;
+       amd64)
+               basic_machine=x86_64-pc
+               ;;
+       amd64-*)
+               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       amdahl)
+               basic_machine=580-amdahl
+               os=-sysv
+               ;;
+       amiga | amiga-*)
+               basic_machine=m68k-unknown
+               ;;
+       amigaos | amigados)
+               basic_machine=m68k-unknown
+               os=-amigaos
+               ;;
+       amigaunix | amix)
+               basic_machine=m68k-unknown
+               os=-sysv4
+               ;;
+       apollo68)
+               basic_machine=m68k-apollo
+               os=-sysv
+               ;;
+       apollo68bsd)
+               basic_machine=m68k-apollo
+               os=-bsd
+               ;;
+       aros)
+               basic_machine=i386-pc
+               os=-aros
+               ;;
+       aux)
+               basic_machine=m68k-apple
+               os=-aux
+               ;;
+       balance)
+               basic_machine=ns32k-sequent
+               os=-dynix
+               ;;
+       blackfin)
+               basic_machine=bfin-unknown
+               os=-linux
+               ;;
+       blackfin-*)
+               basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       bluegene*)
+               basic_machine=powerpc-ibm
+               os=-cnk
+               ;;
+       c90)
+               basic_machine=c90-cray
+               os=-unicos
+               ;;
+        cegcc)
+               basic_machine=arm-unknown
+               os=-cegcc
+               ;;
+       convex-c1)
+               basic_machine=c1-convex
+               os=-bsd
+               ;;
+       convex-c2)
+               basic_machine=c2-convex
+               os=-bsd
+               ;;
+       convex-c32)
+               basic_machine=c32-convex
+               os=-bsd
+               ;;
+       convex-c34)
+               basic_machine=c34-convex
+               os=-bsd
+               ;;
+       convex-c38)
+               basic_machine=c38-convex
+               os=-bsd
+               ;;
+       cray | j90)
+               basic_machine=j90-cray
+               os=-unicos
+               ;;
+       craynv)
+               basic_machine=craynv-cray
+               os=-unicosmp
+               ;;
+       cr16)
+               basic_machine=cr16-unknown
+               os=-elf
+               ;;
+       crds | unos)
+               basic_machine=m68k-crds
+               ;;
+       crisv32 | crisv32-* | etraxfs*)
+               basic_machine=crisv32-axis
+               ;;
+       cris | cris-* | etrax*)
+               basic_machine=cris-axis
+               ;;
+       crx)
+               basic_machine=crx-unknown
+               os=-elf
+               ;;
+       da30 | da30-*)
+               basic_machine=m68k-da30
+               ;;
+       decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+               basic_machine=mips-dec
+               ;;
+       decsystem10* | dec10*)
+               basic_machine=pdp10-dec
+               os=-tops10
+               ;;
+       decsystem20* | dec20*)
+               basic_machine=pdp10-dec
+               os=-tops20
+               ;;
+       delta | 3300 | motorola-3300 | motorola-delta \
+             | 3300-motorola | delta-motorola)
+               basic_machine=m68k-motorola
+               ;;
+       delta88)
+               basic_machine=m88k-motorola
+               os=-sysv3
+               ;;
+       dicos)
+               basic_machine=i686-pc
+               os=-dicos
+               ;;
+       djgpp)
+               basic_machine=i586-pc
+               os=-msdosdjgpp
+               ;;
+       dpx20 | dpx20-*)
+               basic_machine=rs6000-bull
+               os=-bosx
+               ;;
+       dpx2* | dpx2*-bull)
+               basic_machine=m68k-bull
+               os=-sysv3
+               ;;
+       ebmon29k)
+               basic_machine=a29k-amd
+               os=-ebmon
+               ;;
+       elxsi)
+               basic_machine=elxsi-elxsi
+               os=-bsd
+               ;;
+       encore | umax | mmax)
+               basic_machine=ns32k-encore
+               ;;
+       es1800 | OSE68k | ose68k | ose | OSE)
+               basic_machine=m68k-ericsson
+               os=-ose
+               ;;
+       fx2800)
+               basic_machine=i860-alliant
+               ;;
+       genix)
+               basic_machine=ns32k-ns
+               ;;
+       gmicro)
+               basic_machine=tron-gmicro
+               os=-sysv
+               ;;
+       go32)
+               basic_machine=i386-pc
+               os=-go32
+               ;;
+       h3050r* | hiux*)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       h8300hms)
+               basic_machine=h8300-hitachi
+               os=-hms
+               ;;
+       h8300xray)
+               basic_machine=h8300-hitachi
+               os=-xray
+               ;;
+       h8500hms)
+               basic_machine=h8500-hitachi
+               os=-hms
+               ;;
+       harris)
+               basic_machine=m88k-harris
+               os=-sysv3
+               ;;
+       hp300-*)
+               basic_machine=m68k-hp
+               ;;
+       hp300bsd)
+               basic_machine=m68k-hp
+               os=-bsd
+               ;;
+       hp300hpux)
+               basic_machine=m68k-hp
+               os=-hpux
+               ;;
+       hp3k9[0-9][0-9] | hp9[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k2[0-9][0-9] | hp9k31[0-9])
+               basic_machine=m68000-hp
+               ;;
+       hp9k3[2-9][0-9])
+               basic_machine=m68k-hp
+               ;;
+       hp9k6[0-9][0-9] | hp6[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hp9k7[0-79][0-9] | hp7[0-79][0-9])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k78[0-9] | hp78[0-9])
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+               # FIXME: really hppa2.0-hp
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][13679] | hp8[0-9][13679])
+               basic_machine=hppa1.1-hp
+               ;;
+       hp9k8[0-9][0-9] | hp8[0-9][0-9])
+               basic_machine=hppa1.0-hp
+               ;;
+       hppa-next)
+               os=-nextstep3
+               ;;
+       hppaosf)
+               basic_machine=hppa1.1-hp
+               os=-osf
+               ;;
+       hppro)
+               basic_machine=hppa1.1-hp
+               os=-proelf
+               ;;
+       i370-ibm* | ibm*)
+               basic_machine=i370-ibm
+               ;;
+# I'm not sure what "Sysv32" means.  Should this be sysv3.2?
+       i*86v32)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv32
+               ;;
+       i*86v4*)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv4
+               ;;
+       i*86v)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-sysv
+               ;;
+       i*86sol2)
+               basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+               os=-solaris2
+               ;;
+       i386mach)
+               basic_machine=i386-mach
+               os=-mach
+               ;;
+       i386-vsta | vsta)
+               basic_machine=i386-unknown
+               os=-vsta
+               ;;
+       iris | iris4d)
+               basic_machine=mips-sgi
+               case $os in
+                   -irix*)
+                       ;;
+                   *)
+                       os=-irix4
+                       ;;
+               esac
+               ;;
+       isi68 | isi)
+               basic_machine=m68k-isi
+               os=-sysv
+               ;;
+       m68knommu)
+               basic_machine=m68k-unknown
+               os=-linux
+               ;;
+       m68knommu-*)
+               basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       m88k-omron*)
+               basic_machine=m88k-omron
+               ;;
+       magnum | m3230)
+               basic_machine=mips-mips
+               os=-sysv
+               ;;
+       merlin)
+               basic_machine=ns32k-utek
+               os=-sysv
+               ;;
+        microblaze)
+               basic_machine=microblaze-xilinx
+               ;;
+       mingw32)
+               basic_machine=i386-pc
+               os=-mingw32
+               ;;
+       mingw32ce)
+               basic_machine=arm-unknown
+               os=-mingw32ce
+               ;;
+       miniframe)
+               basic_machine=m68000-convergent
+               ;;
+       *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+               basic_machine=m68k-atari
+               os=-mint
+               ;;
+       mips3*-*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+               ;;
+       mips3*)
+               basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+               ;;
+       monitor)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       morphos)
+               basic_machine=powerpc-unknown
+               os=-morphos
+               ;;
+       msdos)
+               basic_machine=i386-pc
+               os=-msdos
+               ;;
+       ms1-*)
+               basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+               ;;
+       mvs)
+               basic_machine=i370-ibm
+               os=-mvs
+               ;;
+       ncr3000)
+               basic_machine=i486-ncr
+               os=-sysv4
+               ;;
+       netbsd386)
+               basic_machine=i386-unknown
+               os=-netbsd
+               ;;
+       netwinder)
+               basic_machine=armv4l-rebel
+               os=-linux
+               ;;
+       news | news700 | news800 | news900)
+               basic_machine=m68k-sony
+               os=-newsos
+               ;;
+       news1000)
+               basic_machine=m68030-sony
+               os=-newsos
+               ;;
+       news-3600 | risc-news)
+               basic_machine=mips-sony
+               os=-newsos
+               ;;
+       necv70)
+               basic_machine=v70-nec
+               os=-sysv
+               ;;
+       next | m*-next )
+               basic_machine=m68k-next
+               case $os in
+                   -nextstep* )
+                       ;;
+                   -ns2*)
+                     os=-nextstep2
+                       ;;
+                   *)
+                     os=-nextstep3
+                       ;;
+               esac
+               ;;
+       nh3000)
+               basic_machine=m68k-harris
+               os=-cxux
+               ;;
+       nh[45]000)
+               basic_machine=m88k-harris
+               os=-cxux
+               ;;
+       nindy960)
+               basic_machine=i960-intel
+               os=-nindy
+               ;;
+       mon960)
+               basic_machine=i960-intel
+               os=-mon960
+               ;;
+       nonstopux)
+               basic_machine=mips-compaq
+               os=-nonstopux
+               ;;
+       np1)
+               basic_machine=np1-gould
+               ;;
+       nsr-tandem)
+               basic_machine=nsr-tandem
+               ;;
+       op50n-* | op60c-*)
+               basic_machine=hppa1.1-oki
+               os=-proelf
+               ;;
+       openrisc | openrisc-*)
+               basic_machine=or32-unknown
+               ;;
+       os400)
+               basic_machine=powerpc-ibm
+               os=-os400
+               ;;
+       OSE68000 | ose68000)
+               basic_machine=m68000-ericsson
+               os=-ose
+               ;;
+       os68k)
+               basic_machine=m68k-none
+               os=-os68k
+               ;;
+       pa-hitachi)
+               basic_machine=hppa1.1-hitachi
+               os=-hiuxwe2
+               ;;
+       paragon)
+               basic_machine=i860-intel
+               os=-osf
+               ;;
+       parisc)
+               basic_machine=hppa-unknown
+               os=-linux
+               ;;
+       parisc-*)
+               basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+               os=-linux
+               ;;
+       pbd)
+               basic_machine=sparc-tti
+               ;;
+       pbb)
+               basic_machine=m68k-tti
+               ;;
+       pc532 | pc532-*)
+               basic_machine=ns32k-pc532
+               ;;
+       pc98)
+               basic_machine=i386-pc
+               ;;
+       pc98-*)
+               basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium | p5 | k5 | k6 | nexgen | viac3)
+               basic_machine=i586-pc
+               ;;
+       pentiumpro | p6 | 6x86 | athlon | athlon_*)
+               basic_machine=i686-pc
+               ;;
+       pentiumii | pentium2 | pentiumiii | pentium3)
+               basic_machine=i686-pc
+               ;;
+       pentium4)
+               basic_machine=i786-pc
+               ;;
+       pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+               basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumpro-* | p6-* | 6x86-* | athlon-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+               basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pentium4-*)
+               basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       pn)
+               basic_machine=pn-gould
+               ;;
+       power)  basic_machine=power-ibm
+               ;;
+       ppc)    basic_machine=powerpc-unknown
+               ;;
+       ppc-*)  basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppcle | powerpclittle | ppc-le | powerpc-little)
+               basic_machine=powerpcle-unknown
+               ;;
+       ppcle-* | powerpclittle-*)
+               basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64)  basic_machine=powerpc64-unknown
+               ;;
+       ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+               basic_machine=powerpc64le-unknown
+               ;;
+       ppc64le-* | powerpc64little-*)
+               basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+               ;;
+       ps2)
+               basic_machine=i386-ibm
+               ;;
+       pw32)
+               basic_machine=i586-unknown
+               os=-pw32
+               ;;
+       rdos)
+               basic_machine=i386-pc
+               os=-rdos
+               ;;
+       rom68k)
+               basic_machine=m68k-rom68k
+               os=-coff
+               ;;
+       rm[46]00)
+               basic_machine=mips-siemens
+               ;;
+       rtpc | rtpc-*)
+               basic_machine=romp-ibm
+               ;;
+       s390 | s390-*)
+               basic_machine=s390-ibm
+               ;;
+       s390x | s390x-*)
+               basic_machine=s390x-ibm
+               ;;
+       sa29200)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       sb1)
+               basic_machine=mipsisa64sb1-unknown
+               ;;
+       sb1el)
+               basic_machine=mipsisa64sb1el-unknown
+               ;;
+       sde)
+               basic_machine=mipsisa32-sde
+               os=-elf
+               ;;
+       sei)
+               basic_machine=mips-sei
+               os=-seiux
+               ;;
+       sequent)
+               basic_machine=i386-sequent
+               ;;
+       sh)
+               basic_machine=sh-hitachi
+               os=-hms
+               ;;
+       sh5el)
+               basic_machine=sh5le-unknown
+               ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
+       sparclite-wrs | simso-wrs)
+               basic_machine=sparclite-wrs
+               os=-vxworks
+               ;;
+       sps7)
+               basic_machine=m68k-bull
+               os=-sysv2
+               ;;
+       spur)
+               basic_machine=spur-unknown
+               ;;
+       st2000)
+               basic_machine=m68k-tandem
+               ;;
+       stratus)
+               basic_machine=i860-stratus
+               os=-sysv4
+               ;;
+       sun2)
+               basic_machine=m68000-sun
+               ;;
+       sun2os3)
+               basic_machine=m68000-sun
+               os=-sunos3
+               ;;
+       sun2os4)
+               basic_machine=m68000-sun
+               os=-sunos4
+               ;;
+       sun3os3)
+               basic_machine=m68k-sun
+               os=-sunos3
+               ;;
+       sun3os4)
+               basic_machine=m68k-sun
+               os=-sunos4
+               ;;
+       sun4os3)
+               basic_machine=sparc-sun
+               os=-sunos3
+               ;;
+       sun4os4)
+               basic_machine=sparc-sun
+               os=-sunos4
+               ;;
+       sun4sol2)
+               basic_machine=sparc-sun
+               os=-solaris2
+               ;;
+       sun3 | sun3-*)
+               basic_machine=m68k-sun
+               ;;
+       sun4)
+               basic_machine=sparc-sun
+               ;;
+       sun386 | sun386i | roadrunner)
+               basic_machine=i386-sun
+               ;;
+       sv1)
+               basic_machine=sv1-cray
+               os=-unicos
+               ;;
+       symmetry)
+               basic_machine=i386-sequent
+               os=-dynix
+               ;;
+       t3e)
+               basic_machine=alphaev5-cray
+               os=-unicos
+               ;;
+       t90)
+               basic_machine=t90-cray
+               os=-unicos
+               ;;
+       tic54x | c54x*)
+               basic_machine=tic54x-unknown
+               os=-coff
+               ;;
+       tic55x | c55x*)
+               basic_machine=tic55x-unknown
+               os=-coff
+               ;;
+       tic6x | c6x*)
+               basic_machine=tic6x-unknown
+               os=-coff
+               ;;
+       tile*)
+               basic_machine=tile-unknown
+               os=-linux-gnu
+               ;;
+       tx39)
+               basic_machine=mipstx39-unknown
+               ;;
+       tx39el)
+               basic_machine=mipstx39el-unknown
+               ;;
+       toad1)
+               basic_machine=pdp10-xkl
+               os=-tops20
+               ;;
+       tower | tower-32)
+               basic_machine=m68k-ncr
+               ;;
+       tpf)
+               basic_machine=s390x-ibm
+               os=-tpf
+               ;;
+       udi29k)
+               basic_machine=a29k-amd
+               os=-udi
+               ;;
+       ultra3)
+               basic_machine=a29k-nyu
+               os=-sym1
+               ;;
+       v810 | necv810)
+               basic_machine=v810-nec
+               os=-none
+               ;;
+       vaxv)
+               basic_machine=vax-dec
+               os=-sysv
+               ;;
+       vms)
+               basic_machine=vax-dec
+               os=-vms
+               ;;
+       vpp*|vx|vx-*)
+               basic_machine=f301-fujitsu
+               ;;
+       vxworks960)
+               basic_machine=i960-wrs
+               os=-vxworks
+               ;;
+       vxworks68)
+               basic_machine=m68k-wrs
+               os=-vxworks
+               ;;
+       vxworks29k)
+               basic_machine=a29k-wrs
+               os=-vxworks
+               ;;
+       w65*)
+               basic_machine=w65-wdc
+               os=-none
+               ;;
+       w89k-*)
+               basic_machine=hppa1.1-winbond
+               os=-proelf
+               ;;
+       xbox)
+               basic_machine=i686-pc
+               os=-mingw32
+               ;;
+       xps | xps100)
+               basic_machine=xps100-honeywell
+               ;;
+       ymp)
+               basic_machine=ymp-cray
+               os=-unicos
+               ;;
+       z8k-*-coff)
+               basic_machine=z8k-unknown
+               os=-sim
+               ;;
+       z80-*-coff)
+               basic_machine=z80-unknown
+               os=-sim
+               ;;
+       none)
+               basic_machine=none-none
+               os=-none
+               ;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+       w89k)
+               basic_machine=hppa1.1-winbond
+               ;;
+       op50n)
+               basic_machine=hppa1.1-oki
+               ;;
+       op60c)
+               basic_machine=hppa1.1-oki
+               ;;
+       romp)
+               basic_machine=romp-ibm
+               ;;
+       mmix)
+               basic_machine=mmix-knuth
+               ;;
+       rs6000)
+               basic_machine=rs6000-ibm
+               ;;
+       vax)
+               basic_machine=vax-dec
+               ;;
+       pdp10)
+               # there are many clones, so DEC is not a safe bet
+               basic_machine=pdp10-unknown
+               ;;
+       pdp11)
+               basic_machine=pdp11-dec
+               ;;
+       we32k)
+               basic_machine=we32k-att
+               ;;
+       sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+               basic_machine=sh-unknown
+               ;;
+       sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+               basic_machine=sparc-sun
+               ;;
+       cydra)
+               basic_machine=cydra-cydrome
+               ;;
+       orion)
+               basic_machine=orion-highlevel
+               ;;
+       orion105)
+               basic_machine=clipper-highlevel
+               ;;
+       mac | mpw | mac-mpw)
+               basic_machine=m68k-apple
+               ;;
+       pmac | pmac-mpw)
+               basic_machine=powerpc-apple
+               ;;
+       *-unknown)
+               # Make sure to match an already-canonicalized machine name.
+               ;;
+       *)
+               echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+       *-digital*)
+               basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+               ;;
+       *-commodore*)
+               basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+               ;;
+       *)
+               ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+        # First match some system type aliases
+        # that might get confused with valid system types.
+       # -solaris* is a basic system type, with this one exception.
+        -auroraux)
+               os=-auroraux
+               ;;
+       -solaris1 | -solaris1.*)
+               os=`echo $os | sed -e 's|solaris1|sunos4|'`
+               ;;
+       -solaris)
+               os=-solaris2
+               ;;
+       -svr4*)
+               os=-sysv4
+               ;;
+       -unixware*)
+               os=-sysv4.2uw
+               ;;
+       -gnu/linux*)
+               os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+               ;;
+       # First accept the basic system types.
+       # The portable systems comes first.
+       # Each alternative MUST END IN A *, to match a version number.
+       # -sysv* is not here because it comes later, after sysvr4.
+       -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+             | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+             | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+             | -sym* | -kopensolaris* \
+             | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+             | -aos* | -aros* \
+             | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+             | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+             | -openbsd* | -solidbsd* \
+             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+             | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+             | -chorusos* | -chorusrdb* | -cegcc* \
+             | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+             | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+             | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+             | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+             | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+             | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+             | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+             | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
+       # Remember, each alternative MUST END IN *, to match a version number.
+               ;;
+       -qnx*)
+               case $basic_machine in
+                   x86-* | i*86-*)
+                       ;;
+                   *)
+                       os=-nto$os
+                       ;;
+               esac
+               ;;
+       -nto-qnx*)
+               ;;
+       -nto*)
+               os=`echo $os | sed -e 's|nto|nto-qnx|'`
+               ;;
+       -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+               ;;
+       -mac*)
+               os=`echo $os | sed -e 's|mac|macos|'`
+               ;;
+       -linux-dietlibc)
+               os=-linux-dietlibc
+               ;;
+       -linux*)
+               os=`echo $os | sed -e 's|linux|linux-gnu|'`
+               ;;
+       -sunos5*)
+               os=`echo $os | sed -e 's|sunos5|solaris2|'`
+               ;;
+       -sunos6*)
+               os=`echo $os | sed -e 's|sunos6|solaris3|'`
+               ;;
+       -opened*)
+               os=-openedition
+               ;;
+        -os400*)
+               os=-os400
+               ;;
+       -wince*)
+               os=-wince
+               ;;
+       -osfrose*)
+               os=-osfrose
+               ;;
+       -osf*)
+               os=-osf
+               ;;
+       -utek*)
+               os=-bsd
+               ;;
+       -dynix*)
+               os=-bsd
+               ;;
+       -acis*)
+               os=-aos
+               ;;
+       -atheos*)
+               os=-atheos
+               ;;
+       -syllable*)
+               os=-syllable
+               ;;
+       -386bsd)
+               os=-bsd
+               ;;
+       -ctix* | -uts*)
+               os=-sysv
+               ;;
+       -nova*)
+               os=-rtmk-nova
+               ;;
+       -ns2 )
+               os=-nextstep2
+               ;;
+       -nsk*)
+               os=-nsk
+               ;;
+       # Preserve the version number of sinix5.
+       -sinix5.*)
+               os=`echo $os | sed -e 's|sinix|sysv|'`
+               ;;
+       -sinix*)
+               os=-sysv4
+               ;;
+        -tpf*)
+               os=-tpf
+               ;;
+       -triton*)
+               os=-sysv3
+               ;;
+       -oss*)
+               os=-sysv3
+               ;;
+       -svr4)
+               os=-sysv4
+               ;;
+       -svr3)
+               os=-sysv3
+               ;;
+       -sysvr4)
+               os=-sysv4
+               ;;
+       # This must come after -sysvr4.
+       -sysv*)
+               ;;
+       -ose*)
+               os=-ose
+               ;;
+       -es1800*)
+               os=-ose
+               ;;
+       -xenix)
+               os=-xenix
+               ;;
+       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+               os=-mint
+               ;;
+       -aros*)
+               os=-aros
+               ;;
+       -kaos*)
+               os=-kaos
+               ;;
+       -zvmoe)
+               os=-zvmoe
+               ;;
+       -dicos*)
+               os=-dicos
+               ;;
+       -none)
+               ;;
+       *)
+               # Get rid of the `-' at the beginning of $os.
+               os=`echo $os | sed 's/[^-]*-//'`
+               echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+               exit 1
+               ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+        score-*)
+               os=-elf
+               ;;
+        spu-*)
+               os=-elf
+               ;;
+       *-acorn)
+               os=-riscix1.2
+               ;;
+       arm*-rebel)
+               os=-linux
+               ;;
+       arm*-semi)
+               os=-aout
+               ;;
+        c4x-* | tic4x-*)
+               os=-coff
+               ;;
+       # This must come before the *-dec entry.
+       pdp10-*)
+               os=-tops20
+               ;;
+       pdp11-*)
+               os=-none
+               ;;
+       *-dec | vax-*)
+               os=-ultrix4.2
+               ;;
+       m68*-apollo)
+               os=-domain
+               ;;
+       i386-sun)
+               os=-sunos4.0.2
+               ;;
+       m68000-sun)
+               os=-sunos3
+               # This also exists in the configure program, but was not the
+               # default.
+               # os=-sunos4
+               ;;
+       m68*-cisco)
+               os=-aout
+               ;;
+        mep-*)
+               os=-elf
+               ;;
+       mips*-cisco)
+               os=-elf
+               ;;
+       mips*-*)
+               os=-elf
+               ;;
+       or32-*)
+               os=-coff
+               ;;
+       *-tti)  # must be before sparc entry or we get the wrong os.
+               os=-sysv3
+               ;;
+       sparc-* | *-sun)
+               os=-sunos4.1.1
+               ;;
+       *-be)
+               os=-beos
+               ;;
+       *-haiku)
+               os=-haiku
+               ;;
+       *-ibm)
+               os=-aix
+               ;;
+       *-knuth)
+               os=-mmixware
+               ;;
+       *-wec)
+               os=-proelf
+               ;;
+       *-winbond)
+               os=-proelf
+               ;;
+       *-oki)
+               os=-proelf
+               ;;
+       *-hp)
+               os=-hpux
+               ;;
+       *-hitachi)
+               os=-hiux
+               ;;
+       i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+               os=-sysv
+               ;;
+       *-cbm)
+               os=-amigaos
+               ;;
+       *-dg)
+               os=-dgux
+               ;;
+       *-dolphin)
+               os=-sysv3
+               ;;
+       m68k-ccur)
+               os=-rtu
+               ;;
+       m88k-omron*)
+               os=-luna
+               ;;
+       *-next )
+               os=-nextstep
+               ;;
+       *-sequent)
+               os=-ptx
+               ;;
+       *-crds)
+               os=-unos
+               ;;
+       *-ns)
+               os=-genix
+               ;;
+       i370-*)
+               os=-mvs
+               ;;
+       *-next)
+               os=-nextstep3
+               ;;
+       *-gould)
+               os=-sysv
+               ;;
+       *-highlevel)
+               os=-bsd
+               ;;
+       *-encore)
+               os=-bsd
+               ;;
+       *-sgi)
+               os=-irix
+               ;;
+       *-siemens)
+               os=-sysv4
+               ;;
+       *-masscomp)
+               os=-rtu
+               ;;
+       f30[01]-fujitsu | f700-fujitsu)
+               os=-uxpv
+               ;;
+       *-rom68k)
+               os=-coff
+               ;;
+       *-*bug)
+               os=-coff
+               ;;
+       *-apple)
+               os=-macos
+               ;;
+       *-atari*)
+               os=-mint
+               ;;
+       *)
+               os=-none
+               ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+       *-unknown)
+               case $os in
+                       -riscix*)
+                               vendor=acorn
+                               ;;
+                       -sunos*)
+                               vendor=sun
+                               ;;
+                       -cnk*|-aix*)
+                               vendor=ibm
+                               ;;
+                       -beos*)
+                               vendor=be
+                               ;;
+                       -hpux*)
+                               vendor=hp
+                               ;;
+                       -mpeix*)
+                               vendor=hp
+                               ;;
+                       -hiux*)
+                               vendor=hitachi
+                               ;;
+                       -unos*)
+                               vendor=crds
+                               ;;
+                       -dgux*)
+                               vendor=dg
+                               ;;
+                       -luna*)
+                               vendor=omron
+                               ;;
+                       -genix*)
+                               vendor=ns
+                               ;;
+                       -mvs* | -opened*)
+                               vendor=ibm
+                               ;;
+                       -os400*)
+                               vendor=ibm
+                               ;;
+                       -ptx*)
+                               vendor=sequent
+                               ;;
+                       -tpf*)
+                               vendor=ibm
+                               ;;
+                       -vxsim* | -vxworks* | -windiss*)
+                               vendor=wrs
+                               ;;
+                       -aux*)
+                               vendor=apple
+                               ;;
+                       -hms*)
+                               vendor=hitachi
+                               ;;
+                       -mpw* | -macos*)
+                               vendor=apple
+                               ;;
+                       -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+                               vendor=atari
+                               ;;
+                       -vos*)
+                               vendor=stratus
+                               ;;
+               esac
+               basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+               ;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/configure b/configure
new file mode 100644 (file)
index 0000000..30931b4
--- /dev/null
+++ b/configure
@@ -0,0 +1,8148 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.63 for nazghul 0.7.1.
+#
+# Report bugs to <nazghul-devel@lists.sourceforge.net>.
+#
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+# 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+if test "x$CONFIG_SHELL" = x; then
+  if (eval ":") 2>/dev/null; then
+  as_have_required=yes
+else
+  as_have_required=no
+fi
+
+  if test $as_have_required = yes &&    (eval ":
+(as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=\$LINENO
+  as_lineno_2=\$LINENO
+  test \"x\$as_lineno_1\" != \"x\$as_lineno_2\" &&
+  test \"x\`expr \$as_lineno_1 + 1\`\" = \"x\$as_lineno_2\") || { (exit 1); exit 1; }
+") 2> /dev/null; then
+  :
+else
+  as_candidate_shells=
+    as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  case $as_dir in
+        /*)
+          for as_base in sh bash ksh sh5; do
+            as_candidate_shells="$as_candidate_shells $as_dir/$as_base"
+          done;;
+       esac
+done
+IFS=$as_save_IFS
+
+
+      for as_shell in $as_candidate_shells $SHELL; do
+        # Try only shells that exist, to save several forks.
+        if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+               { ("$as_shell") 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+_ASEOF
+}; then
+  CONFIG_SHELL=$as_shell
+              as_have_required=yes
+              if { "$as_shell" 2> /dev/null <<\_ASEOF
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+:
+(as_func_return () {
+  (exit $1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = "$1" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test $exitcode = 0) || { (exit 1); exit 1; }
+
+(
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2") || { (exit 1); exit 1; }
+
+_ASEOF
+}; then
+  break
+fi
+
+fi
+
+      done
+
+      if test "x$CONFIG_SHELL" != x; then
+  for as_var in BASH_ENV ENV
+       do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+       done
+       export CONFIG_SHELL
+       exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"}
+fi
+
+
+    if test $as_have_required = no; then
+  echo This script requires a shell more modern than all the
+      echo shells that I found on your system.  Please install a
+      echo modern shell, or manually run the script under such a
+      echo shell if you do have one.
+      { (exit 1); exit 1; }
+fi
+
+
+fi
+
+fi
+
+
+
+(eval "as_func_return () {
+  (exit \$1)
+}
+as_func_success () {
+  as_func_return 0
+}
+as_func_failure () {
+  as_func_return 1
+}
+as_func_ret_success () {
+  return 0
+}
+as_func_ret_failure () {
+  return 1
+}
+
+exitcode=0
+if as_func_success; then
+  :
+else
+  exitcode=1
+  echo as_func_success failed.
+fi
+
+if as_func_failure; then
+  exitcode=1
+  echo as_func_failure succeeded.
+fi
+
+if as_func_ret_success; then
+  :
+else
+  exitcode=1
+  echo as_func_ret_success failed.
+fi
+
+if as_func_ret_failure; then
+  exitcode=1
+  echo as_func_ret_failure succeeded.
+fi
+
+if ( set x; as_func_ret_success y && test x = \"\$1\" ); then
+  :
+else
+  exitcode=1
+  echo positional parameters were not saved.
+fi
+
+test \$exitcode = 0") || {
+  echo No shell found that supports shell functions.
+  echo Please tell bug-autoconf@gnu.org about your system,
+  echo including any error possibly output before this message.
+  echo This can help us improve future autoconf versions.
+  echo Configuration will now proceed without shell functions.
+}
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+
+exec 7<&0 </dev/null 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+SHELL=${CONFIG_SHELL-/bin/sh}
+
+# Identity of this package.
+PACKAGE_NAME='nazghul'
+PACKAGE_TARNAME='nazghul'
+PACKAGE_VERSION='0.7.1'
+PACKAGE_STRING='nazghul 0.7.1'
+PACKAGE_BUGREPORT='nazghul-devel@lists.sourceforge.net'
+
+ac_unique_file="src/nazghul.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='am__EXEEXT_FALSE
+am__EXEEXT_TRUE
+LTLIBOBJS
+LIBOBJS
+CXXCPP
+EGREP
+GREP
+CPP
+SDL_LIBS
+SDL_CFLAGS
+SDL_CONFIG
+am__fastdepCXX_FALSE
+am__fastdepCXX_TRUE
+CXXDEPMODE
+ac_ct_CXX
+CXXFLAGS
+CXX
+am__fastdepCC_FALSE
+am__fastdepCC_TRUE
+CCDEPMODE
+AMDEPBACKSLASH
+AMDEP_FALSE
+AMDEP_TRUE
+am__quote
+am__include
+DEPDIR
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+MAINT
+MAINTAINER_MODE_FALSE
+MAINTAINER_MODE_TRUE
+am__untar
+am__tar
+AMTAR
+am__leading_dot
+SET_MAKE
+AWK
+mkdir_p
+MKDIR_P
+INSTALL_STRIP_PROGRAM
+STRIP
+install_sh
+MAKEINFO
+AUTOHEADER
+AUTOMAKE
+AUTOCONF
+ACLOCAL
+VERSION
+PACKAGE
+CYGPATH_W
+am__isrc
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+enable_maintainer_mode
+enable_dependency_tracking
+with_sdl_prefix
+with_sdl_exec_prefix
+enable_sdltest
+enable_dynamic_link
+'
+      ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CXX
+CXXFLAGS
+CCC
+CPP
+CXXCPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+  # If the previous option needs an argument, assign it.
+  if test -n "$ac_prev"; then
+    eval $ac_prev=\$ac_option
+    ac_prev=
+    continue
+  fi
+
+  case $ac_option in
+  *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+  *)   ac_optarg=yes ;;
+  esac
+
+  # Accept the important Cygnus configure options, so we can diagnose typos.
+
+  case $ac_dashdash$ac_option in
+  --)
+    ac_dashdash=yes ;;
+
+  -bindir | --bindir | --bindi | --bind | --bin | --bi)
+    ac_prev=bindir ;;
+  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+    bindir=$ac_optarg ;;
+
+  -build | --build | --buil | --bui | --bu)
+    ac_prev=build_alias ;;
+  -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+    build_alias=$ac_optarg ;;
+
+  -cache-file | --cache-file | --cache-fil | --cache-fi \
+  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+    ac_prev=cache_file ;;
+  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+    cache_file=$ac_optarg ;;
+
+  --config-cache | -C)
+    cache_file=config.cache ;;
+
+  -datadir | --datadir | --datadi | --datad)
+    ac_prev=datadir ;;
+  -datadir=* | --datadir=* | --datadi=* | --datad=*)
+    datadir=$ac_optarg ;;
+
+  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+  | --dataroo | --dataro | --datar)
+    ac_prev=datarootdir ;;
+  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+    datarootdir=$ac_optarg ;;
+
+  -disable-* | --disable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=no ;;
+
+  -docdir | --docdir | --docdi | --doc | --do)
+    ac_prev=docdir ;;
+  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+    docdir=$ac_optarg ;;
+
+  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+    ac_prev=dvidir ;;
+  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+    dvidir=$ac_optarg ;;
+
+  -enable-* | --enable-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid feature name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"enable_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval enable_$ac_useropt=\$ac_optarg ;;
+
+  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+  | --exec | --exe | --ex)
+    ac_prev=exec_prefix ;;
+  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+  | --exec=* | --exe=* | --ex=*)
+    exec_prefix=$ac_optarg ;;
+
+  -gas | --gas | --ga | --g)
+    # Obsolete; use --with-gas.
+    with_gas=yes ;;
+
+  -help | --help | --hel | --he | -h)
+    ac_init_help=long ;;
+  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+    ac_init_help=recursive ;;
+  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+    ac_init_help=short ;;
+
+  -host | --host | --hos | --ho)
+    ac_prev=host_alias ;;
+  -host=* | --host=* | --hos=* | --ho=*)
+    host_alias=$ac_optarg ;;
+
+  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+    ac_prev=htmldir ;;
+  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+  | --ht=*)
+    htmldir=$ac_optarg ;;
+
+  -includedir | --includedir | --includedi | --included | --include \
+  | --includ | --inclu | --incl | --inc)
+    ac_prev=includedir ;;
+  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+  | --includ=* | --inclu=* | --incl=* | --inc=*)
+    includedir=$ac_optarg ;;
+
+  -infodir | --infodir | --infodi | --infod | --info | --inf)
+    ac_prev=infodir ;;
+  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+    infodir=$ac_optarg ;;
+
+  -libdir | --libdir | --libdi | --libd)
+    ac_prev=libdir ;;
+  -libdir=* | --libdir=* | --libdi=* | --libd=*)
+    libdir=$ac_optarg ;;
+
+  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+  | --libexe | --libex | --libe)
+    ac_prev=libexecdir ;;
+  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+  | --libexe=* | --libex=* | --libe=*)
+    libexecdir=$ac_optarg ;;
+
+  -localedir | --localedir | --localedi | --localed | --locale)
+    ac_prev=localedir ;;
+  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+    localedir=$ac_optarg ;;
+
+  -localstatedir | --localstatedir | --localstatedi | --localstated \
+  | --localstate | --localstat | --localsta | --localst | --locals)
+    ac_prev=localstatedir ;;
+  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+    localstatedir=$ac_optarg ;;
+
+  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+    ac_prev=mandir ;;
+  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+    mandir=$ac_optarg ;;
+
+  -nfp | --nfp | --nf)
+    # Obsolete; use --without-fp.
+    with_fp=no ;;
+
+  -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+  | --no-cr | --no-c | -n)
+    no_create=yes ;;
+
+  -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+    no_recursion=yes ;;
+
+  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+  | --oldin | --oldi | --old | --ol | --o)
+    ac_prev=oldincludedir ;;
+  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+    oldincludedir=$ac_optarg ;;
+
+  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+    ac_prev=prefix ;;
+  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+    prefix=$ac_optarg ;;
+
+  -program-prefix | --program-prefix | --program-prefi | --program-pref \
+  | --program-pre | --program-pr | --program-p)
+    ac_prev=program_prefix ;;
+  -program-prefix=* | --program-prefix=* | --program-prefi=* \
+  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+    program_prefix=$ac_optarg ;;
+
+  -program-suffix | --program-suffix | --program-suffi | --program-suff \
+  | --program-suf | --program-su | --program-s)
+    ac_prev=program_suffix ;;
+  -program-suffix=* | --program-suffix=* | --program-suffi=* \
+  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+    program_suffix=$ac_optarg ;;
+
+  -program-transform-name | --program-transform-name \
+  | --program-transform-nam | --program-transform-na \
+  | --program-transform-n | --program-transform- \
+  | --program-transform | --program-transfor \
+  | --program-transfo | --program-transf \
+  | --program-trans | --program-tran \
+  | --progr-tra | --program-tr | --program-t)
+    ac_prev=program_transform_name ;;
+  -program-transform-name=* | --program-transform-name=* \
+  | --program-transform-nam=* | --program-transform-na=* \
+  | --program-transform-n=* | --program-transform-=* \
+  | --program-transform=* | --program-transfor=* \
+  | --program-transfo=* | --program-transf=* \
+  | --program-trans=* | --program-tran=* \
+  | --progr-tra=* | --program-tr=* | --program-t=*)
+    program_transform_name=$ac_optarg ;;
+
+  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+    ac_prev=pdfdir ;;
+  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+    pdfdir=$ac_optarg ;;
+
+  -psdir | --psdir | --psdi | --psd | --ps)
+    ac_prev=psdir ;;
+  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+    psdir=$ac_optarg ;;
+
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil)
+    silent=yes ;;
+
+  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+    ac_prev=sbindir ;;
+  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+  | --sbi=* | --sb=*)
+    sbindir=$ac_optarg ;;
+
+  -sharedstatedir | --sharedstatedir | --sharedstatedi \
+  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+  | --sharedst | --shareds | --shared | --share | --shar \
+  | --sha | --sh)
+    ac_prev=sharedstatedir ;;
+  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+  | --sha=* | --sh=*)
+    sharedstatedir=$ac_optarg ;;
+
+  -site | --site | --sit)
+    ac_prev=site ;;
+  -site=* | --site=* | --sit=*)
+    site=$ac_optarg ;;
+
+  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+    ac_prev=srcdir ;;
+  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+    srcdir=$ac_optarg ;;
+
+  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+  | --syscon | --sysco | --sysc | --sys | --sy)
+    ac_prev=sysconfdir ;;
+  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+    sysconfdir=$ac_optarg ;;
+
+  -target | --target | --targe | --targ | --tar | --ta | --t)
+    ac_prev=target_alias ;;
+  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+    target_alias=$ac_optarg ;;
+
+  -v | -verbose | --verbose | --verbos | --verbo | --verb)
+    verbose=yes ;;
+
+  -version | --version | --versio | --versi | --vers | -V)
+    ac_init_version=: ;;
+
+  -with-* | --with-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=\$ac_optarg ;;
+
+  -without-* | --without-*)
+    ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid package name: $ac_useropt" >&2
+   { (exit 1); exit 1; }; }
+    ac_useropt_orig=$ac_useropt
+    ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+    case $ac_user_opts in
+      *"
+"with_$ac_useropt"
+"*) ;;
+      *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+        ac_unrecognized_sep=', ';;
+    esac
+    eval with_$ac_useropt=no ;;
+
+  --x)
+    # Obsolete; use --with-x.
+    with_x=yes ;;
+
+  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+  | --x-incl | --x-inc | --x-in | --x-i)
+    ac_prev=x_includes ;;
+  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+    x_includes=$ac_optarg ;;
+
+  -x-libraries | --x-libraries | --x-librarie | --x-librari \
+  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+    ac_prev=x_libraries ;;
+  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+    x_libraries=$ac_optarg ;;
+
+  -*) { $as_echo "$as_me: error: unrecognized option: $ac_option
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; }
+    ;;
+
+  *=*)
+    ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+    # Reject names that are not valid shell variable names.
+    expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null &&
+      { $as_echo "$as_me: error: invalid variable name: $ac_envvar" >&2
+   { (exit 1); exit 1; }; }
+    eval $ac_envvar=\$ac_optarg
+    export $ac_envvar ;;
+
+  *)
+    # FIXME: should be removed in autoconf 3.0.
+    $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+    expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+      $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+    : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}
+    ;;
+
+  esac
+done
+
+if test -n "$ac_prev"; then
+  ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+  { $as_echo "$as_me: error: missing argument to $ac_option" >&2
+   { (exit 1); exit 1; }; }
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+  case $enable_option_checking in
+    no) ;;
+    fatal) { $as_echo "$as_me: error: unrecognized options: $ac_unrecognized_opts" >&2
+   { (exit 1); exit 1; }; } ;;
+    *)     $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+  esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in  exec_prefix prefix bindir sbindir libexecdir datarootdir \
+               datadir sysconfdir sharedstatedir localstatedir includedir \
+               oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+               libdir localedir mandir
+do
+  eval ac_val=\$$ac_var
+  # Remove trailing slashes.
+  case $ac_val in
+    */ )
+      ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+      eval $ac_var=\$ac_val;;
+  esac
+  # Be sure to have absolute directory names.
+  case $ac_val in
+    [\\/$]* | ?:[\\/]* )  continue;;
+    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+  esac
+  { $as_echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2
+   { (exit 1); exit 1; }; }
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+  if test "x$build_alias" = x; then
+    cross_compiling=maybe
+    $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host.
+    If a cross compiler is detected then cross compile mode will be used." >&2
+  elif test "x$build_alias" != "x$host_alias"; then
+    cross_compiling=yes
+  fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+  { $as_echo "$as_me: error: working directory cannot be determined" >&2
+   { (exit 1); exit 1; }; }
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+  { $as_echo "$as_me: error: pwd does not report name of working directory" >&2
+   { (exit 1); exit 1; }; }
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+  ac_srcdir_defaulted=yes
+  # Try the directory containing this script, then the parent directory.
+  ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_myself" : 'X\(//\)[^/]' \| \
+        X"$as_myself" : 'X\(//\)$' \| \
+        X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  srcdir=$ac_confdir
+  if test ! -r "$srcdir/$ac_unique_file"; then
+    srcdir=..
+  fi
+else
+  ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+  test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+  { $as_echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2
+   { (exit 1); exit 1; }; }
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+       cd "$srcdir" && test -r "./$ac_unique_file" || { $as_echo "$as_me: error: $ac_msg" >&2
+   { (exit 1); exit 1; }; }
+       pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+  srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+  eval ac_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_env_${ac_var}_value=\$${ac_var}
+  eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+  eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+  # Omit some internal or obsolete options to make the list less imposing.
+  # This message is too long to be a string in the A/UX 3.1 sh.
+  cat <<_ACEOF
+\`configure' configures nazghul 0.7.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE.  See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+  -h, --help              display this help and exit
+      --help=short        display options specific to this package
+      --help=recursive    display the short help of all the included packages
+  -V, --version           display version information and exit
+  -q, --quiet, --silent   do not print \`checking...' messages
+      --cache-file=FILE   cache test results in FILE [disabled]
+  -C, --config-cache      alias for \`--cache-file=config.cache'
+  -n, --no-create         do not create output files
+      --srcdir=DIR        find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+                          [$ac_default_prefix]
+  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX
+                          [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc.  You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+  --bindir=DIR            user executables [EPREFIX/bin]
+  --sbindir=DIR           system admin executables [EPREFIX/sbin]
+  --libexecdir=DIR        program executables [EPREFIX/libexec]
+  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
+  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
+  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --libdir=DIR            object code libraries [EPREFIX/lib]
+  --includedir=DIR        C header files [PREFIX/include]
+  --oldincludedir=DIR     C header files for non-gcc [/usr/include]
+  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]
+  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]
+  --infodir=DIR           info documentation [DATAROOTDIR/info]
+  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]
+  --mandir=DIR            man documentation [DATAROOTDIR/man]
+  --docdir=DIR            documentation root [DATAROOTDIR/doc/nazghul]
+  --htmldir=DIR           html documentation [DOCDIR]
+  --dvidir=DIR            dvi documentation [DOCDIR]
+  --pdfdir=DIR            pdf documentation [DOCDIR]
+  --psdir=DIR             ps documentation [DOCDIR]
+_ACEOF
+
+  cat <<\_ACEOF
+
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+  --program-transform-name=PROGRAM   run sed PROGRAM on installed program names
+
+System types:
+  --build=BUILD     configure for building on BUILD [guessed]
+  --host=HOST       cross-compile to build programs to run on HOST [BUILD]
+  --target=TARGET   configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+  case $ac_init_help in
+     short | recursive ) echo "Configuration of nazghul 0.7.1:";;
+   esac
+  cat <<\_ACEOF
+
+Optional Features:
+  --disable-option-checking  ignore unrecognized --enable/--with options
+  --disable-FEATURE       do not include FEATURE (same as --enable-FEATURE=no)
+  --enable-FEATURE[=ARG]  include FEATURE [ARG=yes]
+  --enable-maintainer-mode  enable make rules and dependencies not useful
+                         (and sometimes confusing) to the casual installer
+  --disable-dependency-tracking  speeds up one-time build
+  --enable-dependency-tracking   do not reject slow dependency extractors
+  --disable-sdltest       Do not try to compile and run a test SDL program
+  --enable-dynamic-link   Create dynamically linked binaries (default)
+
+Optional Packages:
+  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
+  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --with-sdl-prefix=PFX   Prefix where SDL is installed (optional)
+  --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)
+
+Some influential environment variables:
+  CC          C compiler command
+  CFLAGS      C compiler flags
+  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a
+              nonstandard directory <lib dir>
+  LIBS        libraries to pass to the linker, e.g. -l<library>
+  CPPFLAGS    C/C++/Objective C preprocessor flags, e.g. -I<include dir> if
+              you have headers in a nonstandard directory <include dir>
+  CXX         C++ compiler command
+  CXXFLAGS    C++ compiler flags
+  CPP         C preprocessor
+  CXXCPP      C++ preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to <nazghul-devel@lists.sourceforge.net>.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+  # If there are subdirs, report their specific --help.
+  for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+    test -d "$ac_dir" ||
+      { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+      continue
+    ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+    cd "$ac_dir" || { ac_status=$?; continue; }
+    # Check for guested configure.
+    if test -f "$ac_srcdir/configure.gnu"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+    elif test -f "$ac_srcdir/configure"; then
+      echo &&
+      $SHELL "$ac_srcdir/configure" --help=recursive
+    else
+      $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+    fi || ac_status=$?
+    cd "$ac_pwd" || { ac_status=$?; break; }
+  done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+  cat <<\_ACEOF
+nazghul configure 0.7.1
+generated by GNU Autoconf 2.63
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
+2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+  exit
+fi
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by nazghul $as_me 0.7.1, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`
+
+/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`
+/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`
+/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  $as_echo "PATH: $as_dir"
+done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+  for ac_arg
+  do
+    case $ac_arg in
+    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+    -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+    | -silent | --silent | --silen | --sile | --sil)
+      continue ;;
+    *\'*)
+      ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    case $ac_pass in
+    1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;;
+    2)
+      ac_configure_args1="$ac_configure_args1 '$ac_arg'"
+      if test $ac_must_keep_next = true; then
+       ac_must_keep_next=false # Got value, back to normal.
+      else
+       case $ac_arg in
+         *=* | --config-cache | -C | -disable-* | --disable-* \
+         | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+         | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+         | -with-* | --with-* | -without-* | --without-* | --x)
+           case "$ac_configure_args0 " in
+             "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+           esac
+           ;;
+         -* ) ac_must_keep_next=true ;;
+       esac
+      fi
+      ac_configure_args="$ac_configure_args '$ac_arg'"
+      ;;
+    esac
+  done
+done
+$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; }
+$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; }
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log.  We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+  # Save into config.log some information that might help in debugging.
+  {
+    echo
+
+    cat <<\_ASBOX
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+_ASBOX
+    echo
+    # The following way of writing the cache mishandles newlines in values,
+(
+  for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+  (set) 2>&1 |
+    case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      sed -n \
+       "s/'\''/'\''\\\\'\'''\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+      ;; #(
+    *)
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+)
+    echo
+
+    cat <<\_ASBOX
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+_ASBOX
+    echo
+    for ac_var in $ac_subst_vars
+    do
+      eval ac_val=\$$ac_var
+      case $ac_val in
+      *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+      esac
+      $as_echo "$ac_var='\''$ac_val'\''"
+    done | sort
+    echo
+
+    if test -n "$ac_subst_files"; then
+      cat <<\_ASBOX
+## ------------------- ##
+## File substitutions. ##
+## ------------------- ##
+_ASBOX
+      echo
+      for ac_var in $ac_subst_files
+      do
+       eval ac_val=\$$ac_var
+       case $ac_val in
+       *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+       esac
+       $as_echo "$ac_var='\''$ac_val'\''"
+      done | sort
+      echo
+    fi
+
+    if test -s confdefs.h; then
+      cat <<\_ASBOX
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+_ASBOX
+      echo
+      cat confdefs.h
+      echo
+    fi
+    test "$ac_signal" != 0 &&
+      $as_echo "$as_me: caught signal $ac_signal"
+    $as_echo "$as_me: exit $exit_status"
+  } >&5
+  rm -f core *.core core.conftest.* &&
+    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+    exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+  trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+  ac_site_file1=$CONFIG_SITE
+elif test "x$prefix" != xNONE; then
+  ac_site_file1=$prefix/share/config.site
+  ac_site_file2=$prefix/etc/config.site
+else
+  ac_site_file1=$ac_default_prefix/share/config.site
+  ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+  test "x$ac_site_file" = xNONE && continue
+  if test -r "$ac_site_file"; then
+    { $as_echo "$as_me:$LINENO: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+    sed 's/^/| /' "$ac_site_file" >&5
+    . "$ac_site_file"
+  fi
+done
+
+if test -r "$cache_file"; then
+  # Some versions of bash will fail to source /dev/null (special
+  # files actually), so we avoid doing that.
+  if test -f "$cache_file"; then
+    { $as_echo "$as_me:$LINENO: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+    case $cache_file in
+      [\\/]* | ?:[\\/]* ) . "$cache_file";;
+      *)                      . "./$cache_file";;
+    esac
+  fi
+else
+  { $as_echo "$as_me:$LINENO: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+  >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+  eval ac_old_set=\$ac_cv_env_${ac_var}_set
+  eval ac_new_set=\$ac_env_${ac_var}_set
+  eval ac_old_val=\$ac_cv_env_${ac_var}_value
+  eval ac_new_val=\$ac_env_${ac_var}_value
+  case $ac_old_set,$ac_new_set in
+    set,)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,set)
+      { $as_echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+      ac_cache_corrupted=: ;;
+    ,);;
+    *)
+      if test "x$ac_old_val" != "x$ac_new_val"; then
+       # differences in whitespace do not lead to failure.
+       ac_old_val_w=`echo x $ac_old_val`
+       ac_new_val_w=`echo x $ac_new_val`
+       if test "$ac_old_val_w" != "$ac_new_val_w"; then
+         { $as_echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+         ac_cache_corrupted=:
+       else
+         { $as_echo "$as_me:$LINENO: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+         eval $ac_var=\$ac_old_val
+       fi
+       { $as_echo "$as_me:$LINENO:   former value:  \`$ac_old_val'" >&5
+$as_echo "$as_me:   former value:  \`$ac_old_val'" >&2;}
+       { $as_echo "$as_me:$LINENO:   current value: \`$ac_new_val'" >&5
+$as_echo "$as_me:   current value: \`$ac_new_val'" >&2;}
+      fi;;
+  esac
+  # Pass precious variables to config.status.
+  if test "$ac_new_set" = set; then
+    case $ac_new_val in
+    *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+    *) ac_arg=$ac_var=$ac_new_val ;;
+    esac
+    case " $ac_configure_args " in
+      *" '$ac_arg' "*) ;; # Avoid dups.  Use of quotes ensures accuracy.
+      *) ac_configure_args="$ac_configure_args '$ac_arg'" ;;
+    esac
+  fi
+done
+if $ac_cache_corrupted; then
+  { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+  { $as_echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+  { { $as_echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5
+$as_echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+  if test -f "$ac_dir/install-sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install-sh -c"
+    break
+  elif test -f "$ac_dir/install.sh"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/install.sh -c"
+    break
+  elif test -f "$ac_dir/shtool"; then
+    ac_aux_dir=$ac_dir
+    ac_install_sh="$ac_aux_dir/shtool install -c"
+    break
+  fi
+done
+if test -z "$ac_aux_dir"; then
+  { { $as_echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&5
+$as_echo "$as_me: error: cannot find install-sh or install.sh in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess"  # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub"  # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure"  # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+  { { $as_echo "$as_me:$LINENO: error: cannot run $SHELL $ac_aux_dir/config.sub" >&5
+$as_echo "$as_me: error: cannot run $SHELL $ac_aux_dir/config.sub" >&2;}
+   { (exit 1); exit 1; }; }
+
+{ $as_echo "$as_me:$LINENO: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if test "${ac_cv_build+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+  ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+  { { $as_echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5
+$as_echo "$as_me: error: cannot guess build type; you must specify one" >&2;}
+   { (exit 1); exit 1; }; }
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+  { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&5
+$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $ac_build_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical build" >&5
+$as_echo "$as_me: error: invalid value of canonical build" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:$LINENO: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if test "${ac_cv_host+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$host_alias" = x; then
+  ac_cv_host=$ac_cv_build
+else
+  ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+    { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&5
+$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $host_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical host" >&5
+$as_echo "$as_me: error: invalid value of canonical host" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+
+{ $as_echo "$as_me:$LINENO: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if test "${ac_cv_target+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test "x$target_alias" = x; then
+  ac_cv_target=$ac_cv_host
+else
+  ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+    { { $as_echo "$as_me:$LINENO: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&5
+$as_echo "$as_me: error: $SHELL $ac_aux_dir/config.sub $target_alias failed" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) { { $as_echo "$as_me:$LINENO: error: invalid value of canonical target" >&5
+$as_echo "$as_me: error: invalid value of canonical target" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+  test "$program_prefix$program_suffix$program_transform_name" = \
+    NONENONEs,x,x, &&
+  program_prefix=${target_alias}-
+
+am__api_version='1.11'
+
+# Find a good install program.  We prefer a C program (faster),
+# so one script is as good as another.  But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if test "${ac_cv_path_install+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in
+  ./ | .// | /cC/* | \
+  /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+  ?:\\/os2\\/install\\/* | ?:\\/OS2\\/INSTALL\\/* | \
+  /usr/ucb/* ) ;;
+  *)
+    # OSF1 and SCO ODT 3.0 have their own names for install.
+    # Don't use installbsd from OSF since it installs stuff as root
+    # by default.
+    for ac_prog in ginstall scoinst install; do
+      for ac_exec_ext in '' $ac_executable_extensions; do
+       if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then
+         if test $ac_prog = install &&
+           grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # AIX install.  It has an incompatible calling convention.
+           :
+         elif test $ac_prog = install &&
+           grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+           # program-specific install script used by HP pwplus--don't use.
+           :
+         else
+           rm -rf conftest.one conftest.two conftest.dir
+           echo one > conftest.one
+           echo two > conftest.two
+           mkdir conftest.dir
+           if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+             test -s conftest.one && test -s conftest.two &&
+             test -s conftest.dir/conftest.one &&
+             test -s conftest.dir/conftest.two
+           then
+             ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+             break 3
+           fi
+         fi
+       fi
+      done
+    done
+    ;;
+esac
+
+done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+  if test "${ac_cv_path_install+set}" = set; then
+    INSTALL=$ac_cv_path_install
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for INSTALL within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    INSTALL=$ac_install_sh
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+{ $as_echo "$as_me:$LINENO: checking whether build environment is sane" >&5
+$as_echo_n "checking whether build environment is sane... " >&6; }
+# Just in case
+sleep 1
+echo timestamp > conftest.file
+# Reject unsafe characters in $srcdir or the absolute working directory
+# name.  Accept space and tab only in the latter.
+am_lf='
+'
+case `pwd` in
+  *[\\\"\#\$\&\'\`$am_lf]*)
+    { { $as_echo "$as_me:$LINENO: error: unsafe absolute working directory name" >&5
+$as_echo "$as_me: error: unsafe absolute working directory name" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+case $srcdir in
+  *[\\\"\#\$\&\'\`$am_lf\ \    ]*)
+    { { $as_echo "$as_me:$LINENO: error: unsafe srcdir value: \`$srcdir'" >&5
+$as_echo "$as_me: error: unsafe srcdir value: \`$srcdir'" >&2;}
+   { (exit 1); exit 1; }; };;
+esac
+
+# Do `set' in a subshell so we don't clobber the current shell's
+# arguments.  Must try -L first in case configure is actually a
+# symlink; some systems play weird games with the mod time of symlinks
+# (eg FreeBSD returns the mod time of the symlink's containing
+# directory).
+if (
+   set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
+   if test "$*" = "X"; then
+      # -L didn't work.
+      set X `ls -t "$srcdir/configure" conftest.file`
+   fi
+   rm -f conftest.file
+   if test "$*" != "X $srcdir/configure conftest.file" \
+      && test "$*" != "X conftest.file $srcdir/configure"; then
+
+      # If neither matched, then we have a broken ls.  This can happen
+      # if, for instance, CONFIG_SHELL is bash and it inherits a
+      # broken ls alias from the environment.  This has actually
+      # happened.  Such a system could not be considered "sane".
+      { { $as_echo "$as_me:$LINENO: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&5
+$as_echo "$as_me: error: ls -t appears to fail.  Make sure there is not a broken
+alias in your environment" >&2;}
+   { (exit 1); exit 1; }; }
+   fi
+
+   test "$2" = conftest.file
+   )
+then
+   # Ok.
+   :
+else
+   { { $as_echo "$as_me:$LINENO: error: newly created file is older than distributed files!
+Check your system clock" >&5
+$as_echo "$as_me: error: newly created file is older than distributed files!
+Check your system clock" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+test "$program_prefix" != NONE &&
+  program_transform_name="s&^&$program_prefix&;$program_transform_name"
+# Use a double $ so make ignores it.
+test "$program_suffix" != NONE &&
+  program_transform_name="s&\$&$program_suffix&;$program_transform_name"
+# Double any \ or $.
+# By default was `s,x,x', remove it if useless.
+ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
+program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
+
+# expand $ac_aux_dir to an absolute path
+am_aux_dir=`cd $ac_aux_dir && pwd`
+
+if test x"${MISSING+set}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
+  *)
+    MISSING="\${SHELL} $am_aux_dir/missing" ;;
+  esac
+fi
+# Use eval to expand $SHELL
+if eval "$MISSING --run true"; then
+  am_missing_run="$MISSING --run "
+else
+  am_missing_run=
+  { $as_echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5
+$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;}
+fi
+
+if test x"${install_sh}" != xset; then
+  case $am_aux_dir in
+  *\ * | *\    *)
+    install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
+  *)
+    install_sh="\${SHELL} $am_aux_dir/install-sh"
+  esac
+fi
+
+# Installed binaries are usually stripped using `strip' when the user
+# run `make install-strip'.  However `strip' might not be the right
+# tool to use in cross-compilation environments, therefore Automake
+# will honor the `STRIP' environment variable to overrule this program.
+if test "$cross_compiling" != no; then
+  if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args.
+set dummy ${ac_tool_prefix}strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_STRIP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$STRIP"; then
+  ac_cv_prog_STRIP="$STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_STRIP="${ac_tool_prefix}strip"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+STRIP=$ac_cv_prog_STRIP
+if test -n "$STRIP"; then
+  { $as_echo "$as_me:$LINENO: result: $STRIP" >&5
+$as_echo "$STRIP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_STRIP"; then
+  ac_ct_STRIP=$STRIP
+  # Extract the first word of "strip", so it can be a program name with args.
+set dummy strip; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_STRIP"; then
+  ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_STRIP="strip"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP
+if test -n "$ac_ct_STRIP"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5
+$as_echo "$ac_ct_STRIP" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_STRIP" = x; then
+    STRIP=":"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    STRIP=$ac_ct_STRIP
+  fi
+else
+  STRIP="$ac_cv_prog_STRIP"
+fi
+
+fi
+INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
+
+{ $as_echo "$as_me:$LINENO: checking for a thread-safe mkdir -p" >&5
+$as_echo_n "checking for a thread-safe mkdir -p... " >&6; }
+if test -z "$MKDIR_P"; then
+  if test "${ac_cv_path_mkdir+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in mkdir gmkdir; do
+        for ac_exec_ext in '' $ac_executable_extensions; do
+          { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue
+          case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #(
+            'mkdir (GNU coreutils) '* | \
+            'mkdir (coreutils) '* | \
+            'mkdir (fileutils) '4.1*)
+              ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext
+              break 3;;
+          esac
+        done
+       done
+done
+IFS=$as_save_IFS
+
+fi
+
+  if test "${ac_cv_path_mkdir+set}" = set; then
+    MKDIR_P="$ac_cv_path_mkdir -p"
+  else
+    # As a last resort, use the slow shell script.  Don't cache a
+    # value for MKDIR_P within a source directory, because that will
+    # break other packages using the cache if that directory is
+    # removed, or if the value is a relative name.
+    test -d ./--version && rmdir ./--version
+    MKDIR_P="$ac_install_sh -d"
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $MKDIR_P" >&5
+$as_echo "$MKDIR_P" >&6; }
+
+mkdir_p="$MKDIR_P"
+case $mkdir_p in
+  [\\/$]* | ?:[\\/]*) ;;
+  */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
+esac
+
+for ac_prog in gawk mawk nawk awk
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_AWK+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$AWK"; then
+  ac_cv_prog_AWK="$AWK" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_AWK="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+AWK=$ac_cv_prog_AWK
+if test -n "$AWK"; then
+  { $as_echo "$as_me:$LINENO: result: $AWK" >&5
+$as_echo "$AWK" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$AWK" && break
+done
+
+{ $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+rm -rf .tst 2>/dev/null
+mkdir .tst 2>/dev/null
+if test -d .tst; then
+  am__leading_dot=.
+else
+  am__leading_dot=_
+fi
+rmdir .tst 2>/dev/null
+
+if test "`cd $srcdir && pwd`" != "`pwd`"; then
+  # Use -I$(srcdir) only when $(srcdir) != ., so that make's output
+  # is not polluted with repeated "-I."
+  am__isrc=' -I$(srcdir)'
+  # test to see if srcdir already configured
+  if test -f $srcdir/config.status; then
+    { { $as_echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5
+$as_echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+fi
+
+# test whether we have cygpath
+if test -z "$CYGPATH_W"; then
+  if (cygpath --version) >/dev/null 2>/dev/null; then
+    CYGPATH_W='cygpath -w'
+  else
+    CYGPATH_W=echo
+  fi
+fi
+
+
+# Define the identity of the package.
+ PACKAGE='nazghul'
+ VERSION='0.7.1'
+
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE "$PACKAGE"
+_ACEOF
+
+
+cat >>confdefs.h <<_ACEOF
+#define VERSION "$VERSION"
+_ACEOF
+
+# Some tools Automake needs.
+
+ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"}
+
+
+AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"}
+
+
+AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"}
+
+
+AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"}
+
+
+MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"}
+
+# We need awk for the "check" target.  The system "awk" is bad on
+# some platforms.
+# Always define AMTAR for backward compatibility.
+
+AMTAR=${AMTAR-"${am_missing_run}tar"}
+
+am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
+
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking whether to enable maintainer-specific portions of Makefiles" >&5
+$as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; }
+    # Check whether --enable-maintainer-mode was given.
+if test "${enable_maintainer_mode+set}" = set; then
+  enableval=$enable_maintainer_mode; USE_MAINTAINER_MODE=$enableval
+else
+  USE_MAINTAINER_MODE=no
+fi
+
+  { $as_echo "$as_me:$LINENO: result: $USE_MAINTAINER_MODE" >&5
+$as_echo "$USE_MAINTAINER_MODE" >&6; }
+   if test $USE_MAINTAINER_MODE = yes; then
+  MAINTAINER_MODE_TRUE=
+  MAINTAINER_MODE_FALSE='#'
+else
+  MAINTAINER_MODE_TRUE='#'
+  MAINTAINER_MODE_FALSE=
+fi
+
+  MAINT=$MAINTAINER_MODE_TRUE
+
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+  # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}gcc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+  ac_ct_CC=$CC
+  # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="gcc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+else
+  CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+          if test -n "$ac_tool_prefix"; then
+    # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="${ac_tool_prefix}cc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  fi
+fi
+if test -z "$CC"; then
+  # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+  ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+       ac_prog_rejected=yes
+       continue
+     fi
+    ac_cv_prog_CC="cc"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+  # We found a bogon in the path, so make sure we never use it.
+  set dummy $ac_cv_prog_CC
+  shift
+  if test $# != 0; then
+    # We chose a different compiler from the bogus one.
+    # However, it has the same basename, so the bogon will be chosen
+    # first if we set CC to just the basename; use the full file name.
+    shift
+    ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+  fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+  if test -n "$ac_tool_prefix"; then
+  for ac_prog in cl.exe
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CC"; then
+  ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+  { $as_echo "$as_me:$LINENO: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CC" && break
+  done
+fi
+if test -z "$CC"; then
+  ac_ct_CC=$CC
+  for ac_prog in cl.exe
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CC+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CC"; then
+  ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CC="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CC" && break
+done
+
+  if test "x$ac_ct_CC" = x; then
+    CC=""
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CC=$ac_ct_CC
+  fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: no acceptable C compiler found in \$PATH
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:$LINENO: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:$LINENO: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+  esac
+done
+rm -f $ac_rmfiles
+
+if { (ac_try="$ac_link_default"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link_default") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile.  We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+       ;;
+    [ab].out )
+       # We found the default executable, but exeext='' is most
+       # certainly right.
+       break;;
+    *.* )
+        if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+       then :; else
+          ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+       fi
+       # We set ac_cv_exeext here because the later test for it is not
+       # safe: cross compilers may not add the suffix if given an `-o'
+       # argument, so we may need to know it at that point already.
+       # Even if this section looks crufty: it has the advantage of
+       # actually working.
+       break;;
+    * )
+       break;;
+  esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+  ac_file=''
+fi
+
+{ $as_echo "$as_me:$LINENO: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+if test -z "$ac_file"; then
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C compiler cannot create executables
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C compiler cannot create executables
+See \`config.log' for more details." >&2;}
+   { (exit 77); exit 77; }; }; }
+fi
+
+ac_exeext=$ac_cv_exeext
+
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+# FIXME: These cross compiler hacks should be removed for Autoconf 3.0
+# If not cross compiling, check that we can run a simple program.
+if test "$cross_compiling" != yes; then
+  if { ac_try='./$ac_file'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+    cross_compiling=no
+  else
+    if test "$cross_compiling" = maybe; then
+       cross_compiling=yes
+    else
+       { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+    fi
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+# Check that the compiler produces executables we can run.  If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:$LINENO: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+{ $as_echo "$as_me:$LINENO: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+{ $as_echo "$as_me:$LINENO: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+  test -f "$ac_file" || continue
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+    *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+         break;;
+    * ) break;;
+  esac
+done
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest$ac_cv_exeext
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+{ $as_echo "$as_me:$LINENO: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if test "${ac_cv_objext+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; then
+  for ac_file in conftest.o conftest.obj conftest.*; do
+  test -f "$ac_file" || continue;
+  case $ac_file in
+    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+    *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+       break;;
+  esac
+done
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: cannot compute suffix of object files: cannot compile
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if test "${ac_cv_c_compiler_gnu+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GCC=yes
+else
+  GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if test "${ac_cv_prog_cc_g+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_c_werror_flag=$ac_c_werror_flag
+   ac_c_werror_flag=yes
+   ac_cv_prog_cc_g=no
+   CFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_c_werror_flag=$ac_save_c_werror_flag
+        CFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+  CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+  if test "$GCC" = yes; then
+    CFLAGS="-g -O2"
+  else
+    CFLAGS="-g"
+  fi
+else
+  if test "$GCC" = yes; then
+    CFLAGS="-O2"
+  else
+    CFLAGS=
+  fi
+fi
+{ $as_echo "$as_me:$LINENO: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if test "${ac_cv_prog_cc_c89+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh.  */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+     char **p;
+     int i;
+{
+  return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+  char *s;
+  va_list v;
+  va_start (v,p);
+  s = g (p, va_arg (v,int));
+  va_end (v);
+  return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has
+   function prototypes and stuff, but not '\xHH' hex character constants.
+   These don't provoke an error unfortunately, instead are silently treated
+   as 'x'.  The following induces an error, until -std is added to get
+   proper ANSI mode.  Curiously '\x00'!='x' always comes out true, for an
+   array size at least.  It's necessary to write '\x00'==0 to get something
+   that's true only with -std.  */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+   inside strings and character constants.  */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0]  ||  f (e, argv, 1) != argv[1];
+  ;
+  return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+       -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+  CC="$ac_save_CC $ac_arg"
+  rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cc_c89=$ac_arg
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext
+  test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+  x)
+    { $as_echo "$as_me:$LINENO: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+  xno)
+    { $as_echo "$as_me:$LINENO: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+  *)
+    CC="$CC $ac_cv_prog_cc_c89"
+    { $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+DEPDIR="${am__leading_dot}deps"
+
+ac_config_commands="$ac_config_commands depfiles"
+
+
+am_make=${MAKE-make}
+cat > confinc << 'END'
+am__doit:
+       @echo this is the am__doit target
+.PHONY: am__doit
+END
+# If we don't find an include directive, just comment out the code.
+{ $as_echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5
+$as_echo_n "checking for style of include used by $am_make... " >&6; }
+am__include="#"
+am__quote=
+_am_result=none
+# First try GNU make style include.
+echo "include confinc" > confmf
+# Ignore all kinds of additional output from `make'.
+case `$am_make -s -f confmf 2> /dev/null` in #(
+*the\ am__doit\ target*)
+  am__include=include
+  am__quote=
+  _am_result=GNU
+  ;;
+esac
+# Now try BSD make style include.
+if test "$am__include" = "#"; then
+   echo '.include "confinc"' > confmf
+   case `$am_make -s -f confmf 2> /dev/null` in #(
+   *the\ am__doit\ target*)
+     am__include=.include
+     am__quote="\""
+     _am_result=BSD
+     ;;
+   esac
+fi
+
+
+{ $as_echo "$as_me:$LINENO: result: $_am_result" >&5
+$as_echo "$_am_result" >&6; }
+rm -f confinc confmf
+
+# Check whether --enable-dependency-tracking was given.
+if test "${enable_dependency_tracking+set}" = set; then
+  enableval=$enable_dependency_tracking;
+fi
+
+if test "x$enable_dependency_tracking" != xno; then
+  am_depcomp="$ac_aux_dir/depcomp"
+  AMDEPBACKSLASH='\'
+fi
+ if test "x$enable_dependency_tracking" != xno; then
+  AMDEP_TRUE=
+  AMDEP_FALSE='#'
+else
+  AMDEP_TRUE='#'
+  AMDEP_FALSE=
+fi
+
+
+
+depcc="$CC"   am_compiler_list=
+
+{ $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CC_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CC_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CC_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CC_dependencies_compiler_type" >&6; }
+CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then
+  am__fastdepCC_TRUE=
+  am__fastdepCC_FALSE='#'
+else
+  am__fastdepCC_TRUE='#'
+  am__fastdepCC_FALSE=
+fi
+
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+if test -z "$CXX"; then
+  if test -n "$CCC"; then
+    CXX=$CCC
+  else
+    if test -n "$ac_tool_prefix"; then
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+  do
+    # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_CXX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$CXX"; then
+  ac_cv_prog_CXX="$CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_CXX="$ac_tool_prefix$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+CXX=$ac_cv_prog_CXX
+if test -n "$CXX"; then
+  { $as_echo "$as_me:$LINENO: result: $CXX" >&5
+$as_echo "$CXX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+    test -n "$CXX" && break
+  done
+fi
+if test -z "$CXX"; then
+  ac_ct_CXX=$CXX
+  for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC
+do
+  # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -n "$ac_ct_CXX"; then
+  ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_prog_ac_ct_CXX="$ac_prog"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CXX=$ac_cv_prog_ac_ct_CXX
+if test -n "$ac_ct_CXX"; then
+  { $as_echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5
+$as_echo "$ac_ct_CXX" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  test -n "$ac_ct_CXX" && break
+done
+
+  if test "x$ac_ct_CXX" = x; then
+    CXX="g++"
+  else
+    case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:$LINENO: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+    CXX=$ac_ct_CXX
+  fi
+fi
+
+  fi
+fi
+# Provide some information about the compiler.
+$as_echo "$as_me:$LINENO: checking for C++ compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+{ (ac_try="$ac_compiler --version >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler --version >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -v >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -v >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+{ (ac_try="$ac_compiler -V >&5"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compiler -V >&5") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }
+
+{ $as_echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5
+$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; }
+if test "${ac_cv_cxx_compiler_gnu+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+#ifndef __GNUC__
+       choke me
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_compiler_gnu=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_compiler_gnu=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_cxx_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5
+$as_echo "$ac_cv_cxx_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+  GXX=yes
+else
+  GXX=
+fi
+ac_test_CXXFLAGS=${CXXFLAGS+set}
+ac_save_CXXFLAGS=$CXXFLAGS
+{ $as_echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5
+$as_echo_n "checking whether $CXX accepts -g... " >&6; }
+if test "${ac_cv_prog_cxx_g+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_save_cxx_werror_flag=$ac_cxx_werror_flag
+   ac_cxx_werror_flag=yes
+   ac_cv_prog_cxx_g=no
+   CXXFLAGS="-g"
+   cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       CXXFLAGS=""
+      cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+        CXXFLAGS="-g"
+        cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_prog_cxx_g=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+   ac_cxx_werror_flag=$ac_save_cxx_werror_flag
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5
+$as_echo "$ac_cv_prog_cxx_g" >&6; }
+if test "$ac_test_CXXFLAGS" = set; then
+  CXXFLAGS=$ac_save_CXXFLAGS
+elif test $ac_cv_prog_cxx_g = yes; then
+  if test "$GXX" = yes; then
+    CXXFLAGS="-g -O2"
+  else
+    CXXFLAGS="-g"
+  fi
+else
+  if test "$GXX" = yes; then
+    CXXFLAGS="-O2"
+  else
+    CXXFLAGS=
+  fi
+fi
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+depcc="$CXX"  am_compiler_list=
+
+{ $as_echo "$as_me:$LINENO: checking dependency style of $depcc" >&5
+$as_echo_n "checking dependency style of $depcc... " >&6; }
+if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then
+  # We make a subdir and do the tests there.  Otherwise we can end up
+  # making bogus files that we don't know about and never remove.  For
+  # instance it was reported that on HP-UX the gcc test will end up
+  # making a dummy file named `D' -- because `-MD' means `put the output
+  # in D'.
+  mkdir conftest.dir
+  # Copy depcomp to subdir because otherwise we won't find it if we're
+  # using a relative directory.
+  cp "$am_depcomp" conftest.dir
+  cd conftest.dir
+  # We will build objects and dependencies in a subdirectory because
+  # it helps to detect inapplicable dependency modes.  For instance
+  # both Tru64's cc and ICC support -MD to output dependencies as a
+  # side effect of compilation, but ICC will put the dependencies in
+  # the current directory while Tru64 will put them in the object
+  # directory.
+  mkdir sub
+
+  am_cv_CXX_dependencies_compiler_type=none
+  if test "$am_compiler_list" = ""; then
+     am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp`
+  fi
+  am__universal=false
+  case " $depcc " in #(
+     *\ -arch\ *\ -arch\ *) am__universal=true ;;
+     esac
+
+  for depmode in $am_compiler_list; do
+    # Setup a source with many dependencies, because some compilers
+    # like to wrap large dependency lists on column 80 (with \), and
+    # we should not choose a depcomp mode which is confused by this.
+    #
+    # We need to recreate these files for each test, as the compiler may
+    # overwrite some of them when testing with obscure command lines.
+    # This happens at least with the AIX C compiler.
+    : > sub/conftest.c
+    for i in 1 2 3 4 5 6; do
+      echo '#include "conftst'$i'.h"' >> sub/conftest.c
+      # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with
+      # Solaris 8's {/usr,}/bin/sh.
+      touch sub/conftst$i.h
+    done
+    echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf
+
+    # We check with `-c' and `-o' for the sake of the "dashmstdout"
+    # mode.  It turns out that the SunPro C++ compiler does not properly
+    # handle `-M -o', and we need to detect this.  Also, some Intel
+    # versions had trouble with output in subdirs
+    am__obj=sub/conftest.${OBJEXT-o}
+    am__minus_obj="-o $am__obj"
+    case $depmode in
+    gcc)
+      # This depmode causes a compiler race in universal mode.
+      test "$am__universal" = false || continue
+      ;;
+    nosideeffect)
+      # after this tag, mechanisms are not by side-effect, so they'll
+      # only be used when explicitly requested
+      if test "x$enable_dependency_tracking" = xyes; then
+       continue
+      else
+       break
+      fi
+      ;;
+    msvisualcpp | msvcmsys)
+      # This compiler won't grok `-c -o', but also, the minuso test has
+      # not run yet.  These depmodes are late enough in the game, and
+      # so weak that their functioning should not be impacted.
+      am__obj=conftest.${OBJEXT-o}
+      am__minus_obj=
+      ;;
+    none) break ;;
+    esac
+    if depmode=$depmode \
+       source=sub/conftest.c object=$am__obj \
+       depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \
+       $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \
+         >/dev/null 2>conftest.err &&
+       grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 &&
+       grep $am__obj sub/conftest.Po > /dev/null 2>&1 &&
+       ${MAKE-make} -s -f confmf > /dev/null 2>&1; then
+      # icc doesn't choke on unknown options, it will just issue warnings
+      # or remarks (even with -Werror).  So we grep stderr for any message
+      # that says an option was ignored or not supported.
+      # When given -MP, icc 7.0 and 7.1 complain thusly:
+      #   icc: Command line warning: ignoring option '-M'; no argument required
+      # The diagnosis changed in icc 8.0:
+      #   icc: Command line remark: option '-MP' not supported
+      if (grep 'ignoring option' conftest.err ||
+          grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else
+        am_cv_CXX_dependencies_compiler_type=$depmode
+        break
+      fi
+    fi
+  done
+
+  cd ..
+  rm -rf conftest.dir
+else
+  am_cv_CXX_dependencies_compiler_type=none
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5
+$as_echo "$am_cv_CXX_dependencies_compiler_type" >&6; }
+CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type
+
+ if
+  test "x$enable_dependency_tracking" != xno \
+  && test "$am_cv_CXX_dependencies_compiler_type" = gcc3; then
+  am__fastdepCXX_TRUE=
+  am__fastdepCXX_FALSE='#'
+else
+  am__fastdepCXX_TRUE='#'
+  am__fastdepCXX_FALSE=
+fi
+
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+       @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+  *@@@%%%=?*=@@@%%%*)
+    eval ac_cv_prog_make_${ac_make}_set=yes;;
+  *)
+    eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+  { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+  SET_MAKE=
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+  SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+
+
+SDL_VERSION=1.2.3
+
+
+# Check whether --with-sdl-prefix was given.
+if test "${with_sdl_prefix+set}" = set; then
+  withval=$with_sdl_prefix; sdl_prefix="$withval"
+else
+  sdl_prefix=""
+fi
+
+
+# Check whether --with-sdl-exec-prefix was given.
+if test "${with_sdl_exec_prefix+set}" = set; then
+  withval=$with_sdl_exec_prefix; sdl_exec_prefix="$withval"
+else
+  sdl_exec_prefix=""
+fi
+
+# Check whether --enable-sdltest was given.
+if test "${enable_sdltest+set}" = set; then
+  enableval=$enable_sdltest;
+else
+  enable_sdltest=yes
+fi
+
+
+  if test x$sdl_exec_prefix != x ; then
+     sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
+     if test x${SDL_CONFIG+set} != xset ; then
+        SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
+     fi
+  fi
+  if test x$sdl_prefix != x ; then
+     sdl_args="$sdl_args --prefix=$sdl_prefix"
+     if test x${SDL_CONFIG+set} != xset ; then
+        SDL_CONFIG=$sdl_prefix/bin/sdl-config
+     fi
+  fi
+
+
+  PATH="$prefix/bin:$prefix/usr/bin:$PATH"
+  # Extract the first word of "sdl-config", so it can be a program name with args.
+set dummy sdl-config; ac_word=$2
+{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if test "${ac_cv_path_SDL_CONFIG+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  case $SDL_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_SDL_CONFIG="$SDL_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
+    ac_cv_path_SDL_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_SDL_CONFIG" && ac_cv_path_SDL_CONFIG="no"
+  ;;
+esac
+fi
+SDL_CONFIG=$ac_cv_path_SDL_CONFIG
+if test -n "$SDL_CONFIG"; then
+  { $as_echo "$as_me:$LINENO: result: $SDL_CONFIG" >&5
+$as_echo "$SDL_CONFIG" >&6; }
+else
+  { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+  min_sdl_version=$SDL_VERSION
+  { $as_echo "$as_me:$LINENO: checking for SDL - version >= $min_sdl_version" >&5
+$as_echo_n "checking for SDL - version >= $min_sdl_version... " >&6; }
+  no_sdl=""
+  if test "$SDL_CONFIG" = "no" ; then
+    no_sdl=yes
+  else
+    SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
+    SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
+
+    sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\1/'`
+    sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\2/'`
+    sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
+           sed 's/\([0-9]*\).\([0-9]*\).\([0-9]*\)/\3/'`
+    if test "x$enable_sdltest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $SDL_CFLAGS"
+      LIBS="$LIBS $SDL_LIBS"
+      rm -f conf.sdltest
+      if test "$cross_compiling" = yes; then
+  echo $ac_n "cross compiling; assumed OK... $ac_c"
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SDL.h"
+
+char*
+my_strdup (char *str)
+{
+  char *new_str;
+
+  if (str)
+    {
+      new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
+      strcpy (new_str, str);
+    }
+  else
+    new_str = NULL;
+
+  return new_str;
+}
+
+int main (int argc, char *argv[])
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  /* This hangs on some systems (?)
+  system ("touch conf.sdltest");
+  */
+  { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); }
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = my_strdup("$min_sdl_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_sdl_version");
+     exit(1);
+   }
+
+   if (($sdl_major_version > major) ||
+      (($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
+      (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
+      printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
+      printf("*** to point to the correct copy of sdl-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+no_sdl=yes
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_sdl" = x ; then
+     { $as_echo "$as_me:$LINENO: result: yes" >&5
+$as_echo "yes" >&6; }
+     :
+  else
+     { $as_echo "$as_me:$LINENO: result: no" >&5
+$as_echo "no" >&6; }
+     if test "$SDL_CONFIG" = "no" ; then
+       echo "*** The sdl-config script installed by SDL could not be found"
+       echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the SDL_CONFIG environment variable to the"
+       echo "*** full path to sdl-config."
+     else
+       if test -f conf.sdltest ; then
+        :
+       else
+          echo "*** Could not run SDL test program, checking why..."
+          CFLAGS="$CFLAGS $SDL_CFLAGS"
+          LIBS="$LIBS $SDL_LIBS"
+          cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+#include <stdio.h>
+#include "SDL.h"
+
+int main(int argc, char *argv[])
+{ return 0; }
+#undef  main
+#define main K_and_R_C_main
+
+int
+main ()
+{
+ return 0;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+   echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding SDL or finding the wrong"
+          echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+         echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+        echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means SDL was incorrectly installed"
+          echo "*** or that you have moved SDL since it was installed. In the latter case, you"
+          echo "*** may want to edit the sdl-config script: $SDL_CONFIG"
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     SDL_CFLAGS=""
+     SDL_LIBS=""
+     { { $as_echo "$as_me:$LINENO: error: *** SDL version $SDL_VERSION not found!" >&5
+$as_echo "$as_me: error: *** SDL version $SDL_VERSION not found!" >&2;}
+   { (exit 1); exit 1; }; }
+
+  fi
+
+
+  rm -f conf.sdltest
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+  CPP=
+fi
+if test -z "$CPP"; then
+  if test "${ac_cv_prog_CPP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CPP needs to be expanded
+    for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CPP=$CPP
+
+fi
+  CPP=$ac_cv_prog_CPP
+else
+  ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:$LINENO: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:$LINENO: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if test "${ac_cv_path_GREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if test -z "$GREP"; then
+  ac_path_GREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in grep ggrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+  # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'GREP' >> "conftest.nl"
+    "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_GREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_GREP="$ac_path_GREP"
+      ac_path_GREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_GREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_GREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if test "${ac_cv_path_EGREP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+   then ac_cv_path_EGREP="$GREP -E"
+   else
+     if test -z "$EGREP"; then
+  ac_path_EGREP_found=false
+  # Loop through the user's path and test for each of PROGNAME-LIST
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_prog in egrep; do
+    for ac_exec_ext in '' $ac_executable_extensions; do
+      ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+      { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+  # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+  ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+  ac_count=0
+  $as_echo_n 0123456789 >"conftest.in"
+  while :
+  do
+    cat "conftest.in" "conftest.in" >"conftest.tmp"
+    mv "conftest.tmp" "conftest.in"
+    cp "conftest.in" "conftest.nl"
+    $as_echo 'EGREP' >> "conftest.nl"
+    "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+    diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+    ac_count=`expr $ac_count + 1`
+    if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+      # Best one so far, save it but keep looking for a better one
+      ac_cv_path_EGREP="$ac_path_EGREP"
+      ac_path_EGREP_max=$ac_count
+    fi
+    # 10*(2^10) chars as input seems more than enough
+    test $ac_count -gt 10 && break
+  done
+  rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+      $ac_path_EGREP_found && break 3
+    done
+  done
+done
+IFS=$as_save_IFS
+  if test -z "$ac_cv_path_EGREP"; then
+    { { $as_echo "$as_me:$LINENO: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&5
+$as_echo "$as_me: error: no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+else
+  ac_cv_path_EGREP=$EGREP
+fi
+
+   fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:$LINENO: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if test "${ac_cv_header_stdc+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_c_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_header_stdc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_header_stdc=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+  # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "memchr" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "free" >/dev/null 2>&1; then
+  :
+else
+  ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+  # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+  if test "$cross_compiling" = yes; then
+  :
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+                  (('a' <= (c) && (c) <= 'i') \
+                    || ('j' <= (c) && (c) <= 'r') \
+                    || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+  int i;
+  for (i = 0; i < 256; i++)
+    if (XOR (islower (i), ISLOWER (i))
+       || toupper (i) != TOUPPER (i))
+      return 2;
+  return 0;
+}
+_ACEOF
+rm -f conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+  { (case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_try") 2>&5
+  ac_status=$?
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  :
+else
+  $as_echo "$as_me: program exited with status $ac_status" >&5
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+( exit $ac_status )
+ac_cv_header_stdc=no
+fi
+rm -rf conftest.dSYM
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define STDC_HEADERS 1
+_ACEOF
+
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+
+
+
+
+
+
+
+
+
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+                 inttypes.h stdint.h unistd.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  eval "$as_ac_Header=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_Header=no"
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+                $as_echo "$as_val"'`
+              { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_Header'}
+                $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+{ $as_echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5
+$as_echo_n "checking how to run the C++ preprocessor... " >&6; }
+if test -z "$CXXCPP"; then
+  if test "${ac_cv_prog_CXXCPP+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+      # Double quotes because CXXCPP needs to be expanded
+    for CXXCPP in "$CXX -E" "/lib/cpp"
+    do
+      ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  break
+fi
+
+    done
+    ac_cv_prog_CXXCPP=$CXXCPP
+
+fi
+  CXXCPP=$ac_cv_prog_CXXCPP
+else
+  ac_cv_prog_CXXCPP=$CXXCPP
+fi
+{ $as_echo "$as_me:$LINENO: result: $CXXCPP" >&5
+$as_echo "$CXXCPP" >&6; }
+ac_preproc_ok=false
+for ac_cxx_preproc_warn_flag in '' yes
+do
+  # Use a header file that comes with gcc, so configuring glibc
+  # with a fresh cross-compiler works.
+  # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+  # <limits.h> exists even on freestanding compilers.
+  # On the NeXT, cc -E runs the code through the compiler's parser,
+  # not just through cpp. "Syntax error" is here to catch this case.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+                    Syntax error
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  :
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Broken: fails on valid input.
+continue
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+  # OK, works on sane cases.  Now check whether nonexistent headers
+  # can be detected and how.
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <ac_nonexistent.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  # Broken: success on invalid input.
+continue
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+
+rm -f conftest.err conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+{ { $as_echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&5
+$as_echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check
+See \`config.log' for more details." >&2;}
+   { (exit 1); exit 1; }; }; }
+fi
+
+ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+
+
+
+
+for ac_header in fcntl.h \
+       malloc.h          \
+       float.h           \
+       limits.h
+do
+as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+                $as_echo "$as_val"'`
+              { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5
+$as_echo_n "checking $ac_header usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <$ac_header>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5
+$as_echo_n "checking $ac_header presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <$ac_header>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $ac_header:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $ac_header:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------------------------------- ##
+## Report this to nazghul-devel@lists.sourceforge.net ##
+## -------------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5
+$as_echo_n "checking for $ac_header... " >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval 'as_val=${'$as_ac_Header'}
+                $as_echo "$as_val"'`
+              { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+
+fi
+as_val=`eval 'as_val=${'$as_ac_Header'}
+                $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+
+{ $as_echo "$as_me:$LINENO: checking whether what binaries we shall create" >&5
+$as_echo_n "checking whether what binaries we shall create... " >&6; }
+# Check whether --enable-dynamic-link was given.
+if test "${enable_dynamic_link+set}" = set; then
+  enableval=$enable_dynamic_link; if test "$enableval" = "yes"; then
+    { $as_echo "$as_me:$LINENO: result: dynamically linked" >&5
+$as_echo "dynamically linked" >&6; }
+else
+    LDFLAGS="$LDFLAGS -static"
+    { $as_echo "$as_me:$LINENO: result: statically linked" >&5
+$as_echo "statically linked" >&6; }
+fi
+else
+  { $as_echo "$as_me:$LINENO: result: dynamically linked" >&5
+$as_echo "dynamically linked" >&6; }
+fi
+
+
+{ $as_echo "$as_me:$LINENO: checking for an ANSI C-conforming const" >&5
+$as_echo_n "checking for an ANSI C-conforming const... " >&6; }
+if test "${ac_cv_c_const+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+/* FIXME: Include the comments suggested by Paul. */
+#ifndef __cplusplus
+  /* Ultrix mips cc rejects this.  */
+  typedef int charset[2];
+  const charset cs;
+  /* SunOS 4.1.1 cc rejects this.  */
+  char const *const *pcpcc;
+  char **ppc;
+  /* NEC SVR4.0.2 mips cc rejects this.  */
+  struct point {int x, y;};
+  static struct point const zero = {0,0};
+  /* AIX XL C 1.02.0.0 rejects this.
+     It does not let you subtract one const X* pointer from another in
+     an arm of an if-expression whose if-part is not a constant
+     expression */
+  const char *g = "string";
+  pcpcc = &g + (g ? g-g : 0);
+  /* HPUX 7.0 cc rejects these. */
+  ++pcpcc;
+  ppc = (char**) pcpcc;
+  pcpcc = (char const *const *) ppc;
+  { /* SCO 3.2v4 cc rejects this.  */
+    char *t;
+    char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+    *t++ = 0;
+    if (s) return 0;
+  }
+  { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
+    int x[] = {25, 17};
+    const int *foo = &x[0];
+    ++foo;
+  }
+  { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+    typedef const int *iptr;
+    iptr p = 0;
+    ++p;
+  }
+  { /* AIX XL C 1.02.0.0 rejects this saying
+       "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+    struct s { int j; const int *ap[3]; };
+    struct s *b; b->j = 5;
+  }
+  { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+    const int foo = 10;
+    if (!foo) return 0;
+  }
+  return !cs[0] && !zero.x;
+#endif
+
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_const=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_const=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_const" >&5
+$as_echo "$ac_cv_c_const" >&6; }
+if test $ac_cv_c_const = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define const /**/
+_ACEOF
+
+fi
+
+{ $as_echo "$as_me:$LINENO: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+if test "${ac_cv_c_inline+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_c_inline=no
+for ac_kw in inline __inline__ __inline; do
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#ifndef __cplusplus
+typedef int foo_t;
+static $ac_kw foo_t static_foo () {return 0; }
+$ac_kw foo_t foo () {return 0; }
+#endif
+
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_inline=$ac_kw
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+  test "$ac_cv_c_inline" != no && break
+done
+
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_inline" >&5
+$as_echo "$ac_cv_c_inline" >&6; }
+
+
+case $ac_cv_c_inline in
+  inline | yes) ;;
+  *)
+    case $ac_cv_c_inline in
+      no) ac_val=;;
+      *) ac_val=$ac_cv_c_inline;;
+    esac
+    cat >>confdefs.h <<_ACEOF
+#ifndef __cplusplus
+#define inline $ac_val
+#endif
+_ACEOF
+    ;;
+esac
+
+{ $as_echo "$as_me:$LINENO: checking for working volatile" >&5
+$as_echo_n "checking for working volatile... " >&6; }
+if test "${ac_cv_c_volatile+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+int
+main ()
+{
+
+volatile int x;
+int * volatile y = (int *) 0;
+return !x && !y;
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_cv_c_volatile=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_c_volatile=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_c_volatile" >&5
+$as_echo "$ac_cv_c_volatile" >&6; }
+if test $ac_cv_c_volatile = no; then
+
+cat >>confdefs.h <<\_ACEOF
+#define volatile /**/
+_ACEOF
+
+fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+for ac_func in malloc  \
+       realloc         \
+       select_argtypes \
+       vprintf         \
+       strerror        \
+       strpbrk         \
+       strstr          \
+       atexit          \
+       floor           \
+       strcasecmp      \
+       strdup          \
+       realloc         \
+       select          \
+        strchr
+do
+as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
+$as_echo_n "checking for $ac_func... " >&6; }
+if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then
+  $as_echo_n "(cached) " >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+/* Define $ac_func to an innocuous variant, in case <limits.h> declares $ac_func.
+   For example, HP-UX 11i <limits.h> declares gettimeofday.  */
+#define $ac_func innocuous_$ac_func
+
+/* System header to define __stub macros and hopefully few prototypes,
+    which can conflict with char $ac_func (); below.
+    Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+    <limits.h> exists even on freestanding compilers.  */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $ac_func
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $ac_func ();
+/* The GNU C library defines this for functions which it implements
+    to always fail with ENOSYS.  Some functions are actually named
+    something starting with __ and the normal name is an alias.  */
+#if defined __stub_$ac_func || defined __stub___$ac_func
+choke me
+#endif
+
+int
+main ()
+{
+return $ac_func ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  eval "$as_ac_var=yes"
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       eval "$as_ac_var=no"
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+ac_res=`eval 'as_val=${'$as_ac_var'}
+                $as_echo "$as_val"'`
+              { $as_echo "$as_me:$LINENO: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+as_val=`eval 'as_val=${'$as_ac_var'}
+                $as_echo "$as_val"'`
+   if test "x$as_val" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+CFLAGS="$CFLAGS $SDL_CFLAGS"
+
+CXXFLAGS="$CFLAGS"
+
+CXXCPP="$CXXCPP $CXXFLAGS"
+
+CC="$CXX"
+
+LIBS="$LIBS $SDL_LIBS"
+
+
+{ $as_echo "$as_me:$LINENO: checking for png_create_write_struct in -lpng" >&5
+$as_echo_n "checking for png_create_write_struct in -lpng... " >&6; }
+if test "${ac_cv_lib_png_png_create_write_struct+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpng  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char png_create_write_struct ();
+int
+main ()
+{
+return png_create_write_struct ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_png_png_create_write_struct=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_png_png_create_write_struct=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_png_png_create_write_struct" >&5
+$as_echo "$ac_cv_lib_png_png_create_write_struct" >&6; }
+if test "x$ac_cv_lib_png_png_create_write_struct" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBPNG 1
+_ACEOF
+
+  LIBS="-lpng $LIBS"
+
+fi
+
+
+if test "${ac_cv_header_png_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for png.h" >&5
+$as_echo_n "checking for png.h... " >&6; }
+if test "${ac_cv_header_png_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5
+$as_echo "$ac_cv_header_png_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking png.h usability" >&5
+$as_echo_n "checking png.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <png.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking png.h presence" >&5
+$as_echo_n "checking png.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <png.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: png.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: png.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: png.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: png.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: png.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: png.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: png.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: png.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: png.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: png.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: png.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: png.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: png.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: png.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: png.h: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------------------------------- ##
+## Report this to nazghul-devel@lists.sourceforge.net ##
+## -------------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for png.h" >&5
+$as_echo_n "checking for png.h... " >&6; }
+if test "${ac_cv_header_png_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_png_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_png_h" >&5
+$as_echo "$ac_cv_header_png_h" >&6; }
+
+fi
+if test "x$ac_cv_header_png_h" = x""yes; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: *** png include file not found!
+You should install development package." >&5
+$as_echo "$as_me: error: *** png include file not found!
+You should install development package." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking for IMG_ReadXPMFromArray in -lSDL_image" >&5
+$as_echo_n "checking for IMG_ReadXPMFromArray in -lSDL_image... " >&6; }
+if test "${ac_cv_lib_SDL_image_IMG_ReadXPMFromArray+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSDL_image  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char IMG_ReadXPMFromArray ();
+int
+main ()
+{
+return IMG_ReadXPMFromArray ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_SDL_image_IMG_ReadXPMFromArray=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_SDL_image_IMG_ReadXPMFromArray=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_image_IMG_ReadXPMFromArray" >&5
+$as_echo "$ac_cv_lib_SDL_image_IMG_ReadXPMFromArray" >&6; }
+if test "x$ac_cv_lib_SDL_image_IMG_ReadXPMFromArray" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSDL_IMAGE 1
+_ACEOF
+
+  LIBS="-lSDL_image $LIBS"
+
+fi
+
+
+if test "${ac_cv_header_SDL_image_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for SDL_image.h" >&5
+$as_echo_n "checking for SDL_image.h... " >&6; }
+if test "${ac_cv_header_SDL_image_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_SDL_image_h" >&5
+$as_echo "$ac_cv_header_SDL_image_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking SDL_image.h usability" >&5
+$as_echo_n "checking SDL_image.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <SDL_image.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking SDL_image.h presence" >&5
+$as_echo_n "checking SDL_image.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <SDL_image.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: SDL_image.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: SDL_image.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: SDL_image.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: SDL_image.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: SDL_image.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: SDL_image.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: SDL_image.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_image.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: SDL_image.h: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------------------------------- ##
+## Report this to nazghul-devel@lists.sourceforge.net ##
+## -------------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for SDL_image.h" >&5
+$as_echo_n "checking for SDL_image.h... " >&6; }
+if test "${ac_cv_header_SDL_image_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_SDL_image_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_SDL_image_h" >&5
+$as_echo "$ac_cv_header_SDL_image_h" >&6; }
+
+fi
+if test "x$ac_cv_header_SDL_image_h" = x""yes; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: *** SDL_image include files not found!
+You should install development package." >&5
+$as_echo "$as_me: error: *** SDL_image include files not found!
+You should install development package." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+{ $as_echo "$as_me:$LINENO: checking for Mix_OpenAudio in -lSDL_mixer" >&5
+$as_echo_n "checking for Mix_OpenAudio in -lSDL_mixer... " >&6; }
+if test "${ac_cv_lib_SDL_mixer_Mix_OpenAudio+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lSDL_mixer  $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char Mix_OpenAudio ();
+int
+main ()
+{
+return Mix_OpenAudio ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest$ac_exeext && {
+        test "$cross_compiling" = yes ||
+        $as_test_x conftest$ac_exeext
+       }; then
+  ac_cv_lib_SDL_mixer_Mix_OpenAudio=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_cv_lib_SDL_mixer_Mix_OpenAudio=no
+fi
+
+rm -rf conftest.dSYM
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_lib_SDL_mixer_Mix_OpenAudio" >&5
+$as_echo "$ac_cv_lib_SDL_mixer_Mix_OpenAudio" >&6; }
+if test "x$ac_cv_lib_SDL_mixer_Mix_OpenAudio" = x""yes; then
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBSDL_MIXER 1
+_ACEOF
+
+  LIBS="-lSDL_mixer $LIBS"
+
+fi
+
+
+if test "${ac_cv_header_SDL_mixer_h+set}" = set; then
+  { $as_echo "$as_me:$LINENO: checking for SDL_mixer.h" >&5
+$as_echo_n "checking for SDL_mixer.h... " >&6; }
+if test "${ac_cv_header_SDL_mixer_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_SDL_mixer_h" >&5
+$as_echo "$ac_cv_header_SDL_mixer_h" >&6; }
+else
+  # Is the header compilable?
+{ $as_echo "$as_me:$LINENO: checking SDL_mixer.h usability" >&5
+$as_echo_n "checking SDL_mixer.h usability... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <SDL_mixer.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+        test -z "$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+       ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:$LINENO: checking SDL_mixer.h presence" >&5
+$as_echo_n "checking SDL_mixer.h presence... " >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <SDL_mixer.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
+$as_echo "$ac_try_echo") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+        test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" ||
+        test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in
+  yes:no: )
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h: present but cannot be compiled" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h:     check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h:     check for missing prerequisite headers?" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h: see the Autoconf documentation" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h:     section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h: proceeding with the preprocessor's result" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h: proceeding with the preprocessor's result" >&2;}
+    { $as_echo "$as_me:$LINENO: WARNING: SDL_mixer.h: in the future, the compiler will take precedence" >&5
+$as_echo "$as_me: WARNING: SDL_mixer.h: in the future, the compiler will take precedence" >&2;}
+    ( cat <<\_ASBOX
+## -------------------------------------------------- ##
+## Report this to nazghul-devel@lists.sourceforge.net ##
+## -------------------------------------------------- ##
+_ASBOX
+     ) | sed "s/^/$as_me: WARNING:     /" >&2
+    ;;
+esac
+{ $as_echo "$as_me:$LINENO: checking for SDL_mixer.h" >&5
+$as_echo_n "checking for SDL_mixer.h... " >&6; }
+if test "${ac_cv_header_SDL_mixer_h+set}" = set; then
+  $as_echo_n "(cached) " >&6
+else
+  ac_cv_header_SDL_mixer_h=$ac_header_preproc
+fi
+{ $as_echo "$as_me:$LINENO: result: $ac_cv_header_SDL_mixer_h" >&5
+$as_echo "$ac_cv_header_SDL_mixer_h" >&6; }
+
+fi
+if test "x$ac_cv_header_SDL_mixer_h" = x""yes; then
+  :
+else
+  { { $as_echo "$as_me:$LINENO: error: *** SDL_mixer include files not found!
+You should install development package." >&5
+$as_echo "$as_me: error: *** SDL_mixer include files not found!
+You should install development package." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+
+
+
+# User directories for saving game data
+
+
+cat >>confdefs.h <<\_ACEOF
+#define NAZGHUL_USER_DIR "/.nazghul"
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define NAZGHUL_USER_DIR_WIN "/_nazghul"
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define HOME_ENV "HOME"
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MIN_SCRIPT_MAJOR 0
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MIN_SCRIPT_MINOR 6
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define MIN_SCRIPT_RELEASE 0
+_ACEOF
+
+
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_SKILLS 1
+_ACEOF
+
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_QUESTS 1
+_ACEOF
+
+
+# Finally create all the generated files
+ac_config_files="$ac_config_files Makefile m4/Makefile src/Makefile worlds/Makefile worlds/haxima-1.002/Makefile worlds/haxima-1.002/music/Makefile"
+
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems.  If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+  for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+    eval ac_val=\$$ac_var
+    case $ac_val in #(
+    *${as_nl}*)
+      case $ac_var in #(
+      *_cv_*) { $as_echo "$as_me:$LINENO: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+      esac
+      case $ac_var in #(
+      _ | IFS | as_nl) ;; #(
+      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+      *) $as_unset $ac_var ;;
+      esac ;;
+    esac
+  done
+
+  (set) 2>&1 |
+    case $as_nl`(ac_space=' '; set) 2>&1` in #(
+    *${as_nl}ac_space=\ *)
+      # `set' does not quote correctly, so add quotes (double-quote
+      # substitution turns \\\\ into \\, and sed turns \\ into \).
+      sed -n \
+       "s/'/'\\\\''/g;
+         s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+      ;; #(
+    *)
+      # `set' quotes correctly as required by POSIX, so do not add quotes.
+      sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+      ;;
+    esac |
+    sort
+) |
+  sed '
+     /^ac_cv_env_/b end
+     t clear
+     :clear
+     s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+     t end
+     s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+     :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+  if test -w "$cache_file"; then
+    test "x$cache_file" != "x/dev/null" &&
+      { $as_echo "$as_me:$LINENO: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+    cat confcache >$cache_file
+  else
+    { $as_echo "$as_me:$LINENO: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+  fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+  # 1. Remove the extension, and $U if already installed.
+  ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+  ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR
+  #    will be set to the directory where LIBOBJS objects are built.
+  ac_libobjs="$ac_libobjs \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+  ac_ltlibobjs="$ac_ltlibobjs \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+ if test -n "$EXEEXT"; then
+  am__EXEEXT_TRUE=
+  am__EXEEXT_FALSE='#'
+else
+  am__EXEEXT_TRUE='#'
+  am__EXEEXT_FALSE=
+fi
+
+if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"MAINTAINER_MODE\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"AMDEP\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"am__fastdepCC\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+if test -z "${am__fastdepCXX_TRUE}" && test -z "${am__fastdepCXX_FALSE}"; then
+  { { $as_echo "$as_me:$LINENO: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&5
+$as_echo "$as_me: error: conditional \"am__fastdepCXX\" was never defined.
+Usually this means the macro was only invoked conditionally." >&2;}
+   { (exit 1); exit 1; }; }
+fi
+
+: ${CONFIG_STATUS=./config.status}
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+cat >$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+SHELL=\${CONFIG_SHELL-$SHELL}
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+## --------------------- ##
+## M4sh Initialization.  ##
+## --------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in
+  *posix*) set -o posix ;;
+esac
+
+fi
+
+
+
+
+# PATH needs CR
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+if (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+  as_echo='printf %s\n'
+  as_echo_n='printf %s'
+else
+  if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+    as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+    as_echo_n='/usr/ucb/echo -n'
+  else
+    as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+    as_echo_n_body='eval
+      arg=$1;
+      case $arg in
+      *"$as_nl"*)
+       expr "X$arg" : "X\\(.*\\)$as_nl";
+       arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+      esac;
+      expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+    '
+    export as_echo_n_body
+    as_echo_n='sh -c $as_echo_n_body as_echo'
+  fi
+  export as_echo_body
+  as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+  PATH_SEPARATOR=:
+  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+      PATH_SEPARATOR=';'
+  }
+fi
+
+# Support unset when possible.
+if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then
+  as_unset=unset
+else
+  as_unset=false
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order.  Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" ""       $as_nl"
+
+# Find who we are.  Look in the path if we contain no directory separator.
+case $0 in
+  *[\\/]* ) as_myself=$0 ;;
+  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+done
+IFS=$as_save_IFS
+
+     ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+  as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+  $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+  { (exit 1); exit 1; }
+fi
+
+# Work around bugs in pre-3.0 UWIN ksh.
+for as_var in ENV MAIL MAILPATH
+do ($as_unset $as_var) >/dev/null 2>&1 && $as_unset $as_var
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# Required to use basename.
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+  as_basename=basename
+else
+  as_basename=false
+fi
+
+
+# Name of the executable.
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+        X"$0" : 'X\(//\)$' \| \
+        X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+    sed '/^.*\/\([^/][^/]*\)\/*$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\/\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+
+# CDPATH.
+$as_unset CDPATH
+
+
+
+  as_lineno_1=$LINENO
+  as_lineno_2=$LINENO
+  test "x$as_lineno_1" != "x$as_lineno_2" &&
+  test "x`expr $as_lineno_1 + 1`" = "x$as_lineno_2" || {
+
+  # Create $as_me.lineno as a copy of $as_myself, but with $LINENO
+  # uniformly replaced by the line number.  The first 'sed' inserts a
+  # line-number line after each line using $LINENO; the second 'sed'
+  # does the real work.  The second script uses 'N' to pair each
+  # line-number line with the line containing $LINENO, and appends
+  # trailing '-' during substitution so that $LINENO is not a special
+  # case at line end.
+  # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the
+  # scripts with optimization help from Paolo Bonzini.  Blame Lee
+  # E. McMahon (1931-1989) for sed's syntax.  :-)
+  sed -n '
+    p
+    /[$]LINENO/=
+  ' <$as_myself |
+    sed '
+      s/[$]LINENO.*/&-/
+      t lineno
+      b
+      :lineno
+      N
+      :loop
+      s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+      t loop
+      s/-\n.*//
+    ' >$as_me.lineno &&
+  chmod +x "$as_me.lineno" ||
+    { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2
+   { (exit 1); exit 1; }; }
+
+  # Don't try to exec as it changes $[0], causing all sort of problems
+  # (the dirname of $[0] is not the place where we might find the
+  # original and so on.  Autoconf is especially sensitive to this).
+  . "./$as_me.lineno"
+  # Exit status is that of the last command.
+  exit
+}
+
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+  as_dirname=dirname
+else
+  as_dirname=false
+fi
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in
+-n*)
+  case `echo 'x\c'` in
+  *c*) ECHO_T='        ';;     # ECHO_T is single tab character.
+  *)   ECHO_C='\c';;
+  esac;;
+*)
+  ECHO_N='-n';;
+esac
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+   test "X`expr 00001 : '.*\(...\)'`" = X001; then
+  as_expr=expr
+else
+  as_expr=false
+fi
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+  rm -f conf$$.dir/conf$$.file
+else
+  rm -f conf$$.dir
+  mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+  if ln -s conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s='ln -s'
+    # ... but there are two gotchas:
+    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+    # In both cases, we have to default to `cp -p'.
+    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+      as_ln_s='cp -p'
+  elif ln conf$$.file conf$$ 2>/dev/null; then
+    as_ln_s=ln
+  else
+    as_ln_s='cp -p'
+  fi
+else
+  as_ln_s='cp -p'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+  as_mkdir_p=:
+else
+  test -d ./-p && rmdir ./-p
+  as_mkdir_p=false
+fi
+
+if test -x / >/dev/null 2>&1; then
+  as_test_x='test -x'
+else
+  if ls -dL / >/dev/null 2>&1; then
+    as_ls_L_option=L
+  else
+    as_ls_L_option=
+  fi
+  as_test_x='
+    eval sh -c '\''
+      if test -d "$1"; then
+       test -d "$1/.";
+      else
+       case $1 in
+       -*)set "./$1";;
+       esac;
+       case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in
+       ???[sx]*):;;*)false;;esac;fi
+    '\'' sh
+  '
+fi
+as_executable_p=$as_test_x
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+
+# Save the log message, to keep $[0] and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by nazghul $as_me 0.7.1, which was
+generated by GNU Autoconf 2.63.  Invocation command line was
+
+  CONFIG_FILES    = $CONFIG_FILES
+  CONFIG_HEADERS  = $CONFIG_HEADERS
+  CONFIG_LINKS    = $CONFIG_LINKS
+  CONFIG_COMMANDS = $CONFIG_COMMANDS
+  $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files from templates according to the
+current configuration.
+
+Usage: $0 [OPTION]... [FILE]...
+
+  -h, --help       print this help, then exit
+  -V, --version    print version number and configuration settings, then exit
+  -q, --quiet, --silent
+                   do not print progress messages
+  -d, --debug      don't remove temporary files
+      --recheck    update $as_me by reconfiguring in the same conditions
+      --file=FILE[:TEMPLATE]
+                   instantiate the configuration file FILE
+      --header=FILE[:TEMPLATE]
+                   instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to <bug-autoconf@gnu.org>."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_version="\\
+nazghul config.status 0.7.1
+configured by $0, generated by GNU Autoconf 2.63,
+  with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
+
+Copyright (C) 2008 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+MKDIR_P='$MKDIR_P'
+AWK='$AWK'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+  case $1 in
+  --*=*)
+    ac_option=`expr "X$1" : 'X\([^=]*\)='`
+    ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+    ac_shift=:
+    ;;
+  *)
+    ac_option=$1
+    ac_optarg=$2
+    ac_shift=shift
+    ;;
+  esac
+
+  case $ac_option in
+  # Handling of the options.
+  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+    ac_cs_recheck=: ;;
+  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+    $as_echo "$ac_cs_version"; exit ;;
+  --debug | --debu | --deb | --de | --d | -d )
+    debug=: ;;
+  --file | --fil | --fi | --f )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_FILES="$CONFIG_FILES '$ac_optarg'"
+    ac_need_defaults=false;;
+  --header | --heade | --head | --hea )
+    $ac_shift
+    case $ac_optarg in
+    *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+    esac
+    CONFIG_HEADERS="$CONFIG_HEADERS '$ac_optarg'"
+    ac_need_defaults=false;;
+  --he | --h)
+    # Conflict between --help and --header
+    { $as_echo "$as_me: error: ambiguous option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; };;
+  --help | --hel | -h )
+    $as_echo "$ac_cs_usage"; exit ;;
+  -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+  | -silent | --silent | --silen | --sile | --sil | --si | --s)
+    ac_cs_silent=: ;;
+
+  # This is an error.
+  -*) { $as_echo "$as_me: error: unrecognized option: $1
+Try \`$0 --help' for more information." >&2
+   { (exit 1); exit 1; }; } ;;
+
+  *) ac_config_targets="$ac_config_targets $1"
+     ac_need_defaults=false ;;
+
+  esac
+  shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+  exec 6>/dev/null
+  ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+  set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+  shift
+  \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+  CONFIG_SHELL='$SHELL'
+  export CONFIG_SHELL
+  exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+  echo
+  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+  $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+  case $ac_config_target in
+    "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+    "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
+    "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+    "m4/Makefile") CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;;
+    "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
+    "worlds/Makefile") CONFIG_FILES="$CONFIG_FILES worlds/Makefile" ;;
+    "worlds/haxima-1.002/Makefile") CONFIG_FILES="$CONFIG_FILES worlds/haxima-1.002/Makefile" ;;
+    "worlds/haxima-1.002/music/Makefile") CONFIG_FILES="$CONFIG_FILES worlds/haxima-1.002/music/Makefile" ;;
+
+  *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5
+$as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;}
+   { (exit 1); exit 1; }; };;
+  esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used.  Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+  test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+  test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+  test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience.  Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+  tmp=
+  trap 'exit_status=$?
+  { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status
+' 0
+  trap '{ (exit 1); exit 1; }' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+  tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+  test -n "$tmp" && test -d "$tmp"
+}  ||
+{
+  tmp=./conf$$-$RANDOM
+  (umask 077 && mkdir "$tmp")
+} ||
+{
+   $as_echo "$as_me: cannot create a temporary directory in ." >&2
+   { (exit 1); exit 1; }
+}
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr='\r'
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+  ac_cs_awk_cr='\\r'
+else
+  ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+  echo "cat >conf$$subs.awk <<_ACEOF" &&
+  echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+  echo "_ACEOF"
+} >conf$$subs.sh ||
+  { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+  . ./conf$$subs.sh ||
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+  ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+  if test $ac_delim_n = $ac_delim_num; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\).*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\).*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+  N
+  s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$tmp/subs1.awk" <<_ACAWK &&
+  for (key in S) S_is_set[key] = 1
+  FS = "\a"
+
+}
+{
+  line = $ 0
+  nfields = split(line, field, "@")
+  substed = 0
+  len = length(field[1])
+  for (i = 2; i < nfields; i++) {
+    key = field[i]
+    keylen = length(key)
+    if (S_is_set[key]) {
+      value = S[key]
+      line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+      len += length(value) + length(field[++i])
+      substed = 1
+    } else
+      len += 1 + keylen
+  }
+
+  print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+  sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+  cat
+fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \
+  || { { $as_echo "$as_me:$LINENO: error: could not setup config files machinery" >&5
+$as_echo "$as_me: error: could not setup config files machinery" >&2;}
+   { (exit 1); exit 1; }; }
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove $(srcdir),
+# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+  ac_vpsub='/^[         ]*VPATH[        ]*=/{
+s/:*\$(srcdir):*/:/
+s/:*\${srcdir}:*/:/
+s/:*@srcdir@:*/:/
+s/^\([^=]*=[    ]*\):*/\1/
+s/:*$//
+s/^[^=]*=[      ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+  ac_t=`sed -n "/$ac_delim/p" confdefs.h`
+  if test -z "$ac_t"; then
+    break
+  elif $ac_last_try; then
+    { { $as_echo "$as_me:$LINENO: error: could not make $CONFIG_HEADERS" >&5
+$as_echo "$as_me: error: could not make $CONFIG_HEADERS" >&2;}
+   { (exit 1); exit 1; }; }
+  else
+    ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+  fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any.  Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[    ]*#[    ]*define[       ][      ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[    ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[        ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  for (key in D) D_is_set[key] = 1
+  FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+  line = \$ 0
+  split(line, arg, " ")
+  if (arg[1] == "#") {
+    defundef = arg[2]
+    mac1 = arg[3]
+  } else {
+    defundef = substr(arg[1], 2)
+    mac1 = arg[2]
+  }
+  split(mac1, mac2, "(") #)
+  macro = mac2[1]
+  prefix = substr(line, 1, index(line, defundef) - 1)
+  if (D_is_set[macro]) {
+    # Preserve the white space surrounding the "#".
+    print prefix "define", macro P[macro] D[macro]
+    next
+  } else {
+    # Replace #undef with comments.  This is necessary, for example,
+    # in the case of _POSIX_SOURCE, which is predefined and required
+    # on some systems where configure will not decide to define it.
+    if (defundef == "undef") {
+      print "/*", prefix defundef, macro, "*/"
+      next
+    }
+  }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+  { { $as_echo "$as_me:$LINENO: error: could not setup config headers machinery" >&5
+$as_echo "$as_me: error: could not setup config headers machinery" >&2;}
+   { (exit 1); exit 1; }; }
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X "  :F $CONFIG_FILES  :H $CONFIG_HEADERS    :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+  case $ac_tag in
+  :[FHLC]) ac_mode=$ac_tag; continue;;
+  esac
+  case $ac_mode$ac_tag in
+  :[FHL]*:*);;
+  :L* | :C*:*) { { $as_echo "$as_me:$LINENO: error: invalid tag $ac_tag" >&5
+$as_echo "$as_me: error: invalid tag $ac_tag" >&2;}
+   { (exit 1); exit 1; }; };;
+  :[FH]-) ac_tag=-:-;;
+  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+  esac
+  ac_save_IFS=$IFS
+  IFS=:
+  set x $ac_tag
+  IFS=$ac_save_IFS
+  shift
+  ac_file=$1
+  shift
+
+  case $ac_mode in
+  :L) ac_source=$1;;
+  :[FH])
+    ac_file_inputs=
+    for ac_f
+    do
+      case $ac_f in
+      -) ac_f="$tmp/stdin";;
+      *) # Look for the file first in the build tree, then in the source tree
+        # (if the path is not absolute).  The absolute path cannot be DOS-style,
+        # because $ac_f cannot contain `:'.
+        test -f "$ac_f" ||
+          case $ac_f in
+          [\\/$]*) false;;
+          *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+          esac ||
+          { { $as_echo "$as_me:$LINENO: error: cannot find input file: $ac_f" >&5
+$as_echo "$as_me: error: cannot find input file: $ac_f" >&2;}
+   { (exit 1); exit 1; }; };;
+      esac
+      case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+      ac_file_inputs="$ac_file_inputs '$ac_f'"
+    done
+
+    # Let's still pretend it is `configure' which instantiates (i.e., don't
+    # use $as_me), people would be surprised to read:
+    #    /* config.h.  Generated by config.status.  */
+    configure_input='Generated from '`
+         $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+       `' by configure.'
+    if test x"$ac_file" != x-; then
+      configure_input="$ac_file.  $configure_input"
+      { $as_echo "$as_me:$LINENO: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+    fi
+    # Neutralize special characters interpreted by sed in replacement strings.
+    case $configure_input in #(
+    *\&* | *\|* | *\\* )
+       ac_sed_conf_input=`$as_echo "$configure_input" |
+       sed 's/[\\\\&|]/\\\\&/g'`;; #(
+    *) ac_sed_conf_input=$configure_input;;
+    esac
+
+    case $ac_tag in
+    *:-:* | *:-) cat >"$tmp/stdin" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; } ;;
+    esac
+    ;;
+  esac
+
+  ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$ac_file" : 'X\(//\)[^/]' \| \
+        X"$ac_file" : 'X\(//\)$' \| \
+        X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+  { as_dir="$ac_dir"
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+  ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+  ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+  # A ".." for each directory in $ac_dir_suffix.
+  ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+  case $ac_top_builddir_sub in
+  "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+  esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+  .)  # We are building in place.
+    ac_srcdir=.
+    ac_top_srcdir=$ac_top_builddir_sub
+    ac_abs_top_srcdir=$ac_pwd ;;
+  [\\/]* | ?:[\\/]* )  # Absolute name.
+    ac_srcdir=$srcdir$ac_dir_suffix;
+    ac_top_srcdir=$srcdir
+    ac_abs_top_srcdir=$srcdir ;;
+  *) # Relative name.
+    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+    ac_top_srcdir=$ac_top_build_prefix$srcdir
+    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+  case $ac_mode in
+  :F)
+  #
+  # CONFIG_FILE
+  #
+
+  case $INSTALL in
+  [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+  *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+  esac
+  ac_MKDIR_P=$MKDIR_P
+  case $MKDIR_P in
+  [\\/$]* | ?:[\\/]* ) ;;
+  */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;;
+  esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+
+ac_sed_dataroot='
+/datarootdir/ {
+  p
+  q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p
+'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+  ac_datarootdir_hack='
+  s&@datadir@&$datadir&g
+  s&@docdir@&$docdir&g
+  s&@infodir@&$infodir&g
+  s&@localedir@&$localedir&g
+  s&@mandir@&$mandir&g
+    s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+s&@MKDIR_P@&$ac_MKDIR_P&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+  { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } &&
+  { ac_out=`sed -n '/^[         ]*datarootdir[  ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } &&
+  { $as_echo "$as_me:$LINENO: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined.  Please make sure it is defined." >&2;}
+
+  rm -f "$tmp/stdin"
+  case $ac_file in
+  -) cat "$tmp/out" && rm -f "$tmp/out";;
+  *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";;
+  esac \
+  || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+ ;;
+  :H)
+  #
+  # CONFIG_HEADER
+  #
+  if test x"$ac_file" != x-; then
+    {
+      $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs"
+    } >"$tmp/config.h" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+    if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then
+      { $as_echo "$as_me:$LINENO: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+    else
+      rm -f "$ac_file"
+      mv "$tmp/config.h" "$ac_file" \
+       || { { $as_echo "$as_me:$LINENO: error: could not create $ac_file" >&5
+$as_echo "$as_me: error: could not create $ac_file" >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+  else
+    $as_echo "/* $configure_input  */" \
+      && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \
+      || { { $as_echo "$as_me:$LINENO: error: could not create -" >&5
+$as_echo "$as_me: error: could not create -" >&2;}
+   { (exit 1); exit 1; }; }
+  fi
+# Compute "$ac_file"'s index in $config_headers.
+_am_arg="$ac_file"
+_am_stamp_count=1
+for _am_header in $config_headers :; do
+  case $_am_header in
+    $_am_arg | $_am_arg:* )
+      break ;;
+    * )
+      _am_stamp_count=`expr $_am_stamp_count + 1` ;;
+  esac
+done
+echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" ||
+$as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$_am_arg" : 'X\(//\)[^/]' \| \
+        X"$_am_arg" : 'X\(//\)$' \| \
+        X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$_am_arg" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`/stamp-h$_am_stamp_count
+ ;;
+
+  :C)  { $as_echo "$as_me:$LINENO: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+  esac
+
+
+  case $ac_file$ac_mode in
+    "depfiles":C) test x"$AMDEP_TRUE" != x"" || {
+  # Autoconf 2.62 quotes --file arguments for eval, but not when files
+  # are listed without --file.  Let's play safe and only enable the eval
+  # if we detect the quoting.
+  case $CONFIG_FILES in
+  *\'*) eval set x "$CONFIG_FILES" ;;
+  *)   set x $CONFIG_FILES ;;
+  esac
+  shift
+  for mf
+  do
+    # Strip MF so we end up with the name of the file.
+    mf=`echo "$mf" | sed -e 's/:.*$//'`
+    # Check whether this is an Automake generated Makefile or not.
+    # We used to match only the files named `Makefile.in', but
+    # some people rename them; so instead we look at the file content.
+    # Grep'ing the first line is not enough: some people post-process
+    # each Makefile.in and add a new line on top of each file to say so.
+    # Grep'ing the whole file is not good either: AIX grep has a line
+    # limit of 2048, but all sed's we know have understand at least 4000.
+    if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then
+      dirpart=`$as_dirname -- "$mf" ||
+$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$mf" : 'X\(//\)[^/]' \| \
+        X"$mf" : 'X\(//\)$' \| \
+        X"$mf" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$mf" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+    else
+      continue
+    fi
+    # Extract the definition of DEPDIR, am__include, and am__quote
+    # from the Makefile without running `make'.
+    DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
+    test -z "$DEPDIR" && continue
+    am__include=`sed -n 's/^am__include = //p' < "$mf"`
+    test -z "am__include" && continue
+    am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
+    # When using ansi2knr, U may be empty or an underscore; expand it
+    U=`sed -n 's/^U = //p' < "$mf"`
+    # Find all dependency output files, they are included files with
+    # $(DEPDIR) in their names.  We invoke sed twice because it is the
+    # simplest approach to changing $(DEPDIR) to its actual value in the
+    # expansion.
+    for file in `sed -n "
+      s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \
+        sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do
+      # Make sure the directory exists.
+      test -f "$dirpart/$file" && continue
+      fdir=`$as_dirname -- "$file" ||
+$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$file" : 'X\(//\)[^/]' \| \
+        X"$file" : 'X\(//\)$' \| \
+        X"$file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$file" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      { as_dir=$dirpart/$fdir
+  case $as_dir in #(
+  -*) as_dir=./$as_dir;;
+  esac
+  test -d "$as_dir" || { $as_mkdir_p && mkdir -p "$as_dir"; } || {
+    as_dirs=
+    while :; do
+      case $as_dir in #(
+      *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+      *) as_qdir=$as_dir;;
+      esac
+      as_dirs="'$as_qdir' $as_dirs"
+      as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+        X"$as_dir" : 'X\(//\)[^/]' \| \
+        X"$as_dir" : 'X\(//\)$' \| \
+        X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+    sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)[^/].*/{
+           s//\1/
+           q
+         }
+         /^X\(\/\/\)$/{
+           s//\1/
+           q
+         }
+         /^X\(\/\).*/{
+           s//\1/
+           q
+         }
+         s/.*/./; q'`
+      test -d "$as_dir" && break
+    done
+    test -z "$as_dirs" || eval "mkdir $as_dirs"
+  } || test -d "$as_dir" || { { $as_echo "$as_me:$LINENO: error: cannot create directory $as_dir" >&5
+$as_echo "$as_me: error: cannot create directory $as_dir" >&2;}
+   { (exit 1); exit 1; }; }; }
+      # echo "creating $dirpart/$file"
+      echo '# dummy' > "$dirpart/$file"
+    done
+  done
+}
+ ;;
+
+  esac
+done # for ac_tag
+
+
+{ (exit 0); exit 0; }
+_ACEOF
+chmod +x $CONFIG_STATUS
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+  { { $as_echo "$as_me:$LINENO: error: write failure creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: error: write failure creating $CONFIG_STATUS" >&2;}
+   { (exit 1); exit 1; }; }
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded.  So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status.  When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+  ac_cs_success=:
+  ac_config_status_args=
+  test "$silent" = yes &&
+    ac_config_status_args="$ac_config_status_args --quiet"
+  exec 5>/dev/null
+  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+  exec 5>>config.log
+  # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+  # would make configure fail if this is the last instruction.
+  $ac_cs_success || { (exit 1); exit 1; }
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+  { $as_echo "$as_me:$LINENO: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+
+cat <<EOF
+
+$PACKAGE_NAME $PACKAGE_VERSION configured.
+
+You can now type \`gmake' to compile $PACKAGE_NAME.
+If \`gmake' is not available on your system, try \`make' instead.
+EOF
diff --git a/configure.ac b/configure.ac
new file mode 100644 (file)
index 0000000..a4081fd
--- /dev/null
@@ -0,0 +1,232 @@
+dnl This file is part of the nazghul program
+dnl
+dnl Process this file with autogen.sh to produce a configure script.
+
+dnl ---------------------------------------------------------------------------
+dnl 1. Boilerplate
+dnl      This section should include standard boilerplate code, such as the call 
+dnl      to AC_INIT (which must be first), AM_INIT_AUTOMAKE, AC_CONFIG_HEADER, 
+dnl      and perhaps AC_REVISION.
+dnl ---------------------------------------------------------------------------
+
+AC_PREREQ(2.59)
+
+dnl   This macro performs essential initialization for the
+dnl   generated `configure' script. An optional argument may provide the name of a
+dnl   file from the source directory to ensure that the directory has been 
+dnl   specified correctly.
+AC_INIT(nazghul, 0.7.1, [nazghul-devel@lists.sourceforge.net])
+AC_CONFIG_SRCDIR([src/nazghul.c])
+AM_CONFIG_HEADER([config.h])
+
+dnl AC_CANONICAL_HOST
+dnl   This macro determines the type of the host system and sets the output 
+dnl   variable `host', as well as other more obscure variables.
+AC_CANONICAL_HOST
+
+dnl AC_CANONICAL_TARGET
+dnl   I'm not certain what this is. The automake book refers to 
+dnl   AC_CANONICAL_SYSTEM, but not AC_CANONICAL_TARGET. A Google search only 
+dnl   yields scads of mailing list reports about people having weird problems 
+dnl   with this,
+AC_CANONICAL_TARGET
+
+dnl AM_INIT_AUTOMAKE(package, version, [nodefine])
+dnl   This macro is used to do all the standard initialization required by 
+dnl   Automake. It has two required arguments: the package name and the version 
+dnl   number. This macro sets and calls AC_SUBST on the shell variables PACKAGE 
+dnl   and VERSION. By default it also defines these variables (via 
+dnl   AC_DEFINE_UNQUOTED). However, this macro also accepts an optional third 
+dnl   argument which, if not empty, means that the AC_DEFINE_UNQUOTED calls for 
+dnl   PACKAGE and VERSION should be suppressed.
+AM_INIT_AUTOMAKE
+AM_MAINTAINER_MODE
+
+dnl ---------------------------------------------------------------------------
+dnl 2. Options
+dnl      The next section should include macros which add command-line options 
+dnl      to configure, such as AC_ARG_ENABLE. It is typical to put support code
+dnl      for the option in this section as well, if it is short enough.
+dnl ---------------------------------------------------------------------------
+
+dnl ---------------------------------------------------------------------------
+dnl 3. Programs
+dnl      Next it is traditional to check for programs that are either needed by
+dnl      the configure process, the build process, or by one of the programs 
+dnl      being built. This usually involves calls to macros like AC_CHECK_PROG
+dnl      and AC_PATH_TOOL.
+dnl ---------------------------------------------------------------------------
+
+dnl AC_PROG_CC
+dnl   This checks for the C compiler to use and sets the shell variable CC to the 
+dnl   value. If the GNU C compiler is being used, this sets the shell variable GCC 
+dnl   to `yes'. This macro sets the shell variable CFLAGS if it has not already 
+dnl   been set. It also calls AC_SUBST on CC and CFLAGS.
+AC_PROG_CC
+
+dnl AC_PROG_CXX
+dnl   This is like AC_PROG_CC, but it checks for the C++ compiler, and sets the
+dnl   variables CXX, 
+AC_PROG_CXX
+
+dnl AC_PROG_LIBTOOL
+dnl   This macro is the primary way to integrate Libtool support into `configure'.
+dnl   If you are using Libtool, you should call this macro in `configure.in'. Among
+dnl    other things, it adds support for the `--enable-shared' configure flag.
+dnl AC_PROG_LIBTOOL
+
+dnl AC_PROG_INSTALL
+dnl   This looks for an install program and sets the output variables INSTALL, 
+dnl   INSTALL_DATA, INSTALL_PROGRAM, and INSTALL_SCRIPT. This macro assumes that if
+dnl   an install program cannot be found on the system, your package will have 
+dnl   `install-sh' available in the directory chosen by AC_CONFIG_AUX_DIR.
+dnl AC_PROG_INSTALL
+
+AC_PROG_MAKE_SET
+
+dnl ---------------------------------------------------------------------------
+dnl 4. Libraries
+dnl      Checks for libraries come before checks for other objects visible to C
+dnl      (or C++, or anything else). This is necessary because some other checks
+dnl      work by trying to link or run a program; by checking for libraries
+dnl      first you ensure that the resulting programs can be linked.
+dnl ---------------------------------------------------------------------------
+
+dnl Check for SDL and SDL features, i.e. -lSDL
+SDL_VERSION=1.2.3
+AM_PATH_SDL($SDL_VERSION,
+            :,
+           AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!])
+)
+
+dnl ---------------------------------------------------------------------------
+dnl 5. Headers
+dnl      Next come checks for existence of headers.
+dnl ---------------------------------------------------------------------------
+AC_LANG([C])
+AC_HEADER_STDC
+AC_LANG([C++])
+AC_CHECK_HEADERS([fcntl.h \
+       malloc.h          \
+       float.h           \
+       limits.h])
+
+dnl ---------------------------------------------------------------------------
+dnl 6. Typedefs and structures
+dnl    We do checks for typedefs after checking for headers for the simple
+dnl    reason that typedefs appear in headers, and we need to know which headers
+dnl    we can use before we look inside them.
+dnl ---------------------------------------------------------------------------
+PETI_ENABLED_DYNAMIC_LINKING
+AC_C_CONST
+AC_C_INLINE
+AC_C_VOLATILE
+
+dnl ---------------------------------------------------------------------------
+dnl 7. Functions
+dnl      Finally we check for functions. These come last because functions have
+dnl      dependencies on the preceding items: when searching for functions,
+dnl      libraries are needed in order to correctly link, headers are needed in
+dnl      order to find prototypes (this is especially important for C++, which
+dnl      has stricter prototyping rules than C), and typedefs are needed for
+dnl      those functions which use or return types which are not built in.
+dnl ---------------------------------------------------------------------------
+AC_CHECK_FUNCS([malloc  \
+       realloc         \
+       select_argtypes \
+       vprintf         \
+       strerror        \
+       strpbrk         \
+       strstr          \
+       atexit          \
+       floor           \
+       strcasecmp      \
+       strdup          \
+       realloc         \
+       select          \
+        strchr])
+
+dnl Add in the SDL CFLAGS
+CFLAGS="$CFLAGS $SDL_CFLAGS"
+
+dnl Use the same flags for c++ as for c
+CXXFLAGS="$CFLAGS"
+
+dnl The preprocessor needs the same info too.
+CXXCPP="$CXXCPP $CXXFLAGS"
+
+dnl Set the compiler to c++ (for now)
+CC="$CXX"
+
+dnl Add libraries to build process
+LIBS="$LIBS $SDL_LIBS"
+
+dnl Check specifically for libpng, i.e. -lpng switch
+AC_CHECK_LIB(png, png_create_write_struct)
+
+AC_CHECK_HEADER([png.h],
+               [],
+               [AC_MSG_ERROR([*** png include file not found!
+You should install development package.])])
+
+dnl Check specifically for SDL_image library, i.e. -lSDL_image switch
+AC_CHECK_LIB(SDL_image, IMG_ReadXPMFromArray)
+
+AC_CHECK_HEADER([SDL_image.h],
+               [],
+               [AC_MSG_ERROR([*** SDL_image include files not found!
+You should install development package.])])
+
+dnl Check specifically for SDL_mixer library, i.e. -lSDL_mixer switch
+AC_CHECK_LIB(SDL_mixer, Mix_OpenAudio)
+
+AC_CHECK_HEADER([SDL_mixer.h],
+               [],
+               [AC_MSG_ERROR([*** SDL_mixer include files not found!
+You should install development package.])])
+
+dnl ---------------------------------------------------------------------------
+dnl 8. Output
+dnl      This is done by invoking AC_OUTPUT.
+dnl ---------------------------------------------------------------------------
+
+# User directories for saving game data
+AC_DEFINE(NAZGHUL_USER_DIR, "/.nazghul",
+           [.nazghul is for Unix users.])
+
+AC_DEFINE(NAZGHUL_USER_DIR_WIN, "/_nazghul",
+           [_nazghul is for Windows users.])
+
+AC_DEFINE(HOME_ENV, "HOME",
+           [Most likely your home directory is stored in $HOME.])
+
+AC_DEFINE(MIN_SCRIPT_MAJOR, 0,
+          [Minimum supported script version])
+
+AC_DEFINE(MIN_SCRIPT_MINOR, 6,
+          [Minimum supported script version])
+
+AC_DEFINE(MIN_SCRIPT_RELEASE, 0,
+          [Minimum supported script version])
+
+AC_DEFINE(USE_SKILLS, 1, [Enable Yuse command and skills])
+AC_DEFINE(USE_QUESTS, 1, [Enable quest log])
+
+# Finally create all the generated files
+AC_CONFIG_FILES([Makefile \
+       m4/Makefile       \
+       src/Makefile      \
+       worlds/Makefile   \
+       worlds/haxima-1.002/Makefile \
+        worlds/haxima-1.002/music/Makefile])
+
+AC_OUTPUT
+
+cat <<EOF
+
+$PACKAGE_NAME $PACKAGE_VERSION configured.
+
+You can now type \`gmake' to compile $PACKAGE_NAME.
+If \`gmake' is not available on your system, try \`make' instead.
+EOF
diff --git a/depcomp b/depcomp
new file mode 100644 (file)
index 0000000..df8eea7
--- /dev/null
+++ b/depcomp
@@ -0,0 +1,630 @@
+#! /bin/sh
+# depcomp - compile a program generating dependencies as side-effects
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007, 2009 Free
+# Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>.
+
+case $1 in
+  '')
+     echo "$0: No command.  Try \`$0 --help' for more information." 1>&2
+     exit 1;
+     ;;
+  -h | --h*)
+    cat <<\EOF
+Usage: depcomp [--help] [--version] PROGRAM [ARGS]
+
+Run PROGRAMS ARGS to compile a file, generating dependencies
+as side-effects.
+
+Environment variables:
+  depmode     Dependency tracking mode.
+  source      Source file read by `PROGRAMS ARGS'.
+  object      Object file output by `PROGRAMS ARGS'.
+  DEPDIR      directory where to store dependencies.
+  depfile     Dependency file to output.
+  tmpdepfile  Temporary file to use when outputing dependencies.
+  libtool     Whether libtool is used (yes/no).
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+    exit $?
+    ;;
+  -v | --v*)
+    echo "depcomp $scriptversion"
+    exit $?
+    ;;
+esac
+
+if test -z "$depmode" || test -z "$source" || test -z "$object"; then
+  echo "depcomp: Variables source, object and depmode must be set" 1>&2
+  exit 1
+fi
+
+# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
+depfile=${depfile-`echo "$object" |
+  sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
+tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
+
+rm -f "$tmpdepfile"
+
+# Some modes work just like other modes, but use different flags.  We
+# parameterize here, but still list the modes in the big case below,
+# to make depend.m4 easier to write.  Note that we *cannot* use a case
+# here, because this file can only contain one case statement.
+if test "$depmode" = hp; then
+  # HP compiler uses -M and no extra arg.
+  gccflag=-M
+  depmode=gcc
+fi
+
+if test "$depmode" = dashXmstdout; then
+   # This is just like dashmstdout with a different argument.
+   dashmflag=-xM
+   depmode=dashmstdout
+fi
+
+cygpath_u="cygpath -u -f -"
+if test "$depmode" = msvcmsys; then
+   # This is just like msvisualcpp but w/o cygpath translation.
+   # Just convert the backslash-escaped backslashes to single forward
+   # slashes to satisfy depend.m4
+   cygpath_u="sed s,\\\\\\\\,/,g"
+   depmode=msvisualcpp
+fi
+
+case "$depmode" in
+gcc3)
+## gcc 3 implements dependency tracking that does exactly what
+## we want.  Yay!  Note: for some reason libtool 1.4 doesn't like
+## it if -MD -MP comes after the -MF stuff.  Hmm.
+## Unfortunately, FreeBSD c89 acceptance of flags depends upon
+## the command line argument order; so add the flags where they
+## appear in depend2.am.  Note that the slowdown incurred here
+## affects only configure: in makefiles, %FASTDEP% shortcuts this.
+  for arg
+  do
+    case $arg in
+    -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
+    *)  set fnord "$@" "$arg" ;;
+    esac
+    shift # fnord
+    shift # $arg
+  done
+  "$@"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  mv "$tmpdepfile" "$depfile"
+  ;;
+
+gcc)
+## There are various ways to get dependency output from gcc.  Here's
+## why we pick this rather obscure method:
+## - Don't want to use -MD because we'd like the dependencies to end
+##   up in a subdir.  Having to rename by hand is ugly.
+##   (We might end up doing this anyway to support other compilers.)
+## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
+##   -MM, not -M (despite what the docs say).
+## - Using -M directly means running the compiler twice (even worse
+##   than renaming).
+  if test -z "$gccflag"; then
+    gccflag=-MD,
+  fi
+  "$@" -Wp,"$gccflag$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
+## The second -e expression handles DOS-style file names with drive letters.
+  sed -e 's/^[^:]*: / /' \
+      -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
+## This next piece of magic avoids the `deleted header file' problem.
+## The problem is that when a header file which appears in a .P file
+## is deleted, the dependency causes make to die (because there is
+## typically no way to rebuild the header).  We avoid this by adding
+## dummy dependencies for each header file.  Too bad gcc doesn't do
+## this for us directly.
+  tr ' ' '
+' < "$tmpdepfile" |
+## Some versions of gcc put a space before the `:'.  On the theory
+## that the space means something, we add a space to the output as
+## well.
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+sgi)
+  if test "$libtool" = yes; then
+    "$@" "-Wp,-MDupdate,$tmpdepfile"
+  else
+    "$@" -MDupdate "$tmpdepfile"
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+
+  if test -f "$tmpdepfile"; then  # yes, the sourcefile depend on other files
+    echo "$object : \\" > "$depfile"
+
+    # Clip off the initial element (the dependent).  Don't try to be
+    # clever and replace this with sed code, as IRIX sed won't handle
+    # lines with more than a fixed number of characters (4096 in
+    # IRIX 6.2 sed, 8192 in IRIX 6.5).  We also remove comment lines;
+    # the IRIX cc adds comments like `#:fec' to the end of the
+    # dependency line.
+    tr ' ' '
+' < "$tmpdepfile" \
+    | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \
+    tr '
+' ' ' >> "$depfile"
+    echo >> "$depfile"
+
+    # The second pass generates a dummy entry for each header file.
+    tr ' ' '
+' < "$tmpdepfile" \
+   | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
+   >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+aix)
+  # The C for AIX Compiler uses -M and outputs the dependencies
+  # in a .u file.  In older versions, this file always lives in the
+  # current directory.  Also, the AIX compiler puts `$object:' at the
+  # start of each line; $object doesn't have directory information.
+  # Version 6 uses the directory in both cases.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$base.u
+    tmpdepfile3=$dir.libs/$base.u
+    "$@" -Wc,-M
+  else
+    tmpdepfile1=$dir$base.u
+    tmpdepfile2=$dir$base.u
+    tmpdepfile3=$dir$base.u
+    "$@" -M
+  fi
+  stat=$?
+
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+    exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    # Each line is of the form `foo.o: dependent.h'.
+    # Do two passes, one to just change these to
+    # `$object: dependent.h' and one to simply `dependent.h:'.
+    sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+    # That's a tab and a space in the [].
+    sed -e 's,^.*\.[a-z]*:[     ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+  else
+    # The sourcefile does not contain any dependencies, so just
+    # store a dummy comment line, to avoid errors with the Makefile
+    # "include basename.Plo" scheme.
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile"
+  ;;
+
+icc)
+  # Intel's C compiler understands `-MD -MF file'.  However on
+  #    icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c
+  # ICC 7.0 will fill foo.d with something like
+  #    foo.o: sub/foo.c
+  #    foo.o: sub/foo.h
+  # which is wrong.  We want:
+  #    sub/foo.o: sub/foo.c
+  #    sub/foo.o: sub/foo.h
+  #    sub/foo.c:
+  #    sub/foo.h:
+  # ICC 7.1 will output
+  #    foo.o: sub/foo.c sub/foo.h
+  # and will wrap long lines using \ :
+  #    foo.o: sub/foo.c ... \
+  #     sub/foo.h ... \
+  #     ...
+
+  "$@" -MD -MF "$tmpdepfile"
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+    rm -f "$tmpdepfile"
+    exit $stat
+  fi
+  rm -f "$depfile"
+  # Each line is of the form `foo.o: dependent.h',
+  # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
+  # Do two passes, one to just change these to
+  # `$object: dependent.h' and one to simply `dependent.h:'.
+  sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
+  # Some versions of the HPUX 10.20 sed can't process this invocation
+  # correctly.  Breaking it into two sed invocations is a workaround.
+  sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" |
+    sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+hp2)
+  # The "hp" stanza above does not work with aCC (C++) and HP's ia64
+  # compilers, which have integrated preprocessors.  The correct option
+  # to use with these is +Maked; it writes dependencies to a file named
+  # 'foo.d', which lands next to the object file, wherever that
+  # happens to be.
+  # Much of this is similar to the tru64 case; see comments there.
+  dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+  test "x$dir" = "x$object" && dir=
+  base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+  if test "$libtool" = yes; then
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir.libs/$base.d
+    "$@" -Wc,+Maked
+  else
+    tmpdepfile1=$dir$base.d
+    tmpdepfile2=$dir$base.d
+    "$@" +Maked
+  fi
+  stat=$?
+  if test $stat -eq 0; then :
+  else
+     rm -f "$tmpdepfile1" "$tmpdepfile2"
+     exit $stat
+  fi
+
+  for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
+  do
+    test -f "$tmpdepfile" && break
+  done
+  if test -f "$tmpdepfile"; then
+    sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile"
+    # Add `dependent.h:' lines.
+    sed -ne '2,${
+              s/^ *//
+              s/ \\*$//
+              s/$/:/
+              p
+            }' "$tmpdepfile" >> "$depfile"
+  else
+    echo "#dummy" > "$depfile"
+  fi
+  rm -f "$tmpdepfile" "$tmpdepfile2"
+  ;;
+
+tru64)
+   # The Tru64 compiler uses -MD to generate dependencies as a side
+   # effect.  `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'.
+   # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
+   # dependencies in `foo.d' instead, so we check for that too.
+   # Subdirectories are respected.
+   dir=`echo "$object" | sed -e 's|/[^/]*$|/|'`
+   test "x$dir" = "x$object" && dir=
+   base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'`
+
+   if test "$libtool" = yes; then
+      # With Tru64 cc, shared objects can also be used to make a
+      # static library.  This mechanism is used in libtool 1.4 series to
+      # handle both shared and static libraries in a single compilation.
+      # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d.
+      #
+      # With libtool 1.5 this exception was removed, and libtool now
+      # generates 2 separate objects for the 2 libraries.  These two
+      # compilations output dependencies in $dir.libs/$base.o.d and
+      # in $dir$base.o.d.  We have to check for both files, because
+      # one of the two compilations can be disabled.  We should prefer
+      # $dir$base.o.d over $dir.libs/$base.o.d because the latter is
+      # automatically cleaned when .libs/ is deleted, while ignoring
+      # the former would cause a distcleancheck panic.
+      tmpdepfile1=$dir.libs/$base.lo.d   # libtool 1.4
+      tmpdepfile2=$dir$base.o.d          # libtool 1.5
+      tmpdepfile3=$dir.libs/$base.o.d    # libtool 1.5
+      tmpdepfile4=$dir.libs/$base.d      # Compaq CCC V6.2-504
+      "$@" -Wc,-MD
+   else
+      tmpdepfile1=$dir$base.o.d
+      tmpdepfile2=$dir$base.d
+      tmpdepfile3=$dir$base.d
+      tmpdepfile4=$dir$base.d
+      "$@" -MD
+   fi
+
+   stat=$?
+   if test $stat -eq 0; then :
+   else
+      rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+      exit $stat
+   fi
+
+   for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4"
+   do
+     test -f "$tmpdepfile" && break
+   done
+   if test -f "$tmpdepfile"; then
+      sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile"
+      # That's a tab and a space in the [].
+      sed -e 's,^.*\.[a-z]*:[   ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile"
+   else
+      echo "#dummy" > "$depfile"
+   fi
+   rm -f "$tmpdepfile"
+   ;;
+
+#nosideeffect)
+  # This comment above is used by automake to tell side-effect
+  # dependency tracking mechanisms from slower ones.
+
+dashmstdout)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout, regardless of -o.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  test -z "$dashmflag" && dashmflag=-M
+  # Require at least two characters before searching for `:'
+  # in the target name.  This is to cope with DOS-style filenames:
+  # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise.
+  "$@" $dashmflag |
+    sed 's:^[  ]*[^: ][^:][^:]*\:[    ]*:'"$object"'\: :' > "$tmpdepfile"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  tr ' ' '
+' < "$tmpdepfile" | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+dashXmstdout)
+  # This case only exists to satisfy depend.m4.  It is never actually
+  # run, as this mode is specially recognized in the preamble.
+  exit 1
+  ;;
+
+makedepend)
+  "$@" || exit $?
+  # Remove any Libtool call
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+  # X makedepend
+  shift
+  cleared=no eat=no
+  for arg
+  do
+    case $cleared in
+    no)
+      set ""; shift
+      cleared=yes ;;
+    esac
+    if test $eat = yes; then
+      eat=no
+      continue
+    fi
+    case "$arg" in
+    -D*|-I*)
+      set fnord "$@" "$arg"; shift ;;
+    # Strip any option that makedepend may not understand.  Remove
+    # the object too, otherwise makedepend will parse it as a source file.
+    -arch)
+      eat=yes ;;
+    -*|$object)
+      ;;
+    *)
+      set fnord "$@" "$arg"; shift ;;
+    esac
+  done
+  obj_suffix=`echo "$object" | sed 's/^.*\././'`
+  touch "$tmpdepfile"
+  ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
+  rm -f "$depfile"
+  cat < "$tmpdepfile" > "$depfile"
+  sed '1,2d' "$tmpdepfile" | tr ' ' '
+' | \
+## Some versions of the HPUX 10.20 sed can't process this invocation
+## correctly.  Breaking it into two sed invocations is a workaround.
+    sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile" "$tmpdepfile".bak
+  ;;
+
+cpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  # Remove `-o $object'.
+  IFS=" "
+  for arg
+  do
+    case $arg in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    *)
+      set fnord "$@" "$arg"
+      shift # fnord
+      shift # $arg
+      ;;
+    esac
+  done
+
+  "$@" -E |
+    sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
+       -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' |
+    sed '$ s: \\$::' > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  cat < "$tmpdepfile" >> "$depfile"
+  sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvisualcpp)
+  # Important note: in order to support this mode, a compiler *must*
+  # always write the preprocessed file to stdout.
+  "$@" || exit $?
+
+  # Remove the call to Libtool.
+  if test "$libtool" = yes; then
+    while test "X$1" != 'X--mode=compile'; do
+      shift
+    done
+    shift
+  fi
+
+  IFS=" "
+  for arg
+  do
+    case "$arg" in
+    -o)
+      shift
+      ;;
+    $object)
+      shift
+      ;;
+    "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
+       set fnord "$@"
+       shift
+       shift
+       ;;
+    *)
+       set fnord "$@" "$arg"
+       shift
+       shift
+       ;;
+    esac
+  done
+  "$@" -E 2>/dev/null |
+  sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
+  rm -f "$depfile"
+  echo "$object : \\" > "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::     \1 \\:p' >> "$depfile"
+  echo "       " >> "$depfile"
+  sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
+  rm -f "$tmpdepfile"
+  ;;
+
+msvcmsys)
+  # This case exists only to let depend.m4 do its work.  It works by
+  # looking at the text of this script.  This case will never be run,
+  # since it is checked for above.
+  exit 1
+  ;;
+
+none)
+  exec "$@"
+  ;;
+
+*)
+  echo "Unknown depmode $depmode" 1>&2
+  exit 1
+  ;;
+esac
+
+exit 0
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/doc/CVS/Entries b/doc/CVS/Entries
new file mode 100644 (file)
index 0000000..41cfae4
--- /dev/null
@@ -0,0 +1,7 @@
+/GAME_RULES/1.3/Tue Jan 23 08:32:13 2007//
+/GHULSCRIPT/1.4/Mon Jun 30 09:42:47 2003//
+/MAP_HACKERS_GUIDE/1.7/Tue Jan 23 08:32:13 2007//
+/USERS_GUIDE/1.31/Sat Oct 10 23:31:19 2009//
+/null.gif/1.1/Mon Aug 28 12:39:23 2006/-kb/
+/users_guide.html/1.8/Sat Oct 27 05:46:49 2007//
+D
diff --git a/doc/CVS/Entries.Log b/doc/CVS/Entries.Log
new file mode 100644 (file)
index 0000000..3fe78de
--- /dev/null
@@ -0,0 +1,2 @@
+A D/engine_extension_and_design////
+A D/world_building////
diff --git a/doc/CVS/Repository b/doc/CVS/Repository
new file mode 100644 (file)
index 0000000..fe6e416
--- /dev/null
@@ -0,0 +1 @@
+nazghul/doc
diff --git a/doc/CVS/Root b/doc/CVS/Root
new file mode 100644 (file)
index 0000000..4d8737a
--- /dev/null
@@ -0,0 +1 @@
+:ext:gmcnutt@nazghul.cvs.sourceforge.net:/cvsroot/nazghul
diff --git a/doc/GAME_RULES b/doc/GAME_RULES
new file mode 100644 (file)
index 0000000..893b236
--- /dev/null
@@ -0,0 +1,491 @@
+Contexts & Control Modes
+------------------------
+
+There are 2 contexts:
+* Party
+* Combat
+
+In party context:
+* A single icon in the center of the screen represents the entire player party
+* A single icon represents npc parties (which consist of one or more
+  characters)
+
+In combat context there are three different modes of control:
+* Solo mode, where a single party member moves while the others do nothing
+* Follow mode, where the player controls the party leader and the other member
+  follow him/her/it
+* Round-robin mode, where the player moves each party member in turn
+
+Place Types
+-----------
+
+And there are 4 types of places:
+* Wilderness (party mode)
+* Town (party mode)
+* Dungeon room (combat mode)
+* Temporary combat map (combat mode)
+
+Place To Place Movement
+-----------------------
+
+U5 is the basic model. Linux cloned unix, nazghul is trying to clone u5. But
+there is at least one feature of u5 I cannot stand: first person dungeons. So
+those have to go.
+
+In u5, the player walks around the FP dungeon and when he enters a room the
+view switches back to a sane top-down combat map. Things get interesting when
+the player leaves the dungeon.
+
+But first, note that all party member must exit the same way. This simple rule
+presents a problem for nazghul: not all party members necessarily share the
+same passability rules. So, for example, if a floater crosses a body of water
+and exits off the map, what happens if the other party members can't get across
+the water? So this problem needs to be solved. And I think the way to solve it
+is to do a check before allowing the first party member to exit. The check
+consists of running a pathfinding alg from each other party member to the exit
+point. If a party member can't find a path the player gets a message and the
+exit is denied. This is a simple, rather stupid way to do it (it ignores the
+possibility of mechanisms or spells being able to create passages, for example,
+which could lead to pathological cases). And things get even hairier when we
+consider that a passability check to the destination is also necessary, which
+I'll cover below. Now u5 did not have any of these issues because everyone in
+the party had the same exact passability. If I can't figure out any other way
+to do it, that will be my solution as well.
+
+Now, let's consider what happens when the player party exits a dungeon combat
+room. There are 3 possibilities.
+
+First, the party may exit to a dungeon corridor tile. If the tile was occupied
+by an npc party then combat on a temporay map immediately ensued. Upon exit
+from combat the party was on the same exact tile (exiting temporary combat maps
+in a certain direction does not move the party to the tile in that direction -
+a sensible strategy which I will emulate).
+
+Next, the party may exit to a dungeon corridor tile with a pit or a field. I've
+never seen a case with an impassable energy field, so probably u5 maps were
+designed to avoid that tricky case. In general, corridors outside dungeon rooms
+were gauranteed to be passable. Unfortunately I don't have that luxury, due to
+the principle of freedom of expression. (The Principle of Freedom of Expression
+states that I don't have any control over the scripts fed to the engine.)
+
+Finally, the party may exit to another dungeon room. Note that in u5 entrance
+was gauranteed in all dungeon rooms. Again, u5 controlled the script, the
+party's passability was hardcoded, and everyone in the party had the same
+passablity (and the number of party members had an upper limit).
+
+Now, I want to get this damned thing finished. And I'm willing to sacrifice
+some dearly held feature ideas to make that happen. Here are the features which
+are causing problems:
+
+* The party will have a fixed passability mask specified at load time. This
+  mask is a property of the party. It is not derived from the party members'
+  masks. It is fixed. The purpose of this is to allow the engine to
+  sanity-check combat map and dungeon room entrances at load time. If a map
+  fails the check the engine refuses to load the game.
+
+* The party will have a fixed upper limit on the number of party members
+  specified at load time. Again, this is to allow sanity-checking of entry
+  zones in combat and dungeon room maps.
+
+* Combat maps and dungeon room maps must have an "entry zone" on all four
+  sides. Even if the map is never placed such that the player party could
+  possibly enter there, it doesn't matter. All four sides will have an entry
+  zone. The zone must be able to fit the maximum number of party members with
+  the party passability mask.
+
+  The engine will be pretty flexible with zones. The algorithm will first
+  search, starting at the midpoint of the map edge, for a passable tile. Once
+  it finds one it will then attempt to pathfind from there to n other passable
+  tiles, where n is the maximum number of party members. So the zones need not
+  be square regions centered on the map edge or anything like that.
+
+  Furthermore, combat maps will not be persistent, even in dungeons. They will
+  be loaded afresh each time they are entered.
+
+* I'll disallow placing autoportals in the entry zones. This will be checked at
+  load time when the portal is declared.
+
+* Everyone in the party will have a superset of the party passability mask.
+  It's ok if they have extra passability (permanent or temporary).
+
+* Party members cannot teleport out of dungeon rooms. They can teleport within
+  dungeon rooms, and I'll allow teleport spells which move the whole party at
+  once.
+
+* Portals which lead into dungeon rooms must have an entry zone around their
+  destinations. This will be checked at load time when the portal is defined.
+
+Now given these limitations we can solve all of our problems.
+
+The Exit Problem
+----------------
+
+All party members must exit a dungeon room the same way. (I'm going to lift
+this restriction on temporary combat maps because the party will not change
+location upon exit). If a party member attempts to exit via an edge or a portal
+the engine will check the destination place and location. If that place and
+location is not passable to the *party* then I will reject the move (note that
+if the tile is occupied by a non-hostile npc party it is not passable). If I
+cannot pathfind from any other party member to the exit point then I will
+reject the move.
+
+Exit From Dungeon Room To Wilderness or Town
+--------------------------------------------
+
+There are several possibilities here. But impassability is not one of them -
+that's tested in the Exit Problem.
+
+First, the destination tile might be occupied by a hostile npc party. In this
+case combat begins immediately on a temporary combat map. Upon exit from that
+combat the party will occupy the destination tile.
+
+Next, the destination tile might contain an automatic portal. The standard
+rules for autoportals apply in this case.
+
+Finally, the destination tile might be empty in which case the party simply
+lands there.
+
+Exit From Dungeon Room To Dungeon Room
+--------------------------------------
+
+Since entrance to the next room is guaranteed, there should be no issues
+here. Note that upon entrance to a dungeon room (or regular combat) the player
+party is positioned first and then the npc party.
+
+That should handle dungeon rooms. Towns are very similar to dungeons, except
+that the engine is always in party context in towns and combat context in
+dungeons. But in towns the party can still exit via a portal or by walking off
+the edge of the map. The exit rules from town are the same (except of course
+the pathfinding rule for party members because we're in party mode).
+
+Entering Wilderness
+-------------------
+
+* If the destination tile's terrain is impassable and there is no unoccupied
+  vehicle there then entry fails
+* Else if a non-hostile npc party is there then entry fails (revisit: add a
+  push mechanism?)
+* Else if a hostile npc party is there then the player immediately enters a
+  temporary combat map. If combat succeeds then when it is over the party is on
+  that tile. If an autoportal was there then it is ignored.
+* Else if an autoportal is there then it's ignored (revisit - necessary?)
+
+Entering Temporary Combat Maps
+------------------------------
+
+* If not all player party members can be placed then combat is denied. The npc
+  party will not be removed from the map in this case.
+
+----------------------------------
+
+Moving In Party Mode
+--------------------
+
+Possible outcomes:
+* blocked by non-hostile
+* fought combat
+* game over
+* couldn't enter combat
+* success
+* impassable
+* couldn't enter dungeon
+* noplace to go
+* blocked by vehicle
+* entered dungeon
+
+if the destination tile is occupied {
+
+    /**************************************************************************
+     * In older versions moving toward a hostile npc party was implicitly
+     * interpreted as an attack. This may cause some user confusion when
+     * moving from one place to another, depending on how other features are
+     * implemented. Examples to consider are exiting town off a map edge,
+     * entering town via a map edge and passing through a portal or other means
+     * of teleporting. In all of these cases the user cannot see the
+     * destination when deciding to move, but he expects the move to take him 
+     * to a new place.
+     *
+     * One way to deal with this is what I have here: block the move (and let
+     * the caller print a user message explaining what happened). I can think
+     * two other ways to deal with this. One, let the attack happen. Two, try
+     * to "bump" the npc out of the way to allow passage.
+     *
+     * Letting the attack happen opens up other problems we must solve:
+     * What happens when combat is over - do we then run through this algorithm
+     * again to see if the move now succeeds? What if the destination is an
+     * autoportal entrance?
+     *
+     * Trying to bump also opens up more issues. What if the bump fails? Should
+     * we allow any npc to be bumpbed? What about npcs in vehicles? What if we
+     * bump them onto an autportal (or should that be disallowed)?
+     *
+     * Since these solutions require yet other solutions to support them, I
+     * tend to disfavor them.
+     *************************************************************************/
+
+    return blocked by npc
+
+} else if the destination tile contains an autoportal and autoportals are not
+  ignored {
+
+    /*************************************************************************
+     * I give automatic portals higher priority than passability. This is
+     * mainly to allow ships to have access to towns which are placed on land
+     * but which may have a port. Passability should be determined by checking
+     * the town map to see if it allows entrance, not checking the terrain the
+     * tile is on.
+     *************************************************************************/
+
+        if portal destination is a dungeon {
+            if dungeon can be entered {
+                return entered dungeon
+            } else {
+                return couldn't enter dungeon
+            }
+        } else {
+            recur on portal destination with autoportals disabled
+            if recursion resulted in combat {
+                retry recursion and return results
+            } else {
+                return recursion results
+            }
+        }
+} else if the destination tile is impassable {
+
+    if the tile has a vehicle (empty) and the player is not in a vehicle {
+
+        move party to destination
+
+        return success
+
+    } else {
+
+        return impassable
+
+    }
+} else if the destination tile is off-map {
+    if this place has no parent map {
+        return noplace to go
+    } else {
+
+        /*********************************************************************
+         * Yes, I'm making the following unconditional with no further checks.
+         * The parent tile is _always_ and _unconditionally_ passable.
+         * Consider everything that could make that tile impassable:
+         *   --Terrain on parent map... don't care
+         *   --Autoportals leading elsewhere... ignore them
+         *   --Npc's... they aren't allowed on town tiles in the wilderness,
+         *     and if one sneaks through ignore it
+         *   --Fields... unlikely, and don't care
+         *   --Vehicles (when player is already in one)... ignore them (and
+         *     don't allow player to abandon a vehicle over a town, otherwise
+         *     we can leak vehicles since consecutive abandonments will 
+         *     clobber previous ones)
+         * See notes on the ship problem in discussion #1 below.
+         *********************************************************************/
+        move party to tile on parent map
+        return success
+    }
+} else if the party is in a vehicle and the destination tile also contains a
+  vehicle {
+    return blocked by vehicle
+} else {
+    move party to destination
+    return success
+}
+
+Exiting Dungeon Rooms
+---------------------
+
+* You cannot exit dungeon rooms via edges. I know this differs from u5, but
+  dungeons are just different from u5. Unlike u5, a nazgul dungeon room can be
+  arbitrarily large. In effect a dungeon room is more like a dungeon level.
+* The only way in or out of dungeon rooms are portals or party teleport
+  effects.
+* To avoid the stranded party member effect, dungeon exits will work like
+  u6. First, the party must be in follow mode. When the party leader attempts
+  to enter a portal all party members must be able to pathfind to the portal
+  within N steps. If any cannot then entrance is denied.
+
+if party is not in follow mode or
+if any party members cannot pathfind to the portal within N steps {
+    failed
+} else {
+    call party move routine on portal destination (autoportals enabled?)
+    case blocked by non-hostile {
+        failed
+    }
+    case fought combat {
+        retry
+    }
+    case game over {
+        game over
+    }
+    case couldn't enter combat {
+        failed
+    }
+    case success {
+        success
+    }
+    case impassable {
+        failed
+    }
+    case couldn't enter dungeon {
+        failed
+    }
+    case noplace to go {
+        portal connection error
+    }
+    case blocked by vehicle {
+        failed
+    }
+    case entered dungeon {
+        restart dungeon loop
+    }
+}
+
+
+----------------------------------------------------------------------------
+Design Discussion #1: Stepping off a map edge
+----------------------------------------------------------------------------
+
+There are two ways to implement this. One way is to emulate u5, where stepping
+off a town map took the party to the wilderness map and the party was located
+directly over the town. Recall that in u5 when entering a town the party always
+appeared in town at the same entrance, so this was fine.
+
+Another way to implement this was suggested by Sam: stepping off the edge of
+town takes you to the wilderness and moves the party one tile in the direction
+of travel. Stepping onto a town makes the party appear on the map edge
+corresponding to the side of town entered from. It's a nice touch, but it is a
+bit of an iceberg. The advantages of this approach are:
+
+* It's more intuitive to the player
+* It allows games where a town blocks passages in the wilderness (for example a
+  fortress town guarding a passage through the mountains)
+* Player's can save some time by entering a specific side to reach a specific
+  part of town more quickly
+* Player's can avoid parts of town they don't like
+* It allows towns with ports and docks for ships to enter and exit from the
+  wilderness, as well as foot traffic through a gate on another side of town
+
+The disadvantages are:
+
+* If the player does end up directly over the town in the wilderness, how does
+  he enter and from which direction? This can be solved with a player prompt.
+* If the player tries to walk off a map edge but the move fails, what should
+  the player see? One possibility is to move the player over the town in this
+  special case, provided we can solve the reentry problem above.
+* If the player teleports onto a town, what should happen? One possibility is
+  he does not enter the town, but may enter as noted above. Another is that he
+  enters from the direction of travel, another is that he lands in the center
+  (or the teleport fails). I like the first solution best because it's
+  simplest.
+
+Example: the player tries to step off a map edge, but the tile in the direction
+of travel is occupied by a hostile npc party in a ship.
+1. First the party is moved to the wilderness directly over the town
+2. Next the party engages the hostiles in combat, using a combat map comprised
+   partially of the terrain beneath the town and partially of the terrain
+   beneath the hostile. Entrance to combat is not gauranteed, since the terrain
+   beneath the town may be impassable to the party (the party may have entered
+   the town through a portal).
+3. If combat entry fails then the move is done. The hostile npc remains next to
+   the town.
+4. If combat entry succeeds then the party will still be on the town and the
+   empty npc ship will be visible next to town.
+
+In general, I want to completely separate combat from movement - at least for
+version 1.0. In fact, I'm probably going to disable the implicit attack that
+occurs when you try to step on a tile with a hostile npc. Attacks will be
+explicit with the (A)ttack-<dir> command like u4/u5.
+
+
+[the ship problem]
+
+Another issue Sam and I discovered the other night is with passability on the
+parent map. We were in a ship on the wilderness and entered town while still on
+the ship. This worked because the edge of town we entered on had a tile
+passable to the ship. But exiting didn't work... the tile the town occupied on
+the parent map had land passability. Here's a disadvantage to the rule! But
+this needs to work. This is the reason I added the clause that moving off the
+edge of a town map _always_ works as long as it has a parent map. Ah... much
+simpler.
+
+
+----------------------------------------------------------------------------
+Design Discussion #2: Should the party move to the destination tile after
+succeeding in combat?
+----------------------------------------------------------------------------
+I'm thinking "no". U5 did not. And taking the opposite apporach might result in
+some surprises for the player. For example, if the hostile npc party was
+standing on an autoportal, after combat when the player party moves to occupy
+that tile should the autoportal be invoked? Consider what the player would see:
+first, he sees the npc party on the wilderness. Next, he attacks and sees
+combat. When he exits combat he expects to go back to the wilderness, but
+instead he is autoportalled somewhere. Confusing.
+
+Also, if the npc party left behind a vehicle then it would be most apparent to
+the player that they've just captured a vehicle if it's sitting next to them
+upon exit from combat.
+
+Furthermore, I can't think of a good reason to say "yes". My original reason
+involved exiting from towns, but with the outcomes of Design Discussion #1 I no
+longer think this is an issue. When the party exits town and encounters a
+hostile npc party then after combat they will be over the town, and are free to
+continue moving or to reenter.
+
+However, what if the party enters a portal but the destination tile contains a
+hostile npc party? If combat is entered, then after combat should the player
+still be standing at the portal entrance? Or at the portal destination?
+
+One way to work around that problem is to treat autportaling specially. Having
+the move routine return a result code is one way. When the party steps on an
+autportal the move routine calls itself recursively on the portal
+destination. If combat occurs the recursive call can return a code to that
+effect, and the calling layer can then do the recursive call again in the case
+of combat. Since the hostile npc party should be gone at that point the
+recursive call will "succeed".
+
+----------------------------------------------------------------------------
+Design Discussion #3: Complications when entering portals
+----------------------------------------------------------------------------
+
+What should happen when a portal destination is on impassable terrain? What if
+a portal itself is on impassable terrain?
+
+In the case where a portal entrance is really a town entrance, the passability
+of the terrain the portal is on should not be a consideration. Instead, the
+engine should check and see if the town edge in question has some passable
+terrain the party can be moved to.
+
+But what about other cases? It looks rather strange when the player can step
+from the shore onto a whirlpool - especially when the whirlpool is linked to
+another whirlpool in the middle of some ocean. Entering whirlpools on a ship
+makes perfect sense. But if the ocean is usually impassable to the party, what
+then?
+
+I think that except for the special case of town entrances the passability of
+the tile a portal is on should be a consideration. If the party can't leap into
+the ocean, they shouldn't be able to leap into a whirlpool.
+
+Likewise the destination passability should also be a consideration. On the one
+hand, it might be kind of fun to let the player drive a ship through a moongate
+and get marooned on dry land - because the player can always walk away. But
+letting the player get marooned someplace they can't get out of seems
+unfriendly. On the other hand, maybe I shouldn't be trying to make that
+decision for game designers. After all, it won't crash the engine.
+
+Ok, yes, that's a good principle to follow. Portal links are completely under
+the game developers control, so I'll leave it to them. Terrain passability will
+not be a consideration for portals, either on the source or on the destination.
+
+Well, I tried it and discovered that ships can turn when stranded. This is sort
+of disconcerting, so I tried to disable that by having the turning code check
+for impassable terrain. And then that broke the ship-exit-town problem! I still
+think that this is a good principle, though, so I'll simply permit turning
+while stranded. This will also permit the case where a ship portals to a
+stranded destination, but right next to it is another auto-portal, so the ship
+can still enter that autoportal and escape. Weird, but I'm not going to lose
+sleep over it.
+
diff --git a/doc/GHULSCRIPT b/doc/GHULSCRIPT
new file mode 100644 (file)
index 0000000..180d015
--- /dev/null
@@ -0,0 +1,794 @@
+The GhulScript Specification
+
+
+-Conversation
+
+A conversation is a set of other conversations and a set of keyword-response
+pairs.
+
+        <conversation> := CONV tag { IMPORT { <conversations> } 
+                                     NATIVE { <qr_pairs> }}
+        <conversation> := tag <conversations> |
+        <qr_pairs> := <qr_pair> <qr_pairs> |
+        <qr_pair> := <query> tag
+
+The lookup rules determine how to match a keyword to a response. The order of
+searching qr_pairs for a keyword match is as follows:
+
+        1. The NATIVE section of a conversation, in the order specified
+        2. Each conversation in the IMPORT section, in the order specified
+        3. The DEFAULT keyword
+
+Note that rule 2 is recursive (and if I haven't said it yet circular inclusion
+of conversations is disallowed). The DEFAULT keyword is a special keyword used
+when a search fails. Other special keywords include HAIL, used when starting a
+conversation, and BYE, used when ending a conversation.
+
+
+--Special Keywords
+
+ Normally a keyword is something the player types during a conversation, but
+ the following keywords are special in that the engine generates them
+ automatically in certain situations.
+
+        DEFAULT If the player keyword does not match anything in the
+                conversation, then the engine looks up the response for the
+                DEFAULT keyword instead. This gives NPC characters the chance
+                to customize their "I don't know" response.
+
+        HAIL    When the conversation first starts up, before the player has a
+                chance to give a query, the engine will check if the
+                conversation has a response for the HAIL keyword and will
+                invoke it if so. This gives NPC characters a chance to have the
+                first word.
+
+        BYE     When the conversation terminates, after the player has issued
+                his last query and received a response, the engine will check
+                if the conversation has a response to the BYE keyword and will
+                invoke it if so. This gives NPC characters a chance to say
+                "Farewell" or have the last word.
+
+The player may type these keywords and they will be looked up in the usual way.
+
+
+--Responses
+
+In the grammar above a qr_pair is a <query> (which is a simple string) and a
+tag. The tag refers to a response. Each response is defined separately in its
+own construct. Because responses are independent you may mix them with
+different keywords in different conversations as you like. The syntax for a
+response declaration is like this:
+
+        <tagged_response> := RESP tag <response-list>
+
+        <response-list> := { <response> <response-or-nil> }
+
+        <response> := SAY string              |
+                      TRADE <trade-list>      |
+                      TURN_AWAY               |
+                      SET_FLAG flag           |
+                      CLEAR_FLAG flag         |
+                      TAKE GOLD               |
+                      CHANGE_PARM <parm-id> <delta> |
+                      TAKE_ITEM tag           |
+                      GIVE_ITEM tag           |
+                      JOIN                    |
+                      ATTACK                  |
+                      GET_AMOUNT              |
+                      <check> <response-list> <response-list>
+
+                      /* Proposed constructs: */
+                      MENU <menu> |
+                      BREAK
+
+        <delta> := +int | -int
+        <trade-list> := { <trade-entry> <trade-entry-or-nil> }
+        <trade-entry> := tag <price>
+        <price> := int
+
+        <check> := GET_YES_NO |
+                   CHECK_PARM <parm-id> operator int |
+                   CHECK_FLAG flag int bool |
+                   CHECK_ITEM tag |
+                   CHECK_MEMBER tag
+
+        <parm-id> := int
+
+        <menu> := { <menu-item> <menu-item-or-nil> }
+        <menu-item> := <name> <cost> <response-list>
+        <name> := string
+        <cost> := int
+
+        <menu-item-or-nil> := <menu-item> |
+        
+        <response-or-nil> := <response> |
+
+
+        SAY     The SAY command prints a line on the console. It prints the
+                literal string that follows it with no formatting.
+
+        TRADE   The TRADE command invokes the trading subroutine of the game
+                engine, providing it a list of items and prices to trade. The
+                engine automatically adds buy/sell and quantity prompts and
+                handles the exchange of money and goods.
+
+                When the player opts to Buy he sees the list of goods and
+                prices. He can buy as many as he cares to and can afford (in
+                other words the merchant has an endless supply of the goods
+                listed).
+
+                When the player opts to Sell then the engine scans player
+                inventory and lists any of the items from inventory which
+                appear on the trade list. The sell price is fixed at 1/4 of the
+                buying price. This constant is currently hard-coded in the
+                engine and applies to all trade situations.
+
+        TURN_AWAY
+                The TURN_AWAY command causes the NPC to terminate the
+                conversation without player consent. The player will see a
+                console message like "Hawknoz turns away." and then
+                conversation mode will be over.
+
+        SET_FLAG
+                The SET_FLAG command sets the value of the specified flag,
+                causing a subsequent CHECK_FLAG to evaluate to true. The
+                opposite of SET_FLAG is CLEAR_FLAG.
+
+        CLEAR_FLAG
+                The opposite of SET_FLAG.
+
+        TAKE_GOLD
+                Decrement the player's gold counter by the indicated
+                amount. The engine will not decrement beyond zero. (Note that
+                there is no corresponding GIVE_GOLD simply because I haven't
+                needed it).
+
+        CHANGE_PARM
+                Change the indicated parameter by the indicated amount. If the
+                amount is negative the engine will not decrement beyond
+                zero. (Note the absence of a SET_PARM - again because I haven't
+                needed it yet).
+
+        TAKE_ITEM
+                Decrement one count of the indicated item type from player
+                inventory. If the player has none in inventory then this has no
+                effect. If the tag does not resolve to an item type then this
+                has no effect.
+
+                Note: currently this does not add the item to the NPC's
+                inventory, as one might expect.
+
+        GIVE_ITEM
+                The opposite of TAKE_ITEM. This does not actually remove
+                anything from the NPC's inventory.
+
+        GET_YES_NO
+                Prompt the player to answer yes or no. The player must respond
+                with one or the other (ie he cannot escape from the
+                prompt). "Yes" means true and "no" means false.
+
+         CHECK_PARM
+                Check if the given expression is true for the indicated
+                parameter.
+
+         CHECK_FLAG
+                Test if a flag is set.
+
+         CHECK_ITEM
+                Check if the player has at least one count of the indicated
+                item in inventory.
+
+         CHECK_MEMBER
+                Check if the indicated character has joined the player party.
+
+         
+         /* Proposed constructs */
+         
+         MENU   Use the status window to display a list of choices to the
+                player. When the player selects an entry from the list the
+                corresponding set of responses is executed. Upon completion -
+                unless one of the responses was a BREAK or EXIT - the menu will
+                "loop", displaying the list of choices again. MENUs may be
+                nested.
+
+         BREAK  Break out of a MENU loop. Execution resumes after the MENU
+                block. If the MENUs are nested, only the lowest level MENU is
+                aborted.
+
+---Flags
+
+The SET_FLAG, CLEAR_FLAG and CHECK_FLAG responses all operate on flags. A flag
+is an unsigned 8-bit integer id for a boolean value. 
+
+Flags may be global or per-conversation. Global flags may be accessed from any
+conversation in the game. Per-conversation flags apply only to the conversation
+in which they appear. Different conversations may use the same per-conversation
+flag id but each will have its own value for the flag. Per-conversation flag
+ids have the high bit clear (giving them the range 0 to 127) and global flag
+ids have the high bit set (giving them the range 128 to 255).
+
+Note: Initially all flags are clear. When savegames are implemented flag values
+will need to be saved/restored, so in the future there will need to be syntax
+for specifying initial flag values.
+
+
+---Parameters
+
+The CHANGE_PARM and CHECK_PARM responses operate on parameters. A parameter is
+a signed 32-bit id for an integer value.
+
+The engine reserves all negative parameter ids. The following parameter ids are
+currently supported by the engine:
+
+        -1 AMOUNT
+                The AMOUNT parameter refers to the value obtained by the last
+                GET_AMOUNT response. A value of -1 means the player did not
+                enter an amount at the last prompt (i.e. escaped out of the
+                prompt).
+
+        -2 GOLD
+                This refers to the player's gold counter.
+
+        -3 FOOD
+                This refers to the player's food counter.
+
+        -4 ACTIVITY
+                This refers to the speaking NPC party's current activity
+                code. Activity codes are used by schedules. This parameter
+                allows conversation scripts to change their response based on
+                what the npc party is currently doing. For example, in u5 the
+                NPC merchants would not trade with the player when they were
+                not in their shop.
+
+All parameter id's of 0 or greater are available for use by the game script.
+
+All parameters are global in scope.
+
+Note: Initially all non-reserved parameters are zero. When savegames are
+implemented parameter values will need to be saved/restored, so in the future
+there will need to be syntax for specifying initial parameter values.
+
+
+---Branching
+
+The GET_YES_NO, CHECK_PARM, CHECK_FLAG, CHECK_ITEM and CHECK_MEMBER responses
+are all branching responses. They each specify a test and two sets of
+responses. If the test evaluates to true then the first set executes, otherwise
+the second set executes.
+
+
+---Examples
+
+These are not final, but are experimental examples for my own benefit while
+designing changes to the language.
+
+Example: a healer. This example illustrates how one might use some as-yet
+unimplemented constructs like MENU, GET_PARTY_MEMBER, CHANGE_HP and an
+unsupported PARTY_MEMBER parameter to script a healer. Note the heavy
+duplication of code for each menu response, and also the dubious syntax for
+checking if the player escaped out of the GET_PARTY_MEMBER prompt.
+
+RESP r_healer {
+    SAY "Hail, traveler! Do you require my healing services?"
+    GET_YES_NO {
+        MENU {
+            "Heal        30g"  {
+                CHECK_PARM GOLD >= 30 {
+                    SAY "Who requires healing?"
+                    GET_PARTY_MEMBER
+                    CHECK_PARM PARTY_MEMBER = 0 {
+                        SAY "Never mind then."
+                    }{                    
+                        CHANGE_HP PARTY_MEMBER +10
+                    }
+                }{
+                    SAY "You lack the gold, my friend."
+                }
+            }
+            "Cure       50g" {
+                SAY "Whom shall I cure?"
+                GET_PARTY_MEMBER
+                CHECK_PARM PARTY_MEMBER = 0 {
+                    SAY "Never mind then."
+                }{
+                    SET_POISONED PARTY_MEMBER false
+                }
+            }
+            "Resurrect 500g" {
+                SAY "Whom shall I call back from the dead?"
+                GET_PARTY_MEMBER
+                CHECK_PARM PARTY_MEMBER = 0 {
+                    SAY "Never mind then."
+                }{
+                    SET_DEAD PARTY_MEMBER false
+                    CHANGE_HP PARTY_MEMBER +10
+                }
+            }
+            "Done" { 
+                SAY "Very well." 
+                BREAK /* exit the MENU loop */
+            }
+        }
+    }{
+        SAY "Very well."    
+    }
+}
+
+
+Example: A weapon merchant. The example illustrates the use of a
+yet-unimplemented technique whereby one response "calls" another by referring
+to its tag. The r_weaponsmith_hail response invokes the r_sell_to_player
+response in order to avoid some of the duplication seen above in the healer
+example. "Arguments" to the "called" response take the form of parameters set
+by the caller before invoking it.
+
+Note that I left the SELL clause blank because I was at a loss on how to
+proceed. There is no proposed syntax for building a MENU list on the fly at
+runtime, and that is essentially what is required for the SELL clause as
+written. An alternative is not to use a MENU for sell, but to use hand-crafted
+checks for items in player inventory followed by offers to buy them one type at
+a time off the player.
+
+Also note the use of multiplication in the r_sell_to_player response. This is
+currently not implemented.
+
+
+RESP r_sell_to_player {
+    SAY "How many would you like?"
+    GET_AMOUNT
+    CHECK_PARM AMOUNT > 0 {
+        SET_PARM COST (AMOUNT * COST)
+        CHECK_PARM GOLD >= COST) {
+            SAY "Here you go.";
+            TAKE GOLD COST;
+            GIVE t_sword AMOUNT;
+        }{
+            SAY "You don't have enough gold!";
+        }
+    }{
+        SAY "Changed your mind, eh?";
+    }     
+}
+
+RESP r_weaponsmith_hail {
+    SAY "Hail, traveler! Do you require my healing services?"
+    GET_YES_NO {
+        MENU {
+            "Buy"  {
+                MENU {
+                    "Swords 100g" {
+
+
+                        /*
+                         * "Call" the other response after setting up the
+                         * "arguments" to it.
+                         */
+                        SET_PARM ITEM $t_sword; 
+                        SET_PARM COST 100;
+                        $r_sell_to_player;
+
+                    }
+                    /*** add other items here ***/
+                    "Done" { 
+                        BREAK;
+                    }
+                }
+            }
+            "Sell" { 
+            
+            }
+            "Done" { 
+                SAY "Very well.";
+                BREAK; /* exit the MENU loop */
+            }
+        }
+    }{
+        SAY "Hrumph.";
+        EXIT;
+    }
+}
+
+----------------------------------------------------------------------------
+Spell Effects
+
+An effect is a change to an object, map or place.
+
+A recurring effect is attached to a target and takes effect every turn. Wether
+or not an effect is recurring is determined by its duration. A duration of < 0
+means it recurs indefinitely (until some other effect removes it). A duration
+of > 0 indicates the number of turns for which the effect will recur before
+expiring. A duration of 0 means the effect is not recurring. Henceforth, I
+DON'T DISTINGUISH BETWEEN RECURRING EFFECTS AND EFFECTS IN THIS DISCUSSION.
+
+A spell attaches a set of effects to a set of targets. A conversation response
+may do the same. So may using an item, stepping on a terrain, or engaging a
+mech. When it comes to effects, the difference between all these things lies in
+how the set of targets is specified. Specifying the set of effects probably
+won't change much between them. But this discussion is about spells. I only
+mention those other things as a reminder.
+
+An effect is a change, so what can be changed? It depends on the target. I've
+listed below some of the most reasonable things I can think of.
+
+        Character Hit Points
+        Character Mana Points
+        Character Strength
+        Character Dexterity
+        Character Intelligence
+        Character Experience
+        Character Level
+        Object Glow
+        Character or Party Turns
+        Object Location
+        Character or Party Alignment
+        Character, Vehicle, Terrain or Mech Passability
+        Character or Party Can Take a Turn
+        Character is Dead  
+        Hidden Objects are Revealed
+        Time is Stopped
+        Magic is Negated
+        Wind Direction
+        Object's Existence
+        Terrain Type
+        Object's Edibility
+        Ambient Glow
+        Mechanism Jam
+        Mechanism Signals
+        Existing Effects (an effect that affects another effect)
+        Object User Bits*
+        Object User Fields*
+
+Those last two (marked with asterisks) probably don't make a lot of sense to
+you now. Why are they there? Well, I can't think of everything a map hacker is
+going to want to design into a game. And some things I don't think require
+engine support. For example, u4/u5 had a virtue system. Currently nazghul does
+not. But by taking advantage of the user bits or user fields a map hacker can
+add one. These bits and fields have no semantic value to the engine, but they
+can be interpreted by the ghulscript. They can be modified by effects, and they
+can be checked by conversation scripts (and perhaps eventually mech
+scripts). Remind me to provide an example somewhere if you're interested in,
+that's all I'm going to say for now.
+
+An effect specification is a piece of ghulscript which declares an effect. Once
+declared, an effect can be referred to elsewhere in the script (such as terrain
+or spell type declarations). I'll show the syntax further down (after I figure
+out what it is ;-)).
+
+Anyway, the first part of an effect specification is WHAT it affects. I refer
+to this as the SUBJECT OF THE EFFECT.
+
+The next part specifies IN WHAT WAY it effects it. This part of the spec
+depends upon what type of attribute is affected. Here's a table:
+
+============================================================================
+Target Type | Subject      | Subject Type    | Notes
+============================================================================
+Character   | Alignment    | SET             |
+Character   | Dead         | BOOL            | Necessary? Or HP==0 enough?
+Character   | Dexterity    | INT             |
+Character   | Experience   | INT             |
+Character   | Field[0-9]   | INT             | Generic attributes
+Character   | Flags        | SET             | Generic flags
+Character   | Hit Points   | INT             |
+Character   | Immunity     | SET             | Effect immunities
+Character   | Intelligence | INT             |
+Character   | Level        | INT             |
+Character   | Lose Turn    | BOOL            |
+Character   | Mana Points  | INT             |
+Character   | Occupation   | TAG             | Change jobs
+Character   | Passability  | SET             |
+Character   | Protections  | SET (?)         |
+Character   | Species      | TAG             | Were-shift somebody
+Character   | Speed        | INT             |
+Character   | Strength     | INT             |
+Effect      | Existence    | BOOL            | Remove another effect
+Mech        | Passability  | SET             | Applies to current state
+Mech        | Jam          | BOOL            |
+Mech        | Signal       | INT             |
+Object      | Glow         | INT             |
+Object      | Location     | (TAG, INT, INT) | Meaning (place, x, y)
+Object      | LocationDelt | (TAG, INT, INT) | 
+Object      | Visible      | BOOL            | Applies to particular object
+Object      | Existence    | BOOL            | Used to destroy an object
+Object      | Type         | TAG             | Morph an object
+Object      | Edibility    | BOOL            | Turn something into food
+Party       | Lose Turn    | BOOL            |
+Party       | Speed        | INT             |
+Party       | Alignment    | SET             |
+Party       | Reveal       | BOOL            | Can see invisible objects
+Party       | TimeStop     | BOOL            | Only this party can take turns
+Party       | MagicNegated | BOOL            | Spellcasting disabled
+Place       | Wind Directi | DIR             | Wind direction
+Place       | Ambient Glow | INT             |
+Terrain     | Passability  | SET             |
+Tile        | Terrain Type | TAG             |
+Vehicle     | Passability  | SET             |
+
+The engine can infer the subject type from the target type and subject, so
+there's no need to specify it in the script. But map hackers will need this
+info as they design effects. If a spec gives a value which is the wrong type
+then the engine needs to complain about it at load time.
+
+The value of an effect is the amount or direction by which the subject changes,
+or the value to which the subject is set. For scaler and vector subject types
+the value of the effect might be a signed offset. This would be added to the
+existing value. The possible operations for each subject meta-type are listed
+below:
+
+============================================================================
+Subject Metatype | Operations
+============================================================================
+scaler           | assign, add, subtract, multiply
+vector           | assign, add, subtract, multiply
+tag              | assign, instantiate, destroy(?)
+bool             | assign, invert
+set              | assign, intersect, union, invert
+============================================================================
+
+Multiple operations can be combined.
+
+An effect is a change which is achieved by some means, and the means indicates
+wether or not the effect will apply to a particular target. Some targets may be
+immune to a particular means so that the effect will not apply. Or some targets
+may have modifiers which apply to a particular means which reduce the value of
+the effect.
+
+At this point I can speculate about what an effect specification is going to
+look like:
+
+EFFECT MagicFireball {
+   target_type Character;
+   subject     HitPoints;
+   value       -10
+   method      (MAGIC|BURN)
+}
+
+// Reduce the value of burn effects by 10
+EFFECT Protection {
+   target_type Character;
+   subject     Protections;
+   value       +10
+   method      (BURN)   
+}
+
+// Make a character immune to burning effects
+EFFECT BurnImmunity {
+   target_type Character;
+   subject     Immunity;
+   value       +BURN
+   method      (MAGIC)
+}
+
+// Here's an effect which might be produced by a sword:
+EFFECT EdgedWeaponDamage {
+   target_type Character;
+   subject     HitPoints;
+   value       -5
+   method      (EDGED_WEAPON)
+}
+
+// And here's one which might be produced by a shield:
+EFFECT EdgedWeaponDamageProtection {
+   target_type Character;
+   subject     Protections;
+   value       +5
+   method      (EDGED_WEAPON)
+}
+
+But what if the character is immune to heat damage? To accomodate immunities in
+the game the effect must specify HOW the effect is achieved. Now the engine has
+no interest in the semantics here, so we can use an open set and let map
+hackers decide what they want the elements of a set to "mean".
+
+Not to get too far off track, but you can see that I'm thinking about the way
+sets should be represented in ghulscript. Currently we use a bitmask. This may
+be a bit too esoteric for normal people. So instead I'm considering a new
+ghulscript construct to pre-declare set elements similar to an
+enumeration. I see no reason to discard the C bitwise operators as a means of
+constructing sets.
+
+EFFECT Burn {
+   // same as before
+   method     (BURN) // where BURN is a script-defined set element
+}
+
+So how does the engine know not to burn a character if that character is immune
+to burn effects? It does this by checking the character's immunity set. If any
+element in the effect method set is not in the character immunity set, then the
+effect is applied. For those who like to think about such things, consider an
+effect which confers immunity to effects which confer immunity... :-)
+
+How is the effect achieved?
+
+        Poison
+        Fire
+        Acid
+        Sleep
+        Paralysis
+        Petrify
+        Frighten
+        Encourage
+        Extensible Bits
+
+How is the effect quantified?
+
+        Integer
+        Integer Offset
+        Boolean
+        Direction
+        Location
+        Location Offset
+        Object Type
+        Terrain Type
+        Terrain Map
+
+How is the target specified?
+
+        Object
+        Object Type
+        Tile
+        Tile Rectangle
+        Tile Circle
+        Alignment        
+        Species
+        Occupation
+        Circle Arc
+        Passability
+
+What special effects apply?
+
+        Change the character's sprite to prone (sleeping, unconscious or dead)
+        Shake the screen
+        Animated missile
+        Animated shockwave (arc-specified)
+        Chain lightning
+        Meteor strike
+        Sounds
+        Screen flash
+        Alpha transparency
+
+Examples:
+
+        An Nox (Cure Poison)
+        What: Existing Character Effect
+        How: Poison
+        Value: False
+        Target Method: Select Party Member
+        
+        In Nox Por (Poison)
+        What:   Character Hit Points
+        How:    Poison
+        Value:  -10
+        Dur:    Indefinite
+        Target: Tile
+        Cumul:  No
+        Multi:  No        
+        
+        Because it affects specifically Character hit points, the engine knows
+        to search the targeted tile for a Character object. Because it does not
+        support multiple targets only the first Character found will be
+        affected. Because the effect is not cumulative the engine will search
+        the list of existing effects for the Character to make sure a Poison
+        effect is not already at work. If not then it checks the Character's
+        immunity mask and if the Poison bit is set then the effect is
+        ignored. Otherwise it inserts the new effect in the list of effects for
+        the character and applies -10 to the Character hit points. Since the
+        duration is indefinite the engine does not decrement the duration
+        counter.
+
+Effects which create objects are a bit different then what is discussed
+above. Such an effect has no subject, as it is not changing an existing
+object's attributes. Instead it is creating a new subject.
+
+There are several ways to carry out object creation. First of all, we must
+unfortunately distinguish between characters and other object types. The reason
+is that most objects have a type, and this type specifies the default values
+for an object. But characters do not have a single type. Instead they have a
+species, an occupation, a schedule and a conversation. Perhaps they should have
+a type which combines all these elements. The downside is you end up with a lot
+of character types which will only have a single instance because the type info
+is so specific to a single character, which is why I deviated from the rule a
+bit. Anyway, besides that distinction we must also recognize that sometimes we
+want to create a new object from scratch and sometimes we want to clone an
+existing object.
+
+EFFECT SlimeCloneWhenDamaged {
+        target_type   Character;
+        target_method Effected;
+        subject       Existence;
+        hook          HpReduced;
+        source        ();
+        value         new;
+        probability   0.25;
+}
+
+
+
+Prototype header file:
+
+        // What the effect applies to.
+        enum effect_target_type {
+                effect_target_type_none = 0,
+        };
+
+        // How to pick what the effect applies to.
+        enum effect_target_method {
+                effect_target_method_none = 0,
+                effect_target_method_affected,
+        };
+
+        // What is being changed about the thing the effect applies to?
+        enum effect_subject {
+                effect_subject_none = 0,
+                effect_subject_affected,
+        };
+
+        // List of subject value types.
+        enum effect_value_type {
+                effect_value_none = 0,
+                effect_value_tag,
+                effect_value_bool,
+                effect_value_int,
+                effect_value_float,
+        };
+
+        // How is the value of the subject going to be changed?
+        struct effect_value {
+                enum effect_value_type type;
+                union value {
+                        char *tag;
+                        int _bool:1;
+                        int _int;
+                        float _float;
+                };
+        };
+
+        // List of events which invoke an effect ("hooks" an effect is attached
+        // to)
+        enum effect_hook {
+                effect_hook_none = 0,
+                effect_hook_hp_reduced,
+        };
+
+        // List of ways to specify a target for an effect.
+        enum effect_target_method {
+                effect_target_none = 0,
+                effect_target_effected,  // whatever the effect is attached to
+        };
+
+        // List of operators applied to the subject
+        enum effect_operator {
+                effect_operator_none     = 0,
+                effect_operator_assign   = '=',
+                effect_operator_new      = 'n',
+                effect_operator_delete   = 'd',
+                effect_operator_clone    = 'c', // the subject
+                effect_operator_add      = '+', // w/ assignment to subject
+                effect_operator_subtract = '-', // w/ assignment to subject
+                effect_operator_multiply = '*', // w/ assignment to subject
+                effect_operator_divide   = '/', // w/ assignment to subject
+        };
+
+        // The effect data structure.
+        struct effect {
+                char *tag;
+                struct list list;
+                enum effect_target_type type;
+                enum effect_target_method target_method;
+                enum effect_subject subject;
+                enum effect_hook hook;
+                enum effect_source source;
+                enum effect_operator operator;
+                struct effect_value value;
+                float probability;
+        };
+
+        // Create and initialize an effect structure from ghulscript.
+        extern struct effect *effect_load(class Loader *);
+
+        // Apply an effect (attempt to, anyway).
+        extern int effect_apply(struct effect *effect, class Object *affected);
+
+        // Properly deallocate an effect structure.
+        extern void effect_destroy(structeffect *effect);
+
diff --git a/doc/MAP_HACKERS_GUIDE b/doc/MAP_HACKERS_GUIDE
new file mode 100644 (file)
index 0000000..006cf68
--- /dev/null
@@ -0,0 +1,304 @@
+$Id: MAP_HACKERS_GUIDE,v 1.7 2007/01/23 08:32:13 icepic Exp $
+
+                     MAP HACKER'S GUIDE TO NAZGHUL/HAXIMA
+
+
+                        "The map is not the territory."
+                                     --Alfred Korzybski
+
+
+                                 INTRODUCTION
+
+So you want to modify Haxima? Or maybe you find Haxima pathetic and know you
+can do better. Then you've come to the right place. The Haxima scripts will
+give you lots of examples on how to do things, if you can figure them
+out. Since you're a smart guy I'm sure you can, but an explanation here or
+there might speed things up. Here you'll find a discussion of the principles of
+how to build a game like Haxima with the nazghul engine.
+
+This manual is still in its infancy. If you don't find what you're looking for
+feel free to email requests or suggestions to
+
+        nazghul-devel@lists.sourceforge.net
+
+Happy hacking!
+
+
+                                   CONCEPTS
+
+COMPOSITE SPRITE
+        First, see SPRITE. A composite sprite is a sprite made up of layers of
+        other sprites.
+
+GOB     Scheme data associated with a kernel data structure. The kernel never
+        accesses this data, it is meant to be used by scripts to customize or
+        augment these data structures. Objects, object types and astral bodies
+        all optionally have gobs.
+
+OBJECT  Something which exists on the map and is not part of the scenery.
+
+OBJECT TYPE
+        Read-only data associated with and shared by a class of objects. A type
+        is a kernel data structure which describes attributes that are common
+        to an entire class of objects. For example, all short swords have the
+        same sprite and basic attributes, and all sword objects refer to the
+        sword object type to provide these attributes. In fact, simple objects
+        like short swords may be implemented in the kernel as little more than
+        an object type and a location.
+
+        There are several classes of object type: a generic base class, an arms
+        type, a vehicle type, and a field type. Every object type class has a
+        fixed set of attributes. These can be extended by the script, however,
+        by attaching a gob to the object type.
+
+SPRITE  An animation sequence which shows an object. Every visible object has a
+        sprite. Sprites can be composed of other sprites, see COMPOSITE SPRITE.
+
+SPRITE SET
+        Usually sprite images are collected into files with lots of images in
+        them. A sprite set refers to the file and stores information like
+        how big the images are, how many are in the file, etc. Sprites refer to
+        sprite sets. Different sprites can share some of the same images,
+        although few ever do.
+
+TAG     A name given to a kernel data structure so that it can be referred to
+        by a scheme variable. Tags are important because they can be used when
+        saving a game to allow objects to refer to one another when the game is
+        reloaded.
+
+
+                       QUICK START: HOW TO CHANGE A MAP
+
+Start haxima with the -d option:
+
+      $ haxima -d
+
+Start a game, then invoke the terrain editor using the Ctrl-T command. Like a
+paint program, terrain editing has the concept of a current "brush", which is a
+terrain type. 
+
+The following keybindings are in effect:
+
+        Arrow keys - move the cursor
+        [0-9]-Arrow - jump the cursor
+        Space/Enter - change the terrain under the cursor
+        PgUp/PgDn - scroll the available terrain list to change the brush
+        Home/End - jump to the top or bottom of the available terrain list
+        C - copy; set the terrain under the cursor as the brush
+        F - terrain fill (uses the 4-neighbor algorithm)
+        ESC - abort edit mode
+        Ctrl-[0-9] - save the brush in a "quick access" terrain slot
+        [0-9] - load the brush with the quick access terrain slot
+"Quick Access" slots start as all walls. Palette.scm holds the list of terrain
+types.
+
+When you are done editing, save the game like you normally would. Your changes
+will be there the next time you start the game. If you want your changes to be
+part of a game started from "Start New Game" the current process involves
+modifying some Scheme files.
+
+To add your changes to the "Start New Game" scripts you need to find your
+changes in the file you saved and copy-and-paste them into the proper startup
+.scm file. In general, you must find the name of the place which is using the
+map and search for it in the .scm files, then replace the starting map with
+your own.
+
+
+                                  KERNEL API
+
+This section documents the kernel calls available to scripts. The document
+format is moduled after the UNIX man pages, which, like so many things in UNIX,
+have served well enough over the last 30-odd years to be worth emulating.
+
+----------------------------------------------------------------------------
+NAME
+        kern-sprite-apply-matrix - apply a color conversion matrix to a sprite
+
+SYNOPSIS
+        (kern-sprite-apply-matrix <sprite> <matrix>)
+
+DESCRIPTION
+        The purpose of this is to alter the colors of a sprite. The idea is you
+        create one sprite, probably in grayscale, and use this procedure to
+        make different colored variations of it. This works by applying the
+        matrix to the sprite, resulting in a linear remapping of the sprite
+        colors to another set of colors. The matrix is in the form:
+
+                (list (list <c01> <c02> <c03>)
+                      (list <c11> <c12> <c13>)
+                      (list <c21> <c22> <c23>)
+                      (list <k1> <k2> <k3>))
+
+        This matrix is applied to the red, green and blue components of each
+        pixel in the sprite like this:
+
+                r = R * c00 + G * c01 + B * c02 + k1
+                g = R * c10 + G * c11 + B * c12 + k2
+                b = R * c20 + G * c21 + B * c22 + k3
+                 
+        Where r, g and b are the result and R, G and B are the original values
+        for the pixel. The result for a component will be clamped to [0, 255].
+
+        The underlying image is copied before being modified. This means that
+        if the sprite is a clone of another sprite, the other sprite will not
+        be modified.
+
+RETURNS
+        The modified sprite. If something is wrong with the arguments it
+        returns the original, unmodified sprite.
+
+EXAMPLES
+
+        This applies an identity matrix, which does nothing:
+
+                (kern-sprite-apply-matrix ksprite
+                                          '((1 0 0)
+                                            (0 1 0)
+                                            (0 0 1)
+                                            (0 0 0)))
+
+        This matrix will convert a grayscale image to blue:
+
+                0 0 0
+                0 0 0
+                0 0 1
+                0 0 0
+
+        This will swap red and blue:
+
+                0 0 1
+                0 1 0
+                1 0 0
+                0 0 0
+
+        This will lighten every pixel by a fixed offset:
+        
+                1   0  0
+                0   1  0
+                0   0  1
+                64 64 64
+
+         This will darken every pixel by a scale factor:
+
+                0.5 0   0
+                0   0.5 0
+                0   0   0.5
+                0   0   0
+
+----------------------------------------------------------------------------
+NAME
+        kern-sprite-blit-over - blit one sprite over another one
+
+SYNOPSIS
+        (kern-sprite-blit-over <dest> <src>)
+
+DESCRIPTION
+        The images of the destination sprite will be copied and then modified
+        by the blit, so you don't have to worry about other sprites that refer
+        to the same images. The two sprites should have the same number of
+        frames and the same dimensions or the results are not defined. The
+        modification will not be saved with the game, so it needs to be redone
+        at load time.
+
+        Blitting over uses more memory than decorating sprites because it makes
+        an extra copy of all the sprite frames. It is faster, though, because
+        it only blits all the sprite components once when it is created,
+        instead of every time it is rendered.
+
+        Blitting is also preferrable for composite weapon sprites, because
+        composite sprite building does not have good support for recursively
+        composite sprites. Unreadying composite weapon sprites will strip them
+        down to their bare sprite. But weapon sprites built via blitting over
+        do not have this problem, because stripping down a blitted-over sprite
+        has no effect.
+
+RETURNS
+        The modified destination sprite.
+
+EXAMPLES
+        (define s_fancy_shield (kern-sprite-blit-over s_shield s_emblem))
+
+----------------------------------------------------------------------------
+NAME
+        kern-sprite-clone - copy a sprite
+
+SYNOPSIS
+        (kern-sprite-clone <original> <new-tag>)
+
+DESCRIPTION
+        Use this when you want to make a modified version of a sprite but still
+        want to keep the original intact. You can assign the clone its own tag
+        and henceforth refer to the tag as a scheme variable, or you can pass
+        in nil and just use the return value.
+
+RETURNS
+        The cloned sprite, or nil if 'original' was a bad arg or a memory
+        allocation failure prevented creation of the clone.
+
+EXAMPLES
+        ;; Clone grass and turn it brown to make dirt
+        (kern-sprite-clone s_grass 's_dirt)
+        (kern-sprite-apply-matrix s_dirt green-to-brown-matrix)
+
+----------------------------------------------------------------------------
+NAME
+        kern-type-set/get-gob - associate scheme data with an object type
+
+SYNOPSIS
+        (kern-type-set-gob <ktype> <cell>)
+        (kern-type-get-gob <ktype>)
+
+DESCRIPTION
+
+        kern-type-set-gob associates 'cell' with the object type 'ktype', so
+        that it can later be found by scripts via kern-type-get-gob. 'ktype'
+        must be the result of a call to kern-mk-obj-type.
+
+        The purpose is to add game-specific information to a kernel data
+        structure so that closures called from the kernel can find it. This
+        information is not visible to the kernel.
+
+        Unlike the gobs attached to objects, gobs attached to object types are
+        not written to the save-game file. For that matter, object types are
+        not written, either, and must be reloaded for every game.
+
+----------------------------------------------------------------------------
+NAME
+        kern-sprite-strip-decorations - remove all decorations from a base
+        sprite
+
+SYNOPSIS
+        (kern-sprite-strip-decorations <sprite>)
+
+DESCRIPTION
+        Remove all decorations from <sprite> and discard them (see
+        sprite_append_decoration()). Useful for rebuilding decorated sprites
+        from scratch.
+
+        This does not remove layers built via kern-sprite-blit-over.
+
+RETURNS
+        The base sprite.
+
+EXAMPLES
+        ;; Make a ship with sails.
+        (define s_ship (kern-sprite-append-decorations (list s_ship s_sails)))
+
+        ;; Nah, changed my mind.
+        (define s_ship (kern-sprite-strip-decorations s_ship))
+
+
+----------------------------------------------------------------------------
+NAME
+        -
+
+SYNOPSIS
+        ()
+
+DESCRIPTION
+
+RETURNS
+
+EXAMPLES
+
diff --git a/doc/USERS_GUIDE b/doc/USERS_GUIDE
new file mode 100644 (file)
index 0000000..7394adf
--- /dev/null
@@ -0,0 +1,671 @@
+
+
+                            USERS GUIDE TO NAZGHUL
+
+Nazghul is an old-school RPG clone modeled after those made in the heyday of
+top-down, 2d tile-based graphics. It is specifically modeled after Ultima V, so
+if you've played that game then this should be familiar.
+
+
+                              INSTALLING THE GAME
+
+If you downloaded a source distribution see the top-level INSTALL file.
+
+If you downloaded a windows binary just unzip the distribution using Winzip or
+similar.
+
+
+                               STARTING THE GAME
+
+
+On Linux/UNIX:
+
+      $ haxima.sh
+
+On Windows:
+
+      Use the start menu or desktop icon
+
+You can play the Tutorial first or jump right in with Start New Game.
+
+
+                                SAVING THE GAME
+
+You can save your game at any time while playing by using the CTRL-S key
+sequence for the S)ave command. An unlimited number of saved games is
+permitted. When you restart, use the Journey Onward option from the main menu
+to select a saved game to continue.
+
+If you die, the game will exit, and when you restart it will pick up where you
+last saved via the Journey Onward option.
+
+
+                               EXITING THE GAME
+
+You can quit at any time by pressing Q for the Q)uit commmand. It will prompt
+you to save if you like and then exit.
+
+
+                                  ORIENTATION
+
+If you are unfamiliar with U5 I recommend the Tutorial option available from the
+Main Menu when you start the game. Here are some more notes to help you get
+started.
+
+                                   Exploring
+
+When you start you will have a party consisting of one character known
+initially as The Wanderer. The icon for this character will be in the center of
+the map view on the left. Explore around a bit using the arrow keys to
+move. Below the map you'll see a little window with a prompt. This gives you
+hints when you're entering commands to tell you what type of input the command
+wants. For example, if you type 'x' (for e[x]amine) the command prompt will
+say:
+
+    Xamine-<target>(ESC to exit)
+
+Which means it wants you to hit the arrow keys and move the targeting
+cursor. When you hit 'ESC' instead the command will cancel. Pretty much all
+commands can be canceled by hitting 'ESC'.
+
+To get a detailed explanation of where you are and what time it is, use the AT
+command by pressing '@'. There is no displayed clock in the game, so this is the
+only way to tell time other than guesstimating from the position of the sun or
+finding time telling devices inside the game.
+
+                                    Talking
+
+When you start the game, after selecting what kind of character to create, you'll
+see your first NPC to the south. To talk to the NPC press 't' for T)alk.
+This brings up a targeting crosshair. It might start out on the NPC or
+on your character, it it's on you then move it to the NPC with the arrow keys
+and hit enter. 
+
+That starts a conversation. During conversation you enter a keyword and the NPC
+will respond. For example, type NAME or JOB and see what this NPC says. When
+you are done talking type 'bye' or hit enter by itself.
+
+                                 Getting Stuff
+
+Eventually you will want to follow the road down to the chamber on the lower
+left. The chamber is marked by mysterious runes on its walls. Within the
+chamber is a chest.
+
+Walk over next to the chest and O)pen it by hitting 'o' and using your arrow
+keys to indicate a direction. The chest will open and deposit a bunch of stuff
+on the ground.
+
+G)et the stuff using the 'g' key. Among the items will be some basic weapons,
+armour and spell reagents as well as some scrolls and potions.
+
+                                   Equipping
+
+To see your stuff hit 'z' for Z)tats and scroll around. The left and right
+arrow keys will switch between different status panes. Hit ESC when you tire of
+admiring yourself and your loot.
+
+To R)eady the weapons and armor hit 'r' then select them. Hit ESC when done.
+
+                                 Mixing A Spell
+
+To M)ix a heal spell type 'm' for mix. Next enter the spell name, in this case
+'m' again for "Mani", and hit ENTER. Next, select Ginseng and Spider Silk from
+the reagents list, and hit 'm' to mix them. Finally, you can mix batches of a
+given spells at once, so you will need to input the quantity of "Mani" spells
+you wish to produce. Enter '1' here, and you will have made a "Mani" spell, a
+spell of minor healing. More on spells later. 
+
+                          Entering and Exiting Towns
+
+When you are ready to face the world walk to the edge of the map and bravely
+step off. You will zoom out to Wilderness Mode, and your entire party (all one
+of you) will appear as an icon in the center. To re-enter take a step south (at
+which point you will see a shrine icon where you just were) and step north
+again. Now you know how to enter and exit towns. Congrats.
+
+When you enter a town, unless you have some enemies there, you will start out
+in "follow mode", which means you control the party leader and everybody else
+in the party tries to keep up. But if hostiles are in town you will be in
+"character mode", which means you control each party member in turn. To switch
+between these two mode use the 'f' key. This will make more sense when you have
+more characters join your party.
+
+IMPORTANT: when you eventually get somebody to join you, don't forget about
+           Follow Mode (the 'f' key). It's much easier to have everybody follow
+           your main dude around than to always individually control them.
+
+
+                                USER INTERFACE
+
+Astronomy Window
+
+    Above the map you'll see a little window embedded in the frame which shows
+    the position of the sun and two moons. It also shows the phase of the
+    moons, which is important for moongate travel.
+
+Wind
+
+    Below the map, embedded in the frame, is the wind direction
+    indicator. Currently the wind only affects ships. Tacking across the wind
+    provides the best rate of travel, the wind at your back is second best, and
+    heading into the wind is the worst. Note that this indicates the direction
+    the wind is blowing _FROM_.
+
+Command Prompt
+
+    Unlike u4/u5/u6 the command prompt has its own window, just below the wind
+    indicator. Interactive command prompts appear here, as well as the things
+    the player says in conversation.
+
+Status Window
+
+    In the top right you have a general-purpose window for viewing and
+    selecting lists of things. Normally it shows some basic party stats, but
+    its contents change as required by user commands. For example, (R)eady will
+    turn it into a selection list.
+
+    Normally the window lists all the player's party members and shows their
+    current hit points and status. The status is reflected in one or more
+    little icons. For example, if a character is poisoned you'll see a little
+    green skull-and-crossbones. You can get a better description of the status
+    by using the Z)tatus command to inspect individual party members.
+
+Foogod Window
+
+    It sounds sacrilegious, but that's just my acronym for Food/Gold
+    Window. This little window appears below the status window and shows the
+    turn, food and gold counters as well as the current combat status and any
+    active global effects (e.g., "Magic Negated"). If you board a vehicle it
+    will also show you the hit points for the vehicle.  The effects are shown
+    with cryptic little icons that appear until the effect expires.
+
+    Magic Negated
+
+        Spellcasting fails.
+
+    Quicken
+
+        Party members get extra turns per round.
+
+    Reveal
+
+        Invisible things are visible.
+
+    Time Stop
+
+        Everything in the world suspends while Party members get to move.
+
+    X-ray Vision
+
+        Party members can see through walls.
+
+Console Window
+
+    Finally on the right hand side you'll find the window where all the game
+    messages get logged.
+
+
+                                PLAYER COMMANDS
+
+
+Here's your chance to let the sweat dry on your mouse - all commands are via
+the keyboard. As it should be, forever and ever amen.
+
+Addendum: For the sake of convenience to mousephiles, targeting prompts will
+accept input from the mouse. But the shortcut keys are faster.
+
+General syntax:
+
+<dir>    = one of the four arrow keys
+<member> = a party member, selected from a list by scrolling with the arrow
+           keys and pressing <enter> or <space>
+<item>   = an inventory item, selected from a list
+<spell>  = a spell, selected from a list
+<space>  = spacebar
+<target> = a combat target, selected by moving the crosshairs and pressing
+           <enter> or <space> (or using the mouse and left-clicking)
+<*>      = varies depending on context
+
+General commands:
+
+    <dir>......................Move in that direction
+    A)ttack-<dir>..............Initiate combat
+    B)oard.....................Board/exit a vehicle like a ship or horse
+    C)ast-<member>-<spell>-<*>...Cast a spell (the last argument depends on the
+                               spell)
+    E)nter.....................Enter a portal, including up or down ladders
+    F)ire-<dir>................Fire vehicle's weapon (e.g., ship cannon)
+    G)et-<dir>.................Get an object from the ground
+    H)andle-<member>-<target>..Activate a switch or lever
+    L)oiter-<0-9/sunrise>......Loiter a few hours
+    N)ew-order-<member>-<member>...Swap order of two party members
+    O)pen-<dir>................Open a container or door
+    Q)uit......................Quit & optionally save the game
+    R)eady-<member>-<item>.....Ready an armament like a weapon, shield, etc.
+    S)earch-<dir>..............Look carefully
+    T)alk-<target>.............Talk to an NPC
+    U)se-<member>-<item>.......Use an item like a torch or potion
+    X)amine-<target>...........Examine map tiles within view
+    Z)tats.....................Show party stats like inventory, armaments, etc
+    @)AT.......................Information about where the party is AT, etc
+    <space>....................Pass one turn
+    CTRL-S)ave.................Save a game
+    CTRL-R)eload...............Reload a game
+
+Wilderness-only commands:
+
+    K)amp-<0-9/sunrise>-<y/n>-<player>
+    ...........................Camp in the wilderness (to heal and recover 
+                               mana) or aboard ship (to repair hull damage as 
+                               well)
+
+Town/Dungeon/Combat-only commands:
+
+    A)ttack-<target>.........Attack the specified target
+    C)ast-<spell>-<*>........Cast a spell
+    F)ollow..................Select follow mode, where the party members
+                             automatically follow the party leader.
+    [1-9]....................Select a party member for solo mode.
+    [0]......................Select turn-based party mode, where each party 
+                             member takes directions one at a time.
+    K)amp-<0-9/sunrise>......Sleep on a bed.  
+
+Special commands:
+
+    <ESC>....................Aborts most commands
+
+Editing commands (run nazghul with -d):
+
+    CTRL-E)valuate...........Evaluate a scheme expression within the game. For
+                             example, the string: "(kern-obj-relocate
+                             ch_wanderer (list p_shard 51 47) nil)" will
+                             teleport the player to the surface at coords [51
+                             47].
+    CTRL-O)..................Save the current map to its own file
+    CTRL-T)erraform..........Alter terrain. This deserves its own section. [1]
+    CTRL-Z)oom...............Zoom in or out (like peering at a gem but free)
+
+Shortcuts:
+
+    +/=......................When targeting an attack, moves cursor to next
+                             hostile npc.
+    -........................When targeting an attack, moves cursor to previous
+                             hostile npc.
+    ESC......................When wilderness combat is over, exits to
+                             wilderness map.
+
+                                MOVEMENT MODES
+
+
+Party Mode (wilderness)
+
+    The party appears as a single icon in the center of the screen.
+
+Follow Mode (town/combat/dungeons)
+
+    You control the party leader and the other members follow the
+    leader. Attacking a target will automatically switch to Round-Robin
+    Mode. The party leader is always the top person in the list who is alive
+    and still on the current map. Enter follow mode from Solo or Round Robin
+    Mode by pressing 'f'.
+
+Solo Mode (town/combat/dungeons)
+
+    You control one party member while the others stand around looking
+    bored. Enter Solo Mode by pressing the number key associated with the
+    party member's order in the list. 1 is the first member in the list.
+
+    NOTE: Solo mode can be very useful if one of your party members has greater
+          passability than the others. For example, if a gazer joins your party
+          he can float over water. Now imagine the possibilities if you get a
+          ghost to join your party.
+
+Round Robin Mode (town/combat/dungeons)
+
+    You control each member in turn. This is the default mode when you enter
+    combat. To enter Round Robin Mode from solo mode, press 0. To enter from
+    Follow Mode press 'f'. Yes, confusing to have two methods. I'll fix it
+    someday. Let me know if you have an opinion.
+
+
+                                    PLACES
+
+Wilderness:
+
+    In the outdoor or wilderness map the party moves as a single unit. You can
+    enter into combat with enemy NPC parties by moving into them or waiting for
+    them to attack you. Likewise you can enter towns, dungeons or moongates by
+    simply walking into them.
+
+Wilderness Combat:
+
+    This is a special temporary combat map that pops up when you engage an
+    enemy NPC party in the wilderness. In this mode you control individual
+    party members. You return to the wilderness map by having all of your
+    living party members walk off the edge of the map. (Hint: if combat is over
+    you can press <ESC> to quickly leave the map).
+
+Towns/Dungeons:
+
+    In towns and dungeons you move just like in combat mode. You can control
+    the individual party members in turn, have one of them scout around in solo
+    mode, or control the leader and have the other party members follow.
+
+
+                                    COMBAT
+
+
+What can I say? It's pretty much like u5. Try the flaming oil at night or in an
+underground place. Oh, and watch out for gazers. They can charm you. Kill them
+or charm them right away.
+
+
+                                  ADVANCEMENT
+
+
+As usual, characters advance a level when they gain sufficient experience
+points. There is no maximum level limit. When a character advances his maximum
+HP and MP increase, depending on his class, species and personal bonuses. At
+the moment of advancment he is fully healed and mana is restored to their new
+maximum levels.
+
+                          XP Required for Advancement
+============================================================================
+Level | XP
+============================================================================
+1     | 0       
+2     | 32      
+3     | 64      
+4     | 128     
+5     | 256     
+6     | 512     
+n     | 2^(n+5)
+============================================================================
+
+                                  Attributes
+
+Characters have three basic attributes: Strength, Dexterity and
+Intelligence. These are fixed when the character is created and don't change
+during the game.
+
+Strength
+
+    Strength limits the total weight of readied weapons and armour. Strong
+       characters do more damage and are better at hitting with heavy or
+       bludgeoning weapons. It is also used when breaking free of spider webs
+       (most trolls don't stay ensnared too long...).
+
+Dexterity
+
+    Dexterity is used when attacking with missile and balanced weaponry, and
+       helps when avoiding your opponents' blows. It is also needed when
+       picking locks and disarming trapped chests.
+
+Intelligence
+
+    Intelligence makes spells more potent and more likely to succeed.
+
+
+                                     MAGIC
+
+
+The example game contains a full complement of spells. The magic system is
+similar to Ultima 5 and Ultima 6: you select a spell by entering magic
+syllables. A spell name is a combination of one to four syllables.
+
+The syllables, spell names and reagent mixtures provided in the example game
+are a direct ripoff of Ultima 5. If you don't have a u5 reference manual lying
+around then the tables below will help:
+
+                               Table 1: Reagents
+============================================================================
+Name           | Abbrev used in spell table
+============================================================================
+Black Pearl    | BP
+Blood Moss     | BM
+Garlic         | GA
+Ginseng        | GI
+Mandrake Root  | MR
+Nightshade     | NI
+Spider Silk    | SS
+Sulphurous Ash | SA
+============================================================================
+
+                                Table 2: Spells
+============================================================================
+Syllables        | Effects        | Reagents               | Party/Combat
+=================================(1)========================================
+An Nox           | Cure Poison    | GI, GA                 | PC
+An Zu            | Awaken         | GI, GA                 | PC
+Grav Por         | Magic Missile  | SA, BP                 | C
+In Lor           | Light          | SA                     | PC
+Mani             | Heal           | GI, SS                 | PC
+Wis Sanct        | Detect Trap    | SA                     | PC
+An Sanct Ylem    | Disarm Trap    | BM                     | PC
+---------------------------------(2)----------------------------------------
+An Sanct         | Unlock         | SA, BM                 | PC
+An Xen Corp      | Repel Undead   | GA, SA                 | C
+In Wis           | Locate         | NI                     | P
+Rel Hur          | Change Wind    | SA, BM                 | P
+In Nox Por       | Poison Missile | NI, BM, BP             | C
+Bet Flam Hur     | Fire Spray     | BP, SA, BM             | C
+In Bet Xen       | Summon Vermin  | SS, BM, SA             | C
+---------------------------------(3)----------------------------------------
+In Flam Grav     | Fire Field     | SA, BP, SS             | C
+In Zu Grav       | Sleep Field    | GI, BP, SS             | C
+In Nox Grav      | Poison Field   | NI, BP, SS             | C
+Vas Flam         | Fire Ball      | BP, SA                 | C
+Vas Lor          | Great Light    | SA, MA                 | PC
+---------------------------------(4)----------------------------------------
+An Grav          | Dispel Field   | BP, SA                 | PC
+In Sanct Grav    | Energy Field   | MA, BP, SS             | C
+In Sanct         | Protection     | SA, GI, GA             | PC
+Wis Quas         | Reveal Hidden  | NI, SA                 | PC
+Bet Por          | Blink (Caster) | BP, BM                 | C
+---------------------------------(5)----------------------------------------
+In Ex Por        | Unlock Magic   | SA, BM                 | PC
+An Ex Por        | Magic Lock     | SA, BM, GA             | PC
+In Zu            | Sleep          | GI, NI, SS             | C
+Vas Mani         | Great Heal     | GI, SS, MA             | PC
+Rel Tym          | Quickness      | SA, BM, MA             | PC
+Kal Xen          | Summon Beast   | SS, MA                 | C
+---------------------------------(6)----------------------------------------
+An Xen Ex        | Charm          | BP, NI, SS             | C
+In An            | Negate Magic   | GA, MA, SA             | C
+In Vas Por Ylem  | Earthquake     | BM, MA, SA             | C
+Quas An Wis      | Confuse        | MA, NI                 | C
+Wis An Ylen      | Xray Vision    | MA, SA                 | PC
+In Rel Por       | Telekinesis    | BP, BM, SS             | C
+Vas Por          | Blink (Party)  | MA, BP, BM             | P
+---------------------------------(7)----------------------------------------
+In Nox Hur       | Poison Wind    | NI, SA, BM             | C
+In Zu Hur        | Sleep Wind     | MA, GI, BM             | C
+In Quas Corp     | Fear           | NI, MA, GA             | C
+In Quas Xen      | Clone          | NI, MA, SA, SS, BM, GI | C
+Sanct Lor        | Invisibility   | NI, MA, BM             | C
+Xen Corp         | Kill           | NI, BP                 | C
+---------------------------------(8)----------------------------------------
+An Tym           | Stop Time      | MA, GA, BM             | WC
+In Flam Hur      | Flame Wind     | MA, SA, BM             | C
+In Vas Grav Corp | Energy Wind    | MA, SA, NI             | C
+In Mani Corp     | Resurrect      | GA, GI, SS, SA, BM, MA | PC
+Kal Xen Corp     | Summon Undead  | SS, MA, NI             | C
+Vas Rel Por      | Gate Travel    | SA, MA, BP             | P
+============================================================================
+
+[1] In Towns and Dungeons teleport spells that can move the party from one
+    place to another will fail unless combat is over and the party is in Follow
+    Mode.
+
+
+                                    EFFECTS
+
+From time to time your characters might run into a little trouble with magical
+foes, natural hazards, or their own weakness for alcohol. Don't panic. Most
+effects are non-fatal, but a few are.
+
+Asleep (S)
+
+    Sleeping party members will eventually wake up of their own accord. If you
+    don't feel like waiting use the An Zu spell.
+
+Charmed (C)
+
+    Enemy wizards might charm party members, causing them to fight on their
+    behalf. Charm wears off after 10 minutes.
+
+Diseased (D)
+
+    Some monsters may infect party members with disease. Disease is not fatal,
+    but it will not wear off until your party member is nearly out of hit
+    points.
+
+Drunk (A)
+
+    Anytime your character buys alcoholic drinks or picks them up from the
+    ground he gets drunk. Drunkenness lasts an hour or so and causes him to
+    randomly bump into things.
+
+Ensnared (E)
+
+    When stuck in a spider web, a character will break free after struggling
+    for a while. The time required to free himself depends on the character's
+    strength.
+
+Paralyzed (Z)
+
+    Spiders inject paralyzing venom to make their foes helpless before feeding
+    on them. Paralysis will wear off after a short random interval.
+
+Poisoned (P)
+
+    Bogs or spells may poison party members, causing them to lose hit points
+    every turn until the poison is cured with a spell or potion. Poison is
+    fatal! It won't wear off like disease.
+
+
+                                 CONVERSATION
+
+
+Start a conversation with an NPC with the T)alk command. During conversation
+you type simple inquiries and the NPC responds, sometimes asking you a question
+in return. Conversations with shopkeepers will allow you to BUY and SELL
+items. Most NPCs respond to the 'NAME' and 'JOB' queries, as well as queries
+about their town and fellow townsmen. Their responses usually give you clues to
+further fruitful queries. Also, with the special 'JOIN' query you can ask an
+NPC to join your party (some will join you, and some will join you only if you
+do or say something that impresses them).
+
+
+                                     MISC
+
+Food is consumed three times per day, one unit for each living party
+member. When the food runs out, party members take a point of damage at each
+meal time.
+
+
+                             APPENDIX A: MAP HACKING
+
+Like many games, "nazghul" is separated into an engine [2] and some data
+files. In this case the data files are written in the Scheme programmming
+language. If you examine the default start file 'session.scm' you will see that
+it is a scheme file which loads the game types from other files and then
+defines the starting game variables.
+
+I encourage people to experiment with modifying the example files or even using
+them as a basis to create their own games. The example script code is all
+committed to the public domain. The image and sound files come from various
+sources - see the COPYING file in the top nazghul directory for details on
+where they came from.
+
+If you want to make a proprietary game you may use the example script files,
+but you will probably need to make your own image and sound resource files as
+the ones in the examples directory come from other open-source or freeware
+projects and their copyright holders might object to proprietary use.
+
+
+                             APPENDIX B: Spoilers
+
+These apply specifically to Haxima, and not necessarily to any other game made
+with the Nazghul engine.
+
+                            Projectile Weapon Stats
+============================================================================
+Name          To-Hit  Damage  To-Def  Hnds  Rng  Ammo       Weight
+============================================================================
+Sling         1d2-2   1d4     -1      1     4    slingstone 0
+Sling+4       3       1d4+4    0      1     6    slingstone 0
+Bow           1d3-2   2d4     -2      2     6    arrow      2
+Crossbow      1d4-2   4d4     -1      2     4    bolt       3
+Doom Staff    1d4     1       +2      2     5    -          2
+Stun Wand [1] -2      1d4     -1      1     6    -          2
+============================================================================
+[1] Temporarily paralyzes target
+
+                              Thrown Weapon Stats
+============================================================================
+Name              To-Hit  Damage  To-Def  Hnds  Rng  Weight
+============================================================================
+Flaming oil [1]   -1      1d6     -2      1     4    1
+Spear              0      1d8     +1      1     4    2
+Boulder           -2      3d4+1   -2      2     5    10
+============================================================================
+[1] Leaves a temporary burning patch of ground
+
+                              Melee Weapon Stats
+============================================================================
+Name            To-Hit Damage To-Def Hnds Rng Weight
+============================================================================
+Dagger          1d4    1d4    1d2    1    1   0
+Dagger+4        1d4+4  1d4+4  1d2+4  1    1   0
+Mace            1d4    1d6+2  +0     1    1   3
+Axe             1d2    2d3+2  +0     1    1   3
+Sword           1d2    1d8+1  1d2    1    1   2
+Sword+2         1d2+2  1d8+3  1d2+2  1    1   2
+Sword+4         1d2+4  1d8+5  1d2+4  1    1   2
+2H Axe          0      4d3+2  -2     2    1   4
+2H Sword        0      2d8+2   1     2    1   4
+Morning star    1d2+2  1d6+1  -1     1    2   3
+Morning star+2  1d2+4  1d6+3  2      1    2   3
+Halberd         1d3+1  2d8-2  1d2    2    2   4
+Staff           1d3    1d4    1d3    2    2   2
+Eldritch blade  2      2d8+5  +0     2    1   2
+Mystic sword    +3     1d10+5 +2     1    1   1
+Flaming sword   1d2    1d10+3 1d2    1    1   2
+============================================================================
+
+                                  Armor Stats
+============================================================================
+Name              To-Hit  Damage Armor To-Def Weight
+============================================================================
+Leather helm      -1      -      1d2   -      0
+Leather helm+2     0      -      1d2+2 -      0
+Leather helm+4     0      -      1d2+4 -      0
+chain coif        -1      -      1d3   -      1
+Chain coif+4       0      -      1d3+4 -      1
+iron helm         -1      -      1d4   -      2
+Iron helm+4        0      -      1d4+4 -      2
+leather armor     -1      -      1d4   -      2
+Leather armor+2    0      -      1d4+2 -      2
+Leather armor+4    0      -      1d4+4 -      2
+chain armor       -2      -      2d4   -      4
+Chain armor+4      0      -      2d4+4 -      4
+plate armor       -4      -      4d4   -      8
+Plate armor+4      0      -      4d4+4 -      8
+Small shield      -1      -      0     2      2
+Small shield+4     0      -      0     6      2
+Spiked shield      0      1d5    0     1      3
+Spiked helm        0      1d4    3     0      2
+============================================================================
+
+
+--gmcnutt (gmcnutt@cableone.net)
+
+
+FOOTNOTES
+
+[1] Alas, there isn't one. Yet.
+
+[2] I like to refer to it as a "kernel". This makes me feel like it is really
+    cool, and like I'm not a loser since Linus Torvalds and I are about the
+    same age and he works on a kernel, too.
diff --git a/doc/engine_extension_and_design/CVS/Entries b/doc/engine_extension_and_design/CVS/Entries
new file mode 100644 (file)
index 0000000..6789c80
--- /dev/null
@@ -0,0 +1,5 @@
+/ENGINE_CLEANUP/1.2/Sat Nov  6 23:41:45 2004//
+/ENGINE_DESIGN_NOTES/1.2/Sat Nov  6 23:41:45 2004//
+/README/1.1/Thu Aug  5 01:53:27 2004//
+/my_TODO.2004.05.05.txt/1.1/Thu Aug  5 01:53:27 2004//
+D
diff --git a/doc/engine_extension_and_design/CVS/Repository b/doc/engine_extension_and_design/CVS/Repository
new file mode 100644 (file)
index 0000000..4125aad
--- /dev/null
@@ -0,0 +1 @@
+nazghul/doc/engine_extension_and_design
diff --git a/doc/engine_extension_and_design/CVS/Root b/doc/engine_extension_and_design/CVS/Root
new file mode 100644 (file)
index 0000000..4d8737a
--- /dev/null
@@ -0,0 +1 @@
+:ext:gmcnutt@nazghul.cvs.sourceforge.net:/cvsroot/nazghul
diff --git a/doc/engine_extension_and_design/ENGINE_CLEANUP b/doc/engine_extension_and_design/ENGINE_CLEANUP
new file mode 100644 (file)
index 0000000..f77cbad
--- /dev/null
@@ -0,0 +1,40 @@
+* Command-line args. Go through and remove unused/unwanted commands. Document
+  others in the USERS_GUIDE.
+
+* Remove all references to the obsolete Turn counter, including the unused work
+  queue. 
+
+* Remove the useless spriteInit call
+
+* The two player_party constructors share a lot of common initialization
+  code. Pull that into a setup method. In fact, the default one is only used by
+  the suspect player_init() function traditionally invoked on startup so look
+  at getting rid of it, first.
+
+* Pull default formation code into combat.c and get rid of formation.[ch]?
+  Check that reference to it in Party.cpp first.
+
+* player_party should at least be per-session (even if the session is globally
+  accessible) to get rid of the creation/destruction conflict in
+  kern_mk_player.
+
+* place.c: replace the tile locks with refcounts
+
+* Move the global Place variable into the global session struct.
+
+* Use refcounts on all the read-only structures like sprite sets, sprites,
+  etc. The session needs to hold a reference until done loading, then it should
+  traverse everything and release its reference. Hmm... no, that may not
+  work. Anything clicked with a scm_define() will be referenced by the
+  interpreter...
+
+* Convert the ObjectType class to a struct, link all the kernel read-only-types
+  (ROTs) on their own list on the session struct. Use refcounting on them. Ref
+  them as they are loaded. Objects should also ref/unref them. Destroy all the
+  RDWR types first in the session, then unref all the ROTs. If any ROTs remain
+  we can detect a reference leak.
+
+* Define an interface for plugging other types of script interpreters into the
+  kernel. The kern_* API should be made generic, and the scheme unpacking left
+  to a shim layer. Likewise the save code should use some kind of abstraction
+  layer to pack objects into script code.
\ No newline at end of file
diff --git a/doc/engine_extension_and_design/ENGINE_DESIGN_NOTES b/doc/engine_extension_and_design/ENGINE_DESIGN_NOTES
new file mode 100644 (file)
index 0000000..904a675
--- /dev/null
@@ -0,0 +1,200 @@
+* Startup
+
+Life begins in main() in nazghul.c. First we parse command-line arguments, then
+we initialize all the internal "libs" or "modules" (they aren't really modular,
+but they are conceptually separate).
+
+By the time all this is done SDL has been initialized, all the UI widgets are
+ready, the internal libs are ready for use and we have an empty player party
+allocated (not sure we need that last thing there).
+
+** commonInit
+
+Sets the globals:
+
+Tick - drives the tick work queue, currently only used by the kern-add-tick-job
+       call, which in turn is currently only used by the moongate sequence
+
+Turn - drives the turn work queue, which appears to be completely obsolete and
+       unfreferenced by anyone
+
+Also seeds srand() and initializes the busywait loop, which in turn is only
+used by map.c to add a small delay to projectile animations.
+
+** screenInit
+
+Bunch of stuff related to screen colors and special blitting surfaces, but most
+importantly this is where SDL_Init gets called to setup the SDL lib.
+
+** spriteInit
+
+Initializes the ticks_to_next_animation counter. This could probably be done
+statically, eliminating the need for this call altogether.
+
+** player_init
+
+Creates a player party object. Do I still need to do this here, just so I can
+blow it away on reload? I hope not. Maybe things will be clear by the time I'm
+done writing these notes.
+
+*** player party constructor
+
+Bunch of harmless initialization. Creates a view for the party, which may be
+interesting later... the base Object class destructor will destroy it.
+
+** eventInit
+
+Inits the handler stacks (leaves them empty), sets up to record or playback
+events, and enables unicode in SDL.
+
+** windInit
+
+Sets up the screen rectangles for the viewer, sets default wind direction to
+NORTH.
+
+** formationInit
+
+Wow, totally forgot about this one. The formation is just a big array of
+vectors. The init sets the default formation to this array, accessible via
+formation_get_default(), which is still used to this day in combat.c since most
+party types  don't specify a formation. Damn, I probably haven't looked at that
+code for two years.
+
+** astar_init
+
+Allocates the priority heap used by the alg.
+
+** cmdwinInit
+
+Sets up the screen rects, allocates the line buffer, clears the cmdwin and
+opens the cmdwin log file.
+
+** consoleInit
+
+Sets up the screen rect, allocates the text buffer, inits all the pointers and
+indices and opens the console log file.
+
+** mapInit
+
+Creates a persistent camera view, inits the (empty) list of map views, sets up
+the screen rects and some flags.
+
+** vmask_init
+
+Initializes some vars to empty/nil/etc.
+
+** combatInit
+
+Sets combat state to COMBAT_STATE_DONE and zeros out all the other combat vars.
+
+** foogodInit
+
+Sets up the screen rects.
+
+** statusInit
+
+Sets up the screen rects and dimensions.
+
+
+** soundInit
+
+Sets up SDL_audio which will kick off a thread that keeps calling into the
+sound_mix() function for more stuff to play. We only do this if the useSound
+flag is set.
+
+** nazghul_splash
+
+Opens a splash image file and blits it to the screen.
+
+** tick_start
+
+Kicks off the timer tick thread to generate tick events.
+
+** playRun
+
+This loads the session, starts it up, pushes the default tick and quit handlers
+then enters the main loop. If the session fails to load it will return an error
+to main(), which will 
+
+*** session_load
+
+The easy part is now over. The global Session pointer is initialized to NULL
+statically. session_load() remembers the existing session so it can try and go
+back to it if things go badly setting up the new one. On startup, this is moot
+since we don't have a session yet.
+
+session_load() opens the load file, creates a new instance of scheme, creates a
+new session instance, then tells scheme to load from the opened FILE
+pointer. Scheme runs all the code, most of which invokes calls into the kern
+API to setup kernel data structures, objects and parameters. Calls that setup
+read-once things like ObjectTypes put themselves on the session data_objects
+list for cleanup.
+
+An important call which must be made by the script is kern_mk_player(). This
+function (unconditionally!) destroys the existing player_party created by
+player_init() above. This is a hack, plain and simple, and arose mostly due to
+the fact that the player party is a global variable. The player party should at
+least be per-session and referenced through the global session pointer, which
+at least is reasonably well-managed across reloads.
+
+Either the result of kern_mk_player() will be fed (by the script) to a place
+constructor or the script must make an explicit call to kern_obj_put_at() in
+order to position the player party on the map. If the target location is a
+town, the latter approach MUST be taken, as it knows that it needs to break out
+the player party into town mode. The former approach does not handle this
+properly (that's a bug).
+
+If any errors occur session_load cleans up and returns, leaving the original
+session active (but in the case of startup, there is no original session, and
+odds are good that the player party we allocated back with player_init() has
+been destroyed by the call to kern_mk_player).
+
+If all seems to be well it will destory the old session and interpreter and
+make the new session active.
+
+The next thing it does is call the startSession() method in the player party
+class. See below. Upon exit the global Place will be setup.
+
+It then runs through the list of all the data_objects created by the scheme
+script and runs their start function if they registered one. Currently the only
+thing that uses this feature is the place, which registers
+place_start(). place_start() runs through all the objects in it and calls their
+start method. This in turn traverses all the effects attached to the object and
+invokes their "apply" closures, if they have one. Currently, the effects which
+use this feature are light/great light, protection, charm and invisibility. All
+of these examples could be implemented without the apply closure if each object
+saved and loaded its light, defense, charm and invisibility status. Whether or
+not future effects will need this feature is not clear to me. If an effect
+simply changes state, and the state is saved and loaded, I don't think 'apply'
+is necessary.
+
+The final step is to start painting the auxiliary widgets: the screen frame,
+the foogod, console and status windows.
+
+**** kern_init
+
+This is where all the kernal API calls get poked into the new scheme
+interpreter's environment.
+
+**** kern_mk_player
+
+This (unconditionally) blows away the current player party and creates a new
+one. The player party constructor creates a new view, among other things, but
+doesn't add it just yet. Back in kern_mk_player it unpacks and adds the party
+members one by one, connects the party and its vehicle (if applicable), and
+adds the party to the session.
+
+The party is added to the session as a data object because there are times
+(especially like right after this call, for instance) where the player party is
+in "limbo", meaning it isn't on any map or referenced by any place. When the
+player enters a town or dungeon is another example. The reason I need the
+player party on the data_objects list is so that it will generate a call to
+kern_mk_player outside of the context of any place constructor, so that on load
+the party is not physically present as an object/icon in the place where the
+party members are.
+
+Note that this call does not put the player party on the map anywhere - it will
+be located as a result of being loaded by its place (this will happen within
+kern_mk_place()) or the script will explicitly give it a location via
+kern_obj_put_at(). This is the case with the script that starts the game for
+the first time.
diff --git a/doc/engine_extension_and_design/README b/doc/engine_extension_and_design/README
new file mode 100644 (file)
index 0000000..25309b6
--- /dev/null
@@ -0,0 +1,8 @@
+This directory contains miscellaneous notes on extending and designing
+the Haxima engine.
+
+The contents of this directory do not necessarily correspond to what
+_IS_ in the game engine/kernal, but to things which have been proposed
+to be added.  Keeping these sort of notes in CVS seems like a better
+way to communicate than each developer keeping their own notes which
+get lost.
diff --git a/doc/engine_extension_and_design/my_TODO.2004.05.05.txt b/doc/engine_extension_and_design/my_TODO.2004.05.05.txt
new file mode 100644 (file)
index 0000000..0a46a87
--- /dev/null
@@ -0,0 +1,180 @@
+---------------------------------------------------------------------------
+My TODO from meeting 2004/04/29
+-------------------------------
+- Find / rewrite the stencil API (in C, Perl, whatever)
+
+- Prototype the Object Browser Pane "pictures" code for UI
+  specification (in C, Perl, whatever)
+
+- Write Perl scripts for seeded random map generation
+
+- Do data tables for weapons, armour, etc.
+
+- Get a good start on world-building
+
+
+---------------------------------------------------------------------------
+Stencil API:
+------------
+A stencil is simply a terrain_map used as a stencil.
+Each cell (x,y) contains either NULL, or non-NULL.
+When blit_map() or blit_terrain() is called, 
+    NULL cells are not blitted
+    non-NULL cells indicate to blit
+        the from_map terrain for blit_map()
+        the fill_terrain terrain for blit_terrain()
+
+
+blit_map     (map * to_map, map * from_map_stencil, 
+              int x, int y, int w, int h)
+blit_terrain (map * to_map, map * from_map_stencil, 
+              int x, int y, int w, int h, terrain * tt)
+
+Blitting starts at (0,0) in from_map_stencil, blitting onto an origin
+point of (x,y) in to_map.
+
+Blitting iterates over a region (w,h) wide,high.
+
+Blitting truncates any coordinate which is not in-bounds of both
+to_map and from_map_stencil.
+
+
+---------------------------------------------------------------------------
+Object Browser "Picture" UI-building Code:
+------------------------------------------
+An Object Browser "pane" is a rectangular region whose size is
+measured in character cells 8x16 pixels in size.
+
+Standard-sized tiles can be displayed, taking up 4x2 character cells.
+
+Panes can be defined for different object types, which have different
+data to display and which may have a different display layout.  
+For example, a Terrain and an Item which is a melee weapon have
+different data to display.
+
+An object type may specify multiple pages of panes.
+For example, a Being has a lot of data, which may take multiple pages.
+
+An object type may specify multiple pane views, depending on the state
+of the object instance.  For example, an Item subtype might specify
+different panes for an object instance which is identified versus an
+object instance which is not.
+
+
+Pane Specifications:
+--------------------
+Panes can be specified by calling a function whose arguments contain
+information describing the display.  Multiple such functions are
+defined for distinct, common types of pane displays.
+
+new_text_pane (elements_before, 
+               num_lines, lines_of_text, 
+               elements_after)
+
+    - elements_before 
+          is a pane object of full width.
+          It will be rendered above the text region. 
+
+    - num_lines
+          defines the height in character cells of the central text region.
+
+    - lines_of_text 
+          Contains text to fill the central text region.
+
+          Any individual lines which are longer/wider than the pane
+          width will be line-wrapped and treated as multiple lines.
+
+          Explicit line breaks within lines_of_text will be kept.
+          Leading, trailing, and internal spaces will be kept.
+          Tab characters will be treated as single spaces.
+
+          Text with fewer lines than num_lines will be
+          space-padded at the end of the vertical space.
+
+          Text with more lines than num_lines will be scrolled within
+          the central text region.
+
+    - elements_after
+          is a pane object of full width.
+          It will be rendered below the text region.
+
+
+new_pane (picture_lines, ...varargs...)
+
+    - picture_lines
+          An array of lines, each of full width.
+          Each line contains some mix of literal text
+          and "Picture Elements".
+
+          Picture Elements are sequences of reserved characters which
+          define a rectangular region of character cells, serving a
+          purpose analogous to a '%' specifier in printf().
+
+          Picture Elements have an origin (x,y) relative to the origin
+          (1,1) of the array, and a width,height (w,h).  Occupying a
+          rectangular region, they are like a 2D printf() specifier.
+
+          The characters reserved for Picture Elements are 
+          hash '#', carat '^', underscore '_', and pipe '|'.
+
+          The Nazghul window is 1024 pixels wide
+              -608 == -(19 * 32) for map view window
+               -48 == -(16 * 3) for borders
+          This leaves 368 pixels wide for the Object Browser pane,
+          which translates to (368 / 16) 23 character cells wide.
+
+          Example:  (Obj Browser pane for a Terrain tile
+
+          "#### Terrain:          "
+          "#### ################  "
+          "                       "
+          "Passability:           "
+
+          // 1 (4x2 == 32x32 pixels == 1 tile)
+          // 2 (16x1 characters)
+          tile(this.tile),  // Tile for this object
+          text(this.name),  // Name for this object
+
+
+Hmmm...how to express a "foreach" kind of thing...
+I think such a thing is not initial-attempt functionality, unless the
+means of implementation and the script syntax become obvious.
+For now, a passability display would be hard-coded to display up to N
+movement modes.
+    Note also that we will probably want a distinct set of terrain for
+    wilderness-scale maps and town-scale maps (which probably means
+    two terrain palettes), and perhaps two sets of movement modes
+    since "jumping" perhaps makes no sense at wilderness scale.
+    Hmmm...or maybe the _party_ has different modes from the
+    _characters_ or some such thing...
+
+          " ######## ###### (##)  "
+
+          // One or more movement modes:
+          // 1 (8x1 characters) movement mode name
+          // 2 (6x1 characters) speed adjective "slow", "normal", ...
+          // 3 (2x1 characters) movement point cost
+
+
+Algorithm for Parsing a "Picture"
+---------------------------------
+(See UI_panes.perl)
+
+
+
+
+
+
+
+
+
+
+          
+
+
+
+
+
+
+
+---------------------------------------------------------------------------
diff --git a/doc/null.gif b/doc/null.gif
new file mode 100644 (file)
index 0000000..18c5200
Binary files /dev/null and b/doc/null.gif differ
diff --git a/doc/users_guide.html b/doc/users_guide.html
new file mode 100644 (file)
index 0000000..cf97e41
--- /dev/null
@@ -0,0 +1,2445 @@
+<html>
+<head>
+<!-- Note: The manual currently expects to find haxima data files is ./haxima,
+       and documentation specific files in ./doc -->
+<title>Nazghul Users Guide</title>
+<style>
+       .example
+       {
+               color:#333;
+               background-color:#eee;
+               padding-left:60px;
+       }
+       .key, .ph
+       {
+               background-color:#ddd;
+               font-family: monospace;
+               padding-left:2px;
+               padding-right:2px;
+       }
+       .hk
+       {
+               background-color:#ddd;
+               font-weight:bold;
+               color:#114;
+       }
+       table
+       {
+               border:1px outset grey
+       }
+       td
+       {
+               padding:5px;3px;
+               border:1px inset grey;
+       }
+       tr.header td
+       {
+               border:1px outset grey;
+               font-weight:bold;
+       }
+       td.break
+       {
+               border:1px outset grey;
+               height:3px;
+               background color:#999;
+       }
+       td.break span
+       {
+               width:2px;
+       }       
+       img.icon
+       {
+               top:50%;
+               border:1px solid grey; 
+               width:9px;
+               height:16px;
+       }
+       tr.breaker td
+       {
+               border:none;
+               text-align:center;
+       }
+       tr.breaker td span:before
+       {
+               content: "\002192   "
+       }
+       tr.breaker td span:after
+       {
+               content: "   \002190"
+       }
+</style>
+</head>
+<body>
+<a name="toc1"></a>
+<h1>
+       USERS GUIDE TO NAZGHUL
+</h1>
+<p>
+Nazghul is an old-school RPG clone modeled after those made in the heyday of
+top-down, 2d tile-based graphics. It is specifically modeled after Ultima V, so
+if you've played that game then this should be familiar.
+</p>
+
+<a name="toc2"></a>
+<h2>
+       CONTENTS
+</h2>
+<ul>
+       <li>
+               <a href="#toc3">INSTALLING THE GAME</a>
+       </li>
+       <li>
+               <a href="#toc4">STARTING THE GAME</a>
+       </li>
+       <li>
+               <a href="#toc5">SAVING THE GAME</a>
+       </li>
+       <li>
+               <a href="#toc6">EXITING THE GAME</a>
+       </li>
+       <li>
+               <a href="#toc7">ORIENTATION</a>
+               <ul>
+                       <li>
+                               <a href="#toc8">Exploring</a>
+                       </li>
+                       <li>
+                               <a href="#toc9">Talking</a>
+                       </li>
+                       <li>
+                               <a href="#toc10">Getting Stuff</a>
+                       </li>
+                       <li>
+                               <a href="#toc11">Equipping</a>
+                       </li>
+                       <li>
+                               <a href="#toc12">Mixing A Spell</a>
+                       </li>
+                       <li>
+                               <a href="#toc13">Entering and Exiting Towns</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc14">USER INTERFACE</a>
+               <ul>
+                       <li>
+                               <a href="#toc15">Astronomy Window</a>
+                       </li>
+                       <li>
+                               <a href="#toc16">Wind</a>
+                       </li>
+                       <li>
+                               <a href="#toc17">Command Prompt</a>
+                       </li>
+                       <li>
+                               <a href="#toc18">Status Window</a>
+                       </li>
+                       <li>
+                               <a href="#toc19">Foogod Window</a>
+                       </li>
+                       <li>
+                               <a href="#toc20">Console Window</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc21">PLAYER COMMANDS</a>
+               <ul>
+                       <li>
+                               <a href="#toc22">General syntax:</a>
+                       </li>
+                       <li>
+                               <a href="#toc23">General commands:</a>
+                       </li>
+                       <li>
+                               <a href="#toc24">Wilderness-only commands:</a>
+                       </li>
+                       <li>
+                               <a href="#toc25">Town/Dungeon/Combat-only commands:</a>
+                       </li>
+                       <li>
+                               <a href="#toc26">Special commands:</a>
+                       </li>
+                       <li>
+                               <a href="#toc27">Shortcuts:</a>
+                       </li>
+                       <li>
+                               <a href="#toc28">Editing commands:</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc29">MOVEMENT MODES</a>
+               <ul>
+                       <li>
+                               <a href="#toc30">Party Mode (wilderness)</a>
+                       </li>
+                       <li>
+                               <a href="#toc31">Follow Mode (town/combat/dungeons)</a>
+                       </li>
+                       <li>
+                               <a href="#toc32">Solo Mode (town/combat/dungeons)</a>
+                       </li>
+                       <li>
+                               <a href="#toc33">Round Robin Mode (town/combat/dungeons)</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc34">PLACES</a>
+               <ul>
+                       <li>
+                               <a href="#toc35">Wilderness:</a>
+                       </li>
+                       <li>
+                               <a href="#toc36">Wilderness Combat:</a>
+                       </li>
+                       <li>
+                               <a href="#toc37">Towns/Dungeons:</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc38">COMBAT</a>
+       </li>
+       <li>
+               <a href="#toc39">ADVANCEMENT</a>
+               <ul>
+                       <li>
+                               <a href="#toc40">XP Required for Advancement</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc41">Attributes</a>
+               <ul>
+                       <li>
+                               <a href="#toc42">Strength</a>
+                       </li>
+                       <li>
+                               <a href="#toc43">Dexterity</a>
+                       </li>
+                       <li>
+                               <a href="#toc44">Intelligence</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc45">MAGIC</a>
+               <ul>
+                       <li>
+                               <a href="#toc46">Table 1: Reagents</a>
+                       </li>
+                       <li>
+                               <a href="#toc47">Table 2: Spells</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc48">EFFECTS</a>
+       </li>
+       <li>
+               <a href="#toc49">CONVERSATION</a>
+       </li>
+       <li>
+               <a href="#toc50">MISC</a>
+       </li>
+       <li>
+               <a href="#toc51">APPENDIX A: MAP HACKING</a>
+       </li>
+       <li>
+               <a href="#toc52">APPENDIX B: Spoilers</a>
+               <ul>
+                       <li>
+                               <a href="#toc53">Projectile Weapon Stats</a>
+                       </li>
+                       <li>
+                               <a href="#toc54">Thrown Weapon Stats</a>
+                       </li>
+                       <li>
+                               <a href="#toc55">Melee Weapon Stats</a>
+                       </li>
+                       <li>
+                               <a href="#toc56">Armor Stats</a>
+                       </li>
+               </ul>
+       </li>
+       <li>
+               <a href="#toc57">FOOTNOTES</a>
+       </li>
+</ul>
+
+<a name="toc3"></a>
+<h2>
+       INSTALLING THE GAME
+</h2>
+
+<p>
+If you downloaded a source distribution see the top-level INSTALL file.
+</p>
+<p>
+If you downloaded a windows binary just unzip the distribution using Winzip or
+similar.
+</p>
+
+
+<a name="toc4"></a>
+<h2>
+       STARTING THE GAME
+</h2>
+
+<p>
+On Linux/UNIX:
+</p>
+<p class="example">
+       $ haxima.sh
+</p>
+<p>
+On Windows:
+</p>
+<p class="example">
+       Use the start menu or desktop icon
+</p>
+<p>
+You can play the Tutorial first or jump right in with Start New Game.
+</p>
+
+<a name="toc5"></a>
+<h2>
+       SAVING THE GAME
+</h2>
+<p>
+You can save your game at any time while playing by using the CTRL-S key
+sequence for the S)ave command. An unlimited number of saved games is
+permitted. When you restart, use the Journey Onward option from the main menu
+to select a saved game to continue.
+</p>
+<p>
+If you die, the game will exit, and when you restart it will pick up where you
+last saved via the Journey Onward option.
+</p>
+
+<a name="toc6"></a>
+<h2>
+       EXITING THE GAME
+</h2>
+<p>
+You can quit at any time by pressing Q for the Q)uit commmand. It will prompt
+you to save if you like and then exit.
+</p>
+
+<a name="toc7"></a>
+<h2>
+       ORIENTATION
+</h2>
+<p>
+If you are unfamiliar with U5 I recommend the Tutorial option available from the
+Main Menu when you start the game. Here are some more notes to help you get
+started.
+</p>
+
+<a name="toc8"></a>
+<h3>
+       Exploring
+</h3>
+<p>
+When you start you will have a party consisting of one character known
+initially as The Wanderer. The icon for this character will be in the center of
+the map view on the left. Explore around a bit using the arrow keys to
+move. Below the map you'll see a little window with a prompt. This gives you
+hints when you're entering commands to tell you what type of input the command
+wants. For example, if you type 'x' (for e[x]amine) the command prompt will
+say:
+</p>
+<p class="example">
+    Xamine-&lt;target&gt;(ESC to exit)
+</p>
+<p>
+Which means it wants you to hit the arrow keys and move the targeting
+cursor. When you hit 'ESC' instead the command will cancel. Pretty much all
+commands can be canceled by hitting 'ESC'.
+</p>
+<p>
+To get a detailed explanation of where you are and what time it is, use the AT
+command by pressing '@'. There is no clock in the game, so this is the only way
+to tell time other than guesstimating from the position of the sun.
+</p>
+
+<a name="toc9"></a>
+<h3>
+       Talking
+</h3>
+<p>
+You'll see your first NPC to the south. To talk to the NPC press 't' for
+T)alk. This brings up a targeting crosshair. It might start out on the NPC or
+on your character, if it's on you then move it to the NPC with the arrow keys
+and hit enter. 
+</p>
+<p>
+That starts a conversation. During conversation you enter a keyword and the NPC
+will respond. For example, type NAME or JOB and see what this NPC says. When
+you are done talking type 'bye' or hit enter by itself.
+</p>
+
+<a name="toc10"></a>
+<h3>
+       Getting Stuff
+</h3>
+<p>
+Eventually you will want to follow the road down to the chamber on the lower
+left. The chamber is marked by mysterious runes on its walls. Within the
+chamber is a chest.
+</p>
+<p>
+Walk over next to the chest and O)pen it by hitting 'o' and using your arrow
+keys to indicate a direction. The chest will open and deposit a bunch of stuff
+on the ground.
+</p>
+<p>
+G)et the stuff using the 'g' key. Among the items will be some basic weapons,
+armour and spell reagents as well as some scrolls and potions.
+</p>
+
+<a name="toc11"></a>
+<h3>
+       Equipping
+</h3>
+<p>
+To see your stuff hit 'z' for Z)tats and scroll around. The left and right
+arrow keys will switch between different status panes. Hit ESC when you tire of
+admiring yourself and your loot.
+</p>
+<p>
+To R)eady the weapons and armor hit 'r' then select them. Hit ESC when done.
+</p>
+
+<a name="toc12"></a>
+<h3>
+       Mixing A Spell
+</h3>
+<p>
+To M)ix a heal spell type 'm' for mix. Next enter the spell name, in this case
+'m' again for "Mani", and hit ENTER. Next, select Ginseng and Spider Silk from
+the reagents list, and hit 'm' to mix them. Finally, you can mix batches of a
+given spells at once, so you will need to input the quantity of "Mani" spells
+you wish to produce. Enter '1' here, and you will have made a "Mani" spell, a
+spell of minor healing. More on spells later. 
+</p>
+<a name="toc13"></a>
+<h3>
+       Entering and Exiting Towns
+</h3>
+<p>
+When you are ready to face the world walk to the edge of the map and bravely
+step off. You will zoom out to Wilderness Mode, and your entire party (all one
+of you) will appear as an icon in the center. To re-enter take a step south (at
+which point you will see a shrine icon where you just were) and step north
+again. Now you know how to enter and exit towns. Congrats.
+</p>
+<p>
+When you enter a town, unless you have some enemies there, you will start out
+in "follow mode", which means you control the party leader and everybody else
+in the party tries to keep up. But if hostiles are in town you will be in
+"character mode", which means you control each party member in turn. To switch
+between these two mode use the 'f' key. This will make more sense when you add
+more characters to your party.
+</p>
+<p>
+IMPORTANT: when you eventually get somebody to join you, don't forget about
+           Follow Mode (the 'f' key). It's much easier to have everybody follow
+           your main dude around than to always individually control them.
+</p>
+
+<a name="toc14"></a>
+<h2>
+       USER INTERFACE
+</h2>
+<a name="toc15"></a>
+<h3>
+Astronomy Window
+</h3>
+<p>
+    Above the map you'll see a little window embedded in the frame which shows
+    the position of the sun and two moons. It also shows the phase of the
+    moons, which is important for moongate travel.
+</p>
+<a name="toc16"></a>
+<h3>
+Wind
+</h3>
+<p>
+    Below the map, embedded in the frame, is the wind direction
+    indicator. Currently the wind only affects ships. Tacking across the wind
+    provides the best rate of travel, the wind at your back is second best, and
+    heading into the wind is the worst. Note that this indicates the direction
+    the wind is blowing _FROM_.
+</p>
+<a name="toc17"></a>
+<h3>
+Command Prompt
+</h3>
+<p>
+    Unlike u4/u5/u6 the command prompt has its own window, just below the wind
+    indicator. Interactive command prompts appear here, as well as the things
+    the player says in conversation.
+</p>
+<a name="toc18"></a>
+<h3>
+Status Window
+</h3>
+<p>
+    In the top right you have a general-purpose window for viewing and
+    selecting lists of things. Normally it shows some basic party stats, but
+    its contents change as required by user commands. For example, (R)eady will
+    turn it into a selection list.
+</p>
+<p>
+    Normally the window lists all the player's party members and shows their
+    current hit points and status. The status is reflected in one or more
+    little icons. For example, if a character is poisoned you'll see a little
+    green skull-and-crossbones. You can get a better description of the status
+    by using the Z)tatus command to inspect individual party members.
+</p>
+<a name="toc19"></a>
+<h3>
+Foogod Window
+</h3>
+<p>
+    It sounds sacrilegious, but that's just my acronym for Food/Gold
+    Window. This little window appears below the status window and shows the
+    turn, food and gold counters as well as the current combat status and any
+    pending Effects. The effects will be printed in cryptic little codes like
+    "N" for magic negated. If you board a vehicle it will also show you the hit
+    points for the vehicle. Here are some of the codes and what they mean:
+</p>
+
+<dl>
+
+<dt><img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -39px -16px;">
+       Magic Negated
+</dt>
+       <dd>Spellcasting fails.</dd>
+       
+<dt><img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -31px -16px;">
+       Quicken
+</dt>
+       <dd>Party members get extra turns per round.</dd>
+
+<dt><img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -47px -16px;">
+       Reveal
+</dt>
+       <dd>Invisible things are visible.</dd>
+
+<dt><img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -23px -16px;">
+       Time Stop
+</dt>
+       <dd>Everything in the world suspends while Party members get to move.</dd>
+
+<dt><img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -55px -16px;">
+       Xray Vision
+</dt>
+       <dd>Party members can see through walls.</dd>   
+       
+</dl>
+
+<a name="toc20"></a>
+<h3>
+Console Window
+</h3>
+<p>
+    Finally on the right hand side you'll find the window where all the game
+    messages get logged.
+</p>
+
+<a name="toc21"></a>
+<h2>
+       PLAYER COMMANDS
+</h2>
+<p>
+Here's your chance to let the sweat dry on your mouse - all commands are via
+the keyboard. As it should be, forever and ever amen.
+</p>
+<p>
+Addendum: For the sake of convenience to mousephiles, targeting prompts will
+accept input from the mouse. But the shortcut keys are faster.
+</p>
+
+<a name="toc22"></a>
+<h3>
+General syntax:
+</h3>
+<dl>
+<dt><span class="key">dir</span></dt>
+       <dd>one of the four arrow keys</dd>
+<dt><span class="ph">member</span></dt>
+       <dd>a party member, selected from a list by scrolling with the arrow
+    keys and pressing <span class="key">enter</span> or <span class="key">space</span></dd>
+<dt><span class="ph">item</span></dt>
+       <dd>an inventory item, selected from a list</dd>
+<dt><span class="ph">spell</span></dt>
+       <dd>a spell, selected from a list</dd>
+<dt><span class="key">space</span></dt>
+       <dd>spacebar</dd>
+<dt><span class="ph">target</span></dt>
+       <dd>a combat target, selected by moving the crosshairs and pressing
+       <span class="key">enter</span> or <span class="key">space</span> (or using the mouse and left-clicking)</dd>
+<dt><span class="ph">*</span></dt>
+       <dd>varies depending on context</dd>
+</dl>
+
+<a name="toc23"></a>
+<h3>
+General commands:
+</h3>
+<dl>
+<dt><span class="key">dir</span></dt>
+       <dd>Move in that direction</dd>
+<dt>A)ttack-<span class="key">dir</span></dt>
+       <dd>Initiate combat</dd>
+<dt>B)oard</dt>
+       <dd>Board/exit a vehicle like a ship or horse</dd>
+<dt>C)ast-<span class="ph">member</span>-<span class="ph">spell</span>-<span class="ph">*</span></dt>
+       <dd>Cast a spell (the last argument depends on the spell)</dd>
+<dt>E)nter</dt>
+       <dd>Enter a portal, including up or down ladders</dd>
+<dt>F)ire-<span class="key">dir</span></dt>
+       <dd>Fire vehicle's weapon (e.g., ship cannon)</dd>
+<dt>G)et-<span class="key">dir</span></dt>
+       <dd>Get an object from the ground</dd>
+<dt>H)andle-<span class="ph">member</span>-<target></dt>
+       <dd>Activate a switch or lever</dd>
+<dt>L)oiter-<span class="ph">0-9/sunrise</span></dt>
+       <dd>Loiter a few hours</dd>
+<dt>N)ew-order-<span class="ph">member</span>-<span class="ph">member</span></dt>
+       <dd>Swap order of two party members</dd>
+<dt>O)pen-<span class="key">dir</span></dt>
+       <dd>Open a container or door</dd>
+<dt>Q)uit</dt>
+       <dd>Quit &amp; optionally save the game</dd>
+<dt>R)eady-<span class="ph">member</span>-<span class="ph">item</span></dt>
+       <dd>Ready an armament like a weapon, shield, etc.</dd>
+<dt>S)earch-<span class="key">dir</span></dt>
+       <dd>Look carefully</dd>
+<dt>T)alk-<span class="ph">target</span></dt>
+       <dd>Talk to an NPC</dd>
+<dt>U)se-<span class="ph">member</span>-<span class="ph">item</span></dt>
+       <dd>Use an item like a torch or potion</dd>
+<dt>X)amine-<span class="ph">target</span></dt>
+       <dd>Examine map tiles within view</dd>
+<dt>Z)tats</dt>
+       <dd>Show party stats like inventory, armaments, etc</dd>
+<dt>@)AT</dt>
+       <dd>Information about where the party is AT, etc</dd>
+<dt><span class="key">space</span></dt>
+       <dd>Pass one turn</dd>
+<dt>CTRL-S)ave</dt>
+       <dd>Save a game</dd>
+<dt>CTRL-R)eload</dt>
+       <dd>Reload a game</dd>
+</dl>
+
+<a name="toc24"></a>
+<h3>
+Wilderness-only commands:
+</h3>
+<dl>
+<dt>K)amp-<span class="ph">0-9/sunrise</span>-<span class="ph">y/n</span>-<span class="ph">player</span></dt>
+       <dd>Camp in the wilderness (to heal and recover mana) or aboard ship
+       (to repair hull damage as well)</dd>
+</dl>
+
+<a name="toc25"></a>
+<h3>
+Town/Dungeon/Combat-only commands:
+</h3>
+<dl>
+<dt>A)ttack-<span class="ph">target</span></dt>
+       <dd>Attack the specified target</dd>
+<dt>F)ollow</dt>
+       <dd>Select follow mode, where the party members 
+       automatically follow the party leader.</dd>
+<dt>[1-9]</dt>
+       <dd>Select a party member for solo mode.</dd>
+<dt>[0]</dt>
+       <dd>Select turn-based party mode, where each party 
+       member takes directions one at a time.</dd>
+<dt>K)amp-<span class="ph">0-9/sunrise</span></dt>
+       <dd>Sleep on a bed.</dd> 
+</dl>
+
+<a name="toc26"></a>
+<h3>
+Special commands:
+</h3>
+<dl>
+<dt><span class="key">ESC</span></dt>
+       <dd>Aborts most commands</dd>
+</dl>
+
+<a name="toc27"></a>
+<h3>
+Shortcuts:
+</h3>
+<dl>
+<dt><span class="key">+/=</span></dt>
+       <dd>When targeting an attack, moves cursor to next
+       hostile npc.</dd>
+<dt><span class="key">-</span></dt>
+       <dd>When targeting an attack, moves cursor to previous
+       hostile npc.</dd>
+<dt><span class="key">ESC</span></dt>
+       <dd>When wilderness combat is over, exits to
+       wilderness map.</dd>
+</dl>
+
+<a name="toc28"></a>
+<h3>
+Editing commands:
+</h3>
+<dl>
+<dt>CTRL-T)erraform</dt>
+       <dd>Alter terrain. This deserves its own section.<sup><a class="footnote" href="#f1">1</a></sup></dd>
+<dt>CTRL-Z)oom</dt>
+       <dd>Zoom in or out (like peering at a gem but free)</dd>
+
+<a name="toc29"></a>
+<h2>
+       MOVEMENT MODES
+</h2>
+<a name="toc30"></a>
+<h3>
+Party Mode (wilderness)
+</h3>
+<p>
+    The party appears as a single icon in the center of the screen.
+</p>
+
+<a name="toc31"></a>
+<h3>
+Follow Mode (town/combat/dungeons)
+</h3>
+<p>
+    You control the party leader and the other members follow the
+    leader. Attacking a target will automatically switch to Round-Robin
+    Mode. The party leader is always the top person in the list who is alive
+    and still on the current map. Enter follow mode from Solo or Round Robin
+    Mode by pressing 'f'.
+</p>
+
+<a name="toc32"></a>
+<h3>
+Solo Mode (town/combat/dungeons)
+</h3>
+<P>
+    You control one party member while the others stand around looking
+    bored. Enter Solo Mode by pressing the number key associated with the
+    party member's order in the list. 1 is the first member in the list.
+</p>
+<p>
+    NOTE: Solo mode can be very useful if one of your party members has greater
+          passability than the others. For example, if a gazer joins your party
+          he can float over water. Now imagine the possibilities if you get a
+          ghost to join your party.
+</p>
+
+<a name="toc33"></a>
+<h3>
+Round Robin Mode (town/combat/dungeons)
+</h3>
+<p>
+    You control each member in turn. This is the default mode when you enter
+    combat. To enter Round Robin Mode from solo mode, press 0. To enter from
+    Follow Mode press 'f'. Yes, confusing to have two methods. I'll fix it
+    someday. Let me know if you have an opinion.
+</p>
+
+<a name="toc34"></a>
+<h2>
+       PLACES
+</h2>
+
+<a name="toc35"></a>
+<h3>
+Wilderness:
+</h3>
+<p>
+    In the outdoor or wilderness map the party moves as a single unit. You can
+    enter into combat with enemy NPC parties by moving into them or waiting for
+    them to attack you. Likewise you can enter towns, dungeons or moongates by
+    simply walking into them.
+</p>
+
+<a name="toc36"></a>
+<h3>
+Wilderness Combat:
+</h3>
+<p>
+    This is a special temporary combat map that pops up when you engage an
+    enemy NPC party in the wilderness. In this mode you control individual
+    party members. You return to the wilderness map by having all of your
+    living party members walk off the edge of the map. (Hint: if combat is over
+    you can press <span class="key">ESC</span> to quickly leave the map).
+</p>
+
+<a name="toc37"></a>
+<h3>
+Towns/Dungeons:
+</h3>
+<p>
+    In towns and dungeons you move just like in combat mode. You can control
+    the individual party members in turn, have one of them scout around in solo
+    mode, or control the leader and have the other party members follow.
+</p>
+
+<a name="toc38"></a>
+<h2>
+COMBAT
+</h2>
+<p>
+What can I say? It's pretty much like u5. Try the flaming oil at night or in an
+underground place. Oh, and watch out for gazers. They can charm you. Kill them
+or charm them right away.
+</p>
+
+<a name="toc39"></a>
+<h2>
+ADVANCEMENT
+</h2>
+<p>
+As usual, characters advance a level when they gain sufficient experience
+points. There is no maximum level limit. When a character advances his maximum
+HP and MP increase, depending on his class, species and personal bonuses. At
+the moment of advancment he is fully healed and mana is restored to their new
+maximum levels.
+</p>
+
+<a name="toc40"></a>
+<h3>
+XP Required for Advancement
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Level
+       </td><td>
+               XP
+       </td>
+</tr><tr>
+       <td>
+               1
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               2
+       </td><td>
+               32
+       </td>
+</tr><tr>
+       <td>
+               3
+       </td><td>
+               64
+       </td>
+</tr><tr>
+       <td>      
+               4
+       </td><td>
+               128 
+       </td>
+</tr><tr>
+       <td>    
+               5
+       </td><td>
+               256
+       </td>
+</tr><tr>
+       <td>     
+               6
+       </td><td>
+               512
+       </td>
+</tr><tr>
+       <td>     
+               n
+       </td><td>
+               2^(n+5)
+       </td>
+</tr>
+</table>
+
+<a name="toc41"></a>
+<h2>
+       Attributes
+</h2>
+<p>
+Characters have three basic attributes: Strength, Dexterity and
+Intelligence. These are fixed when the character is created and don't change
+during the game.
+</p>
+
+<a name="toc42"></a>
+<h3>
+Strength
+</h3>
+<p>
+    Strength limits the total weight of readied weapons and armour. Strong
+       characters do more damage and are better at hitting with heavy or
+       bludgeoning weapons. It is also used when breaking free of spider webs
+       (most trolls don't stay ensnared too long...).
+</p>
+<a name="toc43"></a>
+<h3>
+Dexterity
+</h3>
+<p>
+    Dexterity is used when attacking with missile and balanced weaponry, and
+       helps when avoiding your opponents' blows. It is also needed when
+       picking locks and disarming trapped chests.
+</p>
+<a name="toc44"></a>
+<h3>
+Intelligence
+</h3>
+<P>
+    Intelligence makes spells more potent and more likely to succeed.
+</p>
+
+<a name="toc45"></a>
+<h2>
+MAGIC
+</h2>
+<p>
+The example game contains a full complement of spells. The magic system is
+similar to Ultima 5 and Ultima 6: you select a spell by entering magic
+syllables. A spell name is a combination of one to four syllables.
+</p>
+<p>
+The syllables, spell names and reagent mixtures provided in the example game
+are a direct ripoff of Ultima 5. If you don't have a u5 reference manual lying
+around then the tables below will help:
+</p>
+
+<a name="toc46"></a>
+<h3>
+Table 1: Reagents
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Name
+       </td><td>
+               Abbrev used in spell table
+       </td>
+</tr><tr>
+       <td>
+               Black Pearl
+       </td><td>
+               BP
+       </td>
+</tr><tr>
+       <td>
+               Blood Moss
+       </td><td>
+               BM
+       </td>
+</tr><tr>
+       <td>
+               Garlic
+       </td><td>
+               GA
+       </td>
+</tr><tr>
+       <td>
+               Ginseng
+       </td><td>
+               GI
+       </td>
+</tr><tr>
+       <td>
+               Mandrake Root
+       </td><td>
+               MR
+       </td>
+</tr><tr>
+       <td>
+               Nightshade
+       </td><td>
+               NI
+       </td>
+</tr><tr>
+       <td>
+               Spider Silk
+       </td><td>
+               SS
+       </td>
+</tr><tr>
+       <td>
+               Sulphurous Ash
+       </td><td>
+               SA
+       </td>
+</tr>
+</table>
+
+<a name="toc47"></a>
+<h3>
+       Table 2: Spells
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Syllables
+       </td><td>
+               Effects
+       </td><td>
+               Reagents
+       </td><td>
+               Party/Combat
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>1</span>
+       </td>
+</tr><tr>
+       <td>
+               An Nox
+       </td><td>
+               Cure Poison
+       </td><td>
+               GI, GA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               An Zu
+       </td><td>
+               Awaken
+       </td><td>
+               GI, GA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Grav Por
+       </td><td>
+               Magic Missile
+       </td><td>
+               SA, BP
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Lor
+       </td><td>
+               Light
+       </td><td>
+               SA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Mani
+       </td><td>
+               Heal
+       </td><td>
+               GI, SS
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Wis Sanct
+       </td><td>
+               Detect Trap
+       </td><td>
+               SA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               An Sanct Ylem
+       </td><td>
+               Disarm Trap
+       </td><td>
+               BM
+       </td><td>
+               PC
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>2</span>
+       </td>
+</tr><tr>
+       <td>
+               An Sanct
+       </td><td>
+               Unlock
+       </td><td>
+               SA, BM
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               An Xen Corp
+       </td><td>
+               Repel Undead
+       </td><td>
+               GA, SA
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Wis
+       </td><td>
+               Locate
+       </td><td>
+               NI
+       </td><td>
+               P
+       </td>
+</tr><tr>
+       <td>
+               Rel Hur
+       </td><td>
+               Change Wind
+       </td><td>
+               SA, BM
+       </td><td>
+               P
+       </td>
+</tr><tr>
+       <td>
+               In Nox Por
+       </td><td>
+               Poison Missile
+       </td><td>
+               NI, BM, BP
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Bet Xen
+       </td><td>
+               Summon Vermin
+       </td><td>
+               SS, BM, SA
+       </td><td>
+               C
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>3</span>
+       </td>
+</tr><tr>
+       <td>
+               In Flam Grav
+       </td><td>
+               Fire Field
+       </td><td>
+               SA, BP, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Zu Grav
+       </td><td>
+               Sleep Field
+       </td><td>
+               GI, BP, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Nox Grav
+       </td><td>
+               Poison Field
+       </td><td>
+               NI, BP, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Vas Flam
+       </td><td>
+               Fire Ball
+       </td><td>
+               BP, SA
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Vas Lor
+       </td><td>
+               Great Light
+       </td><td>
+               SA, MA
+       </td><td>
+               PC
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>4</span>
+       </td>
+</tr><tr>
+       <td>
+               An Grav
+       </td><td>
+               Dispel Field
+       </td><td>
+               BP, SA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               In Sanct Grav
+       </td><td>
+               Energy Field
+       </td><td>
+               MA, BP, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Sanct
+       </td><td>
+               Protection
+       </td><td>
+               SA, GI, GA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Wis Quas
+       </td><td>
+               Reveal Hidden
+       </td><td>
+               NI, SA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Bet Por
+       </td><td>
+               Blink (Caster)
+       </td><td>
+               BP, BM
+       </td><td>
+               C
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>5</span>
+       </td>
+</tr><tr>
+       <td>
+               In Ex Por
+       </td><td>
+               Unlock Magic
+       </td><td>
+               SA, BM
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               An Ex Por
+       </td><td>
+               Magic Lock
+       </td><td>
+               SA, BM, GA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Kal Xen
+       </td><td>
+               Summon Beast
+       </td><td>
+               SS, MA
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Zu
+       </td><td>
+               Sleep
+       </td><td>
+               GI, NS, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Vas Mani
+       </td><td>
+               Great Heal
+       </td><td>
+               GI, SS, MA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Rel Tym
+       </td><td>
+               Quickness
+       </td><td>
+               SA, BM, MA
+       </td><td>
+               PC
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>6</span>
+       </td>
+</tr><tr>
+       <td>
+               An Xen Ex
+       </td><td>
+               Charm
+       </td><td>
+               BP, NI, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In An
+       </td><td>
+               Negate Magic
+       </td><td>
+               GA, MA, SA
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Vas Por Ylem
+       </td><td>
+               Earthquake
+       </td><td>
+               BM, MA, SA
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Quas An Wis
+       </td><td>
+               Confuse
+       </td><td>
+               MA, NI
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Wis An Ylen
+       </td><td>
+               Xray Vision
+       </td><td>
+               MA, SA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               In Rel Por
+       </td><td>
+               Telekinesis
+       </td><td>
+               BP, BM, SS
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Vas Por
+       </td><td>
+               Blink (Party)
+       </td><td>
+               MA, BP, BM
+       </td><td>
+               P
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>7</span>
+       </td>
+</tr><tr>
+       <td>
+               In Nox Hur
+       </td><td>
+               Poison Wind
+       </td><td>
+               NI, SA, BM
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Quas Corp
+       </td><td>
+               Fear
+       </td><td>
+               NI, MA, GA
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Quas Wis
+       </td><td>
+               Peer
+       </td><td>
+               NI, MA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               In Quas Xen
+       </td><td>
+               Clone
+       </td><td>
+               NI, MA, SA, SS, BM, GI
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Sanct Lor
+       </td><td>
+               Invisibility
+       </td><td>
+               NI, MA, BM
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Xen Corp
+       </td><td>
+               Kill
+       </td><td>
+               NI, BP
+       </td><td>
+               C
+       </td>
+</tr><tr class="breaker">
+       <td colspan="4">
+               <span>8</span>
+       </td>
+</tr><tr>
+       <td>
+               An Tym
+       </td><td>
+               Stop Time
+       </td><td>
+               MA, GA, BM
+       </td><td>
+               WC
+       </td>
+</tr><tr>
+       <td>
+               In Flam Hur
+       </td><td>
+               Flame Wind
+       </td><td>
+               MA, SA, BM
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Vas Grav Corp
+       </td><td>
+               Energy Wind
+       </td><td>
+               MA, SA, NI
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               In Mani Corp
+       </td><td>
+               Resurrect
+       </td><td>
+               GA, GI, SS, SA, BM, MA
+       </td><td>
+               PC
+       </td>
+</tr><tr>
+       <td>
+               Kal Xen Corp
+       </td><td>
+               Summon Undead
+       </td><td>
+               SS, MA, NI
+       </td><td>
+               C
+       </td>
+</tr><tr>
+       <td>
+               Vas Rel Por
+       </td><td>
+               Gate Travel
+       </td><td>
+               SA, MA, BP
+       </td><td>
+               P
+       </td>
+</tr>
+</table>
+<p>
+[1] In Towns and Dungeons teleport spells that can move the party from one
+    place to another will fail unless combat is over and the party is in Follow
+    Mode.
+</p>
+
+<a name="toc48"></a>
+<h2>
+EFFECTS
+</h2>
+<p>
+From time to time your characters might run into a little trouble with magical
+foes, natural hazards, or their own weakness for alcohol. Don't panic. Most
+effects are non-fatal, but a few are.
+</p>
+<dl>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -39px 0;">
+Asleep
+</dt>
+<dd>
+    Sleeping party members will eventually wake up of their own accord. If you
+    don't feel like waiting use the An Zu spell.
+</dd>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -55px 0;">
+Charmed
+</dt>
+<dd>
+    Enemy wizards might charm party members, causing them to fight on their
+    behalf. Charm wears off after 10 minutes.
+</dd>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -23px 0;">
+Diseased
+</dt>
+<dd>
+    Some monsters may infect party members with disease. Disease is not fatal,
+    but it will not wear off until your party member is nearly out of hit
+    points.
+</dd>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -79px 0;">
+Drunk
+</dt>
+<dd>
+    Anytime your character buys alcoholic drinks or picks them up from the
+    ground he gets drunk. Drunkenness lasts an hour or so and causes him to
+    randomly bump into things.
+</dd>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -95px 0;">
+Ensnared
+</dt>
+<dd>
+    When stuck in a spider web, a character will break free after struggling
+    for a while. The time required to free himself depends on the character's
+    strength.
+</dd>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -15px -16px;">
+Paralyzed
+</dt>
+<dd>
+    Spiders inject paralyzing venom to make their foes helpless before feeding
+    on them. Paralysis will wear off after a short random interval.
+</dd>
+<dt>
+<img src="doc/null.gif" class="icon" style="background: black url('haxima/effects.png') -15px 0;">
+Poisoned
+</dt>
+<dd>
+    Bogs or spells may poison party members, causing them to lose hit points
+    every turn until the poison is cured with a spell or potion. Poison is
+    fatal! It won't wear off like disease.
+</dd>
+</dl>
+
+<a name="toc49"></a>
+<h2>
+CONVERSATION
+</h2>
+<p>
+Start a conversation with an NPC with the T)alk command. During conversation
+you type simple inquiries and the NPC responds, sometimes asking you a question
+in return. Conversations with shopkeepers will allow you to buy and sell
+items. Most NPCs respond to the 'NAME' and 'JOB' queries, as well as queries
+about their town and fellow townsmen. Their responses usually give you clues to
+further fruitful queries. Also, with the special 'JOIN' query you can ask an
+NPC to join your party (some will join you, and some will join you only if you
+do or say something that impresses them).
+</p>
+
+<a name="toc50"></a>
+<h2>
+MISC
+</h2>
+<p>
+Food is consumed three times per day, one unit for each living party
+member. When the food runs out, party members take a point of damage at each
+meal time.
+</p>
+
+<a name="toc51"></a>
+<h2>
+APPENDIX A: MAP HACKING
+</h2>
+<p>
+Like many games, "nazghul" is separated into an engine<sup><a class="footnote"href="#f2">2</a></sup> and some data
+files. In this case the data files are written in the Scheme programmming
+language. If you examine the default start file 'session.scm' you will see that
+it is a scheme file which loads the game types from other files and then
+defines the starting game variables.
+</p>
+<p>
+I encourage people to experiment with modifying the example files or even using
+them as a basis to create their own games. The example script code is all
+committed to the public domain. The image and sound files come from various
+sources - see the COPYING file in the top nazghul directory for details on
+where they came from.
+</p>
+<p>
+If you want to make a proprietary game you may use the example script files,
+but you will probably need to make your own image and sound resource files as
+the ones in the examples directory come from other open-source or freeware
+projects and their copyright holders might object to proprietary use.
+</p>
+
+<a name="toc52"></a>
+<h2>
+APPENDIX B: Spoilers
+</h2>
+<p>
+These apply specifically to Haxima, and not necessarily to any other game made
+with the Nazghul engine.
+</p>
+
+<a name="toc53"></a>
+<h3>
+Projectile Weapon Stats
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Name
+       </td><td>
+               To-Hit
+       </td><td>
+               Damage
+       </td><td>
+               To-Def
+       </td><td>
+               Hnds
+       </td><td>
+               Rng
+       </td><td>
+               Ammo
+       </td><td>
+               Weight
+       </td>
+</tr><tr>
+       <td>
+               Sling
+       </td><td>
+               1d2-2
+       </td><td>
+               1d4
+       </td><td>
+               -1
+       </td><td>
+               1
+       </td><td>
+               4
+       </td><td>
+               slingstone <sup><a href="#misf1">1</a></sup>
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               Sling+4
+       </td><td>
+               3
+       </td><td>
+               1d4+4
+       </td><td>
+               0
+       </td><td>
+               1
+       </td><td>
+               6
+       </td><td>
+               slingstone <sup><a href="#misf1">1</a></sup>
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               Bow
+       </td><td>
+               1d3-2
+       </td><td>
+               2d4
+       </td><td>
+               -2
+       </td><td>
+               2
+       </td><td>
+               6
+       </td><td>
+               arrow
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Crossbow
+       </td><td>
+               1d4-2
+       </td><td>
+               4d4
+       </td><td>
+               -1
+       </td><td>
+               2
+       </td><td>
+               4
+       </td><td>
+               bolt
+       </td><td>
+               3
+       </td>
+</tr><tr>
+       <td>
+               Doom Staff <sup><a href="#misf2">2</a></sup>
+       </td><td>
+               1d4
+       </td><td>
+               1
+       </td><td>
+               +2
+       </td><td>
+               2
+       </td><td>
+               6
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Stun Wand <sup><a href="#misf3">3</a></sup>
+       </td><td>
+               -2
+       </td><td>
+               1d4
+       </td><td>
+               -1
+       </td><td>
+               1
+       </td><td>
+               6
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr>
+</table>
+<p>
+<a name="misf1"></a>
+[1] Considered 'ubiquitous' (ie you always have enough ammo)
+</p>
+<p>
+<a name="misf2"></a>
+[2] Also inflicts fire damage
+</p>
+<p>
+<a name="misf3"></a>
+[3] Temporarily paralyzes target
+</p>
+
+<a name="toc54"></a>
+<h3>
+Thrown Weapon Stats
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Name
+       </td><td>
+               To-Hit
+       </td><td>
+               Damage
+       </td><td>
+               To-Def
+       </td><td>
+               Hnds
+       </td><td>
+               Rng
+       </td><td>
+               Weight
+       </td>
+</tr><tr>
+       <td>
+               Flaming oil <sup><a href="#throwf1">1</a></sup>
+       </td><td>
+               -1
+       </td><td>
+               1d6
+       </td><td>
+               -2
+       </td><td>
+               1
+       </td><td>
+               4
+       </td><td>
+               1
+       </td>
+</tr><tr>
+       <td>
+               Spear
+       </td><td>
+               0
+       </td><td>
+               1d8
+       </td><td>
+               +1
+       </td><td>
+               1
+       </td><td>
+               4
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Boulder
+       </td><td>
+               -2
+       </td><td>
+               3d4+1
+       </td><td>
+               -2
+       </td><td>
+               2
+       </td><td>
+               5
+       </td><td>
+               10
+       </td>
+</tr>
+</table>
+<p>
+<a name="throwf1"></a>
+[1] Leaves a temporary burning patch of ground
+</p>
+
+<a name="toc55"></a>
+<h3>
+Melee Weapon Stats
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Name
+       </td><td>
+               To-Hit
+       </td><td>
+               Damage
+       </td><td>
+               To-Def
+       </td><td>
+               Hnds
+       </td><td>
+               Rng
+       </td><td>
+               Weight
+       </td>
+</tr><tr>
+       <td>
+               Dagger
+       </td><td>
+               1d4
+       </td><td>
+               1d4
+       </td><td>
+               1d2
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               Dagger+4
+       </td><td>
+               1d4+4
+       </td><td>
+               1d4+4
+       </td><td>
+               1d2+4
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               Mace
+       </td><td>
+               1d4
+       </td><td>
+               1d6+2
+       </td><td>
+               +0
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               3
+       </td>
+</tr><tr>
+       <td>
+               Axe
+       </td><td>
+               1d2
+       </td><td>
+               2d3+2
+       </td><td>
+               +0
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               3
+       </td>
+</tr><tr>
+       <td>
+               Sword
+       </td><td>
+               1d2
+       </td><td>
+               1d8+1
+       </td><td>
+               1d2
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Sword+2
+       </td><td>
+               1d2+2
+       </td><td>
+               1d8+3
+       </td><td>
+               1d2+2
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Sword+4
+       </td><td>
+               1d2+4
+       </td><td>
+               1d8+5
+       </td><td>
+               1d2+4
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               2H Axe
+       </td><td>
+               0
+       </td><td>
+               4d3+2
+       </td><td>
+               -2
+       </td><td>
+               2
+       </td><td>
+               1
+       </td><td>
+               4
+       </td>
+</tr><tr>
+       <td>
+               2H Sword
+       </td><td>
+               0
+       </td><td>
+               2d8+2
+       </td><td>
+               1
+       </td><td>
+               2
+       </td><td>
+               1
+       </td><td>
+               4
+       </td>
+</tr><tr>
+       <td>
+               Morning star
+       </td><td>
+               1d2+2
+       </td><td>
+               1d6+1
+       </td><td>
+               -1
+       </td><td>
+               1
+       </td><td>
+               2
+       </td><td>
+               3
+       </td>
+</tr><tr>
+       <td>
+               Morning star+2
+       </td><td>
+               1d2+4
+       </td><td>
+               1d6+3
+       </td><td>
+               2
+       </td><td>
+               1
+       </td><td>
+               2
+       </td><td>
+               3
+       </td>
+</tr><tr>
+       <td>
+               Halberd
+       </td><td>
+               1d3+1
+       </td><td>
+               2d8-2
+       </td><td>
+               1d2
+       </td><td>
+               2
+       </td><td>
+               2
+       </td><td>
+               4
+       </td>
+</tr><tr>
+       <td>
+               Staff
+       </td><td>
+               1d3
+       </td><td>
+               1d4
+       </td><td>
+               1d3
+       </td><td>
+               2
+       </td><td>
+               2
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Eldritch blade
+       </td><td>
+               2
+       </td><td>
+               2d8+5
+       </td><td>
+               +0
+       </td><td>
+               2
+       </td><td>
+               1
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Mystic sword
+       </td><td>
+               +3
+       </td><td>
+               1d10+5
+       </td><td>
+               +2
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               1
+       </td>
+</tr><tr>
+       <td>
+               Flaming sword
+       </td><td>
+               1d2
+       </td><td>
+               1d10+3
+       </td><td>
+               1d2
+       </td><td>
+               1
+       </td><td>
+               1
+       </td><td>
+               2
+       </td>
+</tr>
+</table>
+
+<a name="toc56"></a>
+<h3>
+Armor Stats
+</h3>
+<table>
+<tr class="header">
+       <td>
+               Name
+       </td><td>
+               To-Hit
+       </td><td>
+               Damage
+       </td><td>
+               Armor
+       </td><td>
+               To-Def
+       </td><td>
+               Weight
+       </td>
+</tr><tr>
+       <td>
+               Leather helm
+       </td><td>
+               -1
+       </td><td>
+               -
+       </td><td>
+               1d2
+       </td><td>
+               -
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               Leather helm+2
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               1d2+2
+       </td><td>
+               -
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               Leather helm+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               1d2+4
+       </td><td>
+               -
+       </td><td>
+               0
+       </td>
+</tr><tr>
+       <td>
+               chain coif
+       </td><td>
+               -1
+       </td><td>
+               -
+       </td><td>
+               1d3
+       </td><td>
+               -
+       </td><td>
+               1
+       </td>
+</tr><tr>
+       <td>
+               Chain coif+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               1d3+4
+       </td><td>
+               -
+       </td><td>
+               1
+       </td>
+</tr><tr>
+       <td>
+               iron helm
+       </td><td>
+               -1
+       </td><td>
+               -
+       </td><td>
+               1d4
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Iron helm+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               1d4+4
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               leather armor
+       </td><td>
+               -1
+       </td><td>
+               -
+       </td><td>
+               1d4
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Leather armor+2
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               1d4+2
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Leather armor+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               1d4+4
+       </td><td>
+               -
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               chain armor
+       </td><td>
+               -2
+       </td><td>
+               -
+       </td><td>
+               2d4
+       </td><td>
+               -
+       </td><td>
+               4
+       </td>
+</tr><tr>
+       <td>
+               Chain armor+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               2d4+4
+       </td><td>
+               -
+       </td><td>
+               4
+       </td>
+</tr><tr>
+       <td>
+               plate armor
+       </td><td>
+               -4
+       </td><td>
+               -
+       </td><td>
+               4d4
+       </td><td>
+               -
+       </td><td>
+               8
+       </td>
+</tr><tr>
+       <td>
+               Plate armor+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               4d4+4
+       </td><td>
+               -
+       </td><td>
+               8
+       </td>
+</tr><tr>
+       <td>
+               Small shield
+       </td><td>
+               -1
+       </td><td>
+               -
+       </td><td>
+               0
+       </td><td>
+               2
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Small shield+4
+       </td><td>
+               0
+       </td><td>
+               -
+       </td><td>
+               0
+       </td><td>
+               6
+       </td><td>
+               2
+       </td>
+</tr><tr>
+       <td>
+               Spiked shield
+       </td><td>
+               0
+       </td><td>
+               1d5
+       </td><td>
+               0
+       </td><td>
+               1
+       </td><td>
+               3
+       </td>
+</tr><tr>
+       <td>
+               Spiked helm
+       </td><td>
+               0
+       </td><td>
+               1d4
+       </td><td>
+               3
+       </td><td>
+               0
+       </td><td>
+               2
+       </td>
+</tr>  
+</table>
+
+<a name="toc57"></a>
+<h2>
+FOOTNOTES
+</h2>
+<p>
+<a name="f1"></a>
+[1] Alas, there isn't one. Yet.
+</p>
+<a name="f2"></a>
+<p>
+[2] I like to refer to it as a "kernel". This makes me feel like it is really
+    cool, and like I'm not a loser since Linus Torvalds and I are about the
+    same age and he works on a kernel, too.
+</p>
+<p>
+--gmcnutt (gmcnutt@cableone.net)
+</p>
\ No newline at end of file
diff --git a/doc/world_building/CVS/Entries b/doc/world_building/CVS/Entries
new file mode 100644 (file)
index 0000000..9b21877
--- /dev/null
@@ -0,0 +1,10 @@
+/advancement.rogue.txt/1.1/Thu Sep  2 05:52:22 2004//
+/advancement.warrior.txt/1.1/Thu Sep  2 05:52:22 2004//
+/advancement.wizard.txt/1.1/Thu Sep  2 05:52:22 2004//
+/advancement.wright.txt/1.1/Thu Sep  2 05:52:22 2004//
+/being_tile_media.txt/1.3/Thu Sep  2 05:52:22 2004//
+/music_loop_media.txt/1.2/Thu Sep  2 05:52:22 2004//
+/sound_sample_media.txt/1.3/Tue Jan 23 08:32:14 2007//
+/town_scale_tile_media.txt/1.2/Thu Sep  2 05:52:22 2004//
+/wilderness_scale_tile_media.txt/1.2/Thu Sep  2 05:52:22 2004//
+D
diff --git a/doc/world_building/CVS/Repository b/doc/world_building/CVS/Repository
new file mode 100644 (file)
index 0000000..90c5636
--- /dev/null
@@ -0,0 +1 @@
+nazghul/doc/world_building
diff --git a/doc/world_building/CVS/Root b/doc/world_building/CVS/Root
new file mode 100644 (file)
index 0000000..4d8737a
--- /dev/null
@@ -0,0 +1 @@
+:ext:gmcnutt@nazghul.cvs.sourceforge.net:/cvsroot/nazghul
diff --git a/doc/world_building/advancement.rogue.txt b/doc/world_building/advancement.rogue.txt
new file mode 100644 (file)
index 0000000..1b73949
--- /dev/null
@@ -0,0 +1,29 @@
+---------------------------------------------------------------------------
+Advancement Path: Rogue
+---------------------------------------------------------------------------
+Rogue Skills by Category
+------------------------
+
+Physical (swim, climb, jump, ...)
+
+Sensory (see, hear, evaluate foe, search, detect traps, ...)
+
+Stealth (overall, urban, wilderness, ...)
+
+Roguery (pick pockets, pick lock, disable mechanism, set trap, ...)
+
+Social (lie, detect lie, intimidate, bluff, seduce, haggle, ...)
+
+Rogue Combat (
+    rogue weapons (knife, sap, lasso, net, small crossbows, 
+                   shuriken, darts) 
+    critical strike, stunning blow, surprise strike,
+    feint/riposte, dodge/tumble, ...)
+
+
+
+
+
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/advancement.warrior.txt b/doc/world_building/advancement.warrior.txt
new file mode 100644 (file)
index 0000000..9851971
--- /dev/null
@@ -0,0 +1,8 @@
+---------------------------------------------------------------------------
+Advancement Path: Warrior
+---------------------------------------------------------------------------
+
+
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/advancement.wizard.txt b/doc/world_building/advancement.wizard.txt
new file mode 100644 (file)
index 0000000..b6636c8
--- /dev/null
@@ -0,0 +1,8 @@
+---------------------------------------------------------------------------
+Advancement Path: Wizard
+---------------------------------------------------------------------------
+
+
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/advancement.wright.txt b/doc/world_building/advancement.wright.txt
new file mode 100644 (file)
index 0000000..fd095a6
--- /dev/null
@@ -0,0 +1,49 @@
+---------------------------------------------------------------------------
+Character Advancement Path: Wright
+---------------------------------------------------------------------------
+
+Items/Objects created/gathered by Wright skills:
+
+Weapons
+Armor and worn items
+Tools
+Materials
+Alchemical goods
+Furniture
+Vehicles
+Structures (buildings, non-portable objects and tools)
+Public Works (terrain modifications)
+
+
+Materials
+---------
+Reagents
+  herbal (plants and parts thereof)
+  mineral (powders, stones, ...)
+  organic (animals and parts thereof)
+  essences (moonlight, abstract essences,
+            ordinary materials infused with essences)
+
+Food
+  plant
+  animal
+  other (honey, ...)
+
+Ores
+
+Fibers
+
+Wood
+
+Hides
+
+...
+
+
+---------------------------------------------------------------------------
+
+Pick the top 3 Wright skills for early implementation...
+
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/being_tile_media.txt b/doc/world_building/being_tile_media.txt
new file mode 100644 (file)
index 0000000..b52dd2d
--- /dev/null
@@ -0,0 +1,11 @@
+Being Sprites Wanted
+--------------------
+Troll (horns, unarmed or club/hammer)  -- exists in U4 and U5 tilesets
+Spider - Wolf Spider  -- exists in U4/U5 tileset
+Spider - Black Widow
+Deer
+
+Female Townsman  -- create by modifying townsman sprite?
+Cat (domestic)   -- create by modifying dog sprite?
+Sheep
+Goat
diff --git a/doc/world_building/music_loop_media.txt b/doc/world_building/music_loop_media.txt
new file mode 100644 (file)
index 0000000..60a11e9
--- /dev/null
@@ -0,0 +1,16 @@
+---------------------------------------------------------------------------
+Music and other Looped Sound Media
+---------------------------------------------------------------------------
+
+Bardic tune "He is brace Sir Robin..."
+
+Bach - "Tocatta En Fugue"
+Edvard Grieg (?) - "Hall of the Mountain King"
+
+
+
+
+
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/sound_sample_media.txt b/doc/world_building/sound_sample_media.txt
new file mode 100644 (file)
index 0000000..542c168
--- /dev/null
@@ -0,0 +1,233 @@
+---------------------------------------------------------------------------
+Non-Looped Sound Media
+---------------------------------------------------------------------------
+
+
+Music (loops, once-off)
+Atmospheric / environment sounds
+Utterances
+  Words
+    Runes
+    spell names
+    species names
+    target specifier names (ground, object, foe type, unseen foe, ...)
+  Non-verbal
+Other Sounds
+  UI
+    Command names
+  Action
+  Object
+  Movement
+  Combat
+
+
+
+Movement Sounds
+---------------
+1 per movement mode (including vehicles/riding)
+2 per terrain
+
+snd = movement_sound(terrain, mode)  ???
+
+Moongate sounds
+  open
+  close
+  enter
+  arrival / exit
+
+
+---------------------------------------------------------------------------
+Sounds for
+----------
+Change to <movement mode>
+  Walking
+  Stealth mode
+  Riding
+  Swimming
+  Sailing
+  Flying
+
+Change to
+  Combat Mode
+  Peace Mode
+
+Change to
+  Solo Mode
+  Follow Mode
+  Round-Robin mode
+
+Rendezvous
+  begin          "Let's go", "follow me"
+  end (success)
+  failed         "I'm stuck", "Wait for me!"
+
+Combat
+  Initiate combat
+  Victory
+  Character Fled
+  Party Fled
+
+UI Sounds
+  Cursor movement
+
+  list element up/down
+  list scrolling
+  list PgUp/PgDn
+  List Home/End
+
+  type a character (when entering text, such as when talking)
+  backspace
+
+  CANCEL action (Escape key)
+  select (character, item, coordinates, targeted being
+
+
+Command names
+  "Attack"
+  "Board" / "Disembark"
+    -- per vehicle, a board and disembark sound
+    "Mount" / "Dismount"
+    "Board <vehicle_name>" / "Disembark <vehicle_name>"
+  "Cast"
+  ...
+
+
+---------------------------------------------------------------------------
+Combat UI Sounds
+----------------
+hit armor vs flesh?
+
+Blunt, Edged, Piercing
+Melee, Thrown, Bow/Xbow, Boomerang, Sling
+
+Attacker
+  fumbles (various)
+  miss
+  miss (parried with weapon, blocked by shield, dodged blow)
+  hit (soaked, damaging, armor-defeating)
+  critical
+
+Defender
+  parry/block/dodge
+  suffer knockdown / knockback
+  suffer wound
+  suffer KO
+  suffer death
+
+Spellcasting
+  ...
+
+
+---------------------------------------------------------------------------
+Runes and Such
+--------------
+
+Ultima IV / V Runes
+-------------------
+An    - Negate
+Bet   - Small
+Corp  - Death / Undead
+Des   - Down
+Ex    - Freedom
+Flam  - Flame / Fire
+Grav  - Energy
+Hur   - Wind
+In    - Create
+Jux   - Trap
+Kal   - Invoke / Summon
+Lor   - Light
+Mani  - Life / Health
+Nox   - Poison
+Ort   - Magic
+Por   - Movement
+Quis  - Illusion
+Rel   - Control / Change
+Sanct - Protection
+Tym   - Time
+Uus   - Up
+Vas   - Great
+Wis   - Vision / Percieve
+Xen   - Creature / Being
+Ylem  - Earth
+Zu    - Sleep
+
+Jzeth - Ether
+Orax  - Water / Waves
+
+
+
+Ultima Virtues / Mantras / Dungeons / Power Words
+--------------------------------------------------------------
+Honesty      / Ahm  / Deceit   / Fallax
+Compassion   / Mu   / Depise   / Vilis
+Valor        / Ra   / Destard  / Inopia
+Sacrifice    / Cah  / Covetous / Avidus
+Justice      / Beh  / Wrong    / Malum
+Honor        / Summ / Shame    / Infama
+Spirituality / Om   / Hythloth / Ignavus
+Humility     / Lum  / Stygia   / Mul
+
+Truth   / Ver / Falsehood / Faulinei
+Love    / Amo / Hatred    / Astaroth
+Courage / Cor / Cowardice / Nosfentor
+
+Veramocor
+Infinity
+
+
+Ultima VI Gargoyle Virtues / Principles
+---------------------------------------
+Control
+Passion
+Diligence
+
+C   - Direction
+P   - Feeling
+D   - Persistence
+CP  - Balance
+PD  - Achievement
+CD  - Precision
+CPD - Order / Chaos
+    - Singularity
+
+
+Dungeon Master Runes
+--------------------
+Power
+-----
+Lo  - 1
+Um  - 2
+On  - 3
+Ee  - 4
+Pal - 5
+Mon - 6
+
+Elemental
+---------
+Ya  - Earth (stamina)
+Vi  - Water (health)
+Oh  - Air
+Ful - Fire
+Des - Negativity
+Zo  - Energy
+
+Form
+----
+Ven  - Poison
+Ew   - Elemental Creature
+Kath - Explosive / Shock
+Ir   - Motion
+Bro  - Support / Friendship
+Gor  - Destruction
+
+Class/Alignment
+---------------
+Ku   - Fighter (strength)
+Ros  - Ninja   (dexterity)
+Dain - Wizard  (wisdom)
+Neta - Priest  (vitality)
+Ra   - Order / Sun
+Sar  - Chaos / Darkness
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/town_scale_tile_media.txt b/doc/world_building/town_scale_tile_media.txt
new file mode 100644 (file)
index 0000000..9a37c35
--- /dev/null
@@ -0,0 +1,237 @@
+---------------------------------------------------------------------------
+Small-Scale Terrain and Tile Media Wanted
+---------------------------------------------------------------------------
+Terrain
+Terrain Features (static)
+  Furniture
+Terrain Features (mechanism-like)
+  Doors, gates, portcullis, drawbridge
+  well, forge, anvil, bellows
+Items
+  weapons, armor/wearable items, 
+  consumable/commodity items (food, drink, potions, oils, herbs, ...)
+  readable items, tools, reagents, musical instruments
+
+
+---------------------------------------------------------------------------
+Small-Scale Environments
+------------------------
+Outdoors
+Village / Urban
+Indoors
+Caves
+Subterranean Chambers (built areas, worked stone)
+Exotic locales
+
+
+Small-Scale Terrain
+-------------------
+Water
+  (shallow, deep, oceanic)
+  (stream, river, lake, ocean)
+  (clear, murky)
+  (still, rippling, flowing N,S,E,W, fast flowing N,S,E,W)
+  shoals, coral, sandbar, rocky shallows, mudbar
+  Other non-solid terrains:
+    lava
+    acid lake
+    boiling mud
+
+Land
+  Grass
+    TF: trails/roads, bridges, droos, portcullis, gates
+  Bog/march/swamp
+  badlands
+  tilled land, crops
+  desert
+  wasteland
+
+  flooring
+    bare earth
+    planks / deck / wooden floors
+    cobblestones
+    flagstones
+    stone/tile floors (various block/tile shapes, colors)
+    various colors / patterns of rugs
+
+  walls
+    (crude stone, brick, giant stone blocks)
+    (frame and plaster, wooden (logs, boards), tent walls)
+    (various colors of stone / plaster / paint)
+
+  Runic signs
+    Latin alphabet (A-Z)
+      -- Add (0-9), (a-z), (I,II,III,IV, V, X, L, C, M) ???
+    Runic alphabet
+
+  vegetation
+    brush, small trees, hedges
+    TF: single tree, fruiting tree, dead tree, stump
+
+
+Small-Scale Terrain Features
+----------------------------
+signs/walls (Terrain or Terrain Feature?)
+cobblestones
+brick paths
+carpets
+plank flooring
+roads
+bridges
+fences
+gates
+doors
+portcullis
+drawbridge
+signs
+gravestones
+standing stones
+boulders
+
+campfire
+firepit
+stove/oven
+fireplace
+forge
+anvil
+bellows
+winch
+hitching posts
+gears
+counterweights
+levers
+floor pressure plate
+
+Portal-type Mechanisms
+  trapdoor
+  ladders
+  stairs
+  moongates (blue, red, black, ...)
+
+tables
+chairs
+thrones
+privy / outhouse
+
+force fields (force waves like U3, colors like U4, ...)
+emplaced traps
+  blades
+  boulder
+  net
+  trap door
+
+organ
+waterclock
+horse trough
+cistern
+pipes
+
+levers
+folding counter sections (like in U6)
+fence stiles
+
+
+Semi-Portable Features
+----------------------
+round boulders
+giant ice cubes
+barrels
+chests
+crates
+potted plants
+chairs
+(smaller) tables
+beds
+dresser / cabinet
+(large) harp
+harpsichord
+mirror
+clock
+cannons
+
+
+Vehicles and Such
+-----------------
+skiff
+raft
+magic carpet
+saddle
+
+
+Porable Items
+-------------
+wall torches (lit, unlit, torch burnt out)
+keys
+
+
+chimney
+fire pit
+cauldron (empty / full, with / without bubbles)
+skeletons
+bones
+manacles
+pillories
+torture rack
+iron maiden
+
+many types of doors
+
+
+Missing Item Sprites
+--------------------
+Weapons
+  boomerang
+
+Armor / Worn Items
+  belts
+  normal clothing (male, female)
+
+Commodities / Consumable Items
+  meal / place setting (to put on tables)
+  more food sprites
+  more drink sprites
+  more single gems
+
+Tools
+  crystal ball
+  telescope (large)
+  spyglass / telescope (small)
+  mirror
+  tongs
+  scissors
+  sextant
+  theodolite
+  keys
+
+Readable Items
+  normal scrolls, books, tablets, maps
+
+Reagents
+  various powders, liquids, gases
+  body parts (heads, hand, feet, ears, hearts, skulls, bones,
+              scales, tails, features, ...)
+
+
+Various Laboratory Furniture (think: wizard's lab or mad scientist)
+----------------------------
+giant crystals
+huge runic stones, tablets
+stone slabs (for corpse / patient / victim)
+statues
+
+
+
+tapestries, paintings
+
+various colors of
+  walls
+  roads / cobblestone / floors
+  rugs
+
+non-stone walls
+  wooden
+  plaster
+  tent wall
+
+
+---------------------------------------------------------------------------
diff --git a/doc/world_building/wilderness_scale_tile_media.txt b/doc/world_building/wilderness_scale_tile_media.txt
new file mode 100644 (file)
index 0000000..04463ad
--- /dev/null
@@ -0,0 +1,138 @@
+---------------------------------------------------------------------------
+Large-Scale Terrain and Tile Media Wanted
+---------------------------------------------------------------------------
+
+Water Terrain Tiles
+-------------------
+Oceanic water
+Deep water
+Shallow water
+
+
+Differentiate water tiles as (river, lake, ocean)
+  - Direction of flow: N,S,E,W, rippling-in-place
+  - different shades/colors of water (clear, murky)
+
+Tidal Terrain is proposed
+  - Shard Tilt Tides
+  - Lunar Tides
+
+Streams (passable by walking, zoom-in contains a stream)
+
+ford
+rapids
+
+rocks / shoals
+sandbar
+mud bank
+reefs
+algae bloom
+kelp
+jellyfish
+fish spawning
+wave crests
+fog banks
+
+Light-emitting water terrain/features
+    coral
+    jellyfish
+    ...
+
+
+Other non-solid Terrains
+------------------------
+Acid Lake
+Boiling Mud
+Lava
+Astral Void
+Swirling Fog
+
+
+Land Terrain Tiles
+------------------
+Grasslands
+  - High Grass
+Fields
+Orchards
+Brush
+Forest
+Hills
+  - Forested Hills
+Mountains
+  - Forested Mountains
+Mountain Peaks
+  - Snow-covered peaks
+Swamp / Marsh / Fens / Bog
+  - Flooded Swamp
+  - Wooded Swamp (blocks LOS)
+Desert (depletes water rations)
+Tundra
+  - Many other terrain types covered in snow
+Wasteland / Blasted Ground
+Rocky Ground
+
+Badlands
+  - Mesas   -- Not for Haxima I, too much art required
+  - Rifts/Canyons
+  - Cliffs  -- Not for Haxima I, too much art required
+
+
+Light-emitting Terrain
+  magical woods
+  towns
+  some coral
+  jellyfish
+  lava
+  swamp glow
+
+
+Large-Scale Terrain Features
+----------------------------
+Roads  - Made with transparency, goes over most any terrain
+Trails - Made with transparency, goes over most any terrain
+Bridges
+Fords                    (terrain or terrain feature?)
+Piers / Ports / Landings (terrain or terrain feature?)
+Signs
+Markers / Monuments (many of these sprites are also used for sub-places)
+  - Standing Stone(s)
+  - Battlefield marker
+  - Ancient graveyard / battlefield
+  - Ancient ruins
+Fog Banks
+Walls (Hadrian's Wall, Great Wall of China, LCB)
+
+
+Portal Types
+------------
+Castle (major, minor, ...)
+Tower
+Town (walled)
+Village
+Ruins
+Hut
+Dungeon Entrance
+Cave Entrance
+Mine Entrance
+Transparent Portal (no visible sprite, no description shown)
+Moongate (blue, red, black, other colors)
+
+
+---------------------------------------------------------------------------
+What attributes Terrain / Terrain Features Have
+-----------------------------------------------
+- Display a sprite
+- Affect passability / movement by movement mode
+- Affect LOS
+- Provide illumination
+- Invoke an effect upon successful/failed movement
+- Act as a portal (auto-enter or no, directional or not)
+  - Portals can invoke a method, often used for confirmation of
+    entering the portal
+
+
+
+
+
+
+---------------------------------------------------------------------------
diff --git a/haxima.desktop b/haxima.desktop
new file mode 100644 (file)
index 0000000..abf77e6
--- /dev/null
@@ -0,0 +1,11 @@
+[Desktop Entry]
+Encoding=UTF-8
+Name=Haxima
+GenericName=Role Playing Game
+Comment=An old school role playing game
+Exec=haxima
+Icon=haxima.png
+Terminal=false
+Type=Application
+Categories=Application;Game;
+Version=1.002
diff --git a/icons/CVS/Entries b/icons/CVS/Entries
new file mode 100644 (file)
index 0000000..dc8fb22
--- /dev/null
@@ -0,0 +1,4 @@
+/haxima.ico/1.2/Fri Jan 26 22:42:48 2007//
+/haxima.png/1.2/Fri Jan 26 22:42:48 2007//
+/haxima.xcf/1.2/Fri Jan 26 22:42:48 2007//
+D
diff --git a/icons/CVS/Repository b/icons/CVS/Repository
new file mode 100644 (file)
index 0000000..2ddffbb
--- /dev/null
@@ -0,0 +1 @@
+nazghul/icons
diff --git a/icons/CVS/Root b/icons/CVS/Root
new file mode 100644 (file)
index 0000000..4d8737a
--- /dev/null
@@ -0,0 +1 @@
+:ext:gmcnutt@nazghul.cvs.sourceforge.net:/cvsroot/nazghul
diff --git a/icons/haxima.ico b/icons/haxima.ico
new file mode 100644 (file)
index 0000000..ca1068b
Binary files /dev/null and b/icons/haxima.ico differ
diff --git a/icons/haxima.png b/icons/haxima.png
new file mode 100644 (file)
index 0000000..428e292
Binary files /dev/null and b/icons/haxima.png differ
diff --git a/icons/haxima.xcf b/icons/haxima.xcf
new file mode 100644 (file)
index 0000000..3b4edec
Binary files /dev/null and b/icons/haxima.xcf differ
diff --git a/install-sh b/install-sh
new file mode 100644 (file)
index 0000000..6781b98
--- /dev/null
@@ -0,0 +1,520 @@
+#!/bin/sh
+# install - install a program, script, or datafile
+
+scriptversion=2009-04-28.21; # UTC
+
+# This originates from X11R5 (mit/util/scripts/install.sh), which was
+# later released in X11R6 (xc/config/util/install.sh) with the
+# following copyright and license.
+#
+# Copyright (C) 1994 X Consortium
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
+# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+# Except as contained in this notice, the name of the X Consortium shall not
+# be used in advertising or otherwise to promote the sale, use or other deal-
+# ings in this Software without prior written authorization from the X Consor-
+# tium.
+#
+#
+# FSF changes to this file are in the public domain.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch.
+
+nl='
+'
+IFS=" ""       $nl"
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit=${DOITPROG-}
+if test -z "$doit"; then
+  doit_exec=exec
+else
+  doit_exec=$doit
+fi
+
+# Put in absolute file names if you don't have them in your path;
+# or use environment vars.
+
+chgrpprog=${CHGRPPROG-chgrp}
+chmodprog=${CHMODPROG-chmod}
+chownprog=${CHOWNPROG-chown}
+cmpprog=${CMPPROG-cmp}
+cpprog=${CPPROG-cp}
+mkdirprog=${MKDIRPROG-mkdir}
+mvprog=${MVPROG-mv}
+rmprog=${RMPROG-rm}
+stripprog=${STRIPPROG-strip}
+
+posix_glob='?'
+initialize_posix_glob='
+  test "$posix_glob" != "?" || {
+    if (set -f) 2>/dev/null; then
+      posix_glob=
+    else
+      posix_glob=:
+    fi
+  }
+'
+
+posix_mkdir=
+
+# Desired mode of installed file.
+mode=0755
+
+chgrpcmd=
+chmodcmd=$chmodprog
+chowncmd=
+mvcmd=$mvprog
+rmcmd="$rmprog -f"
+stripcmd=
+
+src=
+dst=
+dir_arg=
+dst_arg=
+
+copy_on_change=false
+no_target_directory=
+
+usage="\
+Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
+   or: $0 [OPTION]... SRCFILES... DIRECTORY
+   or: $0 [OPTION]... -t DIRECTORY SRCFILES...
+   or: $0 [OPTION]... -d DIRECTORIES...
+
+In the 1st form, copy SRCFILE to DSTFILE.
+In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
+In the 4th, create DIRECTORIES.
+
+Options:
+     --help     display this help and exit.
+     --version  display version info and exit.
+
+  -c            (ignored)
+  -C            install only if different (preserve the last data modification time)
+  -d            create directories instead of installing files.
+  -g GROUP      $chgrpprog installed files to GROUP.
+  -m MODE       $chmodprog installed files to MODE.
+  -o USER       $chownprog installed files to USER.
+  -s            $stripprog installed files.
+  -t DIRECTORY  install into DIRECTORY.
+  -T            report an error if DSTFILE is a directory.
+
+Environment variables override the default commands:
+  CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
+  RMPROG STRIPPROG
+"
+
+while test $# -ne 0; do
+  case $1 in
+    -c) ;;
+
+    -C) copy_on_change=true;;
+
+    -d) dir_arg=true;;
+
+    -g) chgrpcmd="$chgrpprog $2"
+       shift;;
+
+    --help) echo "$usage"; exit $?;;
+
+    -m) mode=$2
+       case $mode in
+         *' '* | *'    '* | *'
+'*       | *'*'* | *'?'* | *'['*)
+           echo "$0: invalid mode: $mode" >&2
+           exit 1;;
+       esac
+       shift;;
+
+    -o) chowncmd="$chownprog $2"
+       shift;;
+
+    -s) stripcmd=$stripprog;;
+
+    -t) dst_arg=$2
+       shift;;
+
+    -T) no_target_directory=true;;
+
+    --version) echo "$0 $scriptversion"; exit $?;;
+
+    --)        shift
+       break;;
+
+    -*)        echo "$0: invalid option: $1" >&2
+       exit 1;;
+
+    *)  break;;
+  esac
+  shift
+done
+
+if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
+  # When -d is used, all remaining arguments are directories to create.
+  # When -t is used, the destination is already specified.
+  # Otherwise, the last argument is the destination.  Remove it from $@.
+  for arg
+  do
+    if test -n "$dst_arg"; then
+      # $@ is not empty: it contains at least $arg.
+      set fnord "$@" "$dst_arg"
+      shift # fnord
+    fi
+    shift # arg
+    dst_arg=$arg
+  done
+fi
+
+if test $# -eq 0; then
+  if test -z "$dir_arg"; then
+    echo "$0: no input file specified." >&2
+    exit 1
+  fi
+  # It's OK to call `install-sh -d' without argument.
+  # This can happen when creating conditional directories.
+  exit 0
+fi
+
+if test -z "$dir_arg"; then
+  trap '(exit $?); exit' 1 2 13 15
+
+  # Set umask so as not to create temps with too-generous modes.
+  # However, 'strip' requires both read and write access to temps.
+  case $mode in
+    # Optimize common cases.
+    *644) cp_umask=133;;
+    *755) cp_umask=22;;
+
+    *[0-7])
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw='% 200'
+      fi
+      cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
+    *)
+      if test -z "$stripcmd"; then
+       u_plus_rw=
+      else
+       u_plus_rw=,u+rw
+      fi
+      cp_umask=$mode$u_plus_rw;;
+  esac
+fi
+
+for src
+do
+  # Protect names starting with `-'.
+  case $src in
+    -*) src=./$src;;
+  esac
+
+  if test -n "$dir_arg"; then
+    dst=$src
+    dstdir=$dst
+    test -d "$dstdir"
+    dstdir_status=$?
+  else
+
+    # Waiting for this to be detected by the "$cpprog $src $dsttmp" command
+    # might cause directories to be created, which would be especially bad
+    # if $src (and thus $dsttmp) contains '*'.
+    if test ! -f "$src" && test ! -d "$src"; then
+      echo "$0: $src does not exist." >&2
+      exit 1
+    fi
+
+    if test -z "$dst_arg"; then
+      echo "$0: no destination specified." >&2
+      exit 1
+    fi
+
+    dst=$dst_arg
+    # Protect names starting with `-'.
+    case $dst in
+      -*) dst=./$dst;;
+    esac
+
+    # If destination is a directory, append the input filename; won't work
+    # if double slashes aren't ignored.
+    if test -d "$dst"; then
+      if test -n "$no_target_directory"; then
+       echo "$0: $dst_arg: Is a directory" >&2
+       exit 1
+      fi
+      dstdir=$dst
+      dst=$dstdir/`basename "$src"`
+      dstdir_status=0
+    else
+      # Prefer dirname, but fall back on a substitute if dirname fails.
+      dstdir=`
+       (dirname "$dst") 2>/dev/null ||
+       expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+            X"$dst" : 'X\(//\)[^/]' \| \
+            X"$dst" : 'X\(//\)$' \| \
+            X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
+       echo X"$dst" |
+           sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)[^/].*/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\/\)$/{
+                  s//\1/
+                  q
+                }
+                /^X\(\/\).*/{
+                  s//\1/
+                  q
+                }
+                s/.*/./; q'
+      `
+
+      test -d "$dstdir"
+      dstdir_status=$?
+    fi
+  fi
+
+  obsolete_mkdir_used=false
+
+  if test $dstdir_status != 0; then
+    case $posix_mkdir in
+      '')
+       # Create intermediate dirs using mode 755 as modified by the umask.
+       # This is like FreeBSD 'install' as of 1997-10-28.
+       umask=`umask`
+       case $stripcmd.$umask in
+         # Optimize common cases.
+         *[2367][2367]) mkdir_umask=$umask;;
+         .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
+
+         *[0-7])
+           mkdir_umask=`expr $umask + 22 \
+             - $umask % 100 % 40 + $umask % 20 \
+             - $umask % 10 % 4 + $umask % 2
+           `;;
+         *) mkdir_umask=$umask,go-w;;
+       esac
+
+       # With -d, create the new directory with the user-specified mode.
+       # Otherwise, rely on $mkdir_umask.
+       if test -n "$dir_arg"; then
+         mkdir_mode=-m$mode
+       else
+         mkdir_mode=
+       fi
+
+       posix_mkdir=false
+       case $umask in
+         *[123567][0-7][0-7])
+           # POSIX mkdir -p sets u+wx bits regardless of umask, which
+           # is incompatible with FreeBSD 'install' when (umask & 300) != 0.
+           ;;
+         *)
+           tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
+           trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
+
+           if (umask $mkdir_umask &&
+               exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
+           then
+             if test -z "$dir_arg" || {
+                  # Check for POSIX incompatibilities with -m.
+                  # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
+                  # other-writeable bit of parent directory when it shouldn't.
+                  # FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
+                  ls_ld_tmpdir=`ls -ld "$tmpdir"`
+                  case $ls_ld_tmpdir in
+                    d????-?r-*) different_mode=700;;
+                    d????-?--*) different_mode=755;;
+                    *) false;;
+                  esac &&
+                  $mkdirprog -m$different_mode -p -- "$tmpdir" && {
+                    ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
+                    test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
+                  }
+                }
+             then posix_mkdir=:
+             fi
+             rmdir "$tmpdir/d" "$tmpdir"
+           else
+             # Remove any dirs left behind by ancient mkdir implementations.
+             rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
+           fi
+           trap '' 0;;
+       esac;;
+    esac
+
+    if
+      $posix_mkdir && (
+       umask $mkdir_umask &&
+       $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
+      )
+    then :
+    else
+
+      # The umask is ridiculous, or mkdir does not conform to POSIX,
+      # or it failed possibly due to a race condition.  Create the
+      # directory the slow way, step by step, checking for races as we go.
+
+      case $dstdir in
+       /*) prefix='/';;
+       -*) prefix='./';;
+       *)  prefix='';;
+      esac
+
+      eval "$initialize_posix_glob"
+
+      oIFS=$IFS
+      IFS=/
+      $posix_glob set -f
+      set fnord $dstdir
+      shift
+      $posix_glob set +f
+      IFS=$oIFS
+
+      prefixes=
+
+      for d
+      do
+       test -z "$d" && continue
+
+       prefix=$prefix$d
+       if test -d "$prefix"; then
+         prefixes=
+       else
+         if $posix_mkdir; then
+           (umask=$mkdir_umask &&
+            $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
+           # Don't fail if two instances are running concurrently.
+           test -d "$prefix" || exit 1
+         else
+           case $prefix in
+             *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
+             *) qprefix=$prefix;;
+           esac
+           prefixes="$prefixes '$qprefix'"
+         fi
+       fi
+       prefix=$prefix/
+      done
+
+      if test -n "$prefixes"; then
+       # Don't fail if two instances are running concurrently.
+       (umask $mkdir_umask &&
+        eval "\$doit_exec \$mkdirprog $prefixes") ||
+         test -d "$dstdir" || exit 1
+       obsolete_mkdir_used=true
+      fi
+    fi
+  fi
+
+  if test -n "$dir_arg"; then
+    { test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
+    { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
+      test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
+  else
+
+    # Make a couple of temp file names in the proper directory.
+    dsttmp=$dstdir/_inst.$$_
+    rmtmp=$dstdir/_rm.$$_
+
+    # Trap to clean up those temp files at exit.
+    trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
+
+    # Copy the file name to the temp name.
+    (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
+
+    # and set any options; do chmod last to preserve setuid bits.
+    #
+    # If any of these fail, we abort the whole thing.  If we want to
+    # ignore errors from any of these, just make sure not to ignore
+    # errors from the above "$doit $cpprog $src $dsttmp" command.
+    #
+    { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
+    { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
+    { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
+    { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
+
+    # If -C, don't bother to copy if it wouldn't change the file.
+    if $copy_on_change &&
+       old=`LC_ALL=C ls -dlL "$dst"    2>/dev/null` &&
+       new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
+
+       eval "$initialize_posix_glob" &&
+       $posix_glob set -f &&
+       set X $old && old=:$2:$4:$5:$6 &&
+       set X $new && new=:$2:$4:$5:$6 &&
+       $posix_glob set +f &&
+
+       test "$old" = "$new" &&
+       $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
+    then
+      rm -f "$dsttmp"
+    else
+      # Rename the file to the real destination.
+      $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
+
+      # The rename failed, perhaps because mv can't rename something else
+      # to itself, or perhaps because mv is so ancient that it does not
+      # support -f.
+      {
+       # Now remove or move aside any old file at destination location.
+       # We try this two ways since rm can't unlink itself on some
+       # systems and the destination file might be busy for other
+       # reasons.  In this case, the final cleanup might fail but the new
+       # file should still install successfully.
+       {
+         test ! -f "$dst" ||
+         $doit $rmcmd -f "$dst" 2>/dev/null ||
+         { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
+           { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
+         } ||
+         { echo "$0: cannot unlink or rename $dst" >&2
+           (exit 1); exit 1
+         }
+       } &&
+
+       # Now rename the file to the real destination.
+       $doit $mvcmd "$dsttmp" "$dst"
+      }
+    fi || exit 1
+
+    trap '' 0
+  fi
+done
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/m4/ChangeLog b/m4/ChangeLog
new file mode 100644 (file)
index 0000000..2847b9e
--- /dev/null
@@ -0,0 +1,21 @@
+2002-10-06  gettextize  <bug-gnu-gettext@gnu.org>
+
+       * codeset.m4: New file, from gettext-0.11.5.
+       * gettext.m4: New file, from gettext-0.11.5.
+       * glibc21.m4: New file, from gettext-0.11.5.
+       * iconv.m4: New file, from gettext-0.11.5.
+       * intdiv0.m4: New file, from gettext-0.11.5.
+       * inttypes.m4: New file, from gettext-0.11.5.
+       * inttypes_h.m4: New file, from gettext-0.11.5.
+       * inttypes-pri.m4: New file, from gettext-0.11.5.
+       * isc-posix.m4: New file, from gettext-0.11.5.
+       * lcmessage.m4: New file, from gettext-0.11.5.
+       * lib-ld.m4: New file, from gettext-0.11.5.
+       * lib-link.m4: New file, from gettext-0.11.5.
+       * lib-prefix.m4: New file, from gettext-0.11.5.
+       * progtest.m4: New file, from gettext-0.11.5.
+       * stdint_h.m4: New file, from gettext-0.11.5.
+       * uintmax_t.m4: New file, from gettext-0.11.5.
+       * ulonglong.m4: New file, from gettext-0.11.5.
+       * Makefile.am: New file.
+
diff --git a/m4/Makefile.am b/m4/Makefile.am
new file mode 100644 (file)
index 0000000..1c938cb
--- /dev/null
@@ -0,0 +1,2 @@
+EXTRA_DIST = sdl.m4 acinclude.m4
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/m4/Makefile.in b/m4/Makefile.in
new file mode 100644 (file)
index 0000000..cd69d0f
--- /dev/null
@@ -0,0 +1,340 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = m4
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ChangeLog
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = sdl.m4 acinclude.m4
+MAINTAINERCLEANFILES = Makefile.in
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu m4/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+       distclean-generic distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       maintainer-clean maintainer-clean-generic mostlyclean \
+       mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/m4/acinclude.m4 b/m4/acinclude.m4
new file mode 100644 (file)
index 0000000..90725dd
--- /dev/null
@@ -0,0 +1,13 @@
+AC_DEFUN([PETI_ENABLED_DYNAMIC_LINKING], [
+AC_MSG_CHECKING(whether what binaries we shall create)
+AC_ARG_ENABLE(dynamic-link,
+[  --enable-dynamic-link   Create dynamically linked binaries (default)],
+if test "$enableval" = "yes"; then
+    AC_MSG_RESULT(dynamically linked)
+else
+    LDFLAGS="$LDFLAGS -static"
+    AC_MSG_RESULT(statically linked)
+fi,
+AC_MSG_RESULT(dynamically linked))
+])
+
diff --git a/m4/sdl.m4 b/m4/sdl.m4
new file mode 100644 (file)
index 0000000..5105810
--- /dev/null
+++ b/m4/sdl.m4
@@ -0,0 +1,175 @@
+# Configure paths for SDL
+# Sam Lantinga 9/21/99
+# stolen from Manish Singh
+# stolen back from Frank Belew
+# stolen from Manish Singh
+# Shamelessly stolen from Owen Taylor
+
+dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS
+dnl
+AC_DEFUN([AM_PATH_SDL],
+[dnl 
+dnl Get the cflags and libraries from the sdl-config script
+dnl
+AC_ARG_WITH(sdl-prefix,[  --with-sdl-prefix=PFX   Prefix where SDL is installed (optional)],
+            sdl_prefix="$withval", sdl_prefix="")
+AC_ARG_WITH(sdl-exec-prefix,[  --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)],
+            sdl_exec_prefix="$withval", sdl_exec_prefix="")
+AC_ARG_ENABLE(sdltest, [  --disable-sdltest       Do not try to compile and run a test SDL program],
+                   , enable_sdltest=yes)
+
+  if test x$sdl_exec_prefix != x ; then
+     sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix"
+     if test x${SDL_CONFIG+set} != xset ; then
+        SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config
+     fi
+  fi
+  if test x$sdl_prefix != x ; then
+     sdl_args="$sdl_args --prefix=$sdl_prefix"
+     if test x${SDL_CONFIG+set} != xset ; then
+        SDL_CONFIG=$sdl_prefix/bin/sdl-config
+     fi
+  fi
+
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  PATH="$prefix/bin:$prefix/usr/bin:$PATH"
+  AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH])
+  min_sdl_version=ifelse([$1], ,0.11.0,$1)
+  AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
+  no_sdl=""
+  if test "$SDL_CONFIG" = "no" ; then
+    no_sdl=yes
+  else
+    SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags`
+    SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs`
+
+    sdl_major_version=`$SDL_CONFIG $sdl_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_sdltest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $SDL_CFLAGS"
+      LIBS="$LIBS $SDL_LIBS"
+dnl
+dnl Now check if the installed SDL is sufficiently new. (Also sanity
+dnl checks the results of sdl-config to some extent
+dnl
+      rm -f conf.sdltest
+      AC_TRY_RUN([
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "SDL.h"
+
+char*
+my_strdup (char *str)
+{
+  char *new_str;
+  
+  if (str)
+    {
+      new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char));
+      strcpy (new_str, str);
+    }
+  else
+    new_str = NULL;
+  
+  return new_str;
+}
+
+int main (int argc, char *argv[])
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  /* This hangs on some systems (?)
+  system ("touch conf.sdltest");
+  */
+  { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); }
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = my_strdup("$min_sdl_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_sdl_version");
+     exit(1);
+   }
+
+   if (($sdl_major_version > major) ||
+      (($sdl_major_version == major) && ($sdl_minor_version > minor)) ||
+      (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro)))
+    {
+      return 0;
+    }
+  else
+    {
+      printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version);
+      printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro);
+      printf("*** best to upgrade to the required version.\n");
+      printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n");
+      printf("*** to point to the correct copy of sdl-config, and remove the file\n");
+      printf("*** config.cache before re-running configure\n");
+      return 1;
+    }
+}
+
+],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_sdl" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$SDL_CONFIG" = "no" ; then
+       echo "*** The sdl-config script installed by SDL could not be found"
+       echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the SDL_CONFIG environment variable to the"
+       echo "*** full path to sdl-config."
+     else
+       if test -f conf.sdltest ; then
+        :
+       else
+          echo "*** Could not run SDL test program, checking why..."
+          CFLAGS="$CFLAGS $SDL_CFLAGS"
+          LIBS="$LIBS $SDL_LIBS"
+          AC_TRY_LINK([
+#include <stdio.h>
+#include "SDL.h"
+
+int main(int argc, char *argv[])
+{ return 0; }
+#undef  main
+#define main K_and_R_C_main
+],      [ return 0; ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding SDL or finding the wrong"
+          echo "*** version of SDL. If it is not finding SDL, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+         echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means SDL was incorrectly installed"
+          echo "*** or that you have moved SDL since it was installed. In the latter case, you"
+          echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     SDL_CFLAGS=""
+     SDL_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(SDL_CFLAGS)
+  AC_SUBST(SDL_LIBS)
+  rm -f conf.sdltest
+])
diff --git a/missing b/missing
new file mode 100644 (file)
index 0000000..28055d2
--- /dev/null
+++ b/missing
@@ -0,0 +1,376 @@
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+
+scriptversion=2009-04-28.21; # UTC
+
+# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006,
+# 2008, 2009 Free Software Foundation, Inc.
+# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+if test $# -eq 0; then
+  echo 1>&2 "Try \`$0 --help' for more information"
+  exit 1
+fi
+
+run=:
+sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p'
+sed_minuso='s/.* -o \([^ ]*\).*/\1/p'
+
+# In the cases where this matters, `missing' is being run in the
+# srcdir already.
+if test -f configure.ac; then
+  configure_ac=configure.ac
+else
+  configure_ac=configure.in
+fi
+
+msg="missing on your system"
+
+case $1 in
+--run)
+  # Try to run requested program, and just exit if it succeeds.
+  run=
+  shift
+  "$@" && exit 0
+  # Exit code 63 means version mismatch.  This often happens
+  # when the user try to use an ancient version of a tool on
+  # a file that requires a minimum version.  In this case we
+  # we should proceed has if the program had been absent, or
+  # if --run hadn't been passed.
+  if test $? = 63; then
+    run=:
+    msg="probably too old"
+  fi
+  ;;
+
+  -h|--h|--he|--hel|--help)
+    echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+  -h, --help      display this help and exit
+  -v, --version   output version information and exit
+  --run           try to run the given command, and emulate it if it fails
+
+Supported PROGRAM values:
+  aclocal      touch file \`aclocal.m4'
+  autoconf     touch file \`configure'
+  autoheader   touch file \`config.h.in'
+  autom4te     touch the output file, or create a stub one
+  automake     touch all \`Makefile.in' files
+  bison        create \`y.tab.[ch]', if possible, from existing .[ch]
+  flex         create \`lex.yy.c', if possible, from existing .c
+  help2man     touch the output file
+  lex          create \`lex.yy.c', if possible, from existing .c
+  makeinfo     touch the output file
+  tar          try tar, gnutar, gtar, then tar without non-portable flags
+  yacc         create \`y.tab.[ch]', if possible, from existing .[ch]
+
+Version suffixes to PROGRAM as well as the prefixes \`gnu-', \`gnu', and
+\`g' are ignored when checking the name.
+
+Send bug reports to <bug-automake@gnu.org>."
+    exit $?
+    ;;
+
+  -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+    echo "missing $scriptversion (GNU Automake)"
+    exit $?
+    ;;
+
+  -*)
+    echo 1>&2 "$0: Unknown \`$1' option"
+    echo 1>&2 "Try \`$0 --help' for more information"
+    exit 1
+    ;;
+
+esac
+
+# normalize program name to check for.
+program=`echo "$1" | sed '
+  s/^gnu-//; t
+  s/^gnu//; t
+  s/^g//; t'`
+
+# Now exit if we have it, but it failed.  Also exit now if we
+# don't have it and --version was passed (most likely to detect
+# the program).  This is about non-GNU programs, so use $1 not
+# $program.
+case $1 in
+  lex*|yacc*)
+    # Not GNU programs, they don't have --version.
+    ;;
+
+  tar*)
+    if test -n "$run"; then
+       echo 1>&2 "ERROR: \`tar' requires --run"
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       exit 1
+    fi
+    ;;
+
+  *)
+    if test -z "$run" && ($1 --version) > /dev/null 2>&1; then
+       # We have it, but it failed.
+       exit 1
+    elif test "x$2" = "x--version" || test "x$2" = "x--help"; then
+       # Could not run --version or --help.  This is probably someone
+       # running `$TOOL --version' or `$TOOL --help' to check whether
+       # $TOOL exists and not knowing $TOOL uses missing.
+       exit 1
+    fi
+    ;;
+esac
+
+# If it does not exist, or fails to run (possibly an outdated version),
+# try to emulate it.
+case $program in
+  aclocal*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acinclude.m4' or \`${configure_ac}'.  You might want
+         to install the \`Automake' and \`Perl' packages.  Grab them from
+         any GNU archive site."
+    touch aclocal.m4
+    ;;
+
+  autoconf*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`${configure_ac}'.  You might want to install the
+         \`Autoconf' and \`GNU m4' packages.  Grab them from any GNU
+         archive site."
+    touch configure
+    ;;
+
+  autoheader*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`acconfig.h' or \`${configure_ac}'.  You might want
+         to install the \`Autoconf' and \`GNU m4' packages.  Grab them
+         from any GNU archive site."
+    files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}`
+    test -z "$files" && files="config.h"
+    touch_files=
+    for f in $files; do
+      case $f in
+      *:*) touch_files="$touch_files "`echo "$f" |
+                                      sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+      *) touch_files="$touch_files $f.in";;
+      esac
+    done
+    touch $touch_files
+    ;;
+
+  automake*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'.
+         You might want to install the \`Automake' and \`Perl' packages.
+         Grab them from any GNU archive site."
+    find . -type f -name Makefile.am -print |
+          sed 's/\.am$/.in/' |
+          while read f; do touch "$f"; done
+    ;;
+
+  autom4te*)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, but is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.
+         You can get \`$1' as part of \`Autoconf' from any GNU
+         archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+       touch $file
+    else
+       test -z "$file" || exec >$file
+       echo "#! /bin/sh"
+       echo "# Created by GNU Automake missing as a replacement of"
+       echo "#  $ $@"
+       echo "exit 0"
+       chmod +x $file
+       exit 1
+    fi
+    ;;
+
+  bison*|yacc*)
+    echo 1>&2 "\
+WARNING: \`$1' $msg.  You should only need it if
+         you modified a \`.y' file.  You may need the \`Bison' package
+         in order for those modifications to take effect.  You can get
+         \`Bison' from any GNU archive site."
+    rm -f y.tab.c y.tab.h
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+       case $LASTARG in
+       *.y)
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+           if test -f "$SRCFILE"; then
+                cp "$SRCFILE" y.tab.c
+           fi
+           SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+           if test -f "$SRCFILE"; then
+                cp "$SRCFILE" y.tab.h
+           fi
+         ;;
+       esac
+    fi
+    if test ! -f y.tab.h; then
+       echo >y.tab.h
+    fi
+    if test ! -f y.tab.c; then
+       echo 'main() { return 0; }' >y.tab.c
+    fi
+    ;;
+
+  lex*|flex*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.l' file.  You may need the \`Flex' package
+         in order for those modifications to take effect.  You can get
+         \`Flex' from any GNU archive site."
+    rm -f lex.yy.c
+    if test $# -ne 1; then
+        eval LASTARG="\${$#}"
+       case $LASTARG in
+       *.l)
+           SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+           if test -f "$SRCFILE"; then
+                cp "$SRCFILE" lex.yy.c
+           fi
+         ;;
+       esac
+    fi
+    if test ! -f lex.yy.c; then
+       echo 'main() { return 0; }' >lex.yy.c
+    fi
+    ;;
+
+  help2man*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+        you modified a dependency of a manual page.  You may need the
+        \`Help2man' package in order for those modifications to take
+        effect.  You can get \`Help2man' from any GNU archive site."
+
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -f "$file"; then
+       touch $file
+    else
+       test -z "$file" || exec >$file
+       echo ".ab help2man is required to generate this page"
+       exit $?
+    fi
+    ;;
+
+  makeinfo*)
+    echo 1>&2 "\
+WARNING: \`$1' is $msg.  You should only need it if
+         you modified a \`.texi' or \`.texinfo' file, or any other file
+         indirectly affecting the aspect of the manual.  The spurious
+         call might also be the consequence of using a buggy \`make' (AIX,
+         DU, IRIX).  You might want to install the \`Texinfo' package or
+         the \`GNU make' package.  Grab either from any GNU archive site."
+    # The file to touch is that specified with -o ...
+    file=`echo "$*" | sed -n "$sed_output"`
+    test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"`
+    if test -z "$file"; then
+      # ... or it is the one specified with @setfilename ...
+      infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+      file=`sed -n '
+       /^@setfilename/{
+         s/.* \([^ ]*\) *$/\1/
+         p
+         q
+       }' $infile`
+      # ... or it is derived from the source name (dir/f.texi becomes f.info)
+      test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info
+    fi
+    # If the file does not exist, the user really needs makeinfo;
+    # let's fail without touching anything.
+    test -f $file || exit 1
+    touch $file
+    ;;
+
+  tar*)
+    shift
+
+    # We have already tried tar in the generic part.
+    # Look for gnutar/gtar before invocation to avoid ugly error
+    # messages.
+    if (gnutar --version > /dev/null 2>&1); then
+       gnutar "$@" && exit 0
+    fi
+    if (gtar --version > /dev/null 2>&1); then
+       gtar "$@" && exit 0
+    fi
+    firstarg="$1"
+    if shift; then
+       case $firstarg in
+       *o*)
+           firstarg=`echo "$firstarg" | sed s/o//`
+           tar "$firstarg" "$@" && exit 0
+           ;;
+       esac
+       case $firstarg in
+       *h*)
+           firstarg=`echo "$firstarg" | sed s/h//`
+           tar "$firstarg" "$@" && exit 0
+           ;;
+       esac
+    fi
+
+    echo 1>&2 "\
+WARNING: I can't seem to be able to run \`tar' with the given arguments.
+         You may want to install GNU tar or Free paxutils, or check the
+         command line arguments."
+    exit 1
+    ;;
+
+  *)
+    echo 1>&2 "\
+WARNING: \`$1' is needed, and is $msg.
+         You might have modified some files without having the
+         proper tools for further handling them.  Check the \`README' file,
+         it often tells you about the needed prerequisites for installing
+         this package.  You may also peek at any GNU archive site, in case
+         some other package would contain this missing \`$1' program."
+    exit 1
+    ;;
+esac
+
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-time-zone: "UTC"
+# time-stamp-end: "; # UTC"
+# End:
diff --git a/src/Arms.cpp b/src/Arms.cpp
new file mode 100644 (file)
index 0000000..e9c91bf
--- /dev/null
@@ -0,0 +1,389 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include <assert.h>
+#include <string.h>
+
+#include "Arms.h"
+#include "character.h"
+#include "dice.h"
+#include "screen.h"
+#include "sprite.h"
+#include "map.h"
+#include "place.h"
+#include "Missile.h"
+#include "sound.h"
+#include "player.h"
+#include "log.h"
+
+ArmsType::ArmsType(const char *tag, const char *name, struct sprite *sprite,
+                       int slotMask,
+                       char *to_hit_dice,
+                       char *to_defend_dice,
+                       int numHands,
+                       int range,
+                       int weight,
+                       char *damage_dice,
+                       char *armor_dice,
+                       int reqActPts,
+                  int AP_mod,
+                       bool thrown,
+                       bool ubiquitousAmmo,
+                       sound_t *fireSound,
+                       class MissileType *missileType,
+                       class ObjectType *ammo_type,
+                       int strAttackMod,
+                       int dexAttackMod,
+                       int charDamageMod,
+                       float charAvoidMod,
+                       bool isBeam
+                       )
+                       : ObjectType(tag, name, sprite, item_layer),
+                               slotMask(slotMask),
+                               numHands(numHands),
+                               range(range),
+                               weight(weight),
+                               thrown(thrown),
+                               ubiquitousAmmo(ubiquitousAmmo)
+{
+       toHitDice = strdup(to_hit_dice);
+       toDefendDice = strdup(to_defend_dice);
+       damageDice = strdup(damage_dice);
+       armorDice = strdup(armor_dice);
+       assert(toHitDice && toDefendDice && damageDice && armorDice);
+       this->fire_sound = fireSound;
+
+       if (missileType)
+       {
+               missile = new Missile(missileType);
+               assert(missile);
+       } else {
+               missile = NULL;
+       }
+       
+       ammoType = ammo_type;
+       
+       if (thrown)
+       {
+               setAmmoType(this);
+       }
+       
+       str_attack_mod = strAttackMod;
+       dex_attack_mod = dexAttackMod;
+       char_damage_mod = charDamageMod;
+       char_avoid_mod = charAvoidMod;
+       
+       required_action_points = reqActPts;
+       modifier_to_AP_of_user = AP_mod;
+       beam = isBeam;
+}
+
+ArmsType::ArmsType()
+{
+        // Don't ever expect to call this. Defining it to override the default
+        // one c++ automatically creates.
+        assert(false);
+
+        missile        = NULL;
+        ammoType                 = NULL;
+        thrown         = false;
+        weight         = 0;
+        ubiquitousAmmo = false;
+        layer          = item_layer;
+        fire_sound     = NULL_SOUND;
+        required_action_points = 1;
+       modifier_to_AP_of_user = 0;
+}
+
+ArmsType::~ArmsType()
+{
+       if (missile != NULL)
+               delete missile;
+       if (toHitDice)
+              free(toHitDice);
+       if (toDefendDice)
+              free(toDefendDice);
+       if (damageDice)
+              free(damageDice);
+       if (armorDice)
+              free(armorDice);
+}
+
+bool ArmsType::isType(int classID) 
+{
+        if (classID == ARMS_TYPE_ID)
+                return true;
+        return ObjectType::isType(classID);
+}
+
+int ArmsType::getType() 
+{
+        return ARMS_TYPE_ID;
+}
+
+class MissileType *ArmsType::getMissileType()
+{
+       if (missile == NULL)
+               return NULL;
+       return (class MissileType *) missile->getObjectType();
+}
+
+void ArmsType::setMissileType(class MissileType * missileType)
+{
+       if (missile != NULL) {
+               delete missile;
+               missile = NULL;
+       }
+
+       if (missileType == NULL)
+               return;
+
+       missile = new Missile(missileType);
+}
+
+class ObjectType *ArmsType::getAmmoType()
+{
+       return ammoType;
+}
+
+void ArmsType::setAmmoType(class ObjectType * ammo_type)
+{
+       ammoType = ammo_type;
+}
+
+bool ArmsType::isMissileWeapon()
+{
+       return (missile != NULL && !thrown);
+}
+
+bool ArmsType::isBeam()
+{
+       return beam;
+}
+
+/*
+       triggers a hit-loc ifc event if appropriate for either weapon or missile
+*/
+void ArmsType::fireHitLoc(Object *attacker, Object *target, struct place *place, int x, int y, int dam)
+{
+       if (isMissileWeapon() || isThrownWeapon())
+       {
+               missile->fireHitLoc(attacker, target, place, x, y, dam);
+       }
+       if (canHitLocation())
+               hitLocation(NULL, attacker, target, place, x, y, dam);  
+}
+
+/*
+       Fires a missile at a specific target, returns true if it reaches the target's location
+       updates misx and misy to be the location the missile reaches.
+*/
+bool ArmsType::fire(class Character * target, int ox, int oy, int *misx, int *misy)
+{
+       if (isMissileWeapon() || isThrownWeapon()) {
+               *misx = target->getX();
+               *misy = target->getY();
+               missile->setPlace(target->getPlace());
+               missile->setX(ox);
+               missile->setY(oy);
+               int frange = 0;
+               if (missile->getObjectType()->isFixedRange())
+               {
+                       frange = getRange();
+               }
+               missile->animate(ox, oy, misx, misy, 0, frange);
+               if (!missile->hitTarget())
+                       return false;
+       }
+       return true;
+}
+
+/*
+       Fires a missile at a specific tile, returns true if it reaches the target's location
+       updates tx and ty to be the location the missile reaches.
+*/
+bool ArmsType::fire(struct place * place, int ox, int oy, int *tx, int *ty)
+{
+       if (isMissileWeapon() || isThrownWeapon()) {
+               missile->setPlace(place);
+               missile->setX(ox);
+               missile->setY(oy);
+               int frange = 0;
+               if (missile->getObjectType()->isFixedRange())
+               {
+                       frange = getRange();
+               }
+               missile->animate(ox, oy, tx, ty, 0, frange);
+               if (!missile->hitTarget())
+                       return false;
+       }
+       return true;
+}
+
+bool ArmsType::fireInDirection(struct place *place, int ox, int oy, 
+                               int dx, int dy, class Object *user)
+{
+        if (!isMissileWeapon() && !isThrownWeapon())
+                return false;
+
+        if (fire_sound)
+                sound_play(fire_sound, SOUND_MAX_VOLUME);
+
+               int misx = dx * getRange() + ox;
+               int misy = dy * getRange() + oy;
+
+        missile->setPlace(place);
+        missile->setX(ox);
+        missile->setY(oy);
+        missile->animate(ox, oy, 
+                         &misx, 
+                         &misy, 
+                         MISSILE_IGNORE_LOS|MISSILE_HIT_PARTY,0);
+
+        if (!missile->hitTarget() || !missile->getStruck())
+                return false;
+
+        log_begin("%s hit ", getName());
+        missile->getStruck()->describe();
+        log_end("!");
+        
+        // Reference the object while damaging it, since damage can remove it
+        // from the map.
+        obj_inc_ref(missile->getStruck());
+
+        missile->getStruck()->damage(dice_roll(damageDice));
+
+        if (missile->getStruck()->isDestroyed()) {
+                log_begin("%s destroyed ", getName());
+                missile->getStruck()->describe();
+                log_end("!");
+                mapSetDirty();
+        }
+        
+        // Release the reference
+        obj_dec_ref(missile->getStruck());
+
+        if (user)
+               user->decActionPoints(getRequiredActionPoints());
+
+        return true;
+}
+
+void ArmsType::setThrown(bool val)
+{
+       if (val == thrown)
+               return;
+       thrown = val;
+
+       if (!val) {
+               if (missile != NULL) {
+                       delete missile;
+                       missile = NULL;
+               }
+               return;
+       }
+       // the usual case:
+       setAmmoType(this);
+}
+
+int ArmsType::getSlotMask()
+{
+        return slotMask;
+}
+
+char * ArmsType::getToHitDice()
+{
+        return toHitDice;
+}
+
+char * ArmsType::getDamageDice()
+{
+        return damageDice;
+}
+
+char * ArmsType::getToDefendDice()
+{
+        return toDefendDice;
+}
+
+char * ArmsType::getArmorDice()
+{
+        return armorDice;
+}
+
+int ArmsType::getNumHands()
+{
+        return numHands;
+}
+
+int ArmsType::getRange()
+{
+        return range;
+}
+
+bool ArmsType::isThrownWeapon()
+{
+        return thrown;
+}
+
+void ArmsType::setUbiquitousAmmo(bool val)
+{
+        ubiquitousAmmo = val;
+}
+
+bool ArmsType::ammoIsUbiquitous() 
+{
+        return ubiquitousAmmo;
+}
+
+void ArmsType::setWeight(int val) 
+{
+        weight = val;
+}
+
+int ArmsType::getWeight(void) 
+{
+        return weight;
+}
+
+int ArmsType::modifyStrAttack(int strBonus)
+{
+       return strBonus *  str_attack_mod;
+}
+
+int ArmsType::modifyDexAttack(int dexBonus)
+{
+       return dexBonus *  dex_attack_mod;
+}
+
+int ArmsType::modifyDamageBonus(int damBonus)
+{
+       return damBonus *  char_damage_mod;
+}
+
+float ArmsType::modifyAvoidBonus(float avoidBonus)
+{
+       return avoidBonus * char_avoid_mod;
+}
+
+int ArmsType::get_AP_mod(void) {
+    return modifier_to_AP_of_user;
+}
diff --git a/src/Arms.h b/src/Arms.h
new file mode 100644 (file)
index 0000000..7356439
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef Arms_h
+#define Arms_h
+
+#include "object.h"
+#include "sound.h"
+
+class Missile;
+
+class ArmsType:public ObjectType {
+
+      public:
+
+       virtual bool isType(int classID);
+       virtual int getType();
+        ArmsType();
+        ArmsType(const char *tag, const char *name, struct sprite *sprite,
+                       int slotMask,
+                       char *to_hit_dice,
+                       char *to_defend_dice,
+                       int numHands,
+                       int range,
+                       int weight,
+                       char *damage_dice,
+                       char *armor_dice,
+                       int reqActPts,
+                int AP_mod,
+                       bool thrown,
+                       bool ubiquitousAmmo,
+                       sound_t *fireSound,
+                       class MissileType *missileType,
+                       class ObjectType *ammo_type,
+                       int strAttackMod,
+                       int dexAttackMod,
+                       int charDamageMod,
+                       float charAvoidMod,
+                       bool isBeam
+                       );
+       virtual ~ ArmsType();
+
+       virtual char * getArmorDice();
+       virtual char * getDamageDice();
+       virtual int getSlotMask();
+        virtual char * getToDefendDice();
+        virtual char * getToHitDice();
+
+       virtual int getNumHands();
+       virtual int getRange();
+       virtual bool isMissileWeapon();
+       virtual bool isBeam(); 
+       virtual void setMissileType(class MissileType * missileType);
+       virtual class MissileType *getMissileType();
+       virtual bool fire(class Character * target, int ox, int oy, int* misx, int* misy);
+       virtual bool fire(struct place *place, int ox, int oy, int* tx, int* ty);
+    virtual bool fireInDirection(struct place *place, int ox, int oy, int dx, int dy, class Object *user);
+       virtual void fireHitLoc(Object *attacker, Object *target, struct place *place, int x, int y, int dam);
+       virtual bool isThrownWeapon();
+       virtual void setThrown(bool val);
+       virtual class ObjectType *getAmmoType();
+       virtual void setAmmoType(ObjectType * ammo_type);
+       virtual void setUbiquitousAmmo(bool val);
+       virtual bool ammoIsUbiquitous();
+       virtual void setWeight(int val);
+       virtual int getWeight(void);
+       virtual int modifyStrAttack(int strBonus);
+       virtual int modifyDexAttack(int dexBonus);
+       virtual int modifyDamageBonus(int damBonus);
+       virtual float modifyAvoidBonus(float avoidBonus);
+       virtual int get_AP_mod(void);
+      
+       
+      protected:
+       int slotMask;
+       int numHands;
+       int range;
+       int weight;
+       int modifier_to_AP_of_user;
+       bool thrown;
+       bool ubiquitousAmmo;
+        char *armorDice;
+        char *damageDice;
+        char *toDefendDice;
+        char *toHitDice;
+        sound_t *fire_sound;
+        bool beam;
+       int str_attack_mod;
+       int dex_attack_mod;
+       int char_damage_mod;
+       float char_avoid_mod;
+       class Missile *missile;
+       class ObjectType *ammoType;
+};
+
+#endif
diff --git a/src/Being.cpp b/src/Being.cpp
new file mode 100644 (file)
index 0000000..2274413
--- /dev/null
@@ -0,0 +1,382 @@
+#include "astar.h"
+#include "factions.h"
+#include "Being.h"
+#include "map.h"
+#include "place.h"
+#include "session.h"
+#include "log.h"
+#include "terrain.h"
+#include "kern_intvar.h"
+
+// USE_CACHED_PATH works but it can cause some strange-seeming behavior. If a
+// new, better route opens than the cached path then the being won't find it,
+// but will blindly follow the cached path. Unless pathfinding becomes a
+// performance issue leave this off.
+//
+// Addendum: actually, we need it on, because otherwise the member will
+// "thrash" when, for example, a portcullis remains closed: pathfinding around
+// it, then pathfinding through it and trying to open it, then around it again,
+// etc...
+#ifndef USE_CACHED_PATH
+# define USE_CACHED_PATH true
+#endif
+
+Being::Being()
+{
+        setDefaults();
+}
+
+Being::Being(class ObjectType *type)
+        : Object(type)
+{
+        setDefaults();
+}
+
+void Being::setDefaults()
+{
+        name = NULL;
+        cachedPath = NULL;
+        cachedPathPlace = NULL;
+        setBaseFaction(INVALID_FACTION);
+}
+
+Being::~Being()
+{
+        if (cachedPath) {
+                astar_path_destroy(cachedPath);
+        }
+        if (name) {
+                free(name);
+        }
+}
+
+void Being::setBaseFaction(int faction)
+{
+        baseFaction = faction;
+        setCurrentFaction(faction);
+}
+
+int Being::getBaseFaction()
+{
+        return baseFaction;
+}
+
+int Being::getCurrentFaction()
+{
+        return currentFaction;
+}
+
+enum layer Being::getLayer()
+{
+        return being_layer;
+}
+
+void Being::switchPlaces(class Being *occupant)
+{
+        int oldx = getX();
+        int oldy = getY();
+        int newx = occupant->getX();
+        int newy = occupant->getY();
+
+        struct place *oldPlace = getPlace();
+        occupant->relocate(oldPlace, oldx, oldy);
+        relocate(oldPlace, newx, newy);
+        decActionPoints(place_get_diagonal_movement_cost(getPlace(), 
+                                                         oldx, oldy,
+                                                         newx, newy,
+                                                         this, 0));
+}
+
+bool Being::pathfindTo(struct place *destplace, int destx, int desty, 
+                       int flags)
+{
+        struct astar_search_info as_info;
+        struct astar_node *pathPtr;
+
+       if (!flags)
+               flags = PFLAG_IGNORECOMPANIONS | PFLAG_IGNOREMECHS;
+
+       if (isStationary())
+               return false;
+       
+       // For now, don't try to pathfind between places.
+       if (destplace != getPlace())
+       {
+               warn("%s in %s, can't pathfind to %s", getName(),
+                       getPlace()->name, destplace->name);
+               return false;
+       }
+       
+       //dbg("%s pathfind from (%d %d) to (%d %d)\n", 
+       //getName(), getX(), getY(), destx, desty);
+
+       // Check the cachedPath
+       if (USE_CACHED_PATH && cachedPath)
+       {
+               
+               //dbg("cachedPath: ");
+               //astar_dbg_dump_path(cachedPath);
+               
+               // If the cached path is for a different place then we can't
+               // use it
+               if (getPlace() != cachedPathPlace)
+               {
+                       //dbg("old place\n");
+                        clearCachedPath();
+               } 
+               else 
+               {
+                       pathPtr = cachedPath;
+                       
+                       
+                       // If the cached path does not start from the current
+                       // coordinates then we can't use it.
+                       if (pathPtr->x != getX() || pathPtr->y != getY())
+                       {
+                               //dbg("old start\n");
+                                clearCachedPath();
+                       }
+                       else if (pathPtr->x != destx || pathPtr->y != desty)
+                       {
+                               pathPtr = pathPtr->next;
+                               
+                               // if we are about to hit nasty terrain, reevaluate our options
+                               if (pathPtr && place_get_terrain(getPlace(),pathPtr->x,pathPtr->y)->effect)
+                               {
+                                       dbg("recheck path (terrain)\n");
+                                       pathPtr = NULL;
+                               }
+                               if (pathPtr && place_get_object(getPlace(),pathPtr->x,pathPtr->y, field_layer) != NULL)
+                               {
+                                       dbg("recheck path (field)\n");
+                                       pathPtr = NULL;
+                               }
+                               
+                               //dbg("tracing\n");
+                               // Trace down the path until it ends or hits
+                               // the target
+                               while (pathPtr && 
+                                               (pathPtr->x != destx || pathPtr->y != desty))
+                                       pathPtr = pathPtr->next;
+                               
+                               // If this path is no good then destroy it,
+                               // we'll have to get a new one.
+                               if (! pathPtr)
+                               {
+                                       //dbg("won't reach\n");
+                                        clearCachedPath();
+                               }
+                       }
+               }
+       }
+
+        // If we don't have a valid path then try to find one, first by
+        // ignoring mechanisms.
+        if (! USE_CACHED_PATH || ! cachedPath) {
+                //dbg("searching\n");
+                memset(&as_info, 0, sizeof (as_info));
+                as_info.x0 = getX();
+                as_info.y0 = getY();
+                as_info.x1 = destx;
+                as_info.y1 = desty;
+                as_info.flags = flags;
+                cachedPath = place_find_path(getPlace(), &as_info, this);
+        }
+
+        // If we still don't have a valid path then give up
+        if (!cachedPath) {
+                //dbg("none found\n");
+                return false;
+        }
+        
+        // If the path does not lead anywhere then we must be at our
+        // destination, so we can destroy it and return.
+        pathPtr = cachedPath->next;
+        if (! pathPtr) {
+                //dbg("already there\n");
+                clearCachedPath();
+                return true;
+        }
+
+        // Otherwise the path is good, so cache the place.
+        cachedPathPlace = getPlace();
+        //dbg("Found path: ");
+        //astar_dbg_dump_path(cachedPath);
+        
+        enum MoveResult result;
+        result = move(pathPtr->x - getX(), 
+                      pathPtr->y - getY());
+
+        // Was the move blocked by an occupant?
+        if (result == WasOccupied) {
+                
+                // Yes - are we supposed to ignore beings?
+                if (flags & PFLAG_IGNOREBEINGS) {
+
+                        // Yes - try to switch. I don't know why I need to
+                        // check for isOnMap() (when would we not be on a map?
+                        // multi-place scehdules maybe?), but it looks like
+                        // something we probably added to fix a corner case, so
+                        // I'm leaving it in.
+                        class Character *occupant;
+                        if (isOnMap() 
+                            && (occupant = (class Character *) place_get_object(getPlace(), 
+                                                                                pathPtr->x, pathPtr->y, 
+                                                                                being_layer))) {
+                                if (!are_hostile(this, occupant)
+                                    && occupant->isIncapacitated())
+                                {
+                                        if (!place_is_passable(getPlace(), getX(), getY(), 
+                                                               occupant, 0))
+                                        {
+                                                relocate(getPlace(), pathPtr->x, pathPtr->y);
+                                                runHook(OBJ_HOOK_MOVE_DONE, "pdd", getPlace(),
+                                                        pathPtr->x, pathPtr->y);
+                                                decActionPoints(place_get_diagonal_movement_cost
+                                                                (
+                                                                        getPlace(), 
+                                                                        getX(), getY(),
+                                                                        pathPtr->x, pathPtr->y, 
+                                                                        this, PFLAG_IGNOREMECHS
+                                                                        ));
+                                        }                                      
+                                        switchPlaces(occupant);
+                                }
+                        }
+                } else {
+                        // No, we are not ignoring beings. We're probably using
+                        // a cached path that was built when the tile was
+                        // unoccupied. Let's just null out the cachedPath now
+                        // and let the being try again on the next turn.
+                        clearCachedPath();
+                }
+        }
+                      
+        // If the move failed because something impassable is there then check
+        // for a mech and try to handle it. This is good enough to get through
+        // the usual implementation of a door.
+        if (result == WasImpassable && isOnMap()) {
+
+                //dbg("impassable\n");
+                class Object *mech;
+                mech = place_get_object(getPlace(), 
+                                        pathPtr->x, 
+                                        pathPtr->y, 
+                                        mech_layer);
+                if (mech && mech->getObjectType()->canHandle()) {
+                        // workaround for [ 1114054 ] messages for off-screen
+                        // NPC's getting printed: temporarily prevent the mech
+                        // script from generating log messages
+                        log_disable();
+                        mech->getObjectType()->handle(mech, this);
+                        log_enable();
+                        mapSetDirty();
+                        
+                        // Now try and move again.
+                        result = move(pathPtr->x - getX(), 
+                                      pathPtr->y - getY());
+
+                        // Workaround an infinite loop in Character::exec()
+                        // where a party member is trying to rendezvous on a
+                        // path through a mech, and it keeps handling the mech,
+                        // thus decrementing its action points, but in fact it
+                        // can't move on any path.
+                        if (MovedOk == result) {
+                                this->decActionPoints(kern_intvar_get("AP_COST:handle_mechanism"));
+                        }
+
+                }
+                
+                if (WasImpassable == result  && isOnMap()) {
+
+                        //dbg("still impassable\n");
+                        // If the move was still impassable then try and find a
+                        // path that avoids mechanisms. Destroy this path
+                        // first.
+                        clearCachedPath();
+                        
+                        // Redo the search
+                        memset(&as_info, 0, sizeof (as_info));
+                        as_info.x0 = getX();
+                        as_info.y0 = getY();
+                        as_info.x1 = destx;
+                        as_info.y1 = desty;
+                        as_info.flags = PFLAG_IGNORECOMPANIONS;
+                        cachedPath = place_find_path(getPlace(), &as_info, 
+                                                     this);
+                        
+                        // If we still don't have a valid path then give up
+                        if (!cachedPath) {
+                                //dbg("no path\n");
+                                return false;
+                        }
+                        
+                        //dbg("New path: ");
+                        //astar_dbg_dump_path(cachedPath);
+
+                        // Otherwise the path is good, so cache the place.
+                        cachedPathPlace = getPlace();
+                        pathPtr = cachedPath->next;
+                        
+                        // Check if already there (can happen if the target changes)
+                        if (! pathPtr) {
+                                //dbg("already there\n");
+                                clearCachedPath();
+                                return true;
+                        }
+
+                        // Try to take the next step along the path.
+                        result = move(pathPtr->x - getX(), 
+                                      pathPtr->y - getY());
+                       
+                }
+        }
+
+        // If the move worked (as evidenced by the fact that our location
+        // changed to the next node) then free the first node and make the next
+        // node the head of the path so we can continue using it next turn.
+        if (getX() == pathPtr->x &&
+            getY() == pathPtr->y) {
+                //dbg("ok\n");
+                if (USE_CACHED_PATH) {
+                        astar_node_destroy(cachedPath);
+                        cachedPath = pathPtr;
+                } else {
+                        clearCachedPath();
+                }
+                return true;
+        }
+
+        return false;
+}
+
+const char *Being::getName() 
+{
+        if (name)
+                return name;
+        return "<no name>";
+}
+
+void Being::setName(const char *val) 
+{
+        if (val)
+                name = strdup(val);
+        else if (name) {
+                free(name);
+                name = NULL;
+        }
+}
+
+void Being::setCurrentFaction(int faction)
+{
+        currentFaction = faction;
+}
+
+void Being::clearCachedPath()
+{
+        if (cachedPath) {
+                astar_path_destroy(cachedPath);
+                cachedPath = NULL;
+                cachedPathPlace = NULL;
+        }
+}
diff --git a/src/Being.h b/src/Being.h
new file mode 100644 (file)
index 0000000..4bad5c7
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef Being_h
+#define Being_h
+
+#include "object.h"
+
+#define obj_is_being(obj) ((obj)->getLayer() == being_layer)
+
+class Being:public Object {
+
+      public:
+
+       Being();
+        Being(class ObjectType *type);
+
+       virtual ~Being();
+        virtual int getCurrentFaction();
+       virtual enum layer getLayer();
+       virtual const char *getName();
+        virtual void setCurrentFaction(int faction);
+
+        int getBaseFaction();
+        bool pathfindTo(struct place *place, int x, int y, int flags = 0);
+        void setBaseFaction(int faction);
+       void setName(const char *name);
+
+        // These are public because player_party::rendezvous makes heavy use of
+        // them...
+        struct astar_node *cachedPath; // for pathfinding
+        struct place *cachedPathPlace; // for pathfinding
+
+      protected:
+        void setDefaults();
+        virtual void switchPlaces(class Being *);
+
+ private:
+        char *name;
+        int baseFaction;
+        int currentFaction;
+        void clearCachedPath();
+};
+
+#endif
diff --git a/src/Container.cpp b/src/Container.cpp
new file mode 100644 (file)
index 0000000..4a07145
--- /dev/null
@@ -0,0 +1,266 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "common.h"
+#include "Container.h"
+#include "session.h"
+
+static void move_to_map(struct inv_entry *ie, void *data)
+{
+       class Container *box = (class Container *) data;
+        assert(ie->count);
+
+        class Object *obj = new Object();
+        assert(obj);
+
+        obj->init(ie->type);
+        obj->setCount(ie->count);
+        obj->relocate(box->getPlace(), box->getX(), box->getY());
+
+       box->takeOut(ie->type, ie->count);
+}
+
+static void destroy_content(struct inv_entry *ie, void *data)
+{
+       list_remove(&ie->list);
+       delete ie;
+}
+
+Container::Container()
+{
+       list_init(&contents);
+}
+
+Container::~Container()
+{
+        return;
+       forEach(destroy_content, NULL);
+}
+
+bool Container::add(class ObjectType * type, int quantity)
+{
+       struct inv_entry *ie;
+
+       if (quantity <= 0)
+                return false;
+
+       ie = search(type);
+       if (!ie) {
+                ie = new struct inv_entry;                
+               list_add(&contents, &ie->list);
+               ie->ref = 0;
+               ie->count = 0;
+               ie->type = type;
+       }
+
+        ie->count += quantity;
+
+        return true;
+}
+
+int Container::numAvail(class ObjectType *type)
+{
+       struct inv_entry *ie;
+
+       ie = search(type);
+        if (!ie)
+                return 0;
+        return ie->count;
+
+}
+
+bool Container::takeOut(class ObjectType * type, int quantity)
+{
+       struct inv_entry *ie;
+
+       ie = search(type);
+        if (!ie)
+                return false;
+
+        if (ie->count < quantity)
+                return false;
+
+       ie->count -= quantity;
+       assert(ie->count >= 0);
+
+       if (!ie->count) {
+               list_remove(&ie->list);
+               delete ie;
+       }
+
+        return true;
+}
+
+void Container::open()
+{
+       forEach(move_to_map, this);
+       assert(list_empty(&contents));
+}
+
+void Container::forEach(void (*fx) (struct inv_entry *, void *), void *data)
+{
+       struct list *elem = contents.next;
+       while (elem != &contents) {
+               struct list *tmp = elem->next;
+               struct inv_entry *ie = outcast(elem, struct inv_entry, list);
+               fx(ie, data);
+               elem = tmp;
+       }
+}
+
+struct inv_entry *Container::search(class ObjectType * type)
+{
+       struct list *elem = contents.next;
+       while (elem != &contents) {
+               struct list *tmp = elem->next;
+               struct inv_entry *ie = outcast(elem, struct inv_entry, list);
+               if (ie->type == type)
+                       return ie;
+               elem = tmp;
+       }
+       return NULL;
+}
+
+void Container::saveContents(struct save *save)
+{
+        struct list *elem;
+        struct inv_entry *ie;
+        int count;
+
+        save->enter(save, "(list ");
+
+        // Iterate backwards to save/reload in the same order
+        for (elem = contents.prev; elem != &contents; elem = elem->prev) {
+                ie = outcast(elem, struct inv_entry, list);
+                count = ie->count - ie->ref;
+                if (count) {
+                        save->write(save, "(list %d %s)\n", 
+                                    count,
+                                    ie->type->getTag());
+                }
+        }
+        save->exit(save, ")\n");
+}
+
+void Container::save(struct save *save)
+{
+        assert(saved < save->session_id);
+
+        saved = save->session_id;
+
+        save->enter(save, "(kern-mk-inventory\n");
+        save->write(save, ";; contents\n");
+        if (list_empty(&contents)) {
+                save->write(save, "nil\n");
+        } else {
+                saveContents(save);
+       }
+        
+        Object::saveHooks(save);
+
+        save->exit(save, ")\n");
+}
+
+int Container::filter_count(struct filter *filter)
+{
+        struct inv_entry *ie;
+        int q = 0;
+
+        ie = first(filter);
+        while (ie) {
+                q++;
+                ie = next(ie, filter);
+        }
+
+        return q;
+}
+
+struct inv_entry *Container::first(struct filter *filter)
+{
+        struct list *elem;
+        struct inv_entry *ie;
+
+        elem = contents.next;
+        while (elem != &contents) {
+                ie = outcast(elem, struct inv_entry, list);
+                if (!filter ||
+                    filter->fx(ie, filter->fdata))
+                        return ie;
+                elem = elem->next;
+        }
+        return NULL;
+}
+
+struct inv_entry *Container::next(struct inv_entry *ie, struct filter *filter)
+{
+        struct list *elem;
+
+        if (ie == NULL)
+                return first(filter);
+
+        elem = ie->list.next;
+        while (elem != &contents) {
+                ie = outcast(elem, struct inv_entry, list);
+                if (!filter ||
+                    filter->fx(ie, filter->fdata))
+                        return ie;
+                elem = elem->next;
+        }
+        return NULL;
+}
+
+struct inv_entry *Container::prev(struct inv_entry *ie, struct filter *filter)
+{
+        struct list *elem;
+
+        elem = ie->list.prev;
+        while (elem != &contents) {
+                ie = outcast(elem, struct inv_entry, list);
+                if (!filter ||
+                    filter->fx(ie, filter->fdata))
+                        return ie;
+                elem = elem->prev;
+        }
+        return NULL;
+}
+
+bool Container::isEmpty()
+{
+        return list_empty(&contents);
+}
+
+void Container::moveToFront(struct inv_entry *ie)
+{
+        list_remove(&ie->list);
+        list_add(&contents, &ie->list);
+}
+
+void Container::relocate(struct place *newplace, int newx, int newy, int flags,
+                         struct closure *place_switch_hook)
+{
+        // Spill the contents but don't try to put this down on the map as a
+        // physical object, because it's not.
+        setPlace(newplace);
+        setX(newx);
+        setY(newy);
+        open();
+}
diff --git a/src/Container.h b/src/Container.h
new file mode 100644 (file)
index 0000000..4d87965
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef Container_h
+#define Container_h
+
+#include "object.h"
+
+class Container:public Object {
+      public:
+       Container();
+       virtual ~ Container();
+       void open();
+       virtual struct inv_entry *search(class ObjectType * type);
+        bool isEmpty();
+
+        // Virtual methods from base class
+       virtual bool add(class ObjectType * type, int quantity);
+        virtual void save(struct save *save);
+       virtual bool takeOut(class ObjectType * type, int quantity);
+       virtual void relocate(struct place *newplace, int newx, int newy, 
+                              int flags = 0,
+                              struct closure *place_switch_hook = NULL);
+        int numAvail(class ObjectType * type);
+
+        int filter_count(struct filter *);
+       struct inv_entry *first(struct filter *);
+       struct inv_entry *next(struct inv_entry *ie, struct filter*);
+       struct inv_entry *prev(struct inv_entry *ie, struct filter*);
+        void moveToFront(struct inv_entry *ie);
+
+       void forEach(void (*fx) (struct inv_entry *, void *), void *);
+
+      protected:
+        void saveContents(struct save *save);
+       struct list contents;
+};
+
+#endif
diff --git a/src/Field.cpp b/src/Field.cpp
new file mode 100644 (file)
index 0000000..1a3dda6
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "Field.h"
+#include "common.h"
+#include "session.h"
+
+bool FieldType::isType(int classID) 
+{
+        if (classID == FIELD_TYPE_ID)
+                return true;
+        return ObjectType::isType(classID);
+}
+
+int FieldType::getType()
+{
+        return FIELD_TYPE_ID;
+}
+
+FieldType::FieldType(const char *tag, const char *name, struct sprite *sprite, 
+                     int light_, int duration_, int pclass_, closure_t *clx)
+        : ObjectType(tag, name, sprite, field_layer), 
+          pclass(pclass_), light(light_), duration(duration_)
+{
+        if (clx) {
+                closure_ref(clx);
+                effect = clx;
+        } else {
+                effect = NULL;
+        }
+}
+
+FieldType::~FieldType()
+{
+        closure_unref_safe(effect);
+}
+
+int  FieldType::getLight()
+{
+        return light;
+}
+
+void  FieldType::setLight(int val)
+{
+        light = val;
+}
+
+void  FieldType::setDuration(int val)
+{
+        duration = val;
+}
+
+int  FieldType::getDuration()
+{
+        return duration;
+}
+
+class Object *FieldType::createInstance()
+{
+        return new Field(this);
+}
+
+class FieldType * Field::getObjectType()
+{
+        return (class FieldType *) Object::getObjectType();
+}
+
+bool FieldType::isPermanent()
+{
+        return (duration < 0);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+Field::Field(FieldType *type)
+        : Object(type)
+{
+        duration = type->getDuration();
+}
+
+Field::Field(FieldType *type, int dur)
+        : Object(type)
+{
+        duration = dur;
+}
+
+Field::Field() : duration(0)
+{        
+}
+
+Field::~ Field()
+{
+}
+
+int Field::getLight()
+{
+        return getObjectType()->getLight();
+}
+
+void Field::exec()
+{
+        startTurn();
+        if (isDestroyed())
+                return;
+        
+        if (getObjectType()->isPermanent())
+                return;
+
+        duration--;
+        assert(duration >= 0);
+        if (duration == 0)
+                destroy();
+}
+
+void Field::save(struct save *save)
+{
+        save->write(save, "(kern-mk-field %s %d)", getObjectType()->getTag(), 
+                    duration);
+}
+
+int Field::getPclass()
+{
+        return getObjectType()->pclass;
+}
diff --git a/src/Field.h b/src/Field.h
new file mode 100644 (file)
index 0000000..0644960
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef Field_h
+#define Field_h
+
+#include "object.h"
+#include "closure.h"
+
+class FieldType:public ObjectType {
+
+      public:
+        FieldType(const char *tag, const char *name, struct sprite *sprite, int light, 
+                  int duration, int pclass, closure_t *effect);
+       virtual ~FieldType();
+       virtual bool isType(int classID);
+       virtual int getType();
+       virtual int getLight();
+       virtual void setLight(int val);
+       virtual void setDuration(int val);
+       virtual int getDuration();
+       virtual class Object *createInstance();
+
+        bool isPermanent();
+
+        closure_t *effect; /* when stepped on */
+        int pclass;
+
+      protected:
+       int light;
+       int duration;
+};
+
+class Field:public Object {
+
+      public:
+       virtual class FieldType * getObjectType();
+       Field();
+        Field(class FieldType *type);
+        Field(class FieldType *type, int duration);
+       virtual ~ Field();
+       virtual int getLight();
+       virtual void exec();
+        virtual void save(struct save *save);
+        virtual int getPclass();
+
+      protected:
+       int duration;
+};
+
+#endif
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..a1ffae4
--- /dev/null
@@ -0,0 +1,786 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# src/Makefile.  Generated from Makefile.in by configure.
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+
+
+
+pkgdatadir = $(datadir)/nazghul
+pkgincludedir = $(includedir)/nazghul
+pkglibdir = $(libdir)/nazghul
+pkglibexecdir = $(libexecdir)/nazghul
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = i686-pc-linux-gnu
+host_triplet = i686-pc-linux-gnu
+target_triplet = i686-pc-linux-gnu
+bin_PROGRAMS = nazghul$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_nazghul_OBJECTS = angband.$(OBJEXT) Arms.$(OBJEXT) ascii.$(OBJEXT) \
+       astar.$(OBJEXT) character.$(OBJEXT) cmdwin.$(OBJEXT) \
+       combat.$(OBJEXT) common.$(OBJEXT) console.$(OBJEXT) \
+       Container.$(OBJEXT) cursor.$(OBJEXT) debug.$(OBJEXT) \
+       event.$(OBJEXT) Field.$(OBJEXT) floodfill.$(OBJEXT) \
+       foogod.$(OBJEXT) formation.$(OBJEXT) hash.$(OBJEXT) \
+       heap.$(OBJEXT) images.$(OBJEXT) knapsack.$(OBJEXT) \
+       los.$(OBJEXT) map.$(OBJEXT) nazghul.$(OBJEXT) Party.$(OBJEXT) \
+       object.$(OBJEXT) occ.$(OBJEXT) olist.$(OBJEXT) place.$(OBJEXT) \
+       play.$(OBJEXT) player.$(OBJEXT) Reagent.$(OBJEXT) \
+       sched.$(OBJEXT) screen.$(OBJEXT) sky.$(OBJEXT) sound.$(OBJEXT) \
+       species.$(OBJEXT) sprite.$(OBJEXT) status.$(OBJEXT) \
+       terrain.$(OBJEXT) terrain_map.$(OBJEXT) tree.$(OBJEXT) \
+       vehicle.$(OBJEXT) wind.$(OBJEXT) wq.$(OBJEXT) \
+       Missile.$(OBJEXT) cmd.$(OBJEXT) clock.$(OBJEXT) \
+       vmask.$(OBJEXT) ctrl.$(OBJEXT) scheme.$(OBJEXT) \
+       session.$(OBJEXT) closure.$(OBJEXT) kern.$(OBJEXT) \
+       dice.$(OBJEXT) gob.$(OBJEXT) magic.$(OBJEXT) effect.$(OBJEXT) \
+       conv.$(OBJEXT) ptable.$(OBJEXT) mmode.$(OBJEXT) log.$(OBJEXT) \
+       dtable.$(OBJEXT) Being.$(OBJEXT) node.$(OBJEXT) tick.$(OBJEXT) \
+       dimensions.$(OBJEXT) cfg.$(OBJEXT) menus.$(OBJEXT) \
+       file.$(OBJEXT) skill.$(OBJEXT) skill_set.$(OBJEXT) \
+       skill_set_entry.$(OBJEXT) repstr.$(OBJEXT) templ.$(OBJEXT) \
+       objectfreezer.$(OBJEXT) kern_intvar.$(OBJEXT) ztats.$(OBJEXT) \
+       ztats_pane.$(OBJEXT) ztats_pm.$(OBJEXT) \
+       ztats_container_pane.$(OBJEXT) ztats_arms.$(OBJEXT) \
+       ztats_reagents.$(OBJEXT) ztats_spells.$(OBJEXT) \
+       ztats_items.$(OBJEXT) ztats_misc.$(OBJEXT) escape.$(OBJEXT) \
+       terrain_editor.$(OBJEXT)
+nazghul_OBJECTS = $(am_nazghul_OBJECTS)
+nazghul_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I. -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+       -o $@
+SOURCES = $(nazghul_SOURCES)
+DIST_SOURCES = $(nazghul_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/missing --run aclocal-1.11
+AMTAR = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/missing --run tar
+AUTOCONF = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/missing --run autoconf
+AUTOHEADER = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/missing --run autoheader
+AUTOMAKE = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/missing --run automake-1.11
+AWK = gawk
+CC = g++
+CCDEPMODE = depmode=gcc3
+CFLAGS = -g -O2 -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CPP = gcc -E
+CPPFLAGS = 
+CXX = g++
+CXXCPP = g++ -E -g -O2 -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CXXDEPMODE = depmode=gcc3
+CXXFLAGS = -g -O2 -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+CYGPATH_W = echo
+DEFS = -DHAVE_CONFIG_H
+DEPDIR = .deps
+ECHO_C = 
+ECHO_N = -n
+ECHO_T = 
+EGREP = /bin/grep -E
+EXEEXT = 
+GREP = /bin/grep
+INSTALL = /usr/bin/install -c
+INSTALL_DATA = ${INSTALL} -m 644
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_SCRIPT = ${INSTALL}
+INSTALL_STRIP_PROGRAM = $(install_sh) -c -s
+LDFLAGS = 
+LIBOBJS = 
+LIBS = -lSDL_mixer -lSDL_image -lpng  -lSDL -lpthread
+LTLIBOBJS = 
+MAINT = 
+MAKEINFO = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/missing --run makeinfo
+MKDIR_P = /bin/mkdir -p
+OBJEXT = o
+PACKAGE = nazghul
+PACKAGE_BUGREPORT = nazghul-devel@lists.sourceforge.net
+PACKAGE_NAME = nazghul
+PACKAGE_STRING = nazghul 0.7.1
+PACKAGE_TARNAME = nazghul
+PACKAGE_VERSION = 0.7.1
+PATH_SEPARATOR = :
+SDL_CFLAGS = -I/usr/include/SDL -D_GNU_SOURCE=1 -D_REENTRANT
+SDL_CONFIG = /usr/bin/sdl-config
+SDL_LIBS = -lSDL -lpthread
+SET_MAKE = 
+SHELL = /bin/sh
+STRIP = 
+VERSION = 0.7.1
+abs_builddir = /home/gmcnutt/projects/haxima/nazghul/src
+abs_srcdir = /home/gmcnutt/projects/haxima/nazghul/src
+abs_top_builddir = /home/gmcnutt/projects/haxima/nazghul
+abs_top_srcdir = /home/gmcnutt/projects/haxima/nazghul
+ac_ct_CC = gcc
+ac_ct_CXX = g++
+am__include = include
+am__leading_dot = .
+am__quote = 
+am__tar = ${AMTAR} chof - "$$tardir"
+am__untar = ${AMTAR} xf -
+bindir = ${exec_prefix}/bin
+build = i686-pc-linux-gnu
+build_alias = 
+build_cpu = i686
+build_os = linux-gnu
+build_vendor = pc
+builddir = .
+datadir = ${datarootdir}
+datarootdir = ${prefix}/share
+docdir = ${datarootdir}/doc/${PACKAGE_TARNAME}
+dvidir = ${docdir}
+exec_prefix = ${prefix}
+host = i686-pc-linux-gnu
+host_alias = 
+host_cpu = i686
+host_os = linux-gnu
+host_vendor = pc
+htmldir = ${docdir}
+includedir = ${prefix}/include
+infodir = ${datarootdir}/info
+install_sh = ${SHELL} /home/gmcnutt/projects/haxima/nazghul/install-sh
+libdir = ${exec_prefix}/lib
+libexecdir = ${exec_prefix}/libexec
+localedir = ${datarootdir}/locale
+localstatedir = ${prefix}/var
+mandir = ${datarootdir}/man
+mkdir_p = /bin/mkdir -p
+oldincludedir = /usr/include
+pdfdir = ${docdir}
+prefix = /usr/local
+program_transform_name = s,x,x,
+psdir = ${docdir}
+sbindir = ${exec_prefix}/sbin
+sharedstatedir = ${prefix}/com
+srcdir = .
+sysconfdir = ${prefix}/etc
+target = i686-pc-linux-gnu
+target_alias = 
+target_cpu = i686
+target_os = linux-gnu
+target_vendor = pc
+top_build_prefix = ../
+top_builddir = ..
+top_srcdir = ..
+AM_CXXFLAGS = -Wall -DDATADIR=\"${datarootdir}\" -DPREFIX=\"/usr/local\"
+AM_CFLAGS = ${AM_CXXFLAGS}
+
+#nazghul_SOURCES = $(wildcard *.c) $(wildcard *.cpp) $(wildcard *.h)
+nazghul_SOURCES = \
+       angband.c \
+        Arms.cpp \
+        Arms.h \
+        ascii.c \
+        ascii.h \
+        astar.c \
+        astar.h \
+        character.cpp \
+        character.h \
+        cmdwin.c \
+        cmdwin.h \
+        combat.c \
+        combat.h \
+        common.c \
+        common.h \
+        console.c \
+        console.h \
+        constants.h \
+        Container.cpp \
+        Container.h \
+        cursor.cpp \
+        cursor.h \
+        debug.h \
+       debug.c \
+        dup_constants.h \
+        event.c \
+        event.h \
+        Field.h \
+       Field.cpp \
+        floodfill.c \
+        foogod.c \
+        foogod.h \
+        formation.h \
+       formation.c \
+        hash.c \
+        hash.h \
+        heap.c \
+        heap.h \
+        images.c \
+        images.h \
+        knapsack.c \
+        knapsack.h \
+        list.h \
+        los.c \
+        los.h \
+        Makefile \
+        map.c \
+        map.h \
+        nazghul.h \
+        nazghul.c \
+        Party.cpp \
+        Party.h \
+        object.c \
+        object.h \
+        occ.c \
+        occ.h \
+        olist.c \
+        olist.h \
+        pinfo.h \
+        place.c \
+        place.h \
+        play.c \
+        player.cpp \
+        player.h \
+        play.h \
+        Reagent.cpp \
+        Reagent.h \
+        sched.c \
+        sched.h \
+        screen.c \
+        screen.h \
+        sky.c \
+        sky.h \
+        sound.c \
+        sound.h \
+        species.c \
+        species.h \
+        sprite.c \
+        sprite.h \
+        status.c \
+        status.h \
+        terrain.c \
+        terrain.h \
+        terrain_map.c \
+        terrain_map.h \
+        tree.c \
+        tree.h \
+        vehicle.cpp \
+        vehicle.h \
+        wind.c \
+        wind.h \
+        wq.c \
+        wq.h \
+       Missile.cpp \
+       Missile.h \
+       cmd.c \
+       cmd.h \
+       clock.c \
+       clock.h \
+       vmask.h \
+       vmask.c \
+       ctrl.h \
+       ctrl.c \
+       scheme.c \
+       scheme.h \
+       scheme-private.h \
+       opdefines.h \
+       macros.h \
+       session.c \
+       session.h \
+       closure.h \
+       closure.c \
+       kern.h \
+       kern.c \
+       dice.h \
+       dice.c \
+       gob.c \
+       gob.h \
+       magic.h \
+       magic.c \
+       effect.h \
+       effect.c \
+       conv.h \
+       conv.c \
+       ptable.c \
+       ptable.h \
+       mmode.c \
+       mmode.h \
+       log.h \
+       log.c \
+       dtable.h \
+       dtable.c \
+       Being.h \
+       Being.cpp \
+       factions.h \
+       result.h \
+       node.h \
+       node.c \
+       tick.h \
+       tick.c \
+       blender.h \
+       dimensions.h dimensions.c \
+       cfg.h cfg.c \
+       menus.h menus.c \
+       file.h file.c \
+       screen_dims.h \
+       skill.h skill.c \
+       skill_set.h skill_set.c \
+       skill_set_entry.h skill_set_entry.c \
+       repstr.h repstr.c \
+       templ.h templ.c \
+       objectfreezer.h objectfreezer.c \
+        kern_intvar.c kern_intvar.h \
+       ztats.h ztats.c \
+       ztats_pane.h ztats_pane.c \
+       ztats_pm.h ztats_pm.c \
+       ztats_container_pane.h ztats_container_pane.c \
+       ztats_arms.h ztats_arms.c \
+       ztats_reagents.h ztats_reagents.c \
+       ztats_spells.h ztats_spells.c \
+       ztats_items.h ztats_items.c \
+       ztats_misc.h ztats_misc.c \
+       applet.h \
+       session_hooks.h \
+       session_queries.h \
+       bitset.h \
+       escape.c escape.h \
+       terrain_editor.c terrain_editor.h
+
+INCLUDES = -I$(includedir)                                      \
+        -I$(srcdir) -I$(top_srcdir)/include -I$(top_srcdir)     \
+        -I$(top_builddir) -I$(top_builddir)/include -I.
+
+MAINTAINERCLEANFILES = Makefile.in
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure:  $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4):  $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p; \
+         then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+             echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+             $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+nazghul$(EXEEXT): $(nazghul_OBJECTS) $(nazghul_DEPENDENCIES) 
+       @rm -f nazghul$(EXEEXT)
+       $(CXXLINK) $(nazghul_OBJECTS) $(nazghul_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+include ./$(DEPDIR)/Arms.Po
+include ./$(DEPDIR)/Being.Po
+include ./$(DEPDIR)/Container.Po
+include ./$(DEPDIR)/Field.Po
+include ./$(DEPDIR)/Missile.Po
+include ./$(DEPDIR)/Party.Po
+include ./$(DEPDIR)/Reagent.Po
+include ./$(DEPDIR)/angband.Po
+include ./$(DEPDIR)/ascii.Po
+include ./$(DEPDIR)/astar.Po
+include ./$(DEPDIR)/cfg.Po
+include ./$(DEPDIR)/character.Po
+include ./$(DEPDIR)/clock.Po
+include ./$(DEPDIR)/closure.Po
+include ./$(DEPDIR)/cmd.Po
+include ./$(DEPDIR)/cmdwin.Po
+include ./$(DEPDIR)/combat.Po
+include ./$(DEPDIR)/common.Po
+include ./$(DEPDIR)/console.Po
+include ./$(DEPDIR)/conv.Po
+include ./$(DEPDIR)/ctrl.Po
+include ./$(DEPDIR)/cursor.Po
+include ./$(DEPDIR)/debug.Po
+include ./$(DEPDIR)/dice.Po
+include ./$(DEPDIR)/dimensions.Po
+include ./$(DEPDIR)/dtable.Po
+include ./$(DEPDIR)/effect.Po
+include ./$(DEPDIR)/escape.Po
+include ./$(DEPDIR)/event.Po
+include ./$(DEPDIR)/file.Po
+include ./$(DEPDIR)/floodfill.Po
+include ./$(DEPDIR)/foogod.Po
+include ./$(DEPDIR)/formation.Po
+include ./$(DEPDIR)/gob.Po
+include ./$(DEPDIR)/hash.Po
+include ./$(DEPDIR)/heap.Po
+include ./$(DEPDIR)/images.Po
+include ./$(DEPDIR)/kern.Po
+include ./$(DEPDIR)/kern_intvar.Po
+include ./$(DEPDIR)/knapsack.Po
+include ./$(DEPDIR)/log.Po
+include ./$(DEPDIR)/los.Po
+include ./$(DEPDIR)/magic.Po
+include ./$(DEPDIR)/map.Po
+include ./$(DEPDIR)/menus.Po
+include ./$(DEPDIR)/mmode.Po
+include ./$(DEPDIR)/nazghul.Po
+include ./$(DEPDIR)/node.Po
+include ./$(DEPDIR)/object.Po
+include ./$(DEPDIR)/objectfreezer.Po
+include ./$(DEPDIR)/occ.Po
+include ./$(DEPDIR)/olist.Po
+include ./$(DEPDIR)/place.Po
+include ./$(DEPDIR)/play.Po
+include ./$(DEPDIR)/player.Po
+include ./$(DEPDIR)/ptable.Po
+include ./$(DEPDIR)/repstr.Po
+include ./$(DEPDIR)/sched.Po
+include ./$(DEPDIR)/scheme.Po
+include ./$(DEPDIR)/screen.Po
+include ./$(DEPDIR)/session.Po
+include ./$(DEPDIR)/skill.Po
+include ./$(DEPDIR)/skill_set.Po
+include ./$(DEPDIR)/skill_set_entry.Po
+include ./$(DEPDIR)/sky.Po
+include ./$(DEPDIR)/sound.Po
+include ./$(DEPDIR)/species.Po
+include ./$(DEPDIR)/sprite.Po
+include ./$(DEPDIR)/status.Po
+include ./$(DEPDIR)/templ.Po
+include ./$(DEPDIR)/terrain.Po
+include ./$(DEPDIR)/terrain_editor.Po
+include ./$(DEPDIR)/terrain_map.Po
+include ./$(DEPDIR)/tick.Po
+include ./$(DEPDIR)/tree.Po
+include ./$(DEPDIR)/vehicle.Po
+include ./$(DEPDIR)/vmask.Po
+include ./$(DEPDIR)/wind.Po
+include ./$(DEPDIR)/wq.Po
+include ./$(DEPDIR)/ztats.Po
+include ./$(DEPDIR)/ztats_arms.Po
+include ./$(DEPDIR)/ztats_container_pane.Po
+include ./$(DEPDIR)/ztats_items.Po
+include ./$(DEPDIR)/ztats_misc.Po
+include ./$(DEPDIR)/ztats_pane.Po
+include ./$(DEPDIR)/ztats_pm.Po
+include ./$(DEPDIR)/ztats_reagents.Po
+include ./$(DEPDIR)/ztats_spells.Po
+
+.c.o:
+       $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+       $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#      source='$<' object='$@' libtool=no \
+#      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#      $(COMPILE) -c $<
+
+.c.obj:
+       $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+       $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#      source='$<' object='$@' libtool=no \
+#      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) \
+#      $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+       $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+       $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#      source='$<' object='$@' libtool=no \
+#      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#      $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+       $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+       $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+#      source='$<' object='$@' libtool=no \
+#      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) \
+#      $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic ctags distclean distclean-compile \
+       distclean-generic distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-binPROGRAMS \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-html install-html-am \
+       install-info install-info-am install-man install-pdf \
+       install-pdf-am install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+       uninstall-am uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644 (file)
index 0000000..44ea19e
--- /dev/null
@@ -0,0 +1,185 @@
+AM_CXXFLAGS = -Wall -DDATADIR=\"@datadir@\" -DPREFIX=\"@prefix@\"
+AM_CFLAGS = ${AM_CXXFLAGS}
+
+bin_PROGRAMS = nazghul
+
+#nazghul_SOURCES = $(wildcard *.c) $(wildcard *.cpp) $(wildcard *.h)
+
+nazghul_SOURCES =              \
+       angband.c \
+        Arms.cpp \
+        Arms.h \
+        ascii.c \
+        ascii.h \
+        astar.c \
+        astar.h \
+        character.cpp \
+        character.h \
+        cmdwin.c \
+        cmdwin.h \
+        combat.c \
+        combat.h \
+        common.c \
+        common.h \
+        console.c \
+        console.h \
+        constants.h \
+        Container.cpp \
+        Container.h \
+        cursor.cpp \
+        cursor.h \
+        debug.h \
+       debug.c \
+        dup_constants.h \
+        event.c \
+        event.h \
+        Field.h \
+       Field.cpp \
+        floodfill.c \
+        foogod.c \
+        foogod.h \
+        formation.h \
+       formation.c \
+        hash.c \
+        hash.h \
+        heap.c \
+        heap.h \
+        images.c \
+        images.h \
+        knapsack.c \
+        knapsack.h \
+        list.h \
+        los.c \
+        los.h \
+        Makefile \
+        map.c \
+        map.h \
+        nazghul.h \
+        nazghul.c \
+        Party.cpp \
+        Party.h \
+        object.c \
+        object.h \
+        occ.c \
+        occ.h \
+        olist.c \
+        olist.h \
+        pinfo.h \
+        place.c \
+        place.h \
+        play.c \
+        player.cpp \
+        player.h \
+        play.h \
+        Reagent.cpp \
+        Reagent.h \
+        sched.c \
+        sched.h \
+        screen.c \
+        screen.h \
+        sky.c \
+        sky.h \
+        sound.c \
+        sound.h \
+        species.c \
+        species.h \
+        sprite.c \
+        sprite.h \
+        status.c \
+        status.h \
+        terrain.c \
+        terrain.h \
+        terrain_map.c \
+        terrain_map.h \
+        tree.c \
+        tree.h \
+        vehicle.cpp \
+        vehicle.h \
+        wind.c \
+        wind.h \
+        wq.c \
+        wq.h \
+       Missile.cpp \
+       Missile.h \
+       cmd.c \
+       cmd.h \
+       clock.c \
+       clock.h \
+       vmask.h \
+       vmask.c \
+       ctrl.h \
+       ctrl.c \
+       scheme.c \
+       scheme.h \
+       scheme-private.h \
+       opdefines.h \
+       macros.h \
+       session.c \
+       session.h \
+       closure.h \
+       closure.c \
+       kern.h \
+       kern.c \
+       dice.h \
+       dice.c \
+       gob.c \
+       gob.h \
+       magic.h \
+       magic.c \
+       effect.h \
+       effect.c \
+       conv.h \
+       conv.c \
+       ptable.c \
+       ptable.h \
+       mmode.c \
+       mmode.h \
+       log.h \
+       log.c \
+       dtable.h \
+       dtable.c \
+       Being.h \
+       Being.cpp \
+       factions.h \
+       result.h \
+       node.h \
+       node.c \
+       tick.h \
+       tick.c \
+       blender.h \
+       dimensions.h dimensions.c \
+       cfg.h cfg.c \
+       menus.h menus.c \
+       file.h file.c \
+       screen_dims.h \
+       skill.h skill.c \
+       skill_set.h skill_set.c \
+       skill_set_entry.h skill_set_entry.c \
+       repstr.h repstr.c \
+       templ.h templ.c \
+       objectfreezer.h objectfreezer.c \
+        kern_intvar.c kern_intvar.h \
+       ztats.h ztats.c \
+       ztats_pane.h ztats_pane.c \
+       ztats_pm.h ztats_pm.c \
+       ztats_container_pane.h ztats_container_pane.c \
+       ztats_arms.h ztats_arms.c \
+       ztats_reagents.h ztats_reagents.c \
+       ztats_spells.h ztats_spells.c \
+       ztats_items.h ztats_items.c \
+       ztats_misc.h ztats_misc.c \
+       applet.h \
+       session_hooks.h \
+       session_queries.h \
+       bitset.h \
+       escape.c escape.h \
+       terrain_editor.c terrain_editor.h
+
+INCLUDES = -I$(includedir)                                      \
+        -I$(srcdir) -I$(top_srcdir)/include -I$(top_srcdir)     \
+        -I$(top_builddir) -I$(top_builddir)/include -I.
+
+LIBS = @LIBS@
+
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644 (file)
index 0000000..1312e14
--- /dev/null
@@ -0,0 +1,786 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+bin_PROGRAMS = nazghul$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)"
+PROGRAMS = $(bin_PROGRAMS)
+am_nazghul_OBJECTS = angband.$(OBJEXT) Arms.$(OBJEXT) ascii.$(OBJEXT) \
+       astar.$(OBJEXT) character.$(OBJEXT) cmdwin.$(OBJEXT) \
+       combat.$(OBJEXT) common.$(OBJEXT) console.$(OBJEXT) \
+       Container.$(OBJEXT) cursor.$(OBJEXT) debug.$(OBJEXT) \
+       event.$(OBJEXT) Field.$(OBJEXT) floodfill.$(OBJEXT) \
+       foogod.$(OBJEXT) formation.$(OBJEXT) hash.$(OBJEXT) \
+       heap.$(OBJEXT) images.$(OBJEXT) knapsack.$(OBJEXT) \
+       los.$(OBJEXT) map.$(OBJEXT) nazghul.$(OBJEXT) Party.$(OBJEXT) \
+       object.$(OBJEXT) occ.$(OBJEXT) olist.$(OBJEXT) place.$(OBJEXT) \
+       play.$(OBJEXT) player.$(OBJEXT) Reagent.$(OBJEXT) \
+       sched.$(OBJEXT) screen.$(OBJEXT) sky.$(OBJEXT) sound.$(OBJEXT) \
+       species.$(OBJEXT) sprite.$(OBJEXT) status.$(OBJEXT) \
+       terrain.$(OBJEXT) terrain_map.$(OBJEXT) tree.$(OBJEXT) \
+       vehicle.$(OBJEXT) wind.$(OBJEXT) wq.$(OBJEXT) \
+       Missile.$(OBJEXT) cmd.$(OBJEXT) clock.$(OBJEXT) \
+       vmask.$(OBJEXT) ctrl.$(OBJEXT) scheme.$(OBJEXT) \
+       session.$(OBJEXT) closure.$(OBJEXT) kern.$(OBJEXT) \
+       dice.$(OBJEXT) gob.$(OBJEXT) magic.$(OBJEXT) effect.$(OBJEXT) \
+       conv.$(OBJEXT) ptable.$(OBJEXT) mmode.$(OBJEXT) log.$(OBJEXT) \
+       dtable.$(OBJEXT) Being.$(OBJEXT) node.$(OBJEXT) tick.$(OBJEXT) \
+       dimensions.$(OBJEXT) cfg.$(OBJEXT) menus.$(OBJEXT) \
+       file.$(OBJEXT) skill.$(OBJEXT) skill_set.$(OBJEXT) \
+       skill_set_entry.$(OBJEXT) repstr.$(OBJEXT) templ.$(OBJEXT) \
+       objectfreezer.$(OBJEXT) kern_intvar.$(OBJEXT) ztats.$(OBJEXT) \
+       ztats_pane.$(OBJEXT) ztats_pm.$(OBJEXT) \
+       ztats_container_pane.$(OBJEXT) ztats_arms.$(OBJEXT) \
+       ztats_reagents.$(OBJEXT) ztats_spells.$(OBJEXT) \
+       ztats_items.$(OBJEXT) ztats_misc.$(OBJEXT) escape.$(OBJEXT) \
+       terrain_editor.$(OBJEXT)
+nazghul_OBJECTS = $(am_nazghul_OBJECTS)
+nazghul_LDADD = $(LDADD)
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+       $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+       $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+CXXLD = $(CXX)
+CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+       -o $@
+SOURCES = $(nazghul_SOURCES)
+DIST_SOURCES = $(nazghul_SOURCES)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CXXFLAGS = -Wall -DDATADIR=\"@datadir@\" -DPREFIX=\"@prefix@\"
+AM_CFLAGS = ${AM_CXXFLAGS}
+
+#nazghul_SOURCES = $(wildcard *.c) $(wildcard *.cpp) $(wildcard *.h)
+nazghul_SOURCES = \
+       angband.c \
+        Arms.cpp \
+        Arms.h \
+        ascii.c \
+        ascii.h \
+        astar.c \
+        astar.h \
+        character.cpp \
+        character.h \
+        cmdwin.c \
+        cmdwin.h \
+        combat.c \
+        combat.h \
+        common.c \
+        common.h \
+        console.c \
+        console.h \
+        constants.h \
+        Container.cpp \
+        Container.h \
+        cursor.cpp \
+        cursor.h \
+        debug.h \
+       debug.c \
+        dup_constants.h \
+        event.c \
+        event.h \
+        Field.h \
+       Field.cpp \
+        floodfill.c \
+        foogod.c \
+        foogod.h \
+        formation.h \
+       formation.c \
+        hash.c \
+        hash.h \
+        heap.c \
+        heap.h \
+        images.c \
+        images.h \
+        knapsack.c \
+        knapsack.h \
+        list.h \
+        los.c \
+        los.h \
+        Makefile \
+        map.c \
+        map.h \
+        nazghul.h \
+        nazghul.c \
+        Party.cpp \
+        Party.h \
+        object.c \
+        object.h \
+        occ.c \
+        occ.h \
+        olist.c \
+        olist.h \
+        pinfo.h \
+        place.c \
+        place.h \
+        play.c \
+        player.cpp \
+        player.h \
+        play.h \
+        Reagent.cpp \
+        Reagent.h \
+        sched.c \
+        sched.h \
+        screen.c \
+        screen.h \
+        sky.c \
+        sky.h \
+        sound.c \
+        sound.h \
+        species.c \
+        species.h \
+        sprite.c \
+        sprite.h \
+        status.c \
+        status.h \
+        terrain.c \
+        terrain.h \
+        terrain_map.c \
+        terrain_map.h \
+        tree.c \
+        tree.h \
+        vehicle.cpp \
+        vehicle.h \
+        wind.c \
+        wind.h \
+        wq.c \
+        wq.h \
+       Missile.cpp \
+       Missile.h \
+       cmd.c \
+       cmd.h \
+       clock.c \
+       clock.h \
+       vmask.h \
+       vmask.c \
+       ctrl.h \
+       ctrl.c \
+       scheme.c \
+       scheme.h \
+       scheme-private.h \
+       opdefines.h \
+       macros.h \
+       session.c \
+       session.h \
+       closure.h \
+       closure.c \
+       kern.h \
+       kern.c \
+       dice.h \
+       dice.c \
+       gob.c \
+       gob.h \
+       magic.h \
+       magic.c \
+       effect.h \
+       effect.c \
+       conv.h \
+       conv.c \
+       ptable.c \
+       ptable.h \
+       mmode.c \
+       mmode.h \
+       log.h \
+       log.c \
+       dtable.h \
+       dtable.c \
+       Being.h \
+       Being.cpp \
+       factions.h \
+       result.h \
+       node.h \
+       node.c \
+       tick.h \
+       tick.c \
+       blender.h \
+       dimensions.h dimensions.c \
+       cfg.h cfg.c \
+       menus.h menus.c \
+       file.h file.c \
+       screen_dims.h \
+       skill.h skill.c \
+       skill_set.h skill_set.c \
+       skill_set_entry.h skill_set_entry.c \
+       repstr.h repstr.c \
+       templ.h templ.c \
+       objectfreezer.h objectfreezer.c \
+        kern_intvar.c kern_intvar.h \
+       ztats.h ztats.c \
+       ztats_pane.h ztats_pane.c \
+       ztats_pm.h ztats_pm.c \
+       ztats_container_pane.h ztats_container_pane.c \
+       ztats_arms.h ztats_arms.c \
+       ztats_reagents.h ztats_reagents.c \
+       ztats_spells.h ztats_spells.c \
+       ztats_items.h ztats_items.c \
+       ztats_misc.h ztats_misc.c \
+       applet.h \
+       session_hooks.h \
+       session_queries.h \
+       bitset.h \
+       escape.c escape.h \
+       terrain_editor.c terrain_editor.h
+
+INCLUDES = -I$(includedir)                                      \
+        -I$(srcdir) -I$(top_srcdir)/include -I$(top_srcdir)     \
+        -I$(top_builddir) -I$(top_builddir)/include -I.
+
+MAINTAINERCLEANFILES = Makefile.in
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .cpp .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       for p in $$list; do echo "$$p $$p"; done | \
+       sed 's/$(EXEEXT)$$//' | \
+       while read p p1; do if test -f $$p; \
+         then echo "$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+           -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+       sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) files[d] = files[d] " " $$1; \
+           else { print "f", $$3 "/" $$4, $$1; } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+           if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+           test -z "$$files" || { \
+             echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+             $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+           } \
+       ; done
+
+uninstall-binPROGRAMS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+       files=`for p in $$list; do echo "$$p"; done | \
+         sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+             -e 's/$$/$(EXEEXT)/' `; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+       -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS)
+nazghul$(EXEEXT): $(nazghul_OBJECTS) $(nazghul_DEPENDENCIES) 
+       @rm -f nazghul$(EXEEXT)
+       $(CXXLINK) $(nazghul_OBJECTS) $(nazghul_LDADD) $(LIBS)
+
+mostlyclean-compile:
+       -rm -f *.$(OBJEXT)
+
+distclean-compile:
+       -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Arms.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Being.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Container.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Field.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Missile.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Party.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Reagent.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/angband.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ascii.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/astar.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cfg.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/character.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/clock.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/closure.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cmdwin.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/combat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/console.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conv.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ctrl.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cursor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dice.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dimensions.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dtable.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/effect.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/escape.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/event.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/floodfill.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/foogod.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/formation.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gob.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/heap.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/images.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kern.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kern_intvar.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/knapsack.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/log.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/los.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/magic.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/map.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/menus.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mmode.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nazghul.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/node.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/objectfreezer.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/occ.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/olist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/place.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/play.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/player.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptable.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/repstr.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sched.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scheme.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/screen.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/session.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skill.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skill_set.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/skill_set_entry.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sky.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sound.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/species.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sprite.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/status.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/templ.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/terrain.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/terrain_editor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/terrain_map.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tick.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tree.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vehicle.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vmask.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wind.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wq.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_arms.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_container_pane.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_items.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_misc.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_pane.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_pm.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_reagents.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ztats_spells.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@   $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@   $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@      DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@  $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.cpp.o:
+@am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@  $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@  $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@  $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS:  $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+       for dir in "$(DESTDIR)$(bindir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+       distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -rf ./$(DEPDIR)
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \
+       clean-generic ctags distclean distclean-compile \
+       distclean-generic distclean-tags distdir dvi dvi-am html \
+       html-am info info-am install install-am install-binPROGRAMS \
+       install-data install-data-am install-dvi install-dvi-am \
+       install-exec install-exec-am install-html install-html-am \
+       install-info install-info-am install-man install-pdf \
+       install-pdf-am install-ps install-ps-am install-strip \
+       installcheck installcheck-am installdirs maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-compile \
+       mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \
+       uninstall-am uninstall-binPROGRAMS
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/Missile.cpp b/src/Missile.cpp
new file mode 100644 (file)
index 0000000..f2d12fa
--- /dev/null
@@ -0,0 +1,194 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "Missile.h"
+#include "dice.h"
+#include "character.h"
+#include "screen.h"
+#include "mmode.h"
+#include "sprite.h"
+#include "map.h"
+#include "console.h"
+#include "Field.h"
+#include "place.h"
+#include "player.h"
+#include "vehicle.h"
+#include "session.h"
+
+MissileType::MissileType()
+{
+       // Don't ever expect to call this. Defining it to override the default
+       // one c++ automatically creates.
+       assert(false);
+       
+       beam = false;
+}
+
+MissileType::MissileType(const char *tag, const char *name, struct sprite *sprite, bool isBeam, bool isFixedRange, struct mmode *mmode)
+       : ObjectType(tag, name, sprite, item_layer),
+               beam(isBeam),
+               fixedrange(isFixedRange)
+{
+       setMovementMode(mmode);
+}
+
+MissileType::~MissileType()
+{
+       //dont think theres anything here that needs cleaning up?
+}
+
+bool MissileType::isType(int classID)
+{
+       if (classID == MISSILE_TYPE_ID)
+               return true;
+       return ObjectType::isType(classID);
+}
+
+int MissileType::getType()
+{
+        return MISSILE_TYPE_ID;
+}
+
+bool MissileType::isBeam()
+{
+       return beam;
+}
+
+// A fixed range missile always fires to its maximum range (LOS allowing).
+// target selection merely affects the angle it travels at
+bool MissileType::isFixedRange()
+{
+       return fixedrange;
+}
+
+void MissileType::fireHitLoc(Object *attacker, Object *target, struct place *place, int x, int y, int dam)
+{
+       if (canHitLocation())
+               hitLocation(NULL, attacker, target, place, x, y, dam);  
+}
+
+bool MissileType::fireEnterTile(Missile *missile, struct place *place, int x, int y)
+{
+       if (closure_exec(gifc, "yppdd", "enter", missile, place, x, y))
+       {
+               return true;    
+       }
+       else
+       {
+               return false;   
+       }
+}
+
+Missile::Missile(MissileType* type)
+        : Object(type)
+{
+
+}
+
+Missile::~Missile()
+{
+}
+
+class MissileType *Missile::getObjectType() 
+{
+        return (class MissileType *) Object::getObjectType();
+}
+
+/* set hit=true if a party or object has been struck
+return true if the missile has not been interupted */
+bool Missile::enterTile(struct place *place, int x, int y)
+{
+        if (! (flags & MISSILE_IGNORE_LOS))
+                       {
+                               int obstruction = place_get_movement_cost(place, x, y, this,0);
+                                //int opacity = place_visibility(place, x, y);
+                                return ((obstruction != 20) && (dice_roll_numeric(1,100,0)>obstruction));
+                       }       
+                       
+        if (! (flags & MISSILE_HIT_PARTY))
+                return true;
+
+        struck = place_get_Party(place, x, y);
+
+        if (struck != NULL) {
+                hit = true;
+                return false;
+        }
+
+        // fugly hack...
+        if (player_party->getPlace() == place &&
+            player_party->getX() == x &&
+            player_party->getY() == y) {
+                struck = player_party;
+                hit = true;
+                return false;
+        }
+
+        /* Allow wilderness-scale weapons to destroy empty vehicles. */
+        struck = place_get_vehicle(place, x, y);
+        if (struck != NULL) {
+                hit = true;
+                return false;
+        }
+
+        return true;
+}
+
+/*
+       triggers a hit-loc ifc event if appropriate
+*/
+void Missile::fireHitLoc(Object *attacker, Object *target, struct place *place, int x, int y, int dam)
+{
+       if (getObjectType()->canHitLocation())
+               getObjectType()->hitLocation(this, attacker, target, place, x, y, dam); 
+}
+
+/*
+       Calculates & animates trajectory, returns true if the missile reached the target location
+       alters Bx, By to be where it reached (so you can tell where it wound up if blocked)
+*/
+void Missile::animate(int Ax, int Ay, int *Bx, int *By, int _flags, float fixedrange)
+{
+        int origBx = *Bx;
+        int origBy = *By;
+        
+        hit = false;
+        struck = NULL;
+        flags = _flags;
+
+        struct sprite *tmpSprite = sprite_clone(getSprite(), 0);
+        mapAnimateProjectile(Ax, Ay, Bx, By, tmpSprite, getPlace(), this, fixedrange);
+        sprite_del(tmpSprite);
+
+        hit = (hit || (origBx == *Bx && origBy == *By));
+}
+
+bool Missile::hitTarget()
+{
+       return hit;
+}
+
+class Object * Missile::getStruck()
+{
+        return struck;
+}
+
diff --git a/src/Missile.h b/src/Missile.h
new file mode 100644 (file)
index 0000000..fc0cbe0
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef Missile_h
+#define Missile_h
+
+#include "object.h"
+#include "Arms.h"
+
+#define MISSILE_IGNORE_LOS (1 << 0)
+#define MISSILE_HIT_PARTY  (1 << 1)
+
+class MissileType:public ObjectType
+{
+               public:
+       MissileType();
+       MissileType(const char *tag, const char *name, struct sprite *sprite, bool isBeam, bool isFixedRange, struct mmode *mmode);
+       virtual ~ MissileType();
+       
+       virtual bool isType(int classID);
+       virtual int getType();
+
+       virtual bool isBeam();
+       virtual bool isFixedRange();
+       virtual void fireHitLoc(Object *attacker, Object *target, struct place *place, int x, int y, int dam);
+       virtual bool fireEnterTile(Missile* missile, struct place *place, int x, int y);
+               
+               protected:
+       bool beam;
+       bool fixedrange;
+};
+
+class Missile:public Object
+{
+               public:
+       Missile(MissileType*);
+       virtual ~Missile();
+       
+       virtual class MissileType *getObjectType();
+       virtual void animate(int Ax, int Ay, int *Bx, int *By, int flags, float fixedrange);
+       virtual void fireHitLoc(Object *attacker, Object *target, struct place *place, int x, int y, int dam);
+       virtual bool hitTarget();
+       virtual class Object *getStruck();
+       virtual bool enterTile(struct place *place, int x, int y);
+       
+               protected:
+       bool hit;
+       class Object *struck;
+       int flags;
+};
+
+#endif
diff --git a/src/Party.cpp b/src/Party.cpp
new file mode 100644 (file)
index 0000000..56614c1
--- /dev/null
@@ -0,0 +1,1156 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "Party.h"
+#include "dice.h"
+#include "place.h"
+#include "player.h"
+#include "combat.h"
+#include "species.h"
+#include "occ.h"
+#include "wind.h"
+#include "vehicle.h"
+#include "console.h"
+#include "formation.h"
+#include "ctrl.h"
+#include "session.h"
+#include "sched.h"
+#include "log.h"
+#include "event.h"
+#include "cmd.h"
+#include "cmdwin.h"
+#include "factions.h"
+#include "sprite.h"
+
+#include <stdio.h>
+
+#define DIRLOC(dir,place,coord) { \
+        if ((dir) < 0) \
+                (coord) = place_w((place)) - 1; \
+        else if (! (dir)) \
+                (coord) = place_w((place)) / 2; \
+        else \
+                (coord) = 0; \
+}
+
+// Convenience macro for iterating over party members:
+#define FOR_EACH_MEMBER(e,c)                                               \
+        for ((e) = node_next(&members), (c) = (class Character *)(e)->ptr; \
+        (e) != &members;                                                   \
+        (e) = node_next(e), (c) = (class Character *)(e)->ptr)
+
+
+Party::Party()
+        : vehicle(NULL)
+          , size(0)
+          , formation(NULL)
+          , wandering(false)
+          , ctrl(ctrl_party_ai)
+{
+       node_init(&members);
+        memset(&pinfo, 0, sizeof(pinfo));
+}
+
+static bool party_remove_member(class Character *ch, void *data)
+{
+        ((Party*)data)->removeMember(ch);
+        return false;
+}
+
+Party::~Party()
+{
+        /* Dereference all the members by removing them from the party. If no
+         * other container references them then they will be automatically
+         * destoyed. */
+        forEachMember(party_remove_member, this);
+        obj_dec_ref_safe(vehicle);
+}
+
+bool Party::isType(int classID)
+{
+        return (classID == PARTY_ID);
+                return true;
+        return Object::isType(classID);
+}
+
+int Party::getType()
+{
+        return PARTY_ID;
+}
+
+int Party::getVisionRadius()
+{
+        int maxVal=0;
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (!member->isDead()) {
+                        int val  = member->getVisionRadius();
+                        maxVal = max(val, maxVal);
+                }
+        }
+
+        return maxVal;
+}
+
+int Party::getSize(void)
+{
+        return size;
+}
+
+
+bool Party::turn_vehicle(void)
+{
+       int cost = 0;
+
+       // Three possible outcomes:
+       // 
+       // 1. We do NOT turn any vehicle, therefore we want to continue
+       // processing the move() command which calls us and we do NOT want to
+       // consume any turns (e.g., no vehicle, or horse turning north/south).
+       // 
+       // 2. We DO turn a vehicle, but it does not cost us anything (e.g.,
+       // horse turning east/west).
+       // 
+       // 3. We do turn a vehicle and it cost us a turn (e.g., ship).
+
+       if (!vehicle || !vehicle->turn(dx, dy, &cost) || !vehicle->mustTurn())
+               return false;
+
+        action_points -= cost;
+
+       return true;
+}
+
+bool Party::attackPlayer(int dx, int dy)
+{
+        // Subtle: check if the player party is on the map. This
+        // catches the case where the player has just engaged another
+        // npc party in combat on this turn. I don't want this npc
+        // party to move to that spot because then when the player
+        // party exits combat they will be on top of this npc party.
+        if (! player_party->isOnMap())
+                return false;
+
+        struct move_info info;
+        struct combat_info cinfo;
+
+        memset(&info, 0, sizeof(info));
+        
+         
+               /* Check for a diagonal attack. */
+               if (dx && dy)
+               {
+                       int xgoodness=0;
+                       int ygoodness=0;
+                       if (place_is_passable(getPlace(), getX() + dx, getY(), 
+                                       this, 0))
+                       {
+                               if (place_is_hazardous(getPlace(), getX() + dx, getY()))
+                               {
+                                       xgoodness=1;
+                               }
+                               else
+                               {
+                                       xgoodness=2;    
+                               }
+                       }
+                       if ((xgoodness<2) && place_is_passable(getPlace(), getX(), getY() + dy, 
+                               this, 0))
+                       {
+                               if (place_is_hazardous(getPlace(), getX() + dx, getY()))
+                               {
+                                       ygoodness=1;
+                               }
+                               else
+                               {
+                                       ygoodness=2;    
+                               }                               
+                       }
+                       if (xgoodness && xgoodness > ygoodness)
+                       {
+                               //changing x is better                          
+                               info.x = getX() + dx;
+                               info.y = getY();
+                               info.dx = 0;
+                               info.dy = dy;
+                       }
+                       else if (ygoodness)
+                       {
+                               //changing y is better  
+                               info.x = getX();
+                               info.y = getY() + dy;
+                               info.dy = 0;
+                               info.dx = dx;
+                       }
+                       else
+                       {
+                               //cant actually get there!
+                               return false;   
+                       }
+               }
+               else
+               {
+                       info.x = getX();
+                       info.y = getY();
+                       info.dx = dx;
+                       info.dy = dy;
+               }
+
+        info.place = getPlace();
+        info.px = player_party->getX();
+        info.py = player_party->getY();
+        info.npc_party = this;
+
+        memset(&cinfo, 0, sizeof(cinfo));
+        cinfo.defend = true;
+        cinfo.move = &info;
+
+        combat_enter(&cinfo);
+        endTurn();
+        return true;
+}
+
+MoveResult Party::move(int dx, int dy)
+{
+       struct place *newplace;
+       int newx;
+       int newy;
+       struct place *oldplace;
+       int oldx;
+       int oldy;
+       class Object *mech;
+
+       this->dx = dx;
+       this->dy = dy;
+
+       /* Check if the party is in a vehicle that must turn its facing before
+        * moving */
+       if (turn_vehicle())
+               return ChangedFacing;
+
+       /* Remember old (current) coordinates */
+       oldplace = getPlace();
+       oldx = getX();
+       oldy = getY();
+
+       /* Setup new coordinates */
+       newx = place_wrap_x(oldplace, oldx + dx);
+       newy = place_wrap_y(oldplace, oldy + dy);
+       newplace = oldplace;
+
+       /* Walking off the edge of a map */
+       if (place_off_map(oldplace, newx, newy)) {
+               return OffMap;
+       }
+
+       /* Check if the player is there. */
+       if (newx == player_party->getX() && 
+            newy == player_party->getY()) {
+
+               /* If this party is hostile to the player then begin combat */
+               if (are_hostile(this, player_party)
+                    && attackPlayer(dx, dy)) {
+                        return EngagedEnemy;
+
+               }
+
+                return WasOccupied;
+       }
+
+       /* Check if another entity is already there */
+       if (place_is_occupied(oldplace, newx, newy)) {
+               return WasOccupied;
+       }
+
+       /* Check for a vehicle. */
+       class Vehicle *veh = place_get_vehicle(newplace, newx, newy);
+       if (veh && (vehicle || veh->getOccupant())) {
+               return WasOccupied;
+       }
+
+       /* Check passability */
+       if (!place_is_passable(oldplace, newx, newy, this,
+                               PFLAG_MOVEATTEMPT)) {
+               return WasImpassable;
+       }
+
+        /* When wandering, don't wander over terrain hazards. When pathfinding,
+         * assume that braving the hazard is the best course. */
+       if (wandering && place_is_hazardous(newplace, newx, newy))
+                return AvoidedHazard;
+
+
+       // Check for a mech (not for passability, for sending the STEP
+        // signal)
+
+       mech = place_get_object(getPlace(), newx, newy, mech_layer);
+        if (mech) {
+                // Bugfix 1411788: avoid step triggers; dungeon step triggers
+                // are relocating the NPC party into non-wilderness places,
+                // corrupting them (note: the code here used to call
+                // mech->step(this), not only did this invoke the step but it
+                // was redundant, because the relocate() call checks for step
+                // trigger mechs)
+                return AvoidedHazard;
+        }
+
+       relocate(newplace, newx, newy);
+
+       action_points -= place_get_diagonal_movement_cost(getPlace(), oldx, oldy, getX(), getY(), this,0);
+
+        return MovedOk;
+}
+
+bool Party::gotoSpot(int mx, int my)
+{
+       // Common routine used by work() and commute().
+       struct astar_node *path;
+       struct astar_node *next;
+       struct astar_search_info as_info;
+       int dx;
+       int dy;
+        enum MoveResult ret = NotApplicable;
+
+        if (isStationary())
+                return StationaryObject;
+
+       /* Look for a path. */
+       memset(&as_info, 0, sizeof(as_info));
+       as_info.x0 = getX();
+       as_info.y0 = getY();
+       as_info.x1 = mx;
+       as_info.y1 = my;
+       as_info.flags = PFLAG_IGNOREMECHS;
+       path = place_find_path(Place, &as_info, this);
+
+       if (!path)
+               return false;
+
+        //dump_path(path);
+
+       /* The first node in the path is the starting location. Get the next
+        * step. */
+       next = path->next;
+       if (next) {
+
+               /* Get the movement vector */
+               dx = next->x - getX();
+               dy = next->y - getY();
+
+               /* Attempt to move */
+               ret = move(dx, dy);
+                        
+       }
+
+       /* Cleanup */
+       astar_path_destroy(path);
+
+       return (ret == MovedOk || ret == EngagedEnemy);
+}
+
+bool Party::attack_with_ordnance(int d)
+{
+       class ArmsType *ordnance;
+       int dx, dy;
+       bool ret;
+
+       if (!vehicle || !(ordnance = vehicle->getOrdnance()))
+               return false;
+
+       // Check if the player is in range.
+       if (d > ordnance->getRange()) {
+               return false;
+       }
+       // Get the normalized vector to the player.
+        place_get_direction_vector(getPlace(),
+                                   getX(), getY(), 
+                                   player_party->getX(), player_party->getY(),
+                                   &dx, &dy);
+       clamp(dx, -1, 1);
+       clamp(dy, -1, 1);
+
+       // Check if the player is on a major axes (assumes we must fire in a
+       // straight line -- always true for now).
+       if (player_party->getY() == getY()) {
+
+               // If necessary, turn the vehicle to broadside the player (this
+               // assumes we must use a broadside, again always true for now).
+               // If we do turn return true to end this turn.
+               if (vehicle->getFacing() != NORTH &&
+                   vehicle->getFacing() != SOUTH) {
+                       int cost;
+                       vehicle->turn(0, 1, &cost);
+                       action_points -= cost;
+                       return true;
+               }
+
+               ret = vehicle->fire_weapon(dx, dy, this);
+               assert(ret);    // to remind me if I change some assumptions
+               return true;
+       }
+       // Ditto but for the other axis.
+       if (player_party->getX() == getX()) {
+               if (vehicle->getFacing() != EAST &&
+                   vehicle->getFacing() != WEST) {
+                       int cost;
+                       vehicle->turn(1, 0, &cost);
+                       return true;
+               }
+               ret = vehicle->fire_weapon(dx, dy, this);
+               assert(ret);    // to remind me if I change some assumptions
+               return true;
+       }
+       // In range but no lined up on an axis. For now just return and let out
+       // strategy be to close with the player's ship. In future I might want
+       // to try and go to find and move toward the nearest axis point.
+       return false;
+}
+
+
+void Party::exec()
+{        
+        assert(!isDestroyed());
+
+        startTurn();
+
+        while (action_points > 0 && !isDestroyed()) {
+
+                int initial_points = action_points;
+                ctrl(this);
+                /* If we didn't use any action points then we're idle and need
+                 * to break to prevent an endless loop. */
+                if (action_points == initial_points)
+                        break;
+       }
+
+        endTurn();
+        Object::decrementTTL(this); // might destroy this!
+}
+
+
+void Party::forEachMember(bool (*fx) (class Character *, void *), void *data)
+{
+       struct node *elem;
+
+       elem = node_next(&members);
+       while (elem != &members) {
+               class Character *c;
+
+               c = (class Character *)elem->ptr;
+                elem = node_next(elem);
+
+               if (fx(c, data))
+                       return;
+       }
+}
+
+
+void Party::forEachReverseMember(bool (*fx) (class Character *, void *), void *data)
+{
+       struct node *elem;
+
+       elem = node_prev(&members);
+       while (elem != &members) {
+               class Character *c;
+
+               c = (class Character *)elem->ptr;
+                elem = node_prev(elem);
+
+               if (fx(c, data))
+                       return;
+       }
+}
+
+static bool party_destroy_and_remove_member(class Character * c, void *data)
+{
+       class Party *party = (class Party *) data;
+
+       c->destroy();
+       party->removeMember(c);
+
+       return false;
+}
+
+void Party::destroy()
+{
+        // Note: this is a case of destroying an object in a container:
+       disembark();
+
+       forEachMember(party_destroy_and_remove_member, this);
+       assert(node_list_empty(&members));
+       Object::destroy();      // removes it
+}
+
+void Party::removeMember(class Character * c)
+{
+        struct node *node;
+
+        /* Convenienve pointer to node */
+        node = c->plnode;
+        
+        /* Should be valid */
+        assert(node);
+
+        /* Unlink the node from the member list */
+       node_remove(node);
+
+        /* Break the link from the char back to the node */
+        c->plnode = NULL;
+
+        /* Break the link from the char back to the party */
+       c->party = NULL;
+
+        /* Reduce party size counter */
+       size--;
+
+        /* Release the node */
+        node_unref(node);
+
+        /* Release the char */
+        obj_dec_ref(c);
+}
+
+bool Party::addMember(class Character * c)
+{
+        struct node *node;
+
+        /* Add ref to char to prevent destruction */
+        obj_inc_ref(c);
+
+        /* Make a new list node for the member list */
+        node = node_new(c);
+
+        /* Link the new member in at the END of the list (otherwise, in the
+         * case of the player party, the order shown in status gets screwed
+         * up) */
+        node_add_tail(&members, node);
+
+        /* Point the member back to its node (for fast removal) */
+        c->plnode = node;
+
+        /* Point the member back to its party */
+        c->party = this;
+
+        /* Set the character's order in the party */
+        c->setOrder(size);
+
+        /* Increase the party size counter */
+        size++;
+
+        /* Make the member loyal to the party */
+        c->setBaseFaction(getBaseFaction());
+
+        return true;
+}
+
+static bool add_to_player_party(class Character * c, void *data)
+{
+       // Note: I'll leave the party set as-is. It does no harm and might do
+       // some good later.  Note: The order will be forgotten (changed to
+       // match player party order).
+
+       if (!c->joinPlayer())
+               assert(false);
+       return false;
+}
+
+bool Party::joinPlayer(void)
+{
+       remove();
+       forEachMember(add_to_player_party, 0);
+       return true;
+}
+
+void Party::paint(int sx, int sy)
+{
+       if (vehicle)
+               vehicle->paint(sx, sy);
+       else
+               Object::paint(sx, sy);
+}
+
+struct sprite *Party::getSprite()
+{
+       if (vehicle)
+               return vehicle->getSprite();
+
+       return Object::getSprite();
+}
+
+void Party::disembark()
+{
+       if (vehicle) {
+               assert(getPlace());
+               vehicle->setOccupant(0);
+                if (!vehicle->isDestroyed()) {
+                        vehicle->relocate(getPlace(), getX(), getY());
+                }
+                obj_dec_ref(vehicle);
+               vehicle = NULL;
+       }
+}
+
+
+int Party::getSpeed()
+{
+       if (vehicle)
+               return vehicle->getSpeed();
+
+        int minVal=255; // something big, whatever
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (!member->isDead()) {
+                        int val  = member->getSpeed();
+                        minVal = min(val, minVal);
+                }
+        }
+
+        return minVal;
+
+}
+
+struct damage_member_info {
+       int damage;
+       bool any_alive;
+};
+
+static bool damage_member(class Character * member, void *data)
+{
+       struct damage_member_info *dm_info = (struct damage_member_info *) data;
+
+       // apply damage
+       member->damage(dm_info->damage);
+
+       // check if dead and remove from party
+       if (member->isDead()) {
+               member->party->removeMember(member);
+               return false;
+       }
+       // otherwise at least one still alive
+       dm_info->any_alive = true;
+
+       return false;
+}
+
+void Party::damage(int damage)
+{
+       struct damage_member_info dm_info;
+
+        Object::damage(damage);
+
+       // First apply damage to the vehicle. If the vehicle is destroyed then
+       // destroy the party, too.
+       if (vehicle) {
+               vehicle->damage(damage);
+                
+                // If the vehicle was destroyed by the above damage, it has
+                // already called destroy() on its occupants (that's us right
+                // here!) and we've already disembarked. So there's really
+                // nothing to do.
+                return;
+
+       }
+
+       // Apply damage to all party members. If they all die then the party is
+       // destroyed, too.
+       dm_info.damage = damage;
+       dm_info.any_alive = false;
+       forEachMember(damage_member, &dm_info);
+       if (!dm_info.any_alive) {
+               destroy();
+       }
+}
+
+void Party::distributeMembers()
+{
+        // -------------------------------------------------------------------
+        // Emulate what I currently do for the player party.
+        // -------------------------------------------------------------------
+
+        // -------------------------------------------------------------------
+        // The combat alg requires me to fill out a "position info" structure
+        // based on the player party destination.
+        // -------------------------------------------------------------------
+        
+        combat_fill_position_info(&pinfo, getPlace(), getX(), getY(), dx, dy, false);
+
+        // -------------------------------------------------------------------
+        // Set the party formation to a sane default.
+        // -------------------------------------------------------------------
+
+        if (NULL == pinfo.formation)
+                pinfo.formation = formation_get_default();
+
+        // -------------------------------------------------------------------
+        // Party members must be placed such that they can pathfind back to the
+        // party. This minimizes the chance of a party member getting stranded
+        // (which in turn will strand the whole party in that place).
+        // -------------------------------------------------------------------
+
+        pinfo.find_party = true;
+
+        // -------------------------------------------------------------------
+        // Remove the party from the current place before distributing members.
+        // -------------------------------------------------------------------
+
+        remove();
+        mapSetDirty();
+
+        // -------------------------------------------------------------------
+        // Use the combat algorithm to place each member. Currently this will
+        // never fail, in the degenerate case all party members will end up
+        // "stranded" on top of the destination tile.
+        // -------------------------------------------------------------------
+
+        forEachMember(combat_place_character, &pinfo);
+
+}
+
+struct formation *Party::get_formation()
+{
+       if (vehicle && vehicle->get_formation())
+               return vehicle->get_formation();
+       return formation;
+}
+
+void Party::describe()
+{
+        assert(Session->subject);
+        const char *diplstr = diplomacy_string(this, Session->subject);
+        if (isvowel(diplstr[0]))
+                log_continue("an ");
+        else
+                log_continue("a ");
+
+        log_continue("%s %s", diplstr, getName());
+
+        if (vehicle) {
+                log_continue(" in ");
+                vehicle->describe();
+        }
+}
+
+static bool member_examine(class Character *member, void *data)
+{
+        log_begin("");
+        member->examine();
+        log_end("");
+        return false;
+}
+
+void Party::examine()
+{
+       describe();
+        log_end(":");
+       forEachMember(member_examine, this);
+        log_begin("");
+       //todo: more details?
+}
+
+
+static bool get_member_movement_sound(class Character * member, void *data)
+{
+        sound_t **sound = (sound_t **)data;
+       *sound = member->get_movement_sound();
+        return data != 0;
+}
+
+
+sound_t *Party::get_movement_sound()
+{
+        sound_t *sound = NULL_SOUND;
+
+       if (vehicle)
+               return vehicle->get_movement_sound();
+        forEachMember(get_member_movement_sound, &sound);
+        return sound;
+}
+
+static bool member_burn(class Character *member, void *data)
+{
+        member->burn();
+        return false;
+}
+
+static bool member_sleep(class Character *member, void *data)
+{
+        member->sleep();
+        return false;
+}
+
+void Party::burn()
+{
+        forEachMember(member_burn, NULL);
+        if (allDead())
+                destroy();
+}
+
+void Party::sleep()
+{
+        forEachMember(member_sleep, NULL);
+        if (allDead())
+                destroy();
+}
+
+static bool member_check_if_alive(class Character *member, void *data)
+{
+        if (!member->isDead()) {
+                *((bool*)data) = false;
+                return true;
+        }
+        return false;
+}
+
+bool Party::allDead()
+{
+        bool dead = true;
+        forEachMember(member_check_if_alive, &dead);
+        return dead;
+}
+
+void Party::switchOrder(class Character *ch1, class Character *ch2)
+{
+        int tmp;
+        node_switch(ch1->plnode, ch2->plnode);
+        tmp = ch1->getOrder();
+        ch1->setOrder(ch2->getOrder());
+        ch2->setOrder(tmp);
+}
+
+void Party::setPlace(struct place *place)
+{
+        struct node *entry;
+        class Character *member;
+        Object::setPlace(place);
+        if (this!=player_party
+            && !place_is_wilderness(place)) {
+                warn("putting %s in non-wilderness %s\n",
+                     getName(), place->name);
+                assert(0);
+        }
+        FOR_EACH_MEMBER(entry, member) {
+                member->setPlace(place);
+        }
+}
+
+void Party::setX(int x)
+{
+        struct node *entry;
+        class Character *member;
+        Object::setX(x);
+        FOR_EACH_MEMBER(entry, member) {
+                member->setX(x);
+        }
+}
+
+void Party::setY(int y)
+{
+        struct node *entry;
+        class Character *member;
+        Object::setY(y);
+        FOR_EACH_MEMBER(entry, member) {
+                member->setY(y);
+        }
+}
+
+bool Party::addEffect(struct effect *effect, struct gob *gob)
+{
+        struct node *entry;
+        class Character *member;
+        bool result = false;
+
+        // NOTE: in the future we'll probably want to distinguish between
+        // start-of-char-turn and start-of-party-turn for characters. Also,
+        // we'll want to specify if the hook should really apply to the party
+        // object or to its members.
+        FOR_EACH_MEMBER(entry, member)
+                result = member->addEffect(effect, gob) || result;
+        
+        return result;
+}
+
+bool Party::removeEffect(struct effect *effect)
+{
+        struct node *entry;
+        class Character *member;
+        bool result = false;
+
+        FOR_EACH_MEMBER(entry, member) {
+                result = member->removeEffect(effect) || result;
+        }
+        
+        return result;
+}
+
+void Party::startTurn()
+{
+        struct node *entry;
+        class Character *member;
+
+        Object::startTurn();
+        if (isDestroyed())
+                return;
+
+        // NOTE: in the future we'll probably want to distinguish between
+        // start-of-char-turn and start-of-party-turn for characters. Also, to
+        // be authentic we really should iterate over this in proportion to the
+        // map scale.
+        FOR_EACH_MEMBER(entry, member)
+                member->runHook(OBJ_HOOK_START_OF_TURN, 0);
+
+        if (allDead())
+                destroy();
+
+}
+
+void Party::applyEffect(closure_t *effect)
+{
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member)
+                member->applyEffect(effect);
+}
+
+void Party::save(struct save *save)
+{
+        struct node *entry;
+        class Character *member;
+
+        save->enter(save, "(let ((kparty (kern-mk-party)))\n");
+        if (getName())
+                save->write(save, "(kern-being-set-name kparty \"%s\")\n", getName());
+        save->write(save, "(kern-obj-set-sprite kparty %s)\n", 
+                    sprite_get_tag(getSprite()));
+        save->write(save, "(kern-being-set-base-faction kparty %d)\n", getBaseFaction());
+        if (vehicle) {
+                save->enter(save, "(kern-party-set-vehicle kparty");
+                vehicle->save(save);
+                save->exit(save, ") ;; end kern-party-set-vehicle\n");
+        }
+        FOR_EACH_MEMBER(entry, member) {
+                save->enter(save, "(kern-party-add-member kparty\n");
+                member->save(save);
+                save->exit(save, ") ;; end kern-party-add-member\n");
+        }
+        if (getTTL() != -1) {
+                save->write(save, "(kern-obj-set-ttl kparty %d)\n", getTTL());
+        }
+        save->write(save, "kparty\n");
+        save->exit(save, ") ;; end let\n");
+}
+
+static bool member_remove(class Character *member, void *data)
+{
+        member->remove();
+        return false;
+}
+
+void Party::removeMembers()
+{
+        forEachMember(member_remove, NULL);
+}
+
+static bool memberStart(class Character *member, void *data)
+{
+        member->start();
+        return false;
+}
+
+void Party::start()
+{
+        forEachMember(memberStart, NULL);
+}
+
+int Party::getMovementCost(int pclass)
+{
+        struct node *entry;
+        class Character *member;
+        int maxCost = 0;
+
+        if (vehicle)
+                return vehicle->getMovementCost(pclass);
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (!member->isDead()) {
+                        int cost = member->getMovementCost(pclass);
+                        maxCost = max(cost, maxCost);
+                }
+        }
+
+        return maxCost;
+}
+
+bool Party::isStationary()
+{
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (!member->isDead()) {
+                        if (member->isStationary())
+                                return true;
+                }
+        }
+
+        return false;
+}
+
+class Character *Party::getMemberByOrder(int order)
+{
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (! order)
+                        return member;
+                order--;
+        }
+
+        return NULL;
+}
+
+Object *Party::getSpeaker()
+{
+        struct node *entry;
+        class Character *member;
+        struct stat_list_entry *statlist;
+        int list_sz = 0;
+        class Character *selected = NULL;
+        enum StatusMode orig_stat_mode;
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+
+        // Allocate an array of status list entries big enough for the entire
+        // party (this is probably more than we need, but it's only temporary).
+        statlist = (struct stat_list_entry*)
+                calloc(getSize(), sizeof(struct stat_list_entry));
+        assert(statlist);
+
+
+        // For each party member that has a conversation, add it to the list.
+        FOR_EACH_MEMBER(entry, member) {
+
+            // Fix for crasher: 'conv' is a member of this object, so don't use
+            // it as a temp variable!
+            if (!member->getConversation()) {
+                continue;
+            }
+
+                statlist[list_sz].sprite = member->getSprite();
+                snprintf(statlist[list_sz].line1, STAT_LIST_CHARS_PER_LINE,
+                         member->getName());
+                statlist[list_sz].data = member;
+                list_sz++;
+        }
+
+        // Remember the current stat mode so we can restore it.
+        orig_stat_mode = statusGetMode();
+
+        // Check if nobody has a conversation.
+        if (! list_sz)
+                goto done;
+
+        // Check if only one has a conversation.
+        if (list_sz == 1) {
+                selected = (class Character*)statlist[0].data;
+                goto done;
+        }
+
+        // The player has to choose. Poke the list into the status state.
+        statusSetGenericList("Choose Speaker", list_sz, statlist);
+
+        // Switch the status mode over to list selection.
+        statusSetMode(GenericList);
+
+        // Setup a keyhandler for handling the scrolling
+       sc.selector  = Generic;
+       sc.selection = NULL;
+       kh.fx        = scroller;
+       kh.data      = &sc;
+
+        // Push the handler and wait for the player to make a selection.
+       eventPushKeyHandler(&kh);
+       cmdwin_spush("<select>");
+       eventHandle();
+       cmdwin_pop();
+       eventPopKeyHandler();
+
+       statusRepaint();
+
+       selected = (class Character *) sc.selection;
+        
+ done:
+        statusSetMode(orig_stat_mode);
+        free(statlist);
+        return selected;
+}
+
+void Party::setVehicle(class Vehicle *val)
+{
+        if (vehicle) {
+                vehicle->setOccupant(0);
+                obj_dec_ref(vehicle);
+        }
+        vehicle=val;
+        if (val) {
+                val->setOccupant(this);
+                obj_inc_ref(val);
+        }
+}
+
+class Vehicle *Party::getVehicle()
+{
+        return vehicle;
+}
+
+static bool party_absorb_member_apdebt(class Character * c, void *data)
+{
+       int *maxapdebt = (int *) data;
+
+       int apdebt = c->getActionPoints();
+       if (apdebt < 0)
+       {
+               c->resetActionPoints();
+               if (apdebt < *maxapdebt)
+               {
+                       *maxapdebt = apdebt;    
+               }       
+       }
+
+       return false;
+}
+
+void Party::absorbMemberAPDebt()
+{
+       int maxapdebt=0;
+       forEachMember(party_absorb_member_apdebt, &maxapdebt);
+       decActionPoints(0-maxapdebt/10); // 0-... because AP debt is negative
+}
+
+class Container *Party::getInventory()
+{
+        return NULL; // subclass(es) may override
+}
diff --git a/src/Party.h b/src/Party.h
new file mode 100644 (file)
index 0000000..2af3038
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef Party_h
+#define Party_h
+
+#include "Being.h"
+#include "common.h"
+#include "character.h"
+#include "list.h"
+#include "node.h"
+#include "pinfo.h"
+
+class Party:public Being {
+      public:
+
+       Party();
+       virtual ~Party();
+
+       virtual bool isType(int classID);
+
+       virtual struct formation *get_formation();
+        virtual sound_t *get_movement_sound();
+        virtual int getMovementCost(int pclass);
+       virtual int getSize(void);
+       virtual int getSpeed();
+        virtual struct sprite *getSprite();
+       virtual int getType();
+       virtual int getVisionRadius();
+        virtual bool addEffect(struct effect *effect, struct gob *gob);
+        virtual bool addMember(class Character *);
+        virtual bool allDead();
+        virtual void burn();
+        virtual void damage(int amount);
+        virtual void describe();
+        virtual void examine();
+       virtual void destroy();        
+       virtual void disembark();
+        virtual void distributeMembers();
+       virtual void exec();
+       virtual bool joinPlayer(void);
+        virtual bool removeEffect(struct effect *effect);
+       virtual void forEachMember(bool (*fx) (class Character *, void *), 
+                                   void *);
+       virtual void forEachReverseMember(bool (*fx) (class Character *, void *), 
+                                   void *);
+       virtual MoveResult move(int dx, int dy);
+       virtual void paint(int sx, int sy);
+       virtual void removeMember(class Character *);
+        virtual void save(struct save *save);
+        virtual void setPlace(struct place *place);
+        virtual void setX(int x);
+        virtual void setY(int y);
+        virtual void sleep();
+        virtual void start();
+        virtual void startTurn();
+        virtual void switchOrder(class Character *ch1, class Character *ch2);
+       virtual bool turn_vehicle();
+        virtual void applyEffect(closure_t *effect);
+        virtual Object *getSpeaker();
+        virtual bool isStationary();
+
+        // NOTE: dup of getMemberAtIndex in player.cpp
+        virtual class Character *getMemberByOrder(int order);
+        virtual class Container *getInventory();
+
+        void removeMembers();
+
+       bool attack_with_ordnance(int d);
+       bool gotoSpot(int x, int y);
+        void setVehicle(class Vehicle *vehicle);
+        bool attackPlayer(int dx, int dy);
+
+
+        class Vehicle *getVehicle();
+
+       struct node members; // Linked list of party members
+
+       struct position_info pinfo;
+       void absorbMemberAPDebt();
+       
+
+      protected:
+       class Vehicle *vehicle;
+       int size;
+       bool loitering;
+       struct formation *formation;
+        bool wandering;
+        void (*ctrl)(class Party*);
+};
+
+#endif
diff --git a/src/Reagent.cpp b/src/Reagent.cpp
new file mode 100644 (file)
index 0000000..4ce2a49
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "Reagent.h"
+#include "common.h"
+
+bool ReagentType::isType(int classID)
+{
+       if (classID == REAGENT_TYPE_ID)
+               return true;
+       return ObjectType::isType(classID);
+}
+
+int ReagentType::getType()
+{
+       return REAGENT_TYPE_ID;
+}
+
+ReagentType::ReagentType(char *tag, char *name, struct sprite *sprite)
+        : ObjectType(tag, name, sprite, item_layer)
+{
+}
+
+ReagentType::ReagentType()
+{
+}
+
+ReagentType::~ReagentType()
+{
+}
diff --git a/src/Reagent.h b/src/Reagent.h
new file mode 100644 (file)
index 0000000..9f40ecd
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef Reagent_h
+#define Reagent_h
+
+#include "object.h"
+
+// A reagent is an object that appears in the list of things which a player can
+// (M)ix to make a spell. It has absolutely no interesting or unusual
+// properties other than it's type. And the fact that I have to write a new
+// class to support this tells me I took a wrong turn somewhere.
+
+class ReagentType:public ObjectType {
+ public:
+        virtual bool isType(int classID);
+        virtual int getType();
+        ReagentType();
+        ReagentType(char *tag, char *name, struct sprite *sprite);
+        virtual ~ReagentType();
+};
+
+#endif
diff --git a/src/angband.c b/src/angband.c
new file mode 100644 (file)
index 0000000..8aad20a
--- /dev/null
@@ -0,0 +1,840 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+/* Note: this is a derived work from the Angband 3.0.0 source file cave.c,
+ * which had the following license header attached:
+ *
+ * Copyright (c) 1997 Ben Harrison, James E. Wilson, Robert A. Koeneke
+ *
+ * This software may be copied and distributed for educational, research,
+ * and not for profit purposes provided that this copyright and statement
+ * are included in all such copies.  Other copyrights may also apply.
+ */
+#include "debug.h"
+#include "los.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Wrapper/Stubs for cave.c code *********************************************/
+
+#include <string.h>
+
+typedef unsigned char byte;
+typedef signed short int s16b;
+typedef unsigned short int u16b;
+typedef unsigned int u32b;
+
+#define MAKE(ptr,type) { \
+    (ptr) = (type *)malloc(sizeof(type)); \
+    if (! (ptr)) \
+        return -1; \
+    memset((ptr), 0, sizeof(type)); \
+}
+
+#define KILL(ptr) free((ptr))
+
+/*
+ * Convert a "location" (Y,X) into a "grid" (G)
+ */
+#define GRID(Y,X,W) \
+       ((W) * (Y) + (X))
+
+/*
+ * Convert a "grid" (G) into a "location" (Y)
+ */
+#define GRID_Y(G,W) \
+       ((int)((G) / (W)))
+
+/*
+ * Convert a "grid" (G) into a "location" (X)
+ */
+#define GRID_X(G,W) \
+       ((int)((G) % (W)))
+
+/*
+ * Maximum possible sight radius minus one.
+ */
+#define MAX_SIGHT 19           /* 19 */
+
+/* From xtra2.c **************************************************************/
+
+/*
+ * Current "comp" function for ang_sort()
+ */
+int (*ang_sort_comp) (const void *u, const void *v, int a, int b);
+
+/*
+ * Current "swap" function for ang_sort()
+ */
+void (*ang_sort_swap) (void *u, void *v, int a, int b);
+
+/*
+ * Angband sorting algorithm -- quick sort in place
+ *
+ * Note that the details of the data we are sorting is hidden,
+ * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
+ * function hooks to interact with the data, which is given as
+ * two pointers, and which may have any user-defined form.
+ */
+void ang_sort_aux(void *u, void *v, int p, int q)
+{
+       int z, a, b;
+
+       /* Done sort */
+       if (p >= q)
+               return;
+
+       /* Pivot */
+       z = p;
+
+       /* Begin */
+       a = p;
+       b = q;
+
+       /* Partition */
+       while (1) {
+               /* Slide i2 */
+               while (!(*ang_sort_comp) (u, v, b, z))
+                       b--;
+
+               /* Slide i1 */
+               while (!(*ang_sort_comp) (u, v, z, a))
+                       a++;
+
+               /* Done partition */
+               if (a >= b)
+                       break;
+
+               /* Swap */
+               (*ang_sort_swap) (u, v, a, b);
+
+               /* Advance */
+               a++, b--;
+       }
+
+       /* Recurse left side */
+       ang_sort_aux(u, v, p, b);
+
+       /* Recurse right side */
+       ang_sort_aux(u, v, b + 1, q);
+}
+
+/*
+ * Angband sorting algorithm -- quick sort in place
+ *
+ * Note that the details of the data we are sorting is hidden,
+ * and we rely on the "ang_sort_comp()" and "ang_sort_swap()"
+ * function hooks to interact with the data, which is given as
+ * two pointers, and which may have any user-defined form.
+ */
+void ang_sort(void *u, void *v, int n)
+{
+       /* Sort the array */
+       ang_sort_aux(u, v, 0, n - 1);
+}
+
+/* Modified from cave.c ******************************************************/
+
+/*
+ * Approximate distance between two points.
+ *
+ * When either the X or Y component dwarfs the other component,
+ * this function is almost perfect, and otherwise, it tends to
+ * over-estimate about one grid per fifteen grids of distance.
+ *
+ * Algorithm: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2
+ */
+int distance(int y1, int x1, int y2, int x2)
+{
+       int ay, ax;
+
+       /* Find the absolute y/x distance components */
+       ay = (y1 > y2) ? (y1 - y2) : (y2 - y1);
+       ax = (x1 > x2) ? (x1 - x2) : (x2 - x1);
+
+       /* Hack -- approximate the distance */
+       return ((ay > ax) ? (ay + (ax >> 1)) : (ax + (ay >> 1)));
+}
+
+/*
+ * Maximum number of grids in a single octant
+ */
+//#define VINFO_MAX_GRIDS 161
+#define VINFO_MAX_GRIDS 147
+
+/*
+ * Maximum number of slopes in a single octant
+ */
+//#define VINFO_MAX_SLOPES 126
+#define VINFO_MAX_SLOPES 113
+
+/*
+ * Mask of bits used in a single octant
+ */
+//#define VINFO_BITS_3 0x3FFFFFFF
+#define VINFO_BITS_3 0x0001FFFF
+#define VINFO_BITS_2 0xFFFFFFFF
+#define VINFO_BITS_1 0xFFFFFFFF
+#define VINFO_BITS_0 0xFFFFFFFF
+
+/*
+ * The 'vinfo_type' structure. There is one of these for each possible grid
+ * location in an octant.
+ */
+struct vinfo_type {
+       s16b grid[8]; /* the location of this grid cell in each of the 8
+                       * octants */
+       u32b bits_3;  /* the rays which strike this grid cell */
+       u32b bits_2;  /* the rays which strike this grid cell */
+       u32b bits_1;  /* the rays which strike this grid cell */
+       u32b bits_0;  /* the rays which strike this grid cell */
+
+       struct vinfo_type *next_0; /* grid to the right */
+       struct vinfo_type *next_1; /* grid to the right and down (usually) */
+
+       byte y;
+       byte x;
+       byte d;
+       byte r;
+};
+
+/*
+ * Slope scale factor
+ */
+#define SCALE 100000L
+
+/*
+ * Temporary data used by "vinfo_init()"
+ */
+struct vinfo_hack {
+       int num_slopes;
+       long slopes[VINFO_MAX_SLOPES];
+       long slopes_min[MAX_SIGHT + 1][MAX_SIGHT + 1];
+       long slopes_max[MAX_SIGHT + 1][MAX_SIGHT + 1];
+};
+
+/*
+ * Sorting hook -- comp function -- array of long's (see below)
+ *
+ * We use "u" to point to an array of long integers.
+ */
+static int ang_sort_comp_hook_longs(const void *u, const void *v, int a, int b)
+{
+       long *x = (long *) (u);
+
+       /* Unused parameter */
+       (void) v;
+
+       return (x[a] <= x[b]);
+}
+
+/*
+ * Sorting hook -- comp function -- array of long's (see below)
+ *
+ * We use "u" to point to an array of long integers.
+ */
+static void ang_sort_swap_hook_longs(void *u, void *v, int a, int b)
+{
+       long *x = (long *) (u);
+
+       long temp;
+
+       /* Unused parameter */
+       (void) v;
+
+       /* Swap */
+       temp = x[a];
+       x[a] = x[b];
+       x[b] = temp;
+}
+
+/*
+ * Save a slope
+ */
+static void vinfo_init_aux(struct vinfo_hack *hack, int y, int x, long m)
+{
+       int i;
+
+       /* Handle "legal" slopes */
+       if ((m > 0) && (m <= SCALE)) {
+               /* Look for that slope */
+               for (i = 0; i < hack->num_slopes; i++) {
+                       if (hack->slopes[i] == m)
+                               break;
+               }
+
+               /* New slope */
+               if (i == hack->num_slopes) {
+                       /* Paranoia */
+                       if (hack->num_slopes >= VINFO_MAX_SLOPES) {
+                               err("Too many slopes (%d)!", VINFO_MAX_SLOPES);
+                               exit(-1);
+                       }
+
+                       /* Save the slope, and advance */
+                       hack->slopes[hack->num_slopes++] = m;
+               }
+       }
+
+       /* Track slope range */
+       if (hack->slopes_min[y][x] > m)
+               hack->slopes_min[y][x] = m;
+       if (hack->slopes_max[y][x] < m)
+               hack->slopes_max[y][x] = m;
+}
+
+/*
+ * Initialize the "vinfo" array
+ *
+ * Full Octagon (radius 20), Grids=1149
+ *
+ * Quadrant (south east), Grids=308, Slopes=251
+ *
+ * Octant (east then south), Grids=161, Slopes=126
+ *
+ * This function assumes that VINFO_MAX_GRIDS and VINFO_MAX_SLOPES
+ * have the correct values, which can be derived by setting them to
+ * a number which is too high, running this function, and using the
+ * error messages to obtain the correct values.
+ *
+ * Note: I eliminated the static vinfo object and replaced it with one
+ * dynamically allocated and associated with each instance of an angband
+ * los object. That's why we now pass the vinfo array in.
+ *
+ * Also, as per my comments above the GRID macros (see above), converting
+ * coordinates to grid indices is no longer hardcoded for a 256-wide grid
+ * array. The width of the grid array is now dynamic and passed in as
+ * a parameter.
+ */
+int vinfo_init(struct vinfo_type *vinfo, int width)
+{
+       int i, g;
+       int y, x;
+       long m;
+       struct vinfo_hack *hack;
+       int num_grids = 0;
+       int queue_head = 0;
+       int queue_tail = 0;
+       struct vinfo_type *queue[VINFO_MAX_GRIDS * 2];
+
+        /* Max width of a single octant (center of grid to edge of LOS) */
+        const int max_sight = width/2;
+
+       /* Make hack */
+       MAKE(hack, struct vinfo_hack);
+
+       /* Analyze grids */
+       for (y = 0; y <= max_sight; ++y) {
+               for (x = y; x <= max_sight; ++x) {
+                       /* Skip grids which are out of sight range */
+                       if (distance(0, 0, y, x) > max_sight)
+                               continue;
+
+                       /* Default slope range */
+                       hack->slopes_min[y][x] = 999999999;
+                       hack->slopes_max[y][x] = 0;
+
+                       /* Paranoia */
+                       if (num_grids >= VINFO_MAX_GRIDS) {
+                               err("Too many grids (%d >= %d)!",
+                                   num_grids, VINFO_MAX_GRIDS);
+                               exit(-1);
+                       }
+
+                       /* Count grids */
+                       num_grids++;
+
+                       /* Slope to the top right corner */
+                       m = SCALE * (1000L * y - 500) / (1000L * x + 500);
+
+                       /* Handle "legal" slopes */
+                       vinfo_init_aux(hack, y, x, m);
+
+                       /* Slope to top left corner */
+                       m = SCALE * (1000L * y - 500) / (1000L * x - 500);
+
+                       /* Handle "legal" slopes */
+                       vinfo_init_aux(hack, y, x, m);
+
+                       /* Slope to bottom right corner */
+                       m = SCALE * (1000L * y + 500) / (1000L * x + 500);
+
+                       /* Handle "legal" slopes */
+                       vinfo_init_aux(hack, y, x, m);
+
+                       /* Slope to bottom left corner */
+                       m = SCALE * (1000L * y + 500) / (1000L * x - 500);
+
+                       /* Handle "legal" slopes */
+                       vinfo_init_aux(hack, y, x, m);
+               }
+       }
+
+       /* Enforce maximal efficiency */
+       if (num_grids < VINFO_MAX_GRIDS) {
+               warn("Too few grids (%d < %d)!\n", num_grids, VINFO_MAX_GRIDS);
+       }
+
+       /* Enforce maximal efficiency */
+       if (hack->num_slopes < VINFO_MAX_SLOPES) {
+               warn("Too few slopes (%d < %d)!\n",
+                   hack->num_slopes, VINFO_MAX_SLOPES);
+       }
+
+       /* Sort slopes numerically */
+       ang_sort_comp = ang_sort_comp_hook_longs;
+
+       /* Sort slopes numerically */
+       ang_sort_swap = ang_sort_swap_hook_longs;
+
+       /* Sort the (unique) slopes */
+       ang_sort(hack->slopes, NULL, hack->num_slopes);
+
+       /* Enqueue player grid */
+       queue[queue_tail++] = &vinfo[0];
+
+       /* Process queue */
+       while (queue_head < queue_tail) {
+               int e;
+
+               /* Index */
+               e = queue_head++;
+
+               if (e == VINFO_MAX_GRIDS)
+                       break;
+
+               /* Main Grid */
+               g = vinfo[e].grid[0];
+
+               /* Location */
+               y = GRID_Y(g, width);
+               x = GRID_X(g, width);
+
+               /* compute grid offsets */
+               vinfo[e].grid[0] = GRID(+y, +x, width);
+               vinfo[e].grid[1] = GRID(+x, +y, width);
+               vinfo[e].grid[2] = GRID(+x, -y, width);
+               vinfo[e].grid[3] = GRID(+y, -x, width);
+               vinfo[e].grid[4] = GRID(-y, -x, width);
+               vinfo[e].grid[5] = GRID(-x, -y, width);
+               vinfo[e].grid[6] = GRID(-x, +y, width);
+               vinfo[e].grid[7] = GRID(-y, +x, width);
+
+               /* Analyze slopes */
+               for (i = 0; i < hack->num_slopes; ++i) {
+                       m = hack->slopes[i];
+
+                       /* Memorize intersection slopes (for non-player-grids) */
+                       if ((e > 0) &&
+                           (hack->slopes_min[y][x] < m) &&
+                           (m < hack->slopes_max[y][x])) {
+                               switch (i / 32) {
+                               case 3:
+                                       vinfo[e].bits_3 |= (1L << (i % 32));
+                                       break;
+                               case 2:
+                                       vinfo[e].bits_2 |= (1L << (i % 32));
+                                       break;
+                               case 1:
+                                       vinfo[e].bits_1 |= (1L << (i % 32));
+                                       break;
+                               case 0:
+                                       vinfo[e].bits_0 |= (1L << (i % 32));
+                                       break;
+                               }
+                       }
+               }
+
+               /* Default */
+               vinfo[e].next_0 = &vinfo[0];
+
+               /* Grid next child */
+               if (distance(0, 0, y, x + 1) <= max_sight) {
+                       g = GRID(y, x + 1, width);
+
+                       if (queue[queue_tail - 1]->grid[0] != g) {
+                               vinfo[queue_tail].grid[0] = g;
+                               queue[queue_tail] = &vinfo[queue_tail];
+                               queue_tail++;
+                       }
+
+                       vinfo[e].next_0 = &vinfo[queue_tail - 1];
+               }
+
+               /* Default */
+               vinfo[e].next_1 = &vinfo[0];
+
+               /* Grid diag child */
+               if (distance(0, 0, y + 1, x + 1) <= max_sight) {
+                       g = GRID(y + 1, x + 1, width);
+
+                       if (queue[queue_tail - 1]->grid[0] != g) {
+                               vinfo[queue_tail].grid[0] = g;
+                               queue[queue_tail] = &vinfo[queue_tail];
+                               queue_tail++;
+                       }
+
+                       vinfo[e].next_1 = &vinfo[queue_tail - 1];
+               }
+
+               /* Hack -- main diagonal has special children */
+               if (y == x)
+                        vinfo[e].next_0 = vinfo[e].next_1;
+
+               /* Extra values */
+               vinfo[e].y = y;
+               vinfo[e].x = x;
+               vinfo[e].d = ((y > x) ? (y + x / 2) : (x + y / 2));
+               vinfo[e].r = ((!y) ? x : (!x) ? y : (y == x) ? y : 0);
+       }
+
+       /* Verify maximal bits XXX XXX XXX */
+       if (((vinfo[1].bits_3 | vinfo[2].bits_3) != VINFO_BITS_3) ||
+           ((vinfo[1].bits_2 | vinfo[2].bits_2) != VINFO_BITS_2) ||
+           ((vinfo[1].bits_1 | vinfo[2].bits_1) != VINFO_BITS_1) ||
+           ((vinfo[1].bits_0 | vinfo[2].bits_0) != VINFO_BITS_0)) {
+               warn("Incorrect bit masks!\n");
+       }
+
+       /* Kill hack */
+       KILL(hack);
+
+       /* Success */
+       return (0);
+}
+
+/* gmcnutt: variable los */
+#ifndef USE_VLOS
+#define USE_VLOS 1
+#endif
+
+/* gmcnutt: max ray strength for vlos */
+#define MAX_RAY_STRENGTH 12
+
+/* gmcnutt: for vlos, track ray strength in each octant */
+static unsigned char ray_strength[VINFO_MAX_SLOPES];
+
+#define OPAQUE(val)  ((val) == (MAX_RAY_STRENGTH))
+#define VISIBLE(val) ((val)  < (MAX_RAY_STRENGTH))
+
+static void check_ray_set(u32b *ray_set, u32b ray_mask, int ray_index, unsigned char tile_val, int diag)
+{
+        int ray_bit = 1;
+        unsigned int ray_num;
+
+        /* walk the rays */
+        for (ray_num = 0; ray_num < sizeof(*ray_set)*8; ray_num++) {
+                                                
+                /* if this ray strikes this grid */
+                if (ray_bit & ray_mask) {
+                                                        
+                        /* decrement ray
+                         * strength by grid
+                         * opacity */
+                        int ray_val = ray_strength[ray_index];
+                        ray_val -= tile_val;
+
+                       // Due to the way the rays are cast
+                       // (Bresenham algorithm), odd effects
+                       // were seen on perfect diagonals.
+                       // 
+                       // A perfect diagonal (degrees 45, 135, 225, 315)
+                       // gets treated as distance n, rather than n * sqrt(2)
+                       // and as such, a "spike" of longer LOS on the diagonals
+                       // was seen.
+                       // 
+                       // To avoid this artifact, we aproximate additional 
+                       // ray strength reduction to correct this.
+                       // Thus far we have reduced by (n * 1), 
+                       // so we reduce by (n * 0.5) more, for a total of 1.5.
+                       // This is a fair approximation of sqrt(2) ~ 1.41,
+                       // and gets rid of the LOS "spikes"
+                       // 
+                        if (ray_index==(VINFO_MAX_SLOPES-1)) {
+                                ray_val -= (tile_val / 2);
+                        }
+
+                        if (ray_val < 0) {
+                                ray_val = 0;
+                        }
+
+                        if (!ray_val) {
+                                *ray_set &= ~ray_bit;
+                        }
+
+                        ray_strength[ray_index] = ray_val;
+                }
+                                                
+                ray_bit <<=1;
+                ray_index++;
+        }
+}
+
+/*
+ * Calculate the complete field of view using a new algorithm
+ *
+ * If "view_g" and "temp_g" were global pointers to arrays of grids, as
+ * opposed to actual arrays of grids, then we could be more efficient by
+ * using "pointer swapping".
+ *
+ * Note the following idiom, which is used in the function below.
+ * This idiom processes each "octant" of the field of view, in a
+ * clockwise manner, starting with the east strip, south side,
+ * and for each octant, allows a simple calculation to set "g"
+ * equal to the proper grids, relative to "pg", in the octant.
+ *
+ *   for (o2 = 0; o2 < 8; o2++)
+ *   ...
+ *         g = pg + p->grid[o2];
+ *   ...
+ *
+ *
+ * Normally, vision along the major axes is more likely than vision
+ * along the diagonal axes, so we check the bits corresponding to
+ * the lines of sight near the major axes first.
+ *
+ * We use the "temp_g" array (and the "CAVE_TEMP" flag) to keep track of
+ * which grids were previously marked "CAVE_SEEN", since only those grids
+ * whose "CAVE_SEEN" value changes during this routine must be redrawn.
+ *
+ * This function is now responsible for maintaining the "CAVE_SEEN"
+ * flags as well as the "CAVE_VIEW" flags, which is good, because
+ * the only grids which normally need to be memorized and/or redrawn
+ * are the ones whose "CAVE_SEEN" flag changes during this routine.
+ *
+ * Basically, this function divides the "octagon of view" into octants of
+ * grids (where grids on the main axes and diagonal axes are "shared" by
+ * two octants), and processes each octant one at a time, processing each
+ * octant one grid at a time, processing only those grids which "might" be
+ * viewable, and setting the "CAVE_VIEW" flag for each grid for which there
+ * is an (unobstructed) line of sight from the center of the player grid to
+ * any internal point in the grid (and collecting these "CAVE_VIEW" grids
+ * into the "view_g" array), and setting the "CAVE_SEEN" flag for the grid
+ * if, in addition, the grid is "illuminated" in some way.
+ *
+ * This function relies on a theorem (suggested and proven by Mat Hostetter)
+ * which states that in each octant of a field of view, a given grid will
+ * be "intersected" by one or more unobstructed "lines of sight" from the
+ * center of the player grid if and only if it is "intersected" by at least
+ * one such unobstructed "line of sight" which passes directly through some
+ * corner of some grid in the octant which is not shared by any other octant.
+ * The proof is based on the fact that there are at least three significant
+ * lines of sight involving any non-shared grid in any octant, one which
+ * intersects the grid and passes though the corner of the grid closest to
+ * the player, and two which "brush" the grid, passing through the "outer"
+ * corners of the grid, and that any line of sight which intersects a grid
+ * without passing through the corner of a grid in the octant can be "slid"
+ * slowly towards the corner of the grid closest to the player, until it
+ * either reaches it or until it brushes the corner of another grid which
+ * is closer to the player, and in either case, the existanc of a suitable
+ * line of sight is thus demonstrated.
+ *
+ * It turns out that in each octant of the radius 20 "octagon of view",
+ * there are 161 grids (with 128 not shared by any other octant), and there
+ * are exactly 126 distinct "lines of sight" passing from the center of the
+ * player grid through any corner of any non-shared grid in the octant.  To
+ * determine if a grid is "viewable" by the player, therefore, you need to
+ * simply show that one of these 126 lines of sight intersects the grid but
+ * does not intersect any wall grid closer to the player.  So we simply use
+ * a bit vector with 126 bits to represent the set of interesting lines of
+ * sight which have not yet been obstructed by wall grids, and then we scan
+ * all the grids in the octant, moving outwards from the player grid.  For
+ * each grid, if any of the lines of sight which intersect that grid have not
+ * yet been obstructed, then the grid is viewable.  Furthermore, if the grid
+ * is a wall grid, then all of the lines of sight which intersect the grid
+ * should be marked as obstructed for future reference.  Also, we only need
+ * to check those grids for whom at least one of the "parents" was a viewable
+ * non-wall grid, where the parents include the two grids touching the grid
+ * but closer to the player grid (one adjacent, and one diagonal).  For the
+ * bit vector, we simply use 4 32-bit integers.  All of the static values
+ * which are needed by this function are stored in the large "vinfo" array
+ * (above), which is machine generated by another program.  XXX XXX XXX
+ *
+ * Hack -- The queue must be able to hold more than VINFO_MAX_GRIDS grids
+ * because the grids at the edge of the field of view use "grid zero" as
+ * their children, and the queue must be able to hold several of these
+ * special grids.  Because the actual number of required grids is bizarre,
+ * we simply allocate twice as many as we would normally need.  XXX XXX XXX
+ */
+void update_view(struct los *los)
+{
+       int pg;
+       int g;
+       int o2;
+       struct vinfo_type *vinfo = (struct vinfo_type *) los->data;
+
+       /* Set pg to be the center */
+       pg = los->h / 2 * los->w + los->w / 2;
+
+       /* Initialize the mask to make everything unseen */
+       memset(los->vmask, 0, los->w * los->h);
+
+       /* Scan each octant */
+       for (o2 = 0; o2 < 8; o2++) {
+               struct vinfo_type *p;
+
+                if (USE_VLOS) {
+                        /* Initially all rays at max strength */
+                        memset(ray_strength, MAX_RAY_STRENGTH, sizeof(ray_strength));
+                }
+
+               /* Last added */
+               struct vinfo_type *last = &vinfo[0];
+
+               /* Grid queue */
+               int queue_head = 0;
+               int queue_tail = 0;
+               struct vinfo_type *queue[VINFO_MAX_GRIDS * 2];
+
+               /* Slope bit vector */
+               u32b bits0 = VINFO_BITS_0;
+               u32b bits1 = VINFO_BITS_1;
+               u32b bits2 = VINFO_BITS_2;
+               u32b bits3 = VINFO_BITS_3;
+
+               /* Reset queue */
+               queue_head = queue_tail = 0;
+
+               /* Initial grids */
+               queue[queue_tail++] = &vinfo[1];
+               queue[queue_tail++] = &vinfo[2];
+
+               /* Process queue */
+               while (queue_head < queue_tail) {
+
+                       /* Dequeue next grid */
+                       p = queue[queue_head++];
+
+                       /* Limit LOS to the radius if given (creating a circle
+                        * of visibility centered on the middle). Otherwise
+                        * limit it to the view dimensions (making the entire
+                        * square window potentially visible). */
+                       if (los->r > 0) {
+                               if (p->d > los->r)
+                                       continue;
+                       } else {
+                               if (p->x > los->w / 2 || p->y > los->h / 2)
+                                       continue;
+                       }
+
+                       /* If none of the unblocked rays strike this grid then
+                        * skip it. */
+                       if (!((bits0 & (p->bits_0)) ||
+                             (bits1 & (p->bits_1)) ||
+                             (bits2 & (p->bits_2)) || (bits3 & (p->bits_3))))
+                               continue;
+
+                       /* Extract grid value XXX XXX XXX */
+                       g = pg + p->grid[o2];
+
+                       /* If this grid is out-of-bounds then skip it (this
+                        * happens on children of edge grids */
+                       if (g < 0 || g >= (los->w * los->h))
+                               continue;
+
+                       /* This grid is visible so unmask it. */
+                       los->vmask[g] = 1;
+
+                       /* If this grid is opaque then mask out the rays which
+                        * strike it and do NOT queue it's children. */
+                       {
+
+                                int ray_index = 0;
+                                unsigned char tile_val = los->alpha[g];
+                                int diag = abs(GRID_Y(g,los->w))==abs(GRID_X(g,los->w));
+                                
+                                /* check rays in first set */
+                                if (bits0 & (p->bits_0)) {
+                                        check_ray_set(&bits0, p->bits_0, ray_index, tile_val, diag);
+                                }
+                                ray_index += (sizeof(bits0)*8);
+
+                                /* check rays in next set */
+                                if (bits1 & (p->bits_1)) {
+                                        check_ray_set(&bits1, p->bits_1, ray_index, tile_val, diag);
+                                }
+                                ray_index += (sizeof(bits1)*8);
+
+                                /* check rays in next set */
+                                if (bits2 & (p->bits_2)) {
+                                        check_ray_set(&bits2, p->bits_2, ray_index, tile_val, diag);
+                                }
+                                ray_index += (sizeof(bits2)*8);
+
+                                /* check rays in next set */
+                                if (bits3 & (p->bits_3)) {
+                                        check_ray_set(&bits3, p->bits_3, ray_index, tile_val, diag);
+                                }
+                                ray_index += (sizeof(bits3)*8);
+                        }
+
+                       /* This grid is transparent so queue it's children */
+                       if (last != p->next_0)
+                               queue[queue_tail++] = last = p->next_0;
+                       if (last != p->next_1)
+                               queue[queue_tail++] = last = p->next_1;
+
+               } // while (queue_head < queue_tail)
+
+       } // for (octant o2)
+
+} // update_view()
+
+
+/* los lib stuff *************************************************************/
+
+static void ANGBAND_destroy(struct los *los)
+{
+       free(los->data);
+}
+
+static void ANGBAND_compute(struct los *los)
+{
+       update_view(los);
+       los->vmask[(los->w * los->h) / 2] = 1;  /* make center always
+                                                 * visible */
+}
+
+int ANGBAND_Init(struct los *los)
+{
+       struct vinfo_type *vinfo;
+
+        if (los->data) {
+                free(los->data);
+        }
+
+       vinfo = (struct vinfo_type *) malloc((VINFO_MAX_GRIDS + 1) *
+                                            sizeof(struct vinfo_type));
+       if (!vinfo)
+               return -1;
+       memset(vinfo, 0, (VINFO_MAX_GRIDS + 1) * sizeof(struct vinfo_type));
+
+       if (vinfo_init(vinfo, los->w) < 0)
+               return -1;
+
+       los->data = vinfo;
+       los->destroy = ANGBAND_destroy;
+       los->compute = ANGBAND_compute;
+
+       return 0;
+
+}
diff --git a/src/applet.h b/src/applet.h
new file mode 100644 (file)
index 0000000..d789bbc
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef applet_h
+#define applet_h
+
+/**
+ * An applet is a little mini-program that runs in the status window. It is
+ * invoked via statusRunApplet. Applets can start and run other applets in a
+ * strictly nested fashion.
+ */
+
+#include "list.h"
+
+#include <SDL.h>
+
+/**
+ * The applet's call table. These functions are called by the status code when
+ * it runs the applet.
+ */
+struct applet_ops {
+
+        /**
+         * Run an applet. This is called to start the applet. It should not
+         * return until the applet is done. This function is required.
+         *
+         * @param applet is the applet instance.
+         * @param dims gives the screen coordinates (in pixels) of the window
+         * the applet occupies. The applet will paint to this window in its
+         * paint operation.
+         * @param session is the current session (identical to the global
+         * variable Session, but using this parameter is preferred for all new
+         * code).
+         */
+        void (*run)(struct applet *applet, SDL_Rect *dims, struct session *session);
+
+        /**
+         * Paint the applet. This function is required. The status code calls
+         * this function for animation repaints. If the applet wants to repaint
+         * itself it should typically call statusRepaint(), which will invoke
+         * this function in a standard way.
+         *
+         * @param applet is the applet instance.
+         */
+        void (*paint)(struct applet *applet);
+
+        /**
+         * Get the desired height (in lines) that the applet wants to use for
+         * its window. This is called prior to run, so the status code can
+         * resize the window before starting the applet. This function is
+         * optional: if the pointer is NULL then the status code will assume
+         * the window should be the standard tall mode size.
+         *
+         * @param applet is the applet instance.
+         */
+        int (*get_desired_height)(struct applet *applet);
+};
+
+/**
+ * The applet instance structure. Most applet implementations will extend this
+ * structure with their own fields.
+ */
+struct applet {
+        struct list list; /* used to stack applets in the status code */
+        SDL_Rect dims; /* window dimensions passed into run may be kept here */
+        struct session *session; /* the session pointer passed to run may be kept here */
+        struct applet_ops *ops; /* the applet's call table */
+};
+
+#endif
diff --git a/src/ascii.c b/src/ascii.c
new file mode 100644 (file)
index 0000000..db8c0f9
--- /dev/null
@@ -0,0 +1,623 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "ascii.h"
+#include "images.h"
+#include "screen.h"
+#include "common.h"
+#include "cfg.h"
+#include "dimensions.h"
+
+#include <SDL_image.h>
+
+#include <assert.h>
+
+
+#define DEBUG 0
+#if DEBUG
+/* To see the function names in backtraces, you need to ask gcc to
+ * add them to the binary with the -rdynamic linker (LDFLAGS) option
+ * and disable the static keyword for objects which static functions
+ * you'd like to see, either with -Dstatic= compiler option or just
+ * using in those sources following: */
+#define static
+
+#include <execinfo.h>
+#define MAX_STACK_DEPTH 16
+static void backtrace2stderr(void)
+{
+       int depth;
+       void *bt[MAX_STACK_DEPTH];
+       depth = backtrace(bt, MAX_STACK_DEPTH);
+       if (depth > 1) {
+               /* skip this fuction and C++ main, show rest */
+               backtrace_symbols_fd(bt+1, depth-2, 2);
+       }
+}
+#endif /* DEBUG */
+
+
+#define ASCII_DEF_CLR White /* default printing color is white */
+#define ASCII_CLR_STK_SZ 32
+
+/* State machine states for embedded control sequences. */
+enum ascii_ctrl_states {
+        ASCII_STATE_DEF = 0,
+        ASCII_STATE_ESC,
+        ASCII_STATE_CLR,
+        ASCII_STATE_CLRPUSH
+};
+
+/* This is a default character image set in XPM format. For emergency use
+ * only. */
+static const char * charset_xpm[] = {
+"128 144 44 1",
+"      c None",
+".     c #000000",
+"+     c #004040",
+"@     c #20FCFC",
+"#     c #E0FCFC",
+"$     c #000060",
+"%     c #000080",
+"&     c #0000A0",
+"*     c #0000C0",
+"=     c #E8E8E8",
+"-     c #C0C0C0",
+";     c #808080",
+">     c #FCFCFC",
+",     c #B0B0B0",
+"'     c #D4D4D4",
+")     c #008080",
+"!     c #006060",
+"~     c #800000",
+"{     c #FC1000",
+"]     c #404040",
+"^     c #505050",
+"/     c #4040FC",
+"(     c #600000",
+"_     c #400000",
+":     c #A0A0A0",
+"<     c #C0C0FC",
+"[     c #C00000",
+"}     c #303030",
+"|     c #909090",
+"1     c #8080FC",
+"2     c #000040",
+"3     c #0000FC",
+"4     c #6060FC",
+"5     c #0000E0",
+"6     c #A00000",
+"7     c #202020",
+"8     c #101010",
+"9     c #606060",
+"0     c #FCFC80",
+"a     c #FCFCE0",
+"b     c #FCFCA0",
+"c     c #A0A0FC",
+"d     c #FCFC40",
+"e     c #FCFCC0",
+".+@##@+.$%%&*&%$=-;-=-;-=-;-=-;-...;>......;-......;>....+@##@+............->>.....->>.............->>..........,-''''-,........",
+".+@##@+.$%%&*&%$=-;-=-;-=-;-=-;-...;>......;-......;>....+@##@+............->>.....->>.............->>..........,-''''-,........",
+".@#)!#@.%~{{{{~%;.;;;;.;;;;;;;;;..;;->.....;-.....;;->...@#)!#@...];;]....-^^^>...-^^^>......->>..->^->.////////-......-..$&&$..",
+".@#)!#@.%~{{{{~%;.;;;;.;;;;;;;;;..;;->.....;-.....;;->...@#)!#@...];;]....-^^^>...-^^^>......->>..->^->.////////-......-..$&&$..",
+".@#.+#@.&~(__(~&;-=-;-=-;-=-;-=-.;;-->>....;-....;;-->>..........^:'=:^..-.->>^>.-.-->^>....^^->.^->^->.<<<<<<<<'......'.%*//*%.",
+".@#.+#@.&~(__(~&;-=-;-=-;-=-;-=-.;;-->>....;-....;;-->>..........^:'=:^..-.->>^>.-.-->^>....^^->.^->^->.<<<<<<<<'......'.%*//*%.",
+".+@##@+.*~[__[~*;;;;;;;;;;;;;;;;...;;......;-......;;....+@##@+.}|'>>'|}^-^-^.^>^-^->^^>..->>-^>.^^->>..11111111'......'2&341/&2",
+".+@##@+.*~[__[~*;;;;;;;;;;;;;;;;...;;......;-......;;....+@##@+.}|'>>'|}^-^-^.^>^-^->^^>..->>-^>.^^->>..11111111'......'2&341/&2",
+"+@####@+&~(__(~&=-;-=-;-=-;-=-;=...;-......;-......;-...........}|--''|}^-^->>^>^-^-^>^>.->^->^...^^>...////////'......'2&55/3&2",
+"+@####@+&~(__(~&=-;-=-;-=-;-=-;=...;-......;-......;-...........}|--''|}^-^->>^>^-^-^>^>.->^->^...^^>...////////'......'2&55/3&2",
+"..+@#+..%~6__6~%;;;;;;;;;;;;;;;;.;;-->>..;;-->>....;-.....+@#+...^:--:^.^^-^^.>.^^-^^.>.^->^->.....->>..********'......'.%*55*%.",
+"..+@#+..%~6__6~%;;;;;;;;;;;;;;;;.;;-->>..;;-->>....;-.....+@#+...^:--:^.^^-^^.>.^^-^^.>.^->^->.....->>..********'......'.%*55*%.",
+"..+@#+..2%~66~%2;.=-;-.-;-=-;-=-..;;->....;;->.....;-.....+@#+....];;]...^^-->...^^-->..^^->>.....^^-...%%%%%%%%-......-..$&&$..",
+"..+@#+..2%~66~%2;.=-;-.-;-=-;-=-..;;->....;;->.....;-.....+@#+....];;]...^^-->...^^-->..^^->>.....^^-...%%%%%%%%-......-..$&&$..",
+"..+@#+...2%~~%2.;;;;;;;;;;;;;;;;...;>......;>......;-.....+@#+............^^^.....^^^....^^^.......^............,-''''-,........",
+"..+@#+...2%~~%2.;;;;;;;;;;;;;;;;...;>......;>......;-.....+@#+............^^^.....^^^....^^^.......^............,-''''-,........",
+"..................................;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888....2%%&&$..%*55*$..%5/5$2..222$$2.",
+"..................................;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888....2%%&&$..%*55*$..%5/5$2..222$$2.",
+"/*%..........%*/.................,9778...,>978...,>0,7...,>a>,...7,>b,...879>,...8779,...87778..2$2$$%*%$*%%%*5%$5*&*5%22%**%2$2",
+"/*%..........%*/.................,9778...,>978...,>0,7...,>a>,...7,>b,...879>,...8779,...87778..2$2$$%*%$*%%%*5%$5*&*5%22%**%2$2",
+"<5*$........$*5c................;'77778.;>b^778.;>>>b97.|>00a0|.79b>b>;.877^b>;.87777';.8777778.$2&53&%*&%&3/**5***/%/*2$5//5&2%",
+"<5*$........$*5c................;'77778.;>b^778.;>>>b97.|>00a0|.79b>b>;.877^b>;.87777';.8777778.$2&53&%*&%&3/**5***/%/*2$5//5&2%",
+"135%........%531................,=77778.,>a9778.,>bbd;7.,>>>0b,.7;eded-.8779a>,.87777=,.8777778.$%5**3%5&$3**/&/5%/*%/*25*%%*5$%",
+"135%........%531................,=77778.,>a9778.,>bbd;7.,>>>0b,.7;eded-.8779a>,.87777=,.8777778.$%5**3%5&$3**/&/5%/*%/*25*%%*5$%",
+"//5%........%5//................;'77778.;>e^778.;>d>097.|>b>ad|.79b>>>;.877^b>;.87777';.8777778.2*/%*/%5%$5*%%*55%3**5%$/&/**3$&",
+"//5%........%5//................;'77778.;>e^778.;>d>097.|>b>ad|.79b>>>;.877^b>;.87777';.8777778.2*/%*/%5%$5*%%*55%3**5%$/&/**3$&",
+"**%$........$%**........->.->.->.,9778...,>978...,>b,7...,>>0,...7,b>,...879>,...8779,...87778..2*/%/***%2&5//5$*%&35&2$5**/3&%&",
+"**%$........$%**........->.->.->.,9778...,>978...,>b,7...,>>0,...7,b>,...879>,...8779,...87778..2*/%/***%2&5//5$*%&35&2$5**/3&%&",
+"%%$..........$%%........->^->^->..;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888...2%5*&*5$2$2%**%2%*%$$2$2%5*%%%*$",
+"%%$..........$%%........->^->^->..;78.....|^8.....|,7.....|,|.....7,|.....8^|.....87;.....888...2%5*&*5$2$2%**%2%*%$$2$2%5*%%%*$",
+"........................^.^^.^^..................................................................2$5/5%..2$$222..$&&%%2..$*55*%.",
+"........................^.^^.^^..................................................................2$5/5%..2$$222..$&&%%2..$*55*%.",
+"...........->.....->.->.............>..............->>....->........->....->..................................................->",
+"...........->.....->.->.............>..............->>....->........->....->..................................................->",
+"..........^->....^->^->...->.->...->>>>..->...->..->^->..^->.......->....^^->.....->.->....->................................->.",
+"..........^->....^->^->...->.->...->>>>..->...->..->^->..^->.......->....^^->.....->.->....->................................->.",
+"..........^->....^->^->..->>>>>>.->^>^..^->..->..^^->>...->.......->......^^->...^^->>....^->...............................->..",
+"..........^->....^->^->..->>>>>>.->^>^..^->..->..^^->>...->.......->......^^->...^^->>....^->...............................->..",
+"..........^->....^^.^^..^^->^->.^^->>>>.^^..->....->>...^^.......^->.......^->...->>>>>>.->>>>>..........->>>>.............->...",
+"..........^->....^^.^^..^^->^->.^^->>>>.^^..->....->>...^^.......^->.......^->...->>>>>>.->>>>>..........->>>>.............->...",
+"..........^->............->>>>>>.^^^>^->...->....->^->->.........^->.......^->..^^^->>^.^^^->...........^^^^^.............->....",
+"..........^->............->>>>>>.^^^>^->...->....->^->->.........^->.......^->..^^^->>^.^^^->...........^^^^^.............->....",
+"..........^^............^^->^->...->>>>...->..->^->.^->..........^^->......->.....->^->...^->......->..............->....->.....",
+"..........^^............^^->^->...->>>>...->..->^->.^->..........^^->......->.....->^->...^->......->..............->....->.....",
+"...........->............^^.^^...^^^>....->..^->^^->>>............^^->....->.....^^.^^....^^......^->.............^->...->......",
+"...........->............^^.^^...^^^>....->..^->^^->>>............^^->....->.....^^.^^....^^......^->.............^->...->......",
+"..........^^.......................^....^^...^^..^^^^..............^^....^^.......................->..............^^....^.......",
+"..........^^.......................^....^^...^^..^^^^..............^^....^^.......................->..............^^....^.......",
+"...->>.....->.....->>>....->>>...->.^->..->>>>>....->>...->>>>>...->>>....->>>......................->............->......->>>..",
+"...->>.....->.....->>>....->>>...->.^->..->>>>>....->>...->>>>>...->>>....->>>......................->............->......->>>..",
+"..->^->...->>....->^^->..->^^->.^->.^->.^->^^^....->^...^^^^^->..->^^->..->^^->....................->............^^->....->^^->.",
+"..->^->...->>....->^^->..->^^->.^->.^->.^->^^^....->^...^^^^^->..->^^->..->^^->....................->............^^->....->^^->.",
+".->.^->..^^->...^^..^->.^^..^->.^->.^->.^->>>>...->.........->..^->.^->.^->.^->....->......->.....->.....->>>>....^^->..^^..^->.",
+".->.^->..^^->...^^..^->.^^..^->.^->.^->.^->>>>...->.........->..^->.^->.^->.^->....->......->.....->.....->>>>....^^->..^^..^->.",
+"^->.^->...^->......->>.....->>..^->>>>>.^^^^^->.^->>>>.....^->..^^->>>..^^->>>>...^->.....^->....->.....^^^^^......^^->.....->..",
+"^->.^->...^->......->>.....->>..^->>>>>.^^^^^->.^->>>>.....^->..^^->>>..^^->>>>...^->.....^->....->.....^^^^^......^^->.....->..",
+"^->.^->...^->.....->^.....^^^->.^^^^^->.....^->.^->^^->....->....->^^->..^^^^->...^^......^^....^^->................->.....->...",
+"^->.^->...^->.....->^.....^^^->.^^^^^->.....^->.^->^^->....->....->^^->..^^^^->...^^......^^....^^->................->.....->...",
+"^->.^->...^->....->......->.^->.....^->..->.^->.^->.^->...^->...^->.^->.....->.....->......->....^^->....->>>>.....->.....^^....",
+"^->.^->...^->....->......->.^->.....^->..->.^->.^->.^->...^->...^->.^->.....->.....->......->....^^->....->>>>.....->.....^^....",
+"^^->>>....->>>..^->>>>>.^^->>>......^->.^^->>>..^^->>>....^->...^^->>>....->>.....^->.....^->.....^^->..^^^^^.....->.......->...",
+"^^->>>....->>>..^->>>>>.^^->>>......^->.^^->>>..^^->>>....^->...^^->>>....->>.....^->.....^->.....^^->..^^^^^.....->.......->...",
+".^^^^....^^^^...^^^^^^...^^^^.......^^...^^^^....^^^^.....^^.....^^^^....^^^......^^......->.......^^............^^.......^^....",
+".^^^^....^^^^...^^^^^^...^^^^.......^^...^^^^....^^^^.....^^.....^^^^....^^^......^^......->.......^^............^^.......^^....",
+"..->>>.....->....->>>>....->>>...->>>>...->>>>>..->>>>>...->>>...->..->...->>>.....->>>..->..->..->......->...->.->..->...->>>..",
+"..->>>.....->....->>>>....->>>...->>>>...->>>>>..->>>>>...->>>...->..->...->>>.....->>>..->..->..->......->...->.->..->...->>>..",
+".->^^->...->>>..^->^^->..->^^->.^->^^->.^->^^^..^->^^^...->^^->.^->.^->..^^->.....^^^->.^->.^->.^->.....^->>.->>^->>^->..->^^->.",
+".->^^->...->>>..^->^^->..->^^->.^->^^->.^->^^^..^->^^^...->^^->.^->.^->..^^->.....^^^->.^->.^->.^->.....^->>.->>^->>^->..->^^->.",
+"^->.->>..->^^->.^->.^->.^->.^^..^->.^->.^->.....^->.....^->.^^..^->.^->...^->.......^->.^->.->..^->.....^->>>>>>^->->->.^->.^->.",
+"^->.->>..->^^->.^->.^->.^->.^^..^->.^->.^->.....^->.....^->.^^..^->.^->...^->.......^->.^->.->..^->.....^->>>>>>^->->->.^->.^->.",
+"^->^-^>.^->.^->.^->>>>..^->.....^->.^->.^->>>...^->>>...^->.->>.^->>>>>...^->.......^->.^->>>...^->.....^->^>^->^->^->>.^->.^->.",
+"^->^-^>.^->.^->.^->>>>..^->.....^->.^->.^->>>...^->>>...^->.->>.^->>>>>...^->.......^->.^->>>...^->.....^->^>^->^->^->>.^->.^->.",
+"^->^->>.^->>>>>.^->^^->.^->.....^->.^->.^->^....^->^....^->^^->.^->^^->...^->....->.^->.^->^->..^->.....^->^.^->^->^^->.^->.^->.",
+"^->^->>.^->>>>>.^->^^->.^->.....^->.^->.^->^....^->^....^->^^->.^->^^->...^->....->.^->.^->^->..^->.....^->^.^->^->^^->.^->.^->.",
+"^->^^^..^->.^->.^->.^->.^->..->.^->.^->.^->.....^->.....^->..->.^->.^->...^->...^->.^->.^->^^->.^->.....^->..^->^->.^->.^->.^->.",
+"^->^^^..^->.^->.^->.^->.^->..->.^->.^->.^->.....^->.....^->..->.^->.^->...^->...^->.^->.^->^^->.^->.....^->..^->^->.^->.^->.^->.",
+"^^->>>..^->.^->.^->>>>..^^->>>..^->>>>..^->>>>>.^->.....^^->>>..^->.^->...->>>..^^->>>..^->.^->.^->>>>>.^->..^->^->.^->.^^->>>..",
+"^^->>>..^->.^->.^->>>>..^^->>>..^->>>>..^->>>>>.^->.....^^->>>..^->.^->...->>>..^^->>>..^->.^->.^->>>>>.^->..^->^->.^->.^^->>>..",
+".^^^^...^^..^^..^^^^^....^^^^...^^^^^...^^^^^^..^^.......^^^^...^^..^^...^^^^....^^^^...^^..^^..^^^^^^..^^...^^.^^..^^...^^^^...",
+".^^^^...^^..^^..^^^^^....^^^^...^^^^^...^^^^^^..^^.......^^^^...^^..^^...^^^^....^^^^...^^..^^..^^^^^^..^^...^^.^^..^^...^^^^...",
+".->>>>....->>>...->>>>....->>>...->>>>>..->..->..->..->..->...->.->..->..->..->..->>>>>..^>-....^>.......^->.......^............",
+".->>>>....->>>...->>>>....->>>...->>>>>..->..->..->..->..->...->.->..->..->..->..->>>>>..^>-....^>.......^->.......^............",
+"^->^^->..->^^->.^->^^->..->^^->.^^^->...^->.^->.^->.^->.^->..^->^->.^->.^->.^->.^^^^^->..^>......^>........>......^->...........",
+"^->^^->..->^^->.^->^^->..->^^->.^^^->...^->.^->.^->.^->.^->..^->^->.^->.^->.^->.^^^^^->..^>......^>........>......^->...........",
+"^->.^->.^->.^->.^->.^->.^->.^^....^->...^->.^->.^->.^->.^->..^->^^->->..^->.^->.....->...^>.......^>.......>.....^-.^>..........",
+"^->.^->.^->.^->.^->.^->.^->.^^....^->...^->.^->.^->.^->.^->..^->^^->->..^->.^->.....->...^>.......^>.......>.....^-.^>..........",
+"^->>>>..^->.^->.^->>>>..^^->>>....^->...^->.^->.^->.^->.^->.>^->.^^->...^^->>>.....->....^>........^>......>....^-...^>.........",
+"^->>>>..^->.^->.^->>>>..^^->>>....^->...^->.^->.^->.^->.^->.>^->.^^->...^^->>>.....->....^>........^>......>....^-...^>.........",
+"^->^^...^->.^->.^->.^->..^^^^->...^->...^->.^->.^->.^->.^->>>>->..->->...^^->.....->.....^>.........^-.....>....................",
+"^->^^...^->.^->.^->.^->..^^^^->...^->...^->.^->.^->.^->.^->>>>->..->->...^^->.....->.....^>.........^-.....>....................",
+"^->.....^->.>>>.^->.^->..->.^->...^->...^->.^->.^^->>>..^->>^->>.->^^->...^->....->......^>..........^-....>....................",
+"^->.....^->.>>>.^->.^->..->.^->...^->...^->.^->.^^->>>..^->>^->>.->^^->...^->....->......^>..........^-....>....................",
+"^->.....^^->->..^->.^->.^^->>>....^->...^^->>>...^^->...^->.^^->^->.^->...^->...^->>>>>..^>-..........^..^->....................",
+"^->.....^^->->..^->.^->.^^->>>....^->...^^->>>...^^->...^->.^^->^->.^->...^->...^->>>>>..^>-..........^..^->....................",
+"^^.......^^^^->.^^..^^...^^^^.....^^.....^^^^.....^^....^^...^^.^^..^^....^^....^^^^^^..................................>>>>>>>>",
+"^^.......^^^^->.^^..^^...^^^^.....^^.....^^^^.....^^....^^...^^.^^..^^....^^....^^^^^^..................................>>>>>>>>",
+".^>..............->..................->............->>...........->........->........->..->.......->>...........................",
+".^>..............->..................->............->>...........->........->........->..->.......->>...........................",
+".^>^............^->.................^->...........->^->.........^->.......^^........^^..^->......^^->...........................",
+".^>^............^->.................^->...........->^->.........^->.......^^........^^..^->......^^->...........................",
+"..^-......->>>..^->.......->>>......^->...->>>...^->^^....->>>>.^->.......->>.......->>.^->..->...^->....->>.>>..->>>>....->>>..",
+"..^-......->>>..^->.......->>>......^->...->>>...^->^^....->>>>.^->.......->>.......->>.^->..->...^->....->>.>>..->>>>....->>>..",
+".........^^^^->.^->>>>...->^^->...->>>>..->^^->..->>>....->^^->.^->>>>...^^->......^^->.^->.->....^->...^->>>>>>^->^^->..->^^->.",
+".........^^^^->.^->>>>...->^^->...->>>>..->^^->..->>>....->^^->.^->>>>...^^->......^^->.^->.->....^->...^->>>>>>^->^^->..->^^->.",
+"..........->>>>.^->^^->.^->.^^...->^^->.^->>>>>.^^->....^->.^->.^->^^->...^->.......^->.^->>>.....^->...^->^>^->^->.^->.^->.^->.",
+"..........->>>>.^->^^->.^->.^^...->^^->.^->>>>>.^^->....^->.^->.^->^^->...^->.......^->.^->>>.....^->...^->^>^->^->.^->.^->.^->.",
+".........->^^->.^->.^->.^->..->.^->.^->.^->^^^...^->....^^->>>>.^->.^->...^->....->.^->.^->^->....^->...^->^.^->^->.^->.^->.^->.",
+".........->^^->.^->.^->.^->..->.^->.^->.^->^^^...^->....^^->>>>.^->.^->...^->....->.^->.^->^->....^->...^->^.^->^->.^->.^->.^->.",
+"........^^->>>>.^->>>>..^^->>>..^^->>>>.^^->>>...^->.....^^^^->.^->.^->...->>>..^->.^->.^->^^->...->>>..^->..^->^->.^->.^^->>>..",
+"........^^->>>>.^->>>>..^^->>>..^^->>>>.^^->>>...^->.....^^^^->.^->.^->...->>>..^->.^->.^->^^->...->>>..^->..^->^->.^->.^^->>>..",
+".........^^^^^..^^^^^....^^^^....^^^^^...^^^^....^^.......->>>..^^..^^...^^^^...^^->>>..^^..^^...^^^^...^^...^^.^^..^^...^^^^...",
+".........^^^^^..^^^^^....^^^^....^^^^^...^^^^....^^.......->>>..^^..^^...^^^^...^^->>>..^^..^^...^^^^...^^...^^.^^..^^...^^^^...",
+"..................................->........................................................->.....->.....->......->>.->........",
+"..................................->........................................................->.....->.....->......->>.->........",
+".................................^->.......................................................->.....^->....^^->....->^->>....^>...",
+".................................^->.......................................................->.....^->....^^->....->^->>....^>...",
+".->>>>....->>>>..->>>>....->>>...->>>....->..->..->..->..->...->.->..->..->..->..->>>>>....->.....^->.....^->...^^.^^^....^-->..",
+".->>>>....->>>>..->>>>....->>>...->>>....->..->..->..->..->...->.->..->..->..->..->>>>>....->.....^->.....^->...^^.^^^....^-->..",
+"^->^^->..->^^->.^->^^->..->^^...^^->....^->.^->.^->.^->.^->.>^->^^->->..^->.^->.^^^^->....->......^^......^^->...........^->^->.",
+"^->^^->..->^^->.^->^^->..->^^...^^->....^->.^->.^->.^->.^->.>^->^^->->..^->.^->.^^^^->....->......^^......^^->...........^->^->.",
+"^->.^->.^->.^->.^->.^^..^^->>>...^->....^->.^->.^->.^->.^->>>>->.^^->...^->.^->....->....^^->......->......->...........^->..^->",
+"^->.^->.^->.^->.^->.^^..^^->>>...^->....^->.^->.^->.^->.^->>>>->.^^->...^->.^->....->....^^->......->......->...........^->..^->",
+"^->>>>..^^->>>>.^->......^^^^->..^->.->.^->.^->.^^->>>..^->>^->>..->->..^^->>>>...->......^->.....^->.....^->...........^->..^->",
+"^->>>>..^^->>>>.^->......^^^^->..^->.->.^->.^->.^^->>>..^->>^->>..->->..^^->>>>...->......^->.....^->.....^->...........^->..^->",
+"^->^^....^^^^->.^->.......->>>...^^->>..^^->>>>..^^->...^->.^^->.->^^->..^^^^->..->>>>>...^^->....^->.....->............^------>",
+"^->^^....^^^^->.^->.......->>>...^^->>..^^->>>>..^^->...^->.^^->.->^^->..^^^^->..->>>>>...^^->....^->.....->............^------>",
+"^->.........^->.^^.......^^^^.....^^^....^^^^^....^^....^^...^^.^^..^^....->>>..^^^^^^.....^^.....^^.....^^.....................",
+"^->.........^->.^^.......^^^^.....^^^....^^^^^....^^....^^...^^.^^..^^....->>>..^^^^^^.....^^.....^^.....^^.....................",
+"................                                                                                                                ",
+"....>>..........                                                                                                                ",
+"..>>>>..........                                                                                                                ",
+">>---->>>>>>>>>>                                                                                                                ",
+";;;;--;;;;;;;;;;                                                                                                                ",
+"..;;;;..........                                                                                                                ",
+"....;;..........                                                                                                                ",
+"................                                                                                                                ",
+"................                                                                                                                ",
+"..........>>....                                                                                                                ",
+"..........>>>>..                                                                                                                ",
+">>>>>>>>------>>                                                                                                                ",
+";;;;;;;;;;--;;;;                                                                                                                ",
+"..........;;;;..                                                                                                                ",
+"..........;;....                                                                                                                ",
+"................                                                                                                                "};
+
+static struct ascii {
+        struct images *images;
+        int offset;
+        ascii_ctrl_states state;
+        Uint32 color_stack[ASCII_CLR_STK_SZ];
+        int i_color;  /* index onto stack */
+        Uint32 color; /* active color */
+} Ascii;
+
+static Uint32  asciiDecodeColor(char clr)
+{
+        switch (clr) {
+        case 'w': return White;
+        case 'B': return Black;
+        case 'r': return TextRed;
+        case 'g': return TextGreen;
+        case 'b': return TextBlue;
+        case 'y': return TextYellow;
+        case 'c': return TextCyan;
+        case 'm': return TextMagenta;
+        case 'G': return Gray;
+        default:
+                warn("Color '%c' unknown\n", clr);
+                return ASCII_DEF_CLR;
+        }
+}
+
+static void asciiPushColor()
+{
+        /* Check for overrun. */
+        if (array_sz(Ascii.color_stack) == Ascii.i_color) {
+                warn("Ascii color stack overrun\n");
+                return;
+        }
+
+        /* Push the new color. */
+        Ascii.color_stack[Ascii.i_color] = Ascii.color;
+        Ascii.i_color++;
+}
+
+static void asciiPopColor()
+{
+        /* Check for underrun. */
+        if (0 == Ascii.i_color) {
+                warn("Ascii color stack already at bottom\n");
+                return;
+        }
+        
+        Ascii.i_color--;
+        Ascii.color = Ascii.color_stack[Ascii.i_color];
+        return;
+}
+
+static void asciiSetColor(char clr)
+{
+        /* Check for a pop. */
+        switch (clr) {
+        case '+': 
+                asciiPushColor();
+                break;
+        case '-':
+                asciiPopColor();
+                break;
+        case '=':
+                /* current color, nop */
+                break;
+        default:
+                Ascii.color = asciiDecodeColor(clr);
+                break;
+        }
+}
+
+static void asciiBlitColored16(SDL_Surface *src, SDL_Rect *srcrect,
+                               SDL_Surface *dst, SDL_Rect *dstrect,
+                               Uint32 color)
+{
+        Uint16 mask = color;
+        Uint16 *srcpix, *dstpix;
+        int x=0, y=0;
+
+        assert(dst->format->BitsPerPixel==16);
+
+        for (y=0; y<dstrect->h; y++) {
+
+                srcpix = (Uint16*)src->pixels 
+                        + (srcrect->y+y)*src->w 
+                        + srcrect->x;
+                dstpix = (Uint16*)dst->pixels 
+                        + (dstrect->y+y)*dst->w 
+                        + dstrect->x;
+
+                for (x=0; x<dstrect->w; x++) {
+                        *dstpix = *srcpix&mask;
+                        srcpix++;
+                        dstpix++;
+                }
+        }
+}
+
+static void asciiBlitColored32(SDL_Surface *src, SDL_Rect *srcrect,
+                               SDL_Surface *dst, SDL_Rect *dstrect,
+                               Uint32 color)
+{
+        Uint32 mask = color;
+        Uint32 *srcpix, *dstpix;
+        int x=0, y=0;
+
+        assert(dst->format->BitsPerPixel==32);
+
+        for (y=0; y<dstrect->h; y++) {
+
+                srcpix = (Uint32*)src->pixels 
+                        + (srcrect->y+y)*src->w 
+                        + srcrect->x;
+                dstpix = (Uint32*)dst->pixels 
+                        + (dstrect->y+y)*dst->w 
+                        + dstrect->x;
+
+                for (x=0; x<dstrect->w; x++) {
+                        *dstpix = *srcpix&mask;
+                        srcpix++;
+                        dstpix++;
+                }
+        }
+}
+
+static void asciiBlitColored(SDL_Surface *src, SDL_Rect *srcrect,
+                             SDL_Surface *dst, SDL_Rect *dstrect,
+                             Uint32 color)
+{
+#if DEBUG
+        if (src->format->BitsPerPixel!=dst->format->BitsPerPixel) {
+               fprintf(stderr,
+                       "ERROR: %dx%d@%d surface not in destination format!\n",
+                       src->w, src->h, src->format->BytesPerPixel);
+               backtrace2stderr();
+               exit(-1);
+       }
+#else
+       assert(src->format->BitsPerPixel==dst->format->BitsPerPixel);
+#endif
+        assert(dstrect->w==srcrect->w);
+        assert(dstrect->h==srcrect->h);
+
+        switch (dst->format->BitsPerPixel) {
+        case 16:
+                asciiBlitColored16(src, srcrect, dst, dstrect, color);
+                break;
+        case 32:
+                asciiBlitColored32(src, srcrect, dst, dstrect, color);
+                break;
+        default:
+                err("asciiBlitColored: unsupported BitsPerPixel: %d\n",
+                    dst->format->BitsPerPixel);
+                break;
+        }
+}
+
+static void asciiPaintColored(unsigned char c, int x, int y, 
+                              SDL_Surface *surf, Uint32 color)
+{
+       SDL_Rect dest;
+       SDL_Rect src;
+       int row;
+       int col;
+
+       assert(Ascii.images);
+
+       if (c == '\t')
+               c = ' ';
+
+       assert(c >= ' ');
+
+        if (c<' ') {
+                warn("c==%d\n", c);
+                c='?';
+        }
+
+       /* fixme -- put these calcs in a table or something. Don't need to do
+        * it every time. */
+       col = c % Ascii.images->cols;
+       row = c / Ascii.images->cols;
+
+       src.x = (col * ASCII_W) + Ascii.images->offx;
+       src.y = (row * ASCII_H) + Ascii.images->offy;
+       src.w = ASCII_W;
+       src.h = ASCII_H;
+
+       dest.x = x;
+       dest.y = y;
+       dest.w = ASCII_W;
+       dest.h = ASCII_H;
+
+        asciiBlitColored(Ascii.images->images, &src, 
+                         surf, &dest, 
+                         color);
+}
+
+static void asciiPaintDefault(unsigned char c, int x, int y, 
+                              SDL_Surface * surf)
+{
+       SDL_Rect dest;
+       SDL_Rect src;
+       int row;
+       int col;
+
+       assert(Ascii.images);
+
+       if (c == '\t')
+               c = ' ';
+
+       /* fixme -- put these calcs in a table or something. Don't need to do
+        * it every time. */
+       col = c % Ascii.images->cols;
+       row = c / Ascii.images->cols;
+
+       src.x = (col * ASCII_W) + Ascii.images->offx;
+       src.y = (row * ASCII_H) + Ascii.images->offy;
+       src.w = ASCII_W;
+       src.h = ASCII_H;
+
+       dest.x = x;
+       dest.y = y;
+       dest.w = ASCII_W;
+       dest.h = ASCII_H;
+
+       SDL_BlitSurface(Ascii.images->images, &src, surf, &dest);
+}
+
+/**
+ * Load the emergency ASCII image set from XPM.
+ *
+ * @returns The images struct ready for use, our 0 if there was some kind of
+ * error in loading it.
+ */
+static struct images *ascii_load_fixed_charset(void)
+{
+       struct images *images;
+
+       images = new struct images;
+        assert(images);
+       memset(images, 0, sizeof(*images));
+
+        images->w       = 8;
+        images->h       = 16;
+        images->offx    = 0;
+        images->offy    = 0;
+        images->rows    = 9;
+        images->cols    = 16;
+
+        images->images = IMG_ReadXPMFromArray((char**)charset_xpm);
+       if (!images->images) {
+               err("IMG_ReadXPMFromArray() failed: '%s'\n", SDL_GetError() );
+               images_del(images);
+               return NULL;
+       }
+       if (!images_convert2display(images)) {
+               images_del(images);
+               return NULL;
+       }
+       return images;
+}
+
+int asciiInit(void)
+{
+        char *fname = cfg_get("ascii-image-filename");
+        
+        /* This lib might be unitialized twice: once early in startup so that
+         * error messages can be displayed, and again later after the
+         * configuration file has been found and parsed. */
+        if (Ascii.images) {
+                images_del(Ascii.images);
+                Ascii.images = 0;
+        }
+
+        if (fname) {
+                Ascii.images = images_new(0, 8, 16, 9, 16, 0, 0, fname);
+        } else {
+                Ascii.images = ascii_load_fixed_charset();
+        }
+        assert(Ascii.images);
+        Ascii.offset = 0;
+        Ascii.state = ASCII_STATE_DEF;
+        Ascii.i_color = 0;
+        Ascii.color = ASCII_DEF_CLR;
+        return 0;
+}
+
+int asciiPaint(char c, int x, int y, SDL_Surface * surf)
+{
+        int ret = 0;
+
+        switch (Ascii.state) {
+                        
+        case ASCII_STATE_CLR:
+                asciiSetColor(c);
+                Ascii.state = ('+'==c?ASCII_STATE_CLRPUSH:ASCII_STATE_DEF);
+                break;
+                
+        case ASCII_STATE_CLRPUSH:
+                asciiSetColor(c);
+                Ascii.state = ASCII_STATE_DEF;
+                break;
+
+        case ASCII_STATE_ESC:
+                if (c == 'c') {
+                        Ascii.state = ASCII_STATE_CLR;
+                }
+                break;
+                
+        case ASCII_STATE_DEF:
+        default:
+                if (c == '^') {
+                        Ascii.state = ASCII_STATE_ESC;
+                } else {
+                        if (ASCII_DEF_CLR==Ascii.color) {
+                                asciiPaintDefault(c, x, y, surf);
+                        } else {
+                                asciiPaintColored(c, x, y, surf, Ascii.color);
+                        }
+                        ret = 1;
+                }
+        }
+
+        return ret;
+}
+
+int asciiStrlen(char *s)
+{
+        /* Start with the current state. */
+        enum ascii_ctrl_states state = Ascii.state;
+        char c = 0;
+        int len = 0;
+
+        while ((c = *s++)) {
+                switch (state) {
+                case ASCII_STATE_CLR:
+                        state = ('+'==c?ASCII_STATE_CLRPUSH:ASCII_STATE_DEF);
+                        break;
+                        
+                case ASCII_STATE_CLRPUSH:
+                        state = ASCII_STATE_DEF;
+                        break;
+                        
+                case ASCII_STATE_ESC:
+                        if (c == 'c') {
+                                state = ASCII_STATE_CLR;
+                        }
+                        break;
+                        
+                case ASCII_STATE_DEF:
+                default:
+                        if ('^' == c) {
+                                state = ASCII_STATE_ESC;
+                        } else {
+                                len++;
+                        }
+                }
+        }
+        
+        return len;
+}
diff --git a/src/ascii.h b/src/ascii.h
new file mode 100644 (file)
index 0000000..f11bf3e
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef ascii_h
+#define ascii_h
+
+#include "macros.h"
+
+#include <SDL.h>
+
+BEGIN_DECL
+
+extern int asciiInit(void);
+
+/**
+ * Print a character using a build-in font and color. In the usual case this
+ * prints the character to the surface using the current font and color. In the
+ * general case, 'c' may be part of a control sequence, where the format is:
+ *
+ *       <SEQ> := ^c<CMD><COLOR>
+ *     <COLOR> := B|w|r|g|b|c|y|m|G|!
+ *       <CMD> := +|-|<NIL>
+ *       <NIL> :=
+ *
+ * The '+' CMD pushes the current color before setting the new color. The '-'
+ * CMD pops the last pushed color and makes it the new color.
+ *
+ * The color codes:
+ *
+ *   w White
+ *   B Black
+ *   r Red
+ *   g Green
+ *   b Blue
+ *   y Yellow
+ *   c Cyan
+ *   m Magenta
+ *   G Gray
+ *
+ * @param c is either a character to print or part of a control sequence.
+ * @param x is the pixel x-coord of the upper left corner to paint to.
+ * @param y is the pixel y-coord of the upper left corner to paint to.
+ * @param surface is the surface to paint to.
+ * @returns 1 if a character was painted, 0 if it was part of a control
+ * sequence
+ */
+extern int asciiPaint(char c, int x, int y, SDL_Surface * surface);
+
+/**
+ * Get the length of a string NOT including the font and color control
+ * characters. This is useful for determining how much screen space the string
+ * will take when printed with asciiPaint().
+ *
+ * The function assumes that the string applies to the current internal state
+ * of the ascii painting engine. This is only important if the last character
+ * to asciiPaint was part of an unfinished control sequence. In that case,
+ * asciiStrlen() assumes that this string continues where that one left off.
+ *
+ * @param s is the null-terminated string to check.
+ * @returns strlen(s) minus the number of control characters
+ */
+extern int asciiStrlen(char *s);
+
+END_DECL
+
+#endif
diff --git a/src/astar.c b/src/astar.c
new file mode 100644 (file)
index 0000000..0cc22d2
--- /dev/null
@@ -0,0 +1,393 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "astar.h"
+#include "list.h"
+#include "heap.h"
+
+//#define DEBUG
+#include "debug.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#define COORD_TO_INDEX(x,y,w) ((y)*(w)+(x))
+
+/**
+ * The number of neighbors to search. If you want to allow NPC's to have
+ * diagonal movement, set this to 8. Otherwise set it to 4.
+ */
+#define CONFIG_NEIGHBORS 8
+#define MAX_DEPTH 1000 /* hack to limit search time on large places */
+
+static struct heap *schedule;  /* Priority queue of nodes to explore */
+static struct tree *found;     /* Nodes with a known path, ordered by location
+                                */
+
+/* Internal ******************************************************************/
+
+#ifdef ASTAR_DBG
+#define dump_node(n) \
+         dbg("%p={x=%d, y=%d, next=%p, len=%d, cost=%d, "\
+         "goodness=%d, order.key=%d}", (n), (n)->x, (n)->y, (n)->next, \
+         (n)->len, (n)->cost, (n)->goodness, (n)->order.key)
+#else
+#define dump_node(n)
+#endif
+
+static inline void astar_search_init(void)
+{
+       heap_clean(schedule);
+}
+
+static inline struct astar_node *astar_node_create(int x, int y, int cost,
+                                                  int goodness,
+                                                  struct astar_node *next,
+                                                  int location)
+{
+       struct astar_node *node;
+
+       node = (struct astar_node *) malloc(sizeof(struct astar_node));
+       if (!node)
+               return 0;
+       memset(node, 0, sizeof(struct astar_node));
+
+       node->x               = x;
+       node->y               = y;
+       node->cost            = cost;
+       node->goodness        = goodness;
+       node->next            = next;
+        node->order.key_type  = tree_i_key;
+       node->order.key.i_key = location;
+
+        if (next)
+                node->depth = next->depth + 1;
+
+       dump_node(node);
+       return node;
+}
+
+void astar_node_destroy(struct astar_node *node)
+{
+       free(node);
+}
+
+static struct astar_node *astar_path_reverse_aux(struct astar_node *node,
+                                                struct astar_node *prev)
+{
+       struct astar_node *ret;
+
+       dump_node(node);
+
+       node->len = prev->len + 1;
+       assert(node->len < 1000);       /* debug */
+       if (node->next)
+               ret = astar_path_reverse_aux(node->next, node);
+       else
+               ret = node;
+       node->next = prev;
+
+       return ret;
+}
+
+static struct astar_node *astar_path_reverse(struct astar_node *node)
+{
+       struct astar_node *ret;
+
+       dump_node(node);
+
+       /* simple case of only one node in the path */
+       if (!node->next)
+               return node;
+
+       node->len = 0;
+       ret = astar_path_reverse_aux(node->next, node);
+       node->next = 0;
+
+       return ret;
+}
+
+static inline int astar_schedule(struct astar_node *node)
+{
+
+       assert(!node->scheduled);
+
+       /* Insert the node in the priority queue. */
+       if (heap_insert(schedule, &node->goodness))
+               return -1;
+
+       node->scheduled = 1;
+
+       /* Insert it in the tree of nodes with known paths. */
+       tree_insert(&found, &node->order);
+
+       return 0;
+}
+
+static inline struct astar_node *astar_schedule_extract(void)
+{
+       struct astar_node *node;
+
+       /* Pull off the top of the heap (caller must ensure non-empty) */
+       node = heap_entry(heap_extract(schedule), struct astar_node, goodness);
+       node->scheduled = 0;
+       return node;
+}
+
+static void astar_explored_remove(struct astar_node *path)
+{
+       struct astar_node *ptr;
+
+       /* Purge the 'found' tree of all nodes in the path */
+       for (ptr = path; ptr; ptr = ptr->next)
+               tree_delete(&found, &ptr->order);
+}
+
+static void astar_cleanup_aux(struct tree *root)
+{
+       /* Recursively attack the subtrees */
+       if (root->left)
+               astar_cleanup_aux(root->left);
+       if (root->right)
+               astar_cleanup_aux(root->right);
+
+       /* Destroy the root */
+       astar_node_destroy(tree_entry(root, struct astar_node, order));
+}
+
+static void astar_cleanup(void)
+{
+       if (found) {
+               astar_cleanup_aux(found);
+               found = 0;
+       }
+}
+
+static inline struct astar_node *astar_old_route(int location)
+{
+       struct tree *tree = tree_i_search(found, location);
+       if (tree)
+               return tree_entry(tree, struct astar_node, order);
+       return 0;
+}
+
+static inline void astar_replace_route(struct astar_node *node, int x, int y,
+                                      int cost, int goodness,
+                                      struct astar_node *next, int location)
+{
+       /* Replace the old route values with the new ones. */
+       node->x = x;
+       node->y = y;
+       node->cost = cost;
+       node->goodness = goodness;
+       node->next = next;
+       node->order.key.i_key = location;
+
+       /* If the old route was scheduled but not explored yet then fixup the
+        * priority queue to reflect the new goodness of the route. */
+       if (node->scheduled) {
+               heapify(schedule, 0);
+               return;
+       }
+
+       /* Otherwise reschedule the route to be explored again. */
+       heap_insert(schedule, &node->goodness);
+       node->scheduled = 1;
+}
+
+static inline void
+astar_schedule_neighbor(struct astar_node *node, 
+                        struct astar_search_info *info)
+{
+       struct astar_node *ptr;
+       int location;
+
+        /* 'cost' is an attribute of the path leading to this node. When we
+         * find two paths leading to the same node, cost helps us decide which
+         * path to take. */
+       int cost = 0;
+
+        /* 'goodness' is an attribute both of a node and of the path leading to
+         * that node. It is important because it allows us to prioritize nodes,
+         * so we can search the more promising nodes first. */
+       int goodness = 0;
+
+       info->heuristic(info, &goodness, &cost, node->x, node->y);
+
+        /* Cost is cumulative along a path, so add the parent node's cost. */
+        cost += node->cost;
+
+        /* Nodes with cheaper paths leading to them are better than nodes with
+         * costlier paths. */
+        goodness -= cost;
+
+       location = COORD_TO_INDEX(info->x0, info->y0, info->width);
+
+       /* Check if we already have a route to this location. */
+       if ((ptr = astar_old_route(location))) {
+
+               /* If the old route is better than skip this neighbor. */
+               if (goodness <= ptr->goodness)
+                       return;
+
+               /* If the new route is better than replace the old with the new
+                * and reschedule. */
+               astar_replace_route(ptr, info->x0, info->y0, cost, goodness,
+                                   node, location);
+               return;
+       }
+
+       /* This is a new route. */
+       ptr = astar_node_create(info->x0, info->y0, cost, goodness, node,
+                               location);
+       if (!ptr) {
+               err("Allocation failed");
+               return;
+       }
+
+       if (astar_schedule(ptr)) {
+                err("Schedule failed!");
+                exit(-1);                
+        }
+}
+
+int astar_init(void)
+{
+       return ((schedule = heap_create(64)) ? 0 : -1);
+}
+
+void astar_quit(void)
+{
+       if (schedule)
+               heap_destroy(schedule);
+}
+
+struct astar_node *astar_search(struct astar_search_info *info)
+{
+       struct astar_node *node;
+       int row;
+       int col;
+        int cost = 0;
+        int goodness = 0;
+
+       astar_search_init();
+
+        info->heuristic(info, &goodness, &cost, info->x0, info->y0);
+       node = astar_node_create(info->x0, info->y0, cost, goodness, NULL, 
+                                 COORD_TO_INDEX(info->x0, info->y0, 
+                                                info->width));
+
+       astar_schedule(node);
+
+       while (!heap_empty(schedule)) {
+
+                //astar_dump_schedule();
+               node = astar_schedule_extract();
+
+               /* Check if this node is the target location */
+               if ((info->flags & ASTAR_HORZ || node->x == info->x1) &&
+                   (info->flags & ASTAR_VERT || node->y == info->y1)) {
+
+                       /* Reverse the path to get a pointer to the start */
+                       node = astar_path_reverse(node);
+
+                       /* Remove the nodes in the path from the tree so that
+                        * we don't free them with the rest */
+                       astar_explored_remove(node);
+
+                       goto done;
+               }
+
+                /* Check if this node is at max depth */
+                if (node->depth == MAX_DEPTH ||
+                    (info->limit_depth && node->depth == info->max_depth)) {
+                        continue;
+                }
+
+               /* Check the four non-diagonal neighbors of this node */
+               for (row = 0, info->y0 = node->y - 1; row < 3;
+                    row++, info->y0++) {
+
+                       /* Wrap y-coord if applicable */
+                       if (info->wraps)
+                               info->y0 = ((info->y0 + info->height) %
+                                           info->height);
+
+                       for (col = 0, info->x0 = node->x - 1; col < 3;
+                            col++, info->x0++) {
+
+#if (CONFIG_NEIGHBORS==4)
+                               /* skip diagonals and center */
+                               if (((row * 3 + col) % 2) == 0) {
+                                       continue;
+                               }
+#elif (CONFIG_NEIGHBORS==8)
+                               /* skip center */
+                               if ((row == col) && (row == 1)) {
+                                       continue;
+                               }
+#else
+#error CONFIG_NEIGHBORS undefined or has bad value
+#endif
+
+                               /* Wrap x-coord if applicable */
+                               if (info->wraps)
+                                       info->x0 = ((info->x0 + info->width) %
+                                                   info->width);
+
+                               /* Skip this neighbor if it's not a valid
+                                * location (impassable, off-map, etc) */
+                               if (!info->is_valid_location(info->context,
+                                                             node->x,
+                                                             node->y,
+                                                            info->x0,
+                                                            info->y0))
+                                       continue;
+
+                               astar_schedule_neighbor(node, info);
+
+                       }
+               }
+
+       }
+
+       node = 0;
+      done:
+       astar_cleanup();
+       return node;
+
+}
+
+void astar_path_destroy(struct astar_node *node)
+{
+       if (node->next)
+               astar_path_destroy(node->next);
+       astar_node_destroy(node);
+}
+
+void astar_dbg_dump_path(struct astar_node *path)
+{
+        while (path) {
+                dbg("(%d, %d)", path->x, path->y);
+                path = path->next;
+        }
+}
diff --git a/src/astar.h b/src/astar.h
new file mode 100644 (file)
index 0000000..50d8209
--- /dev/null
@@ -0,0 +1,101 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef astar_h
+#define astar_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "tree.h"
+
+#define ASTAR_HORZ (1 << 0)
+#define ASTAR_VERT (1 << 1)
+
+struct astar_search_info {
+        int x0;
+        int x1;
+        int y0;
+        int y1;
+        int flags;
+        int (*is_valid_location) (void *context, int fx, int fy, int x, int y);
+        void (*heuristic) (struct astar_search_info * info, 
+                           int *goodness, int *cost, int fx, int fy);
+        unsigned int width;
+        unsigned int height;
+        int wraps;
+        void *context;
+        bool limit_depth;
+        int max_depth;
+};
+
+struct astar_node {
+        struct tree order;
+        struct astar_node *next;
+        int cost;
+        int goodness;
+        int len;
+        int x;
+        int y;
+        int depth;
+        unsigned char scheduled:1;
+};
+
+/**
+ * Initialize the astar lib before first use.
+ */
+extern int astar_init(void);
+
+/**
+ * Cleanup the lib after last use.
+ */
+extern void astar_quit(void);
+
+/**
+ * Given two locations on a map, find the best route from the first to
+ * the second.  Returns a list of nodes representing the best route or
+ * null if no route can be found (or the alg runs out of memory before
+ * finding a route).  The caller should use astar_path_destroy() when
+ * done using the path, or astar_node_destroy on each node of the path.
+ *
+ * WARNING: the info struct may be modified during this call
+ */
+extern struct astar_node *astar_search(struct astar_search_info *info);
+
+/**
+ * Free the memory used to contain a path returned from astar_search().
+ */
+extern void astar_path_destroy(struct astar_node *node);
+
+/**
+ * Free the memory for a single node.
+ */
+extern void astar_node_destroy(struct astar_node *node);
+
+/**
+ * Dump the path for dbg.
+ */
+extern void astar_dbg_dump_path(struct astar_node *path);
+
+END_DECL
+
+#endif
diff --git a/src/bitset.h b/src/bitset.h
new file mode 100644 (file)
index 0000000..bbacf29
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef bitset_h
+#define bitset_h
+
+/**
+ * bitset - an arbitrary-sized bitfield
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * A bitset is an array of unsigned ints. The size of the array is determined
+ * when the bitset is allocated or declared, and is based on the number of
+ * bits.
+ */
+typedef unsigned int bitset_t;
+
+/**
+ * The number of bytes in an array element.
+ */
+#define bitset_elem_bytes sizeof(bitset_t)
+
+/**
+ * The divisor used by bitset_index.
+ */
+#define bitset_div (bitset_elem_bytes*8)
+
+/**
+ * The mask used by bitset_shift.
+ */
+#define bitset_mask (bitset_div-1)
+
+/**
+ * Given a bit, find out which array element the bit is in.
+ *
+ * @param bitno is the number of the bit (0 is the first bit)
+ * @returns the index of the array the bit is in.
+ */
+#define bitset_index(bitno) ((bitno)/bitset_div)
+
+/**
+ * Given a bit, find its position in the array element.
+ *
+ * @param bitno is the number of the bit (0 is the first bit)
+ * @returns the position of the element the bit is in.
+ */
+#define bitset_shift(bitno) ((bitno)&bitset_mask)
+
+/**
+ * Given the number of bits in a bitset, find out how many elements are in its
+ * array.
+ *
+ * @param nbits is the number of bits in the bitfield.
+ * @returns the number of elements in the bitfield array.
+ */
+#define bitset_elems(nbits) (unsigned int)(((nbits)+bitset_mask)/bitset_div)
+
+/**
+ * Given the number of bits in a bitset, find out how many bytes it uses.
+ *
+ * @param nbits is the number of bits in the bitfield.
+ * @returns the number of bytes in the bitfield array.
+ */
+#define bitset_bytes(nbits) (bitset_elems(nbits)*bitset_elem_bytes)
+
+/**
+ * Set a bit.
+ *
+ * @param bs is the bitset.
+ * @param bitno is the number of the bit (0 is the first bit)
+ */
+#define bitset_set(bs,bitno) ((bs)[bitset_index(bitno)] |= (1<<bitset_shift(bitno)))
+
+/**
+ * Clear a bit.
+ *
+ * @param bs is the bitset.
+ * @param bitno is the number of the bit (0 is the first bit)
+ */
+#define bitset_clr(bs,bitno) ((bs)[bitset_index(bitno)] &= ~(1<<bitset_shift(bitno)))
+
+/**
+ * Test if a bit is set.
+ *
+ * @param bs is the bitset.
+ * @param bitno is the number of the bit (0 is the first bit)
+ * @returns non-zero iff the bit is set.
+ */
+#define bitset_tst(bs,bitno) ((bs)[bitset_index(bitno)] & (1<<bitset_shift(bitno)))
+
+/**
+ * Allocate a bitset that can hold a given number of bits. All of the bits are
+ * initialized to zero.
+ *
+ * @param n_bits is the number of bits it needs to hold.
+ * @returns the bitset of NULL if the allocation failed.
+ */
+static inline bitset_t *bitset_alloc(int n_bits)
+{
+        return (bitset_t*)calloc(bitset_elems(n_bits), bitset_elem_bytes);
+}
+
+/**
+ * Free the memory associated with a bitset.
+ *
+ * @param bs is the bitset.
+ */
+static inline void bitset_free(bitset_t *bs)
+{
+        free(bs);
+}
+
+#endif
diff --git a/src/blender.h b/src/blender.h
new file mode 100644 (file)
index 0000000..d39f5e7
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef blender_h
+#define blender_h
+
+#include "list.h"
+
+#define BLENDER_MAX_NONSUP 32
+#define BLENDER_N_RANGE  16
+
+typedef struct blender {
+        struct list list;
+        struct terrain *inf;
+        int n_nonsup;
+        struct terrain *nonsup[BLENDER_MAX_NONSUP];
+        struct terrain *range[BLENDER_N_RANGE];
+} blender_t;
+
+#endif
diff --git a/src/cfg.c b/src/cfg.c
new file mode 100644 (file)
index 0000000..8c466fa
--- /dev/null
+++ b/src/cfg.c
@@ -0,0 +1,110 @@
+/* $Id: cfg.c,v 1.4 2010/08/26 05:56:20 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "cfg.h"
+#include "repstr.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CFG_HASH_SIZE 31
+
+struct cfg_entry {
+        struct cfg_entry *next;
+        char *key, *val;        
+} *cfg_hash[CFG_HASH_SIZE];
+
+static struct cfg_entry *cfg_entry_new(const char *key, const char *val)
+{
+        struct cfg_entry *entry = (struct cfg_entry*)malloc(sizeof(*entry));
+        assert(entry);
+        entry->next = 0;
+        entry->key = strdup(key);
+        assert(entry->key);
+        if (val) {
+                entry->val = strdup(val);
+                assert(entry->val);
+        } else {
+                entry->val = 0;
+        }
+        return entry;
+}
+
+static int hashfn(const char *key)
+{
+        unsigned int hashed = 0; 
+        const char *c; 
+        static const int bits_per_int = sizeof(unsigned int)*8; 
+
+        for (c = key; *c; c++) { 
+                /* letters have about 5 bits in them */ 
+                hashed = (hashed<<5) | (hashed>>(bits_per_int-5)); 
+                hashed ^= *c; 
+        } 
+        return hashed % CFG_HASH_SIZE;
+}
+
+int cfg_init()
+{
+        memset(cfg_hash, 0, sizeof(cfg_hash));
+        return 0;
+}
+
+void cfg_set(const char *key, const char *val)
+{
+        int hashkey = hashfn(key);
+        struct cfg_entry *entry = cfg_hash[hashkey];
+        if (! entry) {
+                cfg_hash[hashkey] = cfg_entry_new(key, val);
+        } else {
+                int match = !strcmp(entry->key, key);
+                while (! match
+                       && entry->next) {
+                        entry = entry->next;
+                        match = !strcmp(entry->key, key);
+                }
+                if (match) {
+                        repstr(&entry->val, val);
+                } else {
+                        entry->next = cfg_entry_new(key, val);
+                }
+        }
+}
+
+char *cfg_get(const char *key)
+{
+        int hashkey = hashfn(key);
+        struct cfg_entry *entry = cfg_hash[hashkey];
+        if (! entry) {
+                return 0;
+        } else {
+                int match = !strcmp(entry->key, key);
+                while (! match
+                       && entry->next) {
+                        entry = entry->next;
+                        match = !strcmp(entry->key, key);
+                }
+                if (match) {
+                        return entry->val;
+                } else {
+                        return 0;
+                }
+        }
+}
diff --git a/src/cfg.h b/src/cfg.h
new file mode 100644 (file)
index 0000000..cb1f919
--- /dev/null
+++ b/src/cfg.h
@@ -0,0 +1,28 @@
+/* $Id: cfg.h,v 1.3 2010/08/26 05:56:20 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef cfg_h
+#define cfg_h
+
+int cfg_init();
+int cfg_save(const char *fname);
+void cfg_set(const char *key, const char *val);
+char *cfg_get(const char *key);
+
+#endif
diff --git a/src/character.cpp b/src/character.cpp
new file mode 100644 (file)
index 0000000..be57fb2
--- /dev/null
@@ -0,0 +1,3682 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "character.h"
+#include "conv.h"
+#include "dice.h"
+#include "effect.h"
+#include "gob.h"
+#include "map.h"
+#include "console.h"
+#include "place.h"
+#include "Container.h"
+#include "Arms.h"
+#include "player.h"
+#include "status.h"
+#include "sound.h"
+#include "common.h"
+#include "screen.h"
+#include "knapsack.h"
+#include "occ.h"
+#include "species.h"
+#include "sched.h"
+#include "combat.h"
+#include "cmdwin.h"
+#include "terrain.h"
+#include "cmd.h"
+#include "event.h"
+#include "vehicle.h"
+#include "foogod.h"
+#include "ctrl.h"
+#include "session.h"
+#include "sprite.h"
+#include "mmode.h"
+#include "log.h"
+#include "factions.h"
+#include "kern_intvar.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+
+/**
+ * Used when calculating an evasion vector away from hostiles.
+ */
+struct evasionVectorInfo {
+        class Character *subj; /**< The character doing the evading. */
+        int dx;          /**< The x component of the evasion vector. */
+        int dy;          /**< The y component of the evasion vector. */
+};
+
+static int wrapReady(void *item, void *context)
+{
+       class ArmsType *type = (class ArmsType *) item;
+       class Character *npc = (class Character *) context;
+       return (npc->hasAmmo(type) && npc->ready(type) == Character::Readied);
+}
+
+static void wrapUnready(void *item, void *context)
+{
+       class ArmsType *type = (class ArmsType *) item;
+       class Character *npc = (class Character *) context;
+       npc->unready(type);
+
+}
+
+static void myConsiderArms(struct inv_entry *ie, void *data)
+{
+       struct knapsack *ks = (struct knapsack *) data;
+       if (!ie->type->isType(ARMS_TYPE_ID))
+               return;
+       class ArmsType *arms = (class ArmsType *) ie->type;
+       int val = 2 * dice_average(arms->getDamageDice()) * arms->getRange()
+                + 2 * dice_average(arms->getArmorDice())
+                + 2 * dice_average(arms->getToDefendDice())
+                + dice_average(arms->getToHitDice())
+                ;
+        if (val) {
+                for (int i = 0; 
+                     i < ie->count && ks->n_items < MAX_N_ITEMS; 
+                     i++, ks->n_items++) {
+                        ks->item[ks->n_items] = arms;
+                        ks->value[ks->n_items] = val;
+                }
+        }
+}
+
+/**
+ * Accumulate the sum of the vectors from hostile foes. This is passed as an
+ * argument to place_for_each() to scan for hostiles. It sums up the vectors
+ * from hostile foes to the subject in order to calculate the best vector to
+ * flee.
+ *
+ * @param obj An object in the current place.
+ * @param data The evasion vector struct which refers to the calling object and
+ * accumulates results.
+ */
+static void getEvasionVectorVisitor(Object *obj, void *data)
+{
+        struct evasionVectorInfo *info;
+        class Character *subj;
+
+        info = (struct evasionVectorInfo *)data;
+        subj = info->subj;
+
+        /* Filter out non-beings */
+        if (obj->getLayer() != being_layer)
+                return;
+
+        /* Filter out non-hostiles */
+        if (! are_hostile(subj, (class Being*)obj))
+                return;
+
+#if 0
+        /* Cheat a bit here, both for performance and to increase the
+         * effectiveness of townsfolk trying to flee raiders. */
+
+        /* Filter out objects not in los of the subject */
+        if (! place_in_los(subj->getPlace(),subj->getX(),subj->getY(),
+                                   obj->getPlace(),obj->getX(),obj->getY()))
+                return;
+
+        /* Filter out object not in the vision radius of the subject */
+        if (place_flying_distance(subj->getPlace(),subj->getX(),subj->getY(),
+                                  obj->getX(),obj->getY())
+            > subj->getVisionRadius())
+                return;
+
+        /* Filter out invisible objects */
+        if (! obj->isVisible())
+                return;
+#endif
+        /* Add the vector going from the hostile to the subject to the
+         * cumulative vector. */
+        info->dx += (subj->getX() - obj->getX());
+        info->dy += (subj->getX() - obj->getX());
+}
+
+Character::Character(const char *tag, const char *name, 
+                     struct sprite *sprite, 
+                     struct species *species, struct occ *occ, 
+                     int str, int intl, int dex, 
+                     int hpmod, int hpmult, 
+                     int mpmod, int mpmult, 
+                     int hp, int xp_, 
+                     int mp, 
+                    int AP_per_round,  // aka speed
+                    int lvl
+                     )
+        : hm(0), xp(xp_), order(-1),
+          sleeping(false),
+          ac(0), 
+          str(str), intl(intl),
+          dex(dex), mana(mp), lvl(lvl),
+          solo(false), target(NULL),
+          rdyArms(NULL),
+          fleeing(false), burden(0),
+          inCombat(false),
+          container(NULL), 
+          //sprite(sprite),
+          sched_chars_node(0),
+          forceContainerDrop(false)
+          , fleePathFound(false)
+          , fleeX(0)
+          , fleeY(0)
+          , fleePathFlags(0)
+          , currentMmode(0)
+          , known(false)
+          , taskname(NULL)
+          , taskproc(NULL)
+          , taskgob(NULL)
+          , taskInterruptOnDamage(false)
+{
+        if (tag) {
+                this->tag = strdup(tag);
+                assert(this->tag);
+        } else {
+                this->tag = NULL;
+        }
+
+        setName(name);
+
+        plnode = NULL;
+       setPlayerControlled(false);     // by default
+       this->current_sprite = sprite;
+       this->light        = MIN_PLAYER_LIGHT;
+       this->party        = 0;
+       this->conv         = conv;
+       this->species      = species;
+       this->occ          = occ;
+        if (occ)
+                occ_ref(occ);
+       this->is_clone     = false;
+       this->visible      = 1;
+       this->target       = 0;
+        this->damage_sound = NULL_SOUND;
+        this->charmed      = false;
+        this->resting      = false;
+        this->loitering    = false;
+        this->guarding     = false;
+        this->mp_mod       = mpmod;
+        this->mp_mult      = mpmult;
+        this->hp_mod       = hpmod;
+        this->hp_mult      = hpmult;
+        this->sched        = NULL;
+        this->appt         = 0;
+        this->is_leader    = false;
+        this->hp           = hp;        
+        this->defenseBonus = 0;
+        factionSwitch      = 0;
+        tmpFaction         = NIL_FACTION;
+        ambushedWhileCamping = false;
+
+        setDead(hp <= 0);
+
+        setActivity(NONE);
+
+
+        initCommon();
+
+       this->hp = min(this->hp, getMaxHp());
+       this->mana = min(this->mana, getMaxMana());
+       this->AP_per_round = AP_per_round;
+
+        setOnMap(false);
+       if (xp == 0)
+               this->xp = getXpForLevel(this->lvl);
+       if (xp < 0)
+       {
+               if (this->lvl == 1)
+               {
+                       this->xp = rand() % getXpForLevel(this->lvl + 1);
+               }
+               else
+               {
+                       this->xp = getXpForLevel(this->lvl) + (rand() % getXpForLevel(this->lvl));
+               }
+       }
+}
+
+Character::Character():hm(0), xp(0), order(-1),
+                       sleeping(false),
+                       ac(0), 
+                       str(0), intl(0),
+                       dex(0), mana(0),
+                      AP_per_round(kern_intvar_get("AP_TOTAL:normal_human")),
+                      lvl(0),
+                       playerControlled(true), solo(false),
+                       target(NULL),
+                       rdyArms(NULL),
+                       fleeing(false), burden(0),
+                       inCombat(false),
+                       container(NULL), 
+                       //sprite(0),
+                       sched_chars_node(0),
+                       forceContainerDrop(false)
+                       , fleePathFound(false)
+                       , fleeX(0)
+                       , fleeY(0)
+                       , fleePathFlags(0)
+                       , currentMmode(0)
+                       , known(false)
+                       , taskname(NULL)
+                       , taskproc(NULL)
+                       , taskgob(NULL)
+{
+        // This method is probably obsolete now
+
+        plnode = NULL;
+       setPlayerControlled(false);     // by default
+        setBaseFaction(NIL_FACTION);
+
+       light        = MIN_PLAYER_LIGHT;
+       tag          = 0;
+       party        = 0;
+       conv         = 0;
+       species      = 0;
+       occ          = 0;
+       is_clone     = false;
+       visible      = 1;
+       occ          = 0;
+       target       = 0;
+        damage_sound = NULL_SOUND;
+        charmed      = false;
+        resting      = false;
+        loitering    = false;
+        guarding     = false;
+        mp_mod       = 0;
+        mp_mult      = 0;
+        hp_mod       = 0;
+        hp_mult      = 0;
+        sched        = NULL;
+        appt         = 0;
+        is_leader    = false;
+        factionSwitch= 0;
+        tmpFaction   = NIL_FACTION;
+        ambushedWhileCamping = false;
+
+       AP_per_round = AP_per_round;
+
+        setDead(hp <= 0);
+
+        //assert(place);
+
+        setActivity(NONE);
+
+        // ------------------------------------------------------------------
+        // Initially always off-map. Loader will position us, put us in a
+        // party, or whatever.
+        // ------------------------------------------------------------------
+
+        setPlace(0);
+        setX(-1);
+        setY(-1);
+        setOnMap(false);
+}
+
+
+Character::~Character()
+{
+        obj_dec_ref_safe(container);
+
+       if (rdyArms != NULL) {
+               free(rdyArms);
+        }
+
+
+        if (party)
+                party->removeMember(this);
+
+        if (ai)
+                closure_unref(ai);
+
+        /* Hack: make sure you deref occ after deleting the
+         * container. Currently the container references traps that are built
+         * into the occ struct. The container unrefs the traps, and if the occ
+         * isn't still holding a ref then you get a double-deallocation and
+         * usually a crash. This will get cleaned up when I rework the way NPCs
+         * are factoried; the traps won't be kept as part of occ any more. */
+        if (occ)
+                occ_unref(occ);
+
+        // subtle: use setAttackTarget to unref the target; it will do so
+        // safely even if 'this' is the target
+        if (target)
+                setAttackTarget(NULL);
+
+        /* remove self from session's special list for chars with multi-place
+         * schedules */
+        if (sched_chars_node)
+                session_rm_sched_char(sched_chars_node);
+}
+
+static int yes_no_ignore(struct KeyHandler * kh, int key, int keymod)
+{
+       int *yesno = (int *) kh->data;
+
+       switch (key) {
+       case 'y':
+       case 'Y':
+               *yesno = 'y';
+               return 1;
+        case 'i':
+        case 'I':
+            *yesno = 'i';
+            return 1;
+       case 'n':
+       case 'N':
+       case CANCEL:
+               *yesno = 'n';
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+void Character::taskPromptToAbort()
+{
+    cmdwin_clear();
+    log_continue("^c+y%s damaged - abort task?^c-\n", getName());
+    log_flush();
+    cmdwin_spush("Abort");
+    cmdwin_spush("(Y/N/Ignore)");
+    int key;
+    getkey(&key, yes_no_ignore);
+    cmdwin_pop();
+    switch (key) {
+    case 'y':
+        taskAbort();
+        cmdwin_spush("abort!");
+        break;
+    case 'i':
+        taskInterruptOnDamage = false;
+        cmdwin_spush("ignore");
+        break;
+    case 'n':
+    default:
+        cmdwin_spush("no");
+        break;
+    }
+}
+
+void Character::damage(int amount)
+{
+        if (hp <= 0)
+                return;
+
+        // This will run the "on-damage-hook":
+        Object::damage(amount);
+
+        // setHP() might call kill(), which calls remove(), which will destroy
+        // most objects
+        obj_inc_ref(this);
+        setHp(hp - amount);
+
+       if (isPlayerControlled()) {
+            statusFlash(getOrder(), Red);
+            if (!isDead()
+                   && engagedInTask() 
+                && taskInterruptOnDamage
+                ) {
+                taskPromptToAbort();
+            }
+       } else {
+            if (!isDead() && inCombat && (getHp() < (getMaxHp() / 4))) {
+                setFleeing(true);
+            }
+       }
+        obj_dec_ref(this);
+}
+
+void Character::inflictDamage(int amount, class Character *attacker)
+{
+       bool mightkill = false;
+       if (!isDead())
+       {
+               mightkill = true;
+               harm_relations(attacker, this);
+       }
+       obj_inc_ref(this);
+       damage(amount);
+       if (mightkill && isDead())
+       {
+               attacker->addExperience(getExperienceValue());
+       }
+       obj_dec_ref(this);
+}
+
+enum Character::ReadyResult Character::ready(class ArmsType * arms)
+{
+       bool foundSlotType = false;
+       int slot = arms->getSlotMask();
+
+       if (burden + arms->getWeight() > getStrength())
+               return TooHeavy;
+
+       for (int i = 0; i < species->n_slots; i++) {
+
+               // Is the slot the right type?
+               if ((slot & species->slots[i]) == 0)
+                       continue;
+
+               foundSlotType = true;
+
+               // Is the slot occupied?
+               if (rdyArms[i] != NULL)
+                       continue;
+
+               // At this point we've found an empty slot of the correct
+               // type. If this is a two-handed item then we also need the
+               // next slot to be empty.
+               if (arms->getNumHands() == 2) {
+
+                       if (i >= species->n_slots - 1)
+                               continue;
+
+                       // Is the slot occupied?
+                       if (rdyArms[i + 1] != NULL)
+                               continue;
+
+                       // Is the slot the right type?
+                       if ((slot & species->slots[i + 1]) == 0)
+                               continue;
+
+                       rdyArms[i + 1] = arms;
+               }
+               // Ready the item. Recalculate armour class.
+               rdyArms[i] = arms;
+               burden += arms->getWeight();
+
+                // Run the "ready" hook, passing in the arms type being readied
+                // and the (first) changed equipment slot.
+                runHook(OBJ_HOOK_READY_EQUIP, "pd", arms, i);
+
+                // Bugfix: for party members, have to change the party
+                // inventory ref here. cmdReady() used to do this, but the
+                // script often calls directly here for things like disarm() or
+                // acid effects.
+                if (isPlayerPartyMember()) {
+                        player_party->refInventoryObject(arms);
+                }
+
+                // Bugfix: for others, take the item out of personal
+                // inventory. 
+                else if (container) {
+                        container->takeOut(arms, 1);
+                }
+
+               return Readied;
+       }
+
+       if (foundSlotType)
+               return NoAvailableSlot;
+       return WrongType;
+}
+
+bool Character::unready(class ArmsType * arms)
+{
+       for (int i = 0; i < species->n_slots; i++) {
+
+               // Is it in this slot?
+               if (rdyArms[i] != arms)
+                       continue;
+
+               // Is this a 2h item (in which case it should be in the next
+               // slot, also)?
+               if (arms->getNumHands() == 2) {
+
+                       assert(i < species->n_slots - 1);
+                       assert(rdyArms[i + 1] == arms);
+                       rdyArms[i + 1] = NULL;
+               }
+               // Unready the item. Recacalculate armour class.
+               rdyArms[i] = NULL;
+               burden -= arms->getWeight();
+
+                // Run the "uunready" hook, passing in the arms type being
+                // unreadied and the (first) changed equipment slot.
+                runHook(OBJ_HOOK_UNREADY_EQUIP, "pd", arms, i);
+
+                // Bugfix: for party members, have to change the party
+                // inventory ref here. cmdReady() used to do this, but the
+                // script often calls directly here for things like disarm() or
+                // acid effects.
+                if (isPlayerPartyMember()) {
+                        player_party->unrefInventoryObject(arms);
+                }
+
+                // Bugfix: for others, put the item back into personal
+                // inventory. This fixes (e.g.) Haxima's acid effect on NPC's,
+                // which first unreadies, and then removes, which is correct
+                // for PC's.
+                else if (container) {
+                        container->add(arms, 1);
+                }
+
+               return true;
+       }
+
+
+       return false;
+}
+
+const char *Character::getWoundDescription()
+{
+       static const char *desc[] = {
+               "Critical",
+               "Heavily wounded",
+               "Moderately wounded",
+               "Barely wounded",
+               "Unscathed"
+       };
+
+       if (isDead())
+               return "Killed";
+
+       if (isFleeing())
+               return "Fleeing";
+
+       return desc[(getHp() * 4) / getMaxHp()];
+       return desc[(getHp() * 4) / getMaxHp()];
+}
+
+void Character::groupExitTo(struct place *dest_place, int dest_x, int dest_y,
+                            struct closure *cutscene)
+{
+        struct place *oldPlace = getPlace();
+
+        player_party->removeMembers();
+
+        // --------------------------------------------------------------------
+        // If the party is in a vehicle check if we need to disembark before
+        // exiting. If the destination is not wilderness or it's impassable
+        // wilderness then we'll disembark.
+        //
+        // When we disembark, we want to put the vehicle on the parent place
+        // of the place we're leaving.
+        // --------------------------------------------------------------------
+
+        class Vehicle *vehicle = party->getVehicle();
+        if (vehicle 
+            && (! place_is_wilderness(dest_place)
+                || ! place_is_passable(dest_place, dest_x, dest_y,
+                                       party, 0))) {
+                
+                assert(getPlace());
+                assert(getPlace()->location.place);
+
+                vehicle->setOccupant(0);
+                vehicle->relocate(getPlace()->location.place,
+                                         getPlace()->location.x,
+                                         getPlace()->location.y);
+                vehicle = NULL;
+        }
+                                       
+
+        if (cutscene) {
+                mapUpdate(0);
+                closure_exec(cutscene, "");
+        }
+
+        // --------------------------------------------------------------------
+        // If combat is active then run its state machine after removing
+        // everybody.
+        // --------------------------------------------------------------------
+
+        //if (combat_get_state() != COMBAT_STATE_DONE) {
+                combat_analyze_results_of_last_turn();
+        //}
+
+        place_exit(oldPlace);
+
+        player_party->relocate(dest_place, dest_x, dest_y, REL_NOSTEP);
+        endTurn();
+}
+
+enum MoveResult Character::move(int dx, int dy)
+{
+       int newx, newy;
+       class Character *occupant;
+
+        if (isStationary())
+                return StationaryObject;
+
+        this->dx = dx;
+        this->dy = dy;
+
+        // ------------------------------------------------------------------
+        // Let's give this next a try, in order to make the code for teleport
+        // spells simpler. If a teleport spell says to teleport the caster,
+        // then perhaps it shouldn't have to concern itself with whether the
+        // caster is in party mode or member mode. It just tells the caster to
+        // move, and the caster then checks its context to see if this means
+        // "move the member" or "move the whole party".
+        // ------------------------------------------------------------------
+
+        if (!isOnMap()) {
+                if (isPlayerControlled()) {
+                        return (player_party->move(dx, dy));
+                } else {
+                        // I don't know how I got here, but I did with an NPC
+                        // in wilderness combat, so its party was NULL. Maybe
+                        // it was summoned?
+                        dbg("%s not on map and not player-controlled...WTF?\n");
+                        if (! party)
+                                return OffMap;
+                        return (party->move(dx, dy) ? MovedOk : WasImpassable);
+                }
+        }
+
+       // Calculate new coordinates.
+       newx = getX() + dx;
+       newy = getY() + dy;
+
+
+       // ------------------------------------------------------------------
+       // Is the character walking off the edge of the map? The same rules as
+       // entering a portal apply here: the party must be in follow mode, and
+        // all other members must be able to pathfind to this location.
+        //
+        // Addendum: since this is not strictly necessary for wilderness
+        // combat, and it is something of an inconvenience to the user, I skip
+        // the checks for wilderness combat.
+        // ------------------------------------------------------------------
+
+       if (place_off_map(getPlace(), newx, newy)) {
+
+                // -----------------------------------------------------------
+                // Npc characters can just step off and will be removed from
+                // the game.
+                // -----------------------------------------------------------
+                
+                // Note: the following used to be || isCharmed(), but since I
+                // changed charm to be just a temporary faction switch I don't
+                // think this is good any more. I don't want charmed player
+                // party members getting destroyed.
+                if (! isPlayerControlled()) {
+                        remove();
+                        destroy();
+                        endTurn();
+                        return ExitedMap;
+                }
+
+                if (place_is_wilderness_combat(getPlace())) {
+                        remove();
+                        endTurn();
+                        return ExitedMap;
+                }
+
+                if (player_party->get_num_living_members() == 1) {
+                        // Force to follow mode to avoid the annoying case
+                        // where only one member is in the party and the player
+                        // wants to leave a combat map.
+                        player_party->enableFollowMode();
+                }
+
+                /* Let's try switching the order used to look for an exit
+                 * place. Instead of checking the parent first, check for a
+                 * neighbor first. */
+
+                // Look for a neighbor in that direction
+                int dir = place_off_map_dir(getPlace(),newx, newy);
+                struct place *dest_place = place_get_neighbor(getPlace(), dir);
+                if (dest_place != NULL) {
+                        
+                        int dest_x, dest_y;
+
+                        // Check if the neighbor has an edge entrance
+                        if (place_get_edge_entrance(dest_place, dir, &dest_x, 
+                                                    &dest_y)) {
+                                return NoDestination;
+                        }
+
+                        // For parties of size 1, force to follow mode
+                        if (player_party->getSize() == 1) {
+                                player_party->enableFollowMode();
+                        }
+
+                        // Ensure in follow mode
+                        if (player_party->getPartyControlMode() 
+                            != PARTY_CONTROL_FOLLOW) {
+                                return NotFollowMode;
+                        }
+                        
+                        // Rendezvous other party members or abort
+                        if (!player_party->rendezvous(getPlace(), getX(), 
+                                                      getY())) {
+                                return CantRendezvous;
+                        }
+
+                        // Goto neighbor
+                        groupExitTo(dest_place, dest_x, dest_y, NULL);
+                        endTurn();
+                        return ExitedMap;
+                }
+
+
+                if (place_get_parent(getPlace()) != NULL) {
+                
+                        if (player_party->getPartyControlMode() 
+                            != PARTY_CONTROL_FOLLOW) {
+                                return NotFollowMode;
+                        }
+                        
+                        if (!player_party->rendezvous(getPlace(), getX(), 
+                                                      getY())) {
+                                return CantRendezvous;
+                        }
+                        
+                        groupExitTo(place_get_parent(getPlace()),
+                                    place_get_x(getPlace()) + dx, 
+                                    place_get_y(getPlace()) + dy,
+                                    NULL);
+                        
+                        endTurn();
+                        return ExitedMap;
+                }
+
+                return OffMap;
+       }
+
+        // ------------------------------------------------------------------
+        // Check passability. If commuting then ignore closed doors (and other
+        // blocking mechs).
+        // ------------------------------------------------------------------
+
+       if (!place_move_is_passable(
+                    getPlace(), getX(), getY(), newx, newy, this,
+                    PFLAG_MOVEATTEMPT | 
+                    (getActivity() == COMMUTING ? PFLAG_IGNOREMECHS : 0))) {
+                return WasImpassable;
+       }
+
+       // Are the new coordinates already occupied by another character?
+       if ((occupant = (class Character *) place_get_object(getPlace(), 
+                                                             newx, newy, 
+                                                             being_layer))) {
+                
+
+               // Is the occupant an enemy?
+               if (are_hostile(this, occupant)) {
+                       return WasImpassable;
+               }
+
+               // *** Switch ***
+
+               if (isPlayerControlled() 
+
+                    // don't allow switching with sleeping NPC's; this would
+                    // allow the player to kick THEM out of bed!
+                    && SLEEPING != occupant->getActivity()
+                    //&& occupant->isPlayerControlled() 
+                    //&& isSelected()
+                        ) {
+
+                       // Special case: if both the occupant and this
+                       // character are player-controlled then have them
+                       // switch places if possible.  This prevents the
+                       // situation where the player party is in follow mode
+                       // and the leader gets boxed in by the other members.
+                       // Note that in this case I'm ignoring movement cost
+                       // (pretend that the characters help each other across
+                       // the rough terrain... yeah, that's it!).
+
+                        // Wait - first have to check if the other character
+                        // can occupy this tile (may have different
+                        // passability). If this fails then go ahead and
+                        // approve the move without switching. Stacking members
+                        // of the same party is permitted in order to resolve
+                        // certain corner cases which could be very unpleasant
+                        // or confusing for the user. (For example: the party
+                        // leader is a gazer, the party enters a dungeon, the
+                        // portal destination is surrounded by water, the gazer
+                        // steps onto the water... oops! Either we allow the
+                        // gazer to stack back onto the party or we require the
+                        // user to figure out how to switch the party order
+                        // just to pick a new leader just to get out of this
+                        // mess...)
+                        if (!place_is_passable(getPlace(), getX(), getY(), 
+                                               occupant, 0)) {
+                                relocate(getPlace(), newx, newy);
+                                runHook(OBJ_HOOK_MOVE_DONE, "pdd", getPlace(),
+                                        newx, newy);
+                                decActionPoints(
+                                        place_get_diagonal_movement_cost(
+                                                getPlace(), 
+                                                getX(), getY(),
+                                                newx, newy, 
+                                                this, (getActivity() == COMMUTING ? PFLAG_IGNOREMECHS : 0)));
+                                return MovedOk;
+        
+                        }
+
+                        // In follow mode only the leader can switch with other
+                        // party members, otherwise two or more followers can
+                        // spin-in-place.
+                        if (occupant->isPlayerControlled()
+                            && CONTROL_MODE_FOLLOW == getControlMode()) {
+                                return WasOccupied;
+                        }
+
+                        switchPlaces(occupant);
+                       return SwitchedOccupants;
+               }
+
+               return WasOccupied;
+       }
+
+        runHook(OBJ_HOOK_MOVE_DONE, "pdd", getPlace(), getX(), getY());
+        decActionPoints(place_get_diagonal_movement_cost(getPlace(), 
+                                                         getX(), getY(), 
+                                                         newx, 
+                                                         newy, this, (getActivity() == COMMUTING ? PFLAG_IGNOREMECHS : 0)));
+       relocate(getPlace(), newx, newy);
+
+        // If this move was visible to the player
+       if (mapTileIsVisible(getX(), getY())) {
+                // And this is a party member following the player
+                if (isPlayerPartyMember()
+                    && (CONTROL_MODE_FOLLOW == getControlMode())) {
+                        // Don't update the map now, just mark it dirty. This
+                        // helps reduce the sluggishness in town maps.
+                        mapSetDirty();
+                } else {
+                        // If this character is being moved by the player and
+                        // they are not in view of the camera
+                        if (isPlayerControlled() 
+                            && ! mapIsInCameraView(getPlace(), getX(), getY())) {
+                                // Recenter the camera to keep the character in view.
+                                mapCenterCamera(getX(), getY());
+                        }
+                        // Repaint the map now
+                        mapUpdate(0);
+                }
+       }
+
+       return MovedOk;
+}
+
+void Character::remove()
+{
+        obj_inc_ref(this);
+       Object::remove();
+       setAttackTarget(this);
+        mapSetDirty();
+
+        // ------------------------------------------------------------------
+        // Handle changes to party control.
+        // ------------------------------------------------------------------
+
+        if (isSolo()) {
+                player_party->enableRoundRobinMode();
+        } else if (isLeader()) {
+                player_party->enableFollowMode();
+        }
+        obj_dec_ref(this);
+}
+
+class ArmsType *Character::enumerateWeapons(int *armsIndex)
+{
+       *armsIndex = -1;
+       class ArmsType *currentArms;
+       currentArms = getNextWeapon(armsIndex);
+       if (!currentArms)
+               currentArms = species->weapon;
+       return currentArms;
+}
+
+class ArmsType *Character::getNextWeapon(int *armsIndex)
+{
+       class ArmsType *currentArms;
+       do {
+               currentArms = getNextArms(armsIndex);
+       } while (currentArms != NULL 
+                 && dice_average(currentArms->getDamageDice()) <= 0);
+       return currentArms;
+}
+
+/* If target is null, then it cant be in range.
+  If weapon is null, then theres no range limitation, so target is
+  considered 'in range' */
+bool Character::isAttackTargetInRange(class ArmsType *weapon)
+{
+       int dx, dy, distance;
+
+       if (target == NULL)
+               return false;
+               
+       if (weapon == NULL)
+               return true;
+
+       dx = target->getX() - getX();
+       dy = target->getY() - getY();
+
+       if (dx < 0)
+               dx = -dx;
+       if (dy < 0)
+               dy = -dy;
+
+       distance = (dx > dy) ? (dx + (dy >> 1)) : (dy + (dx >> 1));
+
+       return (weapon->getRange() >= distance);
+}
+
+class Character *Character::getAttackTarget(class ArmsType *weapon)
+{
+       // Is the old target still valid?
+       if (!target || !target->isOnMap() || target->isDead() ||
+           !isAttackTargetInRange(weapon) || !target->isVisible()) {
+               setAttackTarget(this);
+               return this;
+       }
+
+       return target;
+}
+
+bool Character::hasReadied(class ArmsType * arms)
+{
+       int armsIndex = -1;
+       class ArmsType *readied = enumerateArms(&armsIndex);
+       while (readied != NULL && readied != arms)
+               readied = getNextArms(&armsIndex);
+       return readied == arms;
+}
+
+class ArmsType *Character::enumerateArms(int *armsIndex)
+{
+       *armsIndex = -1;
+       return getNextArms(armsIndex);
+}
+
+class ArmsType *Character::getNextArms(int *armsIndex)
+{
+       // Advance to the next slot
+       // *armsIndex++ doesnt work for some reason...
+       *armsIndex=*armsIndex+1;
+
+       // Search remaining slots for a weapon
+       for (; *armsIndex < species->n_slots; *armsIndex=*armsIndex+1) {
+
+               // Is anything in this slot?
+               if (rdyArms[*armsIndex] == NULL)
+                       continue;
+
+               // Is this just another slot for the same weapon (happens in
+               // the case of multi-slotted weapons like 2h swords)?
+               if (*armsIndex > 0 && rdyArms[*armsIndex-1] == rdyArms[*armsIndex] &&
+                   rdyArms[*armsIndex]->getNumHands() == 2)
+                       continue;
+
+               return rdyArms[*armsIndex];
+       }
+       
+       return 0;
+}
+
+ArmsType *Character::getArmsInSlot(int slot)
+{
+        if (slot < 0
+            || slot >= species->n_slots)
+                return NULL;
+        return rdyArms[slot];
+}
+
+int Character::hasAmmo (class ArmsType * weapon)
+{
+        // SAM: Changed this from returning bool to 
+        //      returning int (0 for no ammo, n for amount)
+       if (weapon->ammoIsUbiquitous())
+                return 1;  // One more available, that is.
+
+       if (isPlayerControlled()) {
+               struct inv_entry *ie;
+
+               if (weapon->isMissileWeapon()) {
+                       ie = player_party->inventory->search(weapon->getAmmoType());
+                        if (ie == NULL)
+                                return 0;  // No ammo
+                       return ie->count;  // 1 or more
+               }
+                else if (weapon->isThrownWeapon()) {
+                       ie = player_party->inventory->search(weapon);
+                       if (ie == NULL) {
+                               unready(weapon);
+                               return 0;  // No more
+                       }
+                       assert(ie->count > 0);
+                       return ie->count;  // 1 or more
+               }
+               return 1;  // Melee weapons are like ubiquitous
+       } else {
+                // SAM: Not bothering with quantity of NPC ammo for now
+               return (!weapon->isMissileWeapon() ||
+                        (container != NULL &&
+                         container->search(weapon->getAmmoType())));
+       }
+} // Character::hasAmmo()
+
+bool Character::hasInInventory (class ObjectType *type)
+{
+       if (isPlayerControlled()) {
+                return player_party->hasInInventory(type);
+       } else {
+               return (container != NULL &&
+                        container->search(type) != NULL);
+       }
+}
+
+void Character::setLight(int val)
+{
+       light = max(val, MIN_PLAYER_LIGHT);
+        mapSetDirty();
+}
+
+void Character::addMana(int delta)
+{
+       mana += delta;
+       mana = max(mana, 0);
+        mana = min(mana, getMaxMana());
+}
+
+void Character::changeSleep(bool val)
+{
+        if (sleeping == val)
+                return;
+
+       sleeping = val;
+        statusRepaint();
+        mapSetDirty();
+
+        if (sleeping) {
+
+                // -----------------------------------------------------------
+                // Going to sleep.
+                // -----------------------------------------------------------
+            if (engagedInTask()) {
+                taskAbort();
+            }
+
+
+            if (isLeader()) {
+                assert(isPlayerControlled());
+                player_party->enableFollowMode();
+            } else if (isSolo()) {
+                assert(isPlayerControlled());
+                player_party->enableRoundRobinMode();
+            }
+
+        } else {
+
+                if (isPlayerControlled()) {
+
+                        // ----------------------------------------------------
+                        // Upon waking up, set this character's control mode
+                        // based on the party's control mode.
+                        // ----------------------------------------------------
+
+                        assert(! isLeader());
+                        assert(! isSolo());
+                        
+                        switch (player_party->getPartyControlMode()) {
+
+                        case PARTY_CONTROL_FOLLOW:
+                                if (this != player_party->get_leader()) {
+                                        setControlMode(CONTROL_MODE_FOLLOW);
+                                }
+                                break;
+
+                        case PARTY_CONTROL_SOLO:
+                                setControlMode(CONTROL_MODE_IDLE);
+                                break;
+
+                        case PARTY_CONTROL_ROUND_ROBIN:
+                                setControlMode(CONTROL_MODE_PLAYER);
+                                break;
+
+                        default:
+                                assert(false);
+                                break;
+                        }
+                        
+                }
+
+        }
+
+}
+
+void Character::awaken(void)
+{
+        if (isAsleep() 
+            && ! isResting()
+            && ! isDead()) {
+                changeSleep(false);
+                log_msg("%s wakes up!", getName());
+        }
+}
+
+void Character::setFleeing(bool val)
+{
+       if (fleeing == val)
+               return;
+
+       fleeing = val;
+        fleePathFound = false;
+        fleePathFlags = 0;
+        cachedPath = 0;
+}
+
+/**
+ * Check if it's a good idea to try and move here in the given place. Checks
+ * for passability and known hazards.
+ */
+bool Character::locationIsOk(int x2, int y2)
+{
+        return (place_is_passable(getPlace(), x2, y2, this, 0)
+                && (! place_is_occupied(getPlace(), x2, y2))
+                && (! place_is_hazardous(getPlace(), x2, y2)));
+}
+
+/**
+ * Compute the optimal vector to move away from hostiles.
+ *
+ * @param dx The x component of the resulting evasion vector.
+ * @param dy The y component of the resulting evasion vector.
+ */
+void Character::getEvasionVector(int *dx, int *dy)
+{
+        struct evasionVectorInfo info;
+        int x2, y2;
+
+        /* Get the vector away from foes. */
+        memset(&info, 0, sizeof(info));
+        info.subj = this;
+        place_for_each_object(getPlace(), getEvasionVectorVisitor, &info);
+
+        /* Normalize the vector. */
+        clamp(info.dx, -1, 1);
+        clamp(info.dy, -1, 1);
+
+        /* Compute the new location. */
+        x2 = getX() + info.dx;
+        y2 = getY() + info.dy;
+
+        /* Check if ok. */
+        if (locationIsOk(x2, y2)) {
+                goto done;
+        }
+
+        /* Not ok, try the vertical. */
+        if (info.dx) {
+                x2 -= info.dx;
+                if (locationIsOk(x2, y2)) {
+                        goto done;
+                }
+                x2 += info.dx;
+        }
+
+        /* Not ok, try the horizontal. */
+        if (info.dy) {
+                y2 -= info.dy;
+                if (locationIsOk(x2, y2)) {
+                        goto done;
+                }
+                y2 += info.dx;
+        }
+
+        /* No place to go. */
+        info.dx = 0;
+        info.dy = 0;
+
+ done:
+        *dx = info.dx;
+        *dy = info.dy;
+}
+
+static bool movedOk(enum MoveResult result)
+{
+        switch (result) {
+        case NotApplicable:
+        case NoDestination:
+        case WasImpassable:
+        case WasOccupied:
+                return false;
+        default:
+                return true;
+        }
+}
+
+bool Character::mapHasEdge()
+{
+        // This is the simple thing to do, and works for towns and wilderness
+        // maps. Dungeon rooms could have edges shared with other rooms, but I
+        // don't want to deal with that right now, mostly because it
+        // complicates the pathfinding heuristics, and I want to get this case
+        // right first.
+        return (place_get_parent(getPlace()));
+}
+
+bool Character::exitMap()
+{
+        if (getX() == 0) {
+                return movedOk(move(-1, 0));
+        } else if (getX() == (place_w(getPlace()) - 1)) {
+                return movedOk(move(1, 0));
+        } else if (getY() == 0) {
+                return movedOk(move(0, -1));
+        } else if (getY() == (place_h(getPlace()) - 1)) {
+                return movedOk(move(0, 1));
+        } else {
+                return false;
+        }
+}
+
+bool Character::followFleePath()
+{
+        return (exitMap()
+                || pathfindTo(getPlace(), fleeX, fleeY, fleePathFlags));
+}
+
+bool Character::findFleePath()
+{
+       // Just look for the nearest map edge. Note that this might not be the
+       // best choice, because it might not have a path. Get this working
+       // first, then get fancy if you want.
+       int leftx = getX();
+       int rightx = place_w(getPlace()) - getX();
+       int boty = getY();
+       int topy = place_h(getPlace()) - getY();
+       int minx, miny;
+
+       // Is the left edge nearer than the right edge?
+       if (leftx < rightx) {
+                fleeX = 0;
+               minx = leftx;
+       } else {
+                fleeX = place_w(getPlace()) - 1;
+               minx = leftx;
+       }
+
+       // Is the top edge nearer than the bottom edge?
+       if (boty < topy) {
+                fleeY = 0;
+               miny = topy;
+       } else {
+                fleeY = place_h(getPlace()) - 1;
+               miny = boty;
+       }
+
+        // Is the vertical edge nearer than the horizontal edge?
+        if (minx < miny) {
+                fleePathFlags = PFLAG_HORZ;
+        } else {
+                fleePathFlags = PFLAG_VERT;
+        }
+
+        fleePathFound = true;
+        return true;
+}
+
+bool Character::pathfindToMapEdge()
+{
+        if (fleePathFound
+            && followFleePath()) {
+                return true;
+        }
+
+        if (! findFleePath()) {
+                return false;
+        }
+
+        return followFleePath();
+}
+
+bool Character::fleeToMapEdge()
+{
+        return (mapHasEdge()
+                && pathfindToMapEdge());
+}
+
+bool Character::evade()
+{
+        int dx = 0, dy = 0;
+        getEvasionVector(&dx, &dy);
+        if (!dx && !dy) {
+                return false;
+        }
+
+        return movedOk(move(dx, dy));
+}
+
+bool Character::flee()
+{
+        return (!isStationary()
+                && (fleeToMapEdge()
+                    || evade()));
+}
+
+void Character::dropRdyArms()
+{
+       assert(!isPlayerControlled());
+
+       for (int i = 0; i < species->n_slots; i++) {
+
+               // Anything in this slot?
+               if (rdyArms[i] == NULL)
+                       continue;
+
+                // roll to drop
+                if ((rand() % 100) > ITEM_DROP_PROB)
+                        continue;
+
+               // Create an object of this type and drop it on the map
+               class Object *object = new Object();
+               if (!object)
+                       continue;
+               object->init(rdyArms[i]);
+               object->relocate(getPlace(), getX(), getY());
+
+               // Unready it
+               unready(rdyArms[i]);
+
+       }
+}
+
+void Character::unreadyAll()
+{
+       for (int i = 0; i < species->n_slots; i++) {
+
+                class ArmsType *type = rdyArms[i];
+
+               // Anything in this slot?
+               if (!type)
+                       continue;
+
+               // Unready it
+               unready(type);
+       }
+}
+
+bool Character::dropItems()
+{
+       assert(!isPlayerControlled());
+
+       if (container == NULL)
+               return false;
+
+        if (container->isEmpty())
+                return true;
+
+        if (! container->isEmpty()
+            && (forceContainerDrop
+                || (rand() % 100) <= CHEST_DROP_PROB))
+                container->relocate(getPlace(), getX(), getY());
+        obj_dec_ref(container);
+       container = NULL;
+
+       return true;
+}
+
+void Character::kill()
+{
+    // Why not turn this on again...? At least dropItems?
+//     if (!isPlayerControlled() && isOnMap()) {
+//             dropRdyArms();
+//             dropItems();
+//     }
+
+        // when a PC dies unready all arms so other party members can use them
+        if (isPlayerControlled()) {
+                unreadyAll();
+        }
+
+        if (isOnMap()
+            && container
+            && forceContainerDrop) {
+                container->relocate(getPlace(), getX(), getY());
+                obj_dec_ref(container);
+                container = NULL;
+        }
+
+        if (engagedInTask()) {
+            taskAbort();
+        }
+
+        if (isPlayerControlled()) {
+                log_msg("%s has fallen!!", getName());
+        }
+
+       hp = 0;
+        setDead(true);
+
+        // Similarly, run the on-death hook
+        runHook(OBJ_HOOK_ON_DEATH, 0);
+       remove();
+}
+
+void Character::useAmmo(class ArmsType *weapon)
+{
+       if (weapon->ammoIsUbiquitous())
+               return;
+
+       if (isPlayerControlled()) {
+               struct inv_entry *ie;
+
+               if (weapon->isMissileWeapon()) {
+                       class ObjectType *ammoType = weapon->getAmmoType();
+                       takeOut(ammoType, 1);
+               } else if (weapon->isThrownWeapon()) {
+
+                        // Handle the case where multiple party members have
+                        // all readied the same throwable weapon, and there is
+                        // no longer enough to supply them all, by forcing the
+                        // character that just threw to unready.
+                       ie = player_party->inventory->search(weapon);
+                        assert(ie);
+                        assert(ie->ref <= ie->count);
+                        if (ie->ref == ie->count) {
+                                unready(weapon);
+                                log_msg("%s : %s now out of ammo\n", 
+                                        getName(), weapon->getName());
+                        }
+                       takeOut(weapon, 1);
+               }
+       } else {
+               if (weapon->isMissileWeapon()) {
+                       container->takeOut(weapon->getAmmoType(), 1);
+                       if (!hasAmmo(weapon)) {
+                               unready(weapon);
+                               rearm = true;
+                       }
+               } else if (weapon->isThrownWeapon()) {
+                       if (container && container->search(weapon)) {
+                               container->takeOut(weapon, 1);
+                       } else {
+                               unready(weapon);
+                               rearm = true;
+                       }
+               }
+       }
+}
+
+/*****************************************************************************/
+
+void Character::armThyself(void)
+{
+       struct knapsack ks;
+
+       //assert(!isPlayerControlled());
+
+       if (container == NULL)
+               return;
+
+       // Setup the context to solve this using the knapsack algorithm
+       memset(&ks, 0, sizeof(ks));
+       ks.item = new void *[MAX_N_ITEMS];
+       ks.value = new int[MAX_N_ITEMS];
+       ks.solution = new unsigned char[MAX_N_ITEMS];
+       if (!ks.item || !ks.value || !ks.solution)
+               goto destroy_ks;
+       ks.put = wrapReady;
+       ks.remove = wrapUnready;
+       ks.context = this;
+
+       container->forEach(myConsiderArms, &ks);
+
+       knapsack_solve(&ks);
+
+       // Ready the chosen items
+       for (int i = 0; i < ks.n_items; i++) {
+               if (!ks.solution[i])
+                       continue;
+               class ArmsType *arms = (class ArmsType *) ks.item[i];
+               if (ready(arms) != Character::Readied)
+                       continue;
+       }
+
+      destroy_ks:
+       if (ks.item)
+               delete [] ks.item;
+       if (ks.value)
+               delete [] ks.value;
+       if (ks.solution)
+               delete [] ks.solution;
+
+       rearm = false;
+}
+
+bool Character::needToRearm()
+{
+        // gmcnutt: I currently don't have any way to tell a charmed player
+        // party member how to rearm themselves. Player characters pull from
+        // party inventory. Non-player characters pull from their own personal
+        // inventory. I really need to merge both types into the same behaviour
+        // to simplify things.
+        if (party == (Party*)player_party)
+                return false;
+
+       return rearm;
+}
+
+bool Character::initCommon(void)
+{
+        if (species && species->n_slots > 0) {
+                rdyArms = (class ArmsType**)calloc(species->n_slots, sizeof(class ArmsType*));
+                assert(rdyArms);
+        }
+
+        ai = NULL;
+
+       return true;
+}
+
+bool Character::initStock(struct species * species, struct occ * occ,
+                         struct sprite * sprite, char *nameStr, int order)
+{
+       // This method is now only used to initialize cloned characters.
+
+       this->species = species;        
+       this->occ = occ;
+        if (occ)
+                occ_ref(occ);
+       this->current_sprite = sprite;
+
+       if (!initCommon())
+               return false;
+
+        setName(nameStr);
+       this->order = order;
+
+       lvl = 1;                // fixme: hardcoded hack!
+
+       hp   = getMaxHp();
+       mana = getMaxMana();
+       AP_per_round = species->spd;
+        setDead(false);
+
+        defenseBonus = 0;
+        
+       return true;
+}
+
+/*****************************************************************************/
+
+void Character::resurrect(void)
+{
+       assert(isPlayerControlled());// shotgun assert put here during refactor
+       setHp(min(10, getMaxHp()));
+        setDead(false);
+       statusFlash(getOrder(), Blue);
+
+        // ------------------------------------------------------------------
+        // If we're in wilderness mode then we're done. Otherwise we need to
+        // put this character near the other party member's on the map.
+        // ------------------------------------------------------------------
+
+        if (player_party->isOnMap())
+                return;
+
+        assert(player_party->get_leader());
+
+        putOnMap(player_party->get_leader()->getPlace(), 
+                 player_party->get_leader()->getX(),
+                 player_party->get_leader()->getY(), 4,
+                 0);
+
+        assert(isOnMap());
+
+}
+
+
+struct sprite *Character::getSprite()
+{
+       if ((isAsleep() || isDead()) && species->sleep_sprite)
+               return species->sleep_sprite;
+       return current_sprite;
+}
+
+void Character::rest(int hours)
+{
+        int healAmount = HP_RECOVERED_PER_HOUR_OF_REST;
+        int manaAmount = MANA_RECOVERED_PER_HOUR_OF_REST;
+
+        /* Partial fix for SF BUG [ 1526910 ] "starvation is lame". Don't let
+         * the player completely rest his way out of starvation. */
+        if (isPlayerPartyMember()) {
+                if (!player_party->food) {
+                        healAmount /= 2;
+                        manaAmount /= 2;
+                }
+        }
+
+       while (hours) {
+                if (!isDead()) {
+                        heal(healAmount);
+                        addMana(manaAmount);
+                }
+               hours--;
+       }
+}
+
+int Character::getExperienceValue()
+{
+        int xpval = 0;
+        if (species)
+                xpval += species->xpval;
+        if (occ)
+                xpval += occ->xpval;
+        return (xpval * lvl);
+}
+
+int Character::getXpForLevel(int lvl)
+{
+       if (lvl == 1)
+               return 0;
+    return (int)pow((double)2, (double)lvl+6);
+}
+
+void Character::addExperience(int amount)
+{
+       xp += amount;
+       if (xp >= getXpForLevel(getLevel()+1)) {
+               lvl++;
+                log_banner("^c+b%s^c- gains level ^c+g%d^c-!", getName(), lvl);
+                if (isPlayerControlled()) {
+                        mapFlash(1000);
+                }
+                setHp(getMaxHp());
+                setMana(getMaxMana());
+       }
+}
+
+int Character::getMaxHp()
+{       
+        int base = hp_mod + species->hp_mod;
+        int mult = hp_mult + species->hp_mult;
+
+        if (occ) {
+                base += occ->hp_mod;
+                mult += occ->hp_mult;
+        }
+
+        mult = max(0, mult);
+        
+        return (base + getLevel() * mult);
+}
+
+int Character::getMaxMana()
+{
+        int base = mp_mod + species->mp_mod;
+        int mult = mp_mult + species->mp_mult;
+
+        if (occ) {
+                base += occ->mp_mod;
+                mult += occ->mp_mult;
+        }
+
+        mult = max(0, mult);
+        return base + getLevel() * mult;
+}
+
+void Character::changeArmourClass(int delta)
+{
+       ac += delta;
+       ac = max(0, ac);
+}
+
+class Object *Character::clone()
+{
+       char buf[64];
+       class Character *clone = new Character();
+       if (!clone)
+               return NULL;
+
+        if (is_clone)
+                snprintf(buf, sizeof(buf), "%s", getName());
+        else
+                snprintf(buf, sizeof(buf), "%s (clone)", getName());
+
+       clone->initStock(species, occ, current_sprite, buf, 0);
+       clone->is_clone = true;
+
+        // clone the readied items
+               int armsIndex = 0;
+        for (ArmsType *arms = enumerateArms(&armsIndex); arms != NULL; arms = getNextArms(&armsIndex)) {
+                clone->ready(arms);
+        }
+
+        // NOTE: effects not cloned... that will require a bit of work and
+        // testing because effects can have gobs (gobs aren't cloned either)
+
+       return clone;
+}
+
+bool Character::isVisible()
+{
+       return ((visible > 0) && species->visible);
+}
+
+bool Character::isShaded()
+{
+       // Friendly invisible characters are shaded
+       return ((! isVisible() && isPlayerControlled()) 
+                || Object::isShaded());
+}
+
+void Character::describe()
+{
+    if (Session->subject) {
+        const char *diplstr = diplomacy_string(this, Session->subject);
+        if (isvowel(diplstr[0]))
+            log_continue("an");
+        else
+            log_continue("a");
+        log_continue(" %s", diplstr);
+    } else {
+        log_continue("an");
+    }
+    log_continue(" L%d", getLevel());
+    if (isKnown()) {
+        log_continue(" %s", getName());
+    } else {
+        if (species && species->name) {
+            log_continue(" %s", species->name);
+        }
+        if (occ && occ->name) {
+            log_continue(" %s", occ->name);
+        }
+    }
+    if (!isVisible())
+        log_continue(" (invisible)");
+    if (isSubmerged()) {
+        log_continue(" (submerged)");
+    }
+}
+
+void Character::examine()
+{
+        int i;
+        int n = 0;
+       const char *diplstr = diplomacy_string(this, Session->subject);
+
+        log_continue("%s level %d", diplstr, getLevel());
+
+        if (isKnown()) {
+                log_continue(" %s,", getName());
+        } else {
+                if (species && species->name) {
+                        log_continue(" %s", species->name);
+                }
+                if (occ && occ->name) {
+                        log_continue(" %s", occ->name);
+                }
+        }
+
+        log_continue(" %s [", getWoundDescription());
+
+        for (ArmsType *arms = enumerateArms(&i); arms; 
+             arms = getNextArms(&i)) {
+                if (n > 0) {
+                        log_continue(", ");
+                }
+                log_continue("%s", arms->getName());
+                n++;
+        }
+
+        if (!n) {
+                log_continue("no arms");
+        }
+
+        log_continue("]");
+}
+
+sound_t *Character::getDamageSound()
+{
+        if (damage_sound)
+                return damage_sound;
+        if (species && species->damage_sound)
+                return species->damage_sound;
+        return NULL_SOUND;
+}
+
+sound_t *Character::get_movement_sound()
+{
+        if (species)
+                return species->movement_sound;
+        return NULL_SOUND;
+}
+
+bool Character::isType(int classID) {
+        if (classID == CHARACTER_ID)
+                return true;
+        return Object::isType(classID);
+}
+
+int Character::getType() {
+        return CHARACTER_ID;
+}
+
+int Character::getHp() {
+        return hp;
+}
+
+int Character::getOrder() {
+        return order;
+}
+
+int Character::getExperience() {
+        return xp;
+}
+
+unsigned char Character::getStrength() {
+        return (species->str + str);
+}
+
+unsigned char Character::getIntelligence() {
+        return (species->intl + intl);
+}
+
+unsigned char Character::getDexterity() {
+        return (species->dex + dex);
+}
+
+unsigned char Character::getBaseStrength() {
+        return (str);
+}
+
+unsigned char Character::getBaseIntelligence() {
+        return (intl);
+}
+
+unsigned char Character::getBaseDexterity() {
+        return (dex);
+}
+
+void Character::setStrength(unsigned char newstat) {
+        str = newstat;
+}
+
+void Character::setIntelligence(unsigned char newstat) {
+       intl = newstat;
+}
+
+void Character::setDexterity(unsigned char newstat) {
+       dex = newstat;
+}
+
+int Character::getLevel() {
+        return lvl;
+}
+
+void Character::setLevel(int val) {
+        assert(val>0);
+               xp = getXpForLevel(val);
+        lvl = val;
+        setHp(getMaxHp());
+        setMana(getMaxMana());
+}
+
+bool Character::isDead() {
+        return dead;
+}
+
+bool Character::isAsleep() {
+        return sleeping;
+}
+
+bool Character::isIncapacitated() {
+        return (!isOnMap() || isDead() || isAsleep());
+}
+
+int Character::getArmourClass() {
+        return ac;
+}
+
+void Character::setHp(int val) 
+{
+        hp = val;
+        hp = clamp(hp, 0, getMaxHp());
+        if (hp == 0) {
+            kill();
+        }
+}
+
+bool Character::isPlayerControlled() {
+        return playerControlled;
+}
+
+void Character::setPlayerControlled(bool val) 
+{
+    playerControlled = val;
+    if (val) {
+        ctrl = ctrl_character_ui;
+        if (isPlayerPartyMember()) {
+            class Character *oldLeader, *newLeader;
+            switch (player_party->getPartyControlMode()) {
+            case PARTY_CONTROL_FOLLOW:
+                oldLeader = player_party->get_leader();
+                player_party->chooseNewLeader();
+                newLeader = player_party->get_leader();
+                if (oldLeader != newLeader) {
+                    oldLeader->setControlMode(CONTROL_MODE_FOLLOW);
+                }
+                if (newLeader != this) {
+                    setControlMode(CONTROL_MODE_FOLLOW);
+                }
+                break;
+            case PARTY_CONTROL_SOLO:
+                setControlMode(CONTROL_MODE_IDLE);
+                break;
+            case PARTY_CONTROL_ROUND_ROBIN:
+                setControlMode(CONTROL_MODE_PLAYER);
+                break;
+            }
+        }
+    } else {
+        ctrl = ctrl_character_ai;
+        if (isPlayerPartyMember()) {
+            if (isLeader()) {
+                player_party->chooseNewLeader();
+                assert(this != player_party->get_leader());
+            }
+            if (isSolo()) {
+                setSolo(false);
+                player_party->enableFollowMode();
+            }
+            if (engagedInTask()) {
+                taskAbort();
+            }
+        }
+        setControlMode(CONTROL_MODE_AUTO);
+    }
+}
+
+void Character::setAttackTarget(class Character * newtarget) 
+{
+        if (target == newtarget)
+                return;
+
+        if (target && target != this)
+                obj_dec_ref(target);
+
+        target = newtarget;
+
+        if (target && target != this)
+                obj_inc_ref(target);
+}
+
+bool Character::isSolo() {
+        return solo;
+}
+
+int Character::getLight() {
+        return light;
+}
+
+int Character::getVisionRadius() {
+        return species->vr;
+}
+
+int Character::getSpeed() {
+    // Returns the character-specific number of 
+    // Action Points per round for this character.
+
+    int total_AP;
+    int AP_modifier_from_equipped_items = 0;
+
+    if (AP_per_round > 0)
+       total_AP = AP_per_round;
+    else
+       total_AP = species->spd;
+
+    int armsIndex = 0;
+    for (class ArmsType * arms = enumerateArms(&armsIndex); arms != NULL; 
+        arms = getNextArms(&armsIndex)) {
+       AP_modifier_from_equipped_items += arms->get_AP_mod();
+    }
+    total_AP += AP_modifier_from_equipped_items;
+
+    if (total_AP < 1)
+       total_AP = 1; // SAM: perhaps revisit this...
+
+    return total_AP;
+}
+
+int Character::setSpeed(int val) {
+    AP_per_round = val;
+    return AP_per_round;
+}
+
+int Character::getMana() {
+        return mana;
+}
+
+void Character::setMana(int val) {
+        mana = val;
+}
+
+bool Character::isFleeing() {
+        return fleeing;
+}
+
+void Character::setOrder(int order) {
+        this->order = order;
+}
+
+void Character::setCombat(bool val) {
+        inCombat = val;
+}
+
+int Character::getDefend()
+{
+        int defend = 0;
+
+        if (isAsleep())
+                return -3; // hack: hard-coded constant
+
+               int armsIndex=0;
+        for (class ArmsType * arms = enumerateArms(&armsIndex); arms != NULL; 
+             arms = getNextArms(&armsIndex)) {
+                defend += dice_roll(arms->getToDefendDice());
+        }
+        
+        defend += defenseBonus;
+
+        if (isSubmerged()) {
+                defend += kern_intvar_get("submerged_def_bonus");
+        }
+
+        return defend;
+}
+
+int Character::getToHitPenalty()
+{
+        int penalty = 0;
+
+               int armsIndex=0;
+        for (class ArmsType * arms = enumerateArms(&armsIndex);
+             arms != NULL; arms = getNextArms(&armsIndex)) {
+                int roll = dice_roll(arms->getToHitDice());
+                if (roll < 0)
+                        penalty += roll;
+        }
+        
+        return penalty;
+}
+
+int Character::getBaseAttackBonus(class ArmsType * weapon)
+{
+       int strbonus = weapon->modifyStrAttack(session_run_query(Session, str_based_attack_query, "p", this));
+       int dexbonus = weapon->modifyDexAttack(session_run_query(Session, dex_based_attack_query, "p", this));
+       int totalbonus = (strbonus + dexbonus) / (100 * 1000);
+       return (1+ totalbonus);
+}
+
+int Character::getAttackBonus(class ArmsType * weapon)
+{
+       return (rand() % getBaseAttackBonus(weapon));
+}
+
+int Character::getDamageBonus(class ArmsType * weapon)
+{
+       int dambonus = weapon->modifyDamageBonus(session_run_query(Session, damage_bonus_query, "p", this))/(100 * 1000);
+       return (rand() % (1+ dambonus));
+}
+
+int Character::getAvoidBonus()
+{
+       //hack: dont get any bonus here if you're asleep on the job
+       if (isAsleep())
+               return 0;
+               
+       int avoidBonus = session_run_query(Session, defense_bonus_query, "p", this);
+       float avoidMod = 1;
+       
+       //roundabout way of getting data in order to preserve info for stderr
+       int armsIndex=0;
+       for (class ArmsType * arms = enumerateArms(&armsIndex);
+                arms != NULL; arms = getNextArms(&armsIndex))
+       {
+               avoidMod = arms->modifyAvoidBonus(avoidMod);
+       }
+       
+       int totalbonus = (int)(avoidBonus * (avoidMod/1000));
+       return (rand() % (1+ totalbonus));
+}
+
+int Character::getArmor()
+{
+        int armor = 0;
+
+               int armsIndex=0;
+        for (class ArmsType * arms = enumerateArms(&armsIndex);
+             arms != NULL; arms = getNextArms(&armsIndex)) {
+                armor += dice_roll(arms->getArmorDice());
+        }
+
+        // the obsolescent 'armor class' is still used by the 'protect' spell
+        // effect
+        armor += ac;
+        
+        // Some species have an armor bonus
+        if (species->armor_dice) {
+                armor += dice_roll(species->armor_dice);
+        }
+
+        return armor;
+
+}
+
+class Party *Character::getParty()
+{
+        return party;
+}
+
+void Character::burn()
+{
+        damage(DAMAGE_FIRE);
+        log_msg("%s burning-%s!", getName(), getWoundDescription());
+}
+
+void Character::sleep()
+{
+        if (isAsleep())
+                return;
+
+        changeSleep(true);
+        log_msg("%s sleeping!", getName());
+}
+
+bool Character::canSee(class Object *obj)
+{
+        return (obj->getPlace() == getPlace() &&
+                place_flying_distance(getPlace(), getX(), getY(), 
+                                      obj->getX(), obj->getY()) <= 
+                getVisionRadius() &&
+                obj->isVisible() &&
+                place_in_los(getPlace(), getX(), getY(),
+                             obj->getPlace(), obj->getX(), obj->getY()));
+}
+
+bool Character::atAppointment()
+{
+        struct appt *curAppt = &sched->appts[appt];
+
+        if (getX() >= curAppt->x
+            && getX() < (curAppt->x + curAppt->w)
+            && getY() >= curAppt->y
+            && getY() < (curAppt->y + curAppt->h)) {
+                return true;
+        }
+        return false;
+}
+
+bool Character::playerIsInMyBed()
+{
+       struct appt *curAppt = &sched->appts[appt];
+       
+       if (SLEEPING!=curAppt->act)
+       return false;
+       
+       class Character *sleeper = 
+               (class Character*)place_get_object(getPlace(), 
+                       curAppt->x,
+                       curAppt->y,
+                       being_layer);
+                       
+       return (sleeper
+               && sleeper->isPlayerControlled()
+               && sleeper->isResting());
+}
+
+//return true if character is next to or on the appointment loc
+bool Character::nextToAppointment()
+{
+   struct appt *curAppt = &sched->appts[appt]; 
+       
+       if (abs(curAppt->x - getX())>1)
+       {
+               return false;      
+       }
+       if (abs(curAppt->y - getY())>1)
+       {
+               return false;      
+       } 
+
+       return true;
+}
+
+void Character::kickPlayerOutOfMyBed()
+{
+        struct appt *curAppt = &sched->appts[appt];
+
+        log_msg("Kicked out of bed!");
+        player_party->throw_out_of_bed();
+
+        // now switch places with whoever is in bed
+       class Character *sleeper = 
+               (class Character*)place_get_object(getPlace(), 
+                                                  curAppt->x,
+                                                  curAppt->y,
+                                                  being_layer);
+       assert(sleeper);
+       switchPlaces(sleeper);
+
+       assert(atAppointment());
+       setActivity(curAppt->act);
+}
+
+void Character::switchPlaces(class Being *occupant)
+{
+        int oldx = getX();
+        int oldy = getY();
+        int newx = occupant->getX();
+        int newy = occupant->getY();
+
+        // Save these before calling remove because remove()
+        // automatically resets these to defaults (for sane
+        // reasons... I think)
+        class Character *oldTarget = target;
+        struct place *oldPlace = getPlace();
+        bool wasSolo = isSolo();
+        
+        //remove();
+        occupant->relocate(oldPlace, oldx, oldy);
+        relocate(oldPlace, newx, newy);
+        decActionPoints(place_get_diagonal_movement_cost(getPlace(), 
+                                                         oldx, oldy,
+                                                         newx, newy,
+                                                         this, 0));
+        setAttackTarget(oldTarget);
+        setSolo(wasSolo);
+}
+
+bool Character::commute()
+{
+       int tx, ty;
+
+        // Note: this could be improved a bit by caching the results of the
+        // rectangle search below. Since the path is cached I'm not sure how
+        // big of a gain it would be.
+
+        struct appt *curAppt = &sched->appts[appt];
+
+        // Check if the commute is over
+        if (atAppointment()) {
+                setActivity(curAppt->act);
+                return true;
+        }
+
+        // Else search for an open place in the appointment rectangle
+        for (ty = curAppt->y; ty < curAppt->y + curAppt->h; ty++) {
+                for (tx = curAppt->x; tx < curAppt->x + curAppt->w;  tx++) {
+
+                        if (!place_is_passable(getPlace(), tx, ty, this, 
+                                               PFLAG_IGNOREMECHS) ||
+                            place_is_hazardous(getPlace(), tx, ty))
+                                continue;
+                        
+                        // Try to go there. Adjacent-to-there is not good
+                        // enough; we will get stuck repeatedly trying to
+                        // pathfind if the last step is impassable (Bug
+                        // 1734069).
+                        if (!pathfindTo(getPlace(), tx, ty, 
+                                        PFLAG_ADJACENTNOTOK|PFLAG_IGNOREMECHS)) {
+                                continue;
+                        }
+                        
+                        // Check if the commute is over.
+                        if (atAppointment()) {
+                                setActivity(curAppt->act);
+                        }
+
+                        return true;
+                }
+        }
+
+        // Special case: if the appointment is the character's bed, and
+        // pathfinding failed because the player is sleeping in it, then kick
+        // the player out of bed
+                       if (playerIsInMyBed())
+                       {
+                               if (nextToAppointment())
+                               {
+                                       //evict the player if we are close enough
+                                       kickPlayerOutOfMyBed();
+                               }
+                               else
+                               {
+                                       //try to reach bed, clambering over other beings as necessary
+                                       pathfindTo(getPlace(), curAppt->x, curAppt->y, PFLAG_IGNOREBEINGS | PFLAG_IGNOREMECHS);
+                               }
+                               return true;
+                       }
+
+        dbg("%s cannot find path to [%d %d %d %d] while commuting\n", 
+               getName(), 
+               sched->appts[appt].x, 
+               sched->appts[appt].y, 
+               sched->appts[appt].w, 
+               sched->appts[appt].h);
+
+        return false;
+}
+
+void Character::synchronize()
+{
+        struct appt *cur_appt = 0;
+
+       if (!sched || sched->n_appts == 0)
+               return;
+               
+       if (isDead())
+               return;
+
+        cur_appt = sched_get_appointment(sched, Session->clock.hour,
+                                         Session->clock.min);
+
+        if (getPlace()
+            && getPlace() != cur_appt->place) {
+                introduce();
+                return;
+        } 
+
+        /* Iff the character is not already in their appointment rectangle then
+         * relocate them to the upper left corner of their appointment. The ULC
+         * is better than the center because it's more obvious to the schedule
+         * designer that the ULC needs to be passable terrain. If they are
+         * already in their appointment then don't relocate them, because it
+         * looks funny when you reload the game.
+         */
+        if ((getX() < cur_appt->x)
+            || (getX() >= (cur_appt->x + cur_appt->w))
+            || (getY() < cur_appt->y)
+            || (getY() >= (cur_appt->y + cur_appt->h))) {
+                relocate(cur_appt->place, cur_appt->x, cur_appt->y);
+        }
+       setActivity(cur_appt->act);
+        appt = cur_appt->index;
+}
+
+void Character::introduce()
+{
+        assert(sched);
+               
+               if (isDead())
+                       return;
+
+        struct appt *newAppt = sched_get_appointment(sched, 
+                                                     Session->clock.hour,
+                                                     Session->clock.min);
+        if (getPlace() != newAppt->place) {
+
+                // Since this code just "teleports" the character, make sure
+                // the player isn't looking.
+
+                // Introduce a character into the place as part of its
+                // schedule. For now, just drop it on its location as in
+                // synchronize(). DO NOT try to use object::relocate(). It's
+                // seriously overextended and has a bunch of logic that will
+                // prevent NPC's from relocating.
+                obj_inc_ref(this);
+                if (getPlace()) {
+                        place_remove_object(getPlace(), this);
+                }
+                setPlace(newAppt->place);
+                setX(newAppt->x);
+                setY(newAppt->y);
+                place_add_object(newAppt->place, this);
+                obj_dec_ref(this);
+                setActivity(newAppt->act);
+                appt = newAppt->index;
+        }
+}
+
+void Character::getAppointment()
+{
+
+        int nextAppt = appt + 1;
+
+        /* Special case: the last appointment of the day is over when the clock
+           rolls over at midnight. We can detect clock rollover by checking if
+           the current time is BEFORE the start of the current appt. */
+        if (nextAppt == sched->n_appts) {
+                if (Session->clock.hour < sched->appts[appt].hr) {
+                        appt = 0;
+                }
+        }
+
+        /* Normal case: check if the clock time exceeds the start time of our
+           next appt. */
+        else if (Session->clock.hour >= sched->appts[nextAppt].hr &&
+                 Session->clock.min >= sched->appts[nextAppt].min) {
+                appt = nextAppt;
+        }
+
+        if (atAppointment()) {
+                setActivity(sched->appts[appt].act);
+        } else {
+                setActivity(COMMUTING);
+        }
+
+}
+
+void Character::exec()
+{
+        int points_last_loop;
+        class Character *leader;
+        bool noHostiles = false;
+        bool appointmentChecked = false;
+                
+        //printf("exec %s\n", getName());
+
+        startTurn();
+        
+        if (isDead() || ! isOnMap() ||action_points <= 0) {
+                endTurn();
+                return;
+        }
+
+        if (isResting()) {
+
+                // -----------------------------------------------------------
+                // Every hour until the wakeup alarm goes off have the
+                // character rest a little.
+                //
+                // The first character to wakeup to the alarm clock will wake
+                // up the party.
+                // -----------------------------------------------------------
+                
+                assert(isAsleep());
+
+                if (clock_alarm_is_expired(&rest_alarm)) {
+                        rest(1);
+                        clock_alarm_set(&rest_alarm, 60);
+                }
+
+                if (clock_alarm_is_expired(&wakeup_alarm)) {
+
+                        if (! isPlayerPartyMember()) {
+                                endResting();
+                        } else {
+                                log_begin_group();
+                                log_msg("Done resting...");
+                                endResting();
+
+                                if (player_party->isCamping())
+                                        player_party->endCamping();
+                                else if (player_party->isResting())
+                                        player_party->endResting();
+
+                                log_end_group();
+                        }
+                }
+
+                endTurn();
+                return;
+        }
+
+        else if (isGuarding()) {
+
+                // -----------------------------------------------------------
+                // Every hour have the guard repair the vehicle by some amount.
+                //
+                // When guarding is over the guard will wake up the party.
+                // -----------------------------------------------------------
+
+                class Vehicle *vehicle = player_party->getVehicle();
+                if (clock_alarm_is_expired(&rest_alarm)) {
+                        if (isPlayerControlled() &&
+                            vehicle &&
+                            vehicle->getHp() < 
+                            vehicle->getMaxHp()) {
+                                vehicle->heal(
+                                        vehicle->getMaxHp() / 
+                                        10);
+                                foogodRepaint();
+                                log_begin("%s repairs ", getName());
+                                vehicle->describe();
+                                log_end(".");
+                        }
+                        clock_alarm_set(&rest_alarm, 60);
+                }
+
+                if (clock_alarm_is_expired(&wakeup_alarm)) {
+                        endGuarding();
+
+                        if (isPlayerPartyMember()) {
+                                if (player_party->isCamping())
+                                        player_party->endCamping();
+                                else if (player_party->isResting())
+                                        player_party->endResting();
+                        }
+                }
+                endTurn();
+                return;
+        }
+
+        else if (isLoitering()) {
+                if (clock_alarm_is_expired(&wakeup_alarm)) {
+                        if (! isPlayerPartyMember()) {
+                                endLoitering();
+                        } else {
+                                log_begin_group();
+                                log_msg("Done loitering...");
+                                endLoitering();
+
+                                if (player_party->isLoitering())
+                                        player_party->endLoitering();
+                                log_end_group();
+                        }
+                }
+                endTurn();
+                return;
+        }
+
+        // ------------------------------------------------------------------
+        // Check for cases that prevent the character from taking a turn. Note
+        // that if the character is sleeping he will still take a turn iff the
+        // sleep is part of his schedule.
+        // ------------------------------------------------------------------
+
+        if (isAsleep() && getActivity() != SLEEPING) {
+                
+                if (ambushedWhileCamping &&
+                    ((rand() % 100) < PROB_AWAKEN)) {
+                        endCamping();
+                } else {
+                        endTurn();
+                        return;
+                }
+        }
+
+        switch (getControlMode()) {
+                
+        case CONTROL_MODE_AUTO:
+
+                // Loop until the turn is over or the character stops using
+                // action points.
+                points_last_loop = 0;
+                while (! isTurnEnded() &&
+                       getActionPoints() != points_last_loop) {
+                        points_last_loop = action_points;
+
+                        // Lookup this character's schedule. We only need to do
+                        // it once per turn; the clock won't change in the
+                        // loop. But we want to do it inside the loop so that
+                        // if there's no AP the schedule won't change the
+                        // character's state. This was specifically added so
+                        // that An Zu could wake up sleeping NPC's for a few
+                        // rounds by waking them up and socking them with an AP
+                        // debt to keep them docile for a bit.
+                        if (sched && ! appointmentChecked) {
+                                getAppointment();
+                                appointmentChecked = true;
+                        }
+
+                        switch (getActivity()) {
+                        case COMMUTING:
+                                // pathfind to next appointment
+                                commute();
+                                break;
+                        case EATING:
+                        case SLEEPING:
+                                // do nothing
+                                break;
+                        case FIGHTING:
+                        default:
+                                // call the AI
+                                ctrl(this);
+                                break;
+                        }
+                }
+                break;
+
+        case CONTROL_MODE_PLAYER:
+
+                /* Highlight the character & prompt the user */
+                select(true);
+
+                // Update name in foogod window
+                if (PARTY_CONTROL_ROUND_ROBIN == player_party->getPartyControlMode()) {
+                    foogod_set_title("Round Robin: %s", getName());
+                    foogodRepaint();
+                }
+
+                // If the character is out-of-site then change the camera to
+                // focus on the character.
+                if (! mapIsInCameraView(getPlace(), getX(), getY())) {
+                        mapCenterCamera(getX(), getY());
+                        mapUpdate(0);
+                }
+
+                /* Hand control over to the player */
+                ctrl(this);
+
+                /* Increment the turn count once per combat round. */
+                if (isSolo() || isLeader()) {
+                        session_inc_turn_count();
+                        foogodRepaint();
+                }
+
+                if (Session->reloaded)
+                        /* Hack: this object has been destroyed. Leave
+                         * now. Don't touch a thing. */
+                        return;
+
+                /* Un-highlight the character */
+                select(false);
+
+                break;
+
+
+        case CONTROL_MODE_FOLLOW:
+
+                // -----------------------------------------------------------
+                // Follow the party leader.
+                // -----------------------------------------------------------
+
+                leader = player_party->get_leader();
+
+                assert(leader);
+                assert(this != leader);
+
+                // -----------------------------------------------------------
+                // Loop until the leader is one tile away, we run out of action
+                // points, or we stop using action points (this last occurs
+                // when we can't find a path)
+                // -----------------------------------------------------------
+
+                points_last_loop = 0;
+
+                // Since this character is in follow mode it's keystroke hook
+                // hasn't been run yet. Do it now so that effects like
+                // paralysis work properly on PC's in follow mode.
+                runHook(OBJ_HOOK_KEYSTROKE, 0);
+                if (isTurnEnded()) {
+                        break;
+                }
+
+                noHostiles = ! place_contains_hostiles(getPlace(), this);
+
+                while (1 < place_flying_distance(Place, getX(), getY(), 
+                                                 leader->getX(), 
+                                                 leader->getY()) 
+                       && (noHostiles || ! isTurnEnded())
+                       && getActionPoints() != points_last_loop
+                        ) {
+
+                        points_last_loop = getActionPoints();
+
+                        // ----------------------------------------------------
+                        // Take a step toward the leader, recompute
+                        // line-of-sight and repaint to show the action.
+                        // ----------------------------------------------------
+
+                        pathfindTo(leader->getPlace(), 
+                                   leader->getX(), 
+                                   leader->getY(),
+                                   PFLAG_IGNOREMECHS
+                                   |PFLAG_IGNORECOMPANIONS
+                                   |PFLAG_IGNORESTEPTRIG
+                                );
+                        mapCenterView(getView(), getX(), getY());
+                        mapSetDirty();
+                }
+
+                // In follow mode don't accumulate action point depth. This
+                // leads to annoying laggardliness in player party members.
+                setActionPoints(0);
+                break;
+        case CONTROL_MODE_IDLE:
+                break;
+
+        case CONTROL_MODE_TASK:
+            assert(taskproc);
+            if (isPlayerControlled()) {
+                log_msg("%s continues %s...", getName(), getTaskName());
+            }
+            closure_exec(taskproc, "pl", this, taskgob->p);
+            break;
+
+        default:
+                assert(false);
+                break;
+        }
+
+        endTurn();
+}
+
+void Character::setSolo(bool val)
+{
+        if (solo == val)
+                return;
+
+        if (val) {
+            assert(isPlayerControlled());
+            if (engagedInTask()) {
+                taskAbort();
+            }
+            solo = val;
+            attachCamera(true);
+            setControlMode(CONTROL_MODE_PLAYER);
+            log_msg("%s goes solo.", getName());
+            mapCenterCamera(getX(), getY());
+            mapSetDirty();
+        } else {
+            solo = val;
+            attachCamera(false);
+            setControlMode(CONTROL_MODE_IDLE);
+        }
+}
+
+void Character::unCharm()
+{
+        // Check for illegal request
+        if (0 == factionSwitch) {
+                warn("%s:uncharm:factionSwitch 0", getName());
+                return;
+        }
+
+        // Decrement the faction switch.
+        factionSwitch--;
+
+        // If the faction switch is still on then there are other charms in
+        // effect and we don't want to disturb them. NOTE: the last faction
+        // used with charm will remain in effect until the factionSwitch falls
+        // to zero. This will match most expected behavior related to multiple
+        // charm effects.
+        if (factionSwitch)
+                return;
+
+        // Is this an NPC or a party member?
+        if (! isPlayerPartyMember()) {
+                
+                // Revert the NPC to AI-control
+                setControlMode(CONTROL_MODE_AUTO);
+                
+                // Remove the NPC's map view, if any
+                if (NULL != getView()) {
+                        rmView();
+                        mapDestroyView(getView());
+                        setView(NULL);
+                }
+
+                // Switch the controller back to the AI
+                //ctrl = ctrl_character_ai;
+                
+        } else {
+
+                // Set the party member's control mode based on the party's
+                // current control mode.
+                switch (player_party->getPartyControlMode()) {
+                case PARTY_CONTROL_ROUND_ROBIN:
+                        setControlMode(CONTROL_MODE_PLAYER);
+                        break;
+                case PARTY_CONTROL_SOLO:
+                        setControlMode(CONTROL_MODE_IDLE);
+                        break;
+                case PARTY_CONTROL_FOLLOW:
+                        if (isLeader()) {
+                                setControlMode(CONTROL_MODE_PLAYER);
+                        } else {
+                                setControlMode(CONTROL_MODE_FOLLOW);
+                        }
+                        break;
+                }
+        }
+}
+
+void Character::charm(int newFaction)
+{
+
+        if (isDead())
+                return;
+
+        // Set the temporary faction (possibly clobbering the previous one).
+        tmpFaction = newFaction;
+        
+        if (isPlayerPartyMember())
+                // Switch the party member to be AI-controlled.
+                setControlMode(CONTROL_MODE_AUTO);
+        else {
+                // Add a map view for the non-party member
+                setView(mapCreateView());
+                addView();
+                
+                // Switch the non-party member to be player-controlled
+                setControlMode(CONTROL_MODE_PLAYER);
+
+                // Switch the controller over to the player
+                // NOTE: this needs a bit more work to be nicely done
+                // ctrl = ctrl_character_ui;
+        }
+
+        // Increment the faction switch (must do this AFTER calling
+        // setControlMode())
+        factionSwitch++;
+
+}
+
+bool Character::isCharmed()
+{
+        return getCurrentFaction() != getBaseFaction();
+}
+
+bool Character::isPlayerPartyMember()
+{
+        // If player party has not been created yet it's safe to assume that
+        // for now this is not a party member.
+        if (!Session || ! player_party) {
+                return false;
+        }
+        return (class Object*)party == (class Object*)player_party;
+}
+
+void Character::setControlMode(enum control_mode mode)
+{
+        // -------------------------------------------------------------------
+        // Player party calls in here to switch between follow, round-robin and
+        // solo modes. Don't want to change the control mode of charmed
+        // member's in this case. Always need to uncharm before switching
+        // control modes.
+        // -------------------------------------------------------------------
+
+        if (isCharmed())
+                return;
+
+        control_mode = mode;
+
+        switch (mode) {
+        case CONTROL_MODE_AUTO:
+                ctrl = ctrl_character_ai;
+                break;
+        case CONTROL_MODE_PLAYER:
+        case CONTROL_MODE_IDLE:
+        case CONTROL_MODE_FOLLOW:
+                ctrl = ctrl_character_ui;
+                break;
+        case CONTROL_MODE_TASK:
+            break;
+        }
+}
+
+
+bool Character::add(ObjectType *type, int amount)
+{
+        if (isPlayerPartyMember()) {
+                return player_party->add(type, amount);
+        } else if (container) {
+                container->add(type, amount);
+                return true;
+        }
+
+        return false;
+}
+
+
+bool Character::takeOut(ObjectType *type, int amount)
+{
+        if (isPlayerPartyMember()) {
+                return player_party->takeOut(type, amount);
+        } else if(container) {
+                return container->takeOut(type, amount);                
+        }
+        return false;
+
+}
+bool Character::addFood(int quantity)
+{
+        if (isPlayerPartyMember()) {
+                player_party->addFood(quantity);
+                return true;
+        }
+        return false;
+}
+
+bool Character::addGold(int quantity)
+{
+        if (isPlayerPartyMember()) {
+                player_party->addGold(quantity);
+                return true;
+        }
+        return false;
+}
+
+void Character::beginResting(int hours)
+{
+        assert(hours > 0);
+
+        if (isDead())
+                return;
+
+        clock_alarm_set(&wakeup_alarm, hours * 60);
+        clock_alarm_set(&rest_alarm, 60);
+        resting = true;
+        changeSleep(true);
+}
+
+void Character::endResting()
+{
+        resting = false;
+        setControlMode(CONTROL_MODE_PLAYER);
+        awaken();
+}
+
+bool Character::isResting()
+{
+        return resting;
+}
+
+void Character::beginLoitering(int hours)
+{
+        assert(hours > 0);
+
+        if (isDead())
+                return;
+
+        clock_alarm_set(&wakeup_alarm, hours * 60);
+        loitering = true;
+}
+
+void Character::endLoitering()
+{
+        loitering = false;
+        if (! engagedInTask()) {
+            setControlMode(CONTROL_MODE_PLAYER);
+        }
+}
+
+bool Character::isLoitering()
+{
+        return loitering;
+}
+
+void Character::beginCamping(int hours)
+{
+        ambushedWhileCamping = false;
+        beginResting(hours);
+}
+
+void Character::endCamping()
+{
+        ambushedWhileCamping = false;
+        endResting();
+}
+
+bool Character::isCamping()
+{
+        return isResting();
+}
+
+void Character::ambushWhileCamping()
+{
+        resting = false;
+        ambushedWhileCamping = true;
+
+        if (!isAsleep())
+                return;
+
+        if ((rand() % 100) < PROB_AWAKEN) {
+                endCamping();
+        }
+
+}
+
+void Character::beginGuarding(int hours)
+{
+        assert(hours > 0);
+        assert(!isAsleep());
+        assert(!isDead());
+
+        clock_alarm_set(&wakeup_alarm, hours * 60);
+        clock_alarm_set(&rest_alarm, 60);
+        setControlMode(CONTROL_MODE_IDLE);
+        guarding  = true;
+}
+
+void Character::endGuarding()
+{
+        guarding = false;
+        setControlMode(CONTROL_MODE_PLAYER);
+}
+
+bool Character::isGuarding()
+{
+        return guarding;
+}
+
+void Character::heal(int amount)
+{
+        amount = min(amount, getMaxHp() - hp);
+        hp += amount;
+        if (isPlayerControlled() && amount)
+                statusFlash(getOrder(), Blue);
+        /* fixme: if sufficiently healed should stop fleeing */
+}
+
+void Character::setLeader(bool val)
+{
+        if (is_leader == val)
+                return;
+
+        if (is_leader) {
+                attachCamera(false);
+                if (isPlayerControlled()) {
+                    setControlMode(CONTROL_MODE_IDLE);
+                }
+        } else {
+                attachCamera(true);
+                setControlMode(CONTROL_MODE_PLAYER);
+                //consolePrint("%s is now party leader.\n", getName());
+                mapSetPlace(getPlace());
+                mapCenterCamera(getX(), getY());
+                mapSetDirty();
+        }
+
+        is_leader = val;
+}
+
+bool Character::canBeLeader()
+{
+        return (! isDead() && isOnMap() && ! isAsleep() && ! isCharmed() && isPlayerControlled()
+                && (getActionPoints() > -(2*getActionPointsPerTurn()))
+                && ! engagedInTask()
+            );
+}
+
+bool Character::isLeader()
+{
+        return is_leader;
+}
+
+bool Character::isCompanionOf(class Object *other)
+{
+        // ------------------------------------------------------------------
+        // Do the simple thing for now. This is only used in
+        // the context of player party follow mode.
+        // ------------------------------------------------------------------
+
+        return isPlayerPartyMember() && other->isPlayerPartyMember();
+}
+
+bool Character::joinPlayer(void)
+{
+        class Party *old_party = party;
+
+        if (old_party == player_party)
+                return false;
+
+        if (NULL != old_party) {
+                old_party->removeMember(this);
+        }
+        
+        if (player_party->addMember(this)) {
+                addView();
+                // Turn off any prior AI.
+                setAI(NULL);
+                return true;
+        }
+
+        if (NULL != old_party) {
+                old_party->addMember(this);
+        }
+
+        setSchedule(NULL);
+
+        return false;
+}
+
+void Character::leavePlayer(void)
+{
+        if (!isPlayerPartyMember())
+                return;
+        if (isSolo()) {
+                assert(isPlayerControlled());
+                player_party->enableRoundRobinMode();
+        }
+
+        bool wasLeader = isLeader();
+
+        unreadyAll();
+
+        player_party->removeMember(this);
+        log_msg("%s leaves the party", getName());
+        if (wasLeader) {
+                player_party->enableFollowMode();
+        }
+}
+
+int Character::getActivity()
+{
+        if (place_contains_hostiles(getPlace(), this))
+                return FIGHTING;
+
+        if (! sched)
+                return NONE;
+        getAppointment();
+        if (atAppointment())
+                return sched->appts[appt].act;
+        return COMMUTING;
+}
+
+void Character::setActivity(int val)
+{
+        activity = val;
+        changeSleep(activity == SLEEPING);
+}
+
+bool Character::canWanderTo(int newx, int newy)
+{
+        // If this party is on a schedule then limit wandering to the
+        // area specied in the current appt.
+        if (sched) {
+                if (newx < sched->appts[appt].x ||
+                    newx > (sched->appts[appt].x + sched->appts[appt].w - 1) ||
+                    newy < sched->appts[appt].y ||
+                    newy > (sched->appts[appt].y + sched->appts[appt].h) - 1)
+                        return false;
+        }
+
+        return true;
+}
+
+void char_dtor(void *val)
+{
+        delete (class Character*)val;
+}
+
+void char_save(save_t *save, void *val)
+{
+        ((class Character*)val)->save(save);
+}
+
+void Character::save(struct save *save)
+{
+        class ArmsType *arms;
+
+        if (saved == save->session_id) {
+                save->write(save, "%s\n", tag);
+                return;
+        }
+
+        saved = save->session_id;
+
+        // Create it within a 'let' block
+        save->enter(save, "(let ((kchar ");
+
+        if (getGob()) {
+                // wrap the declaration in a call to bind the object to the
+                // gob 
+                save->enter(save, "(bind\n");
+
+                if (getForceContainerDrop()) {
+                        save->enter(save, "(kern-char-force-drop");
+                }
+        }
+
+        // Create the object within a 'let' block
+        save->enter(save, "(let ((kchar ");
+        save->enter(save, "(kern-mk-char\n");
+        if (this->tag) {
+                save->write(save, "\'%s  ; tag\n", this->tag );
+        } else {
+                save->write(save, "nil  ; tag\n");
+        }
+        save->write(save, "\"%s\"  ; name\n", this->getName());
+        save->write(save, "%s  ; species\n",  this->species->tag);
+        save->write(save, "%s  ; occ\n", this->occ ? this->occ->tag : "nil");
+        sprite_save(current_sprite, save);
+        /*save->write(save, "%s\n", sprite_get_tag(this->sprite));*/
+        save->write(save, "%d  ; BaseFaction\n", getBaseFaction());
+        save->write(save, "%d %d %d  ; str, int, dex\n",    str, intl, dex);
+        save->write(save, "%d %d  ;    hp_mod, hp_mult\n",  this->hp_mod,    this->hp_mult);
+        save->write(save, "%d %d  ;    mp_mod, mp_mult\n",  this->mp_mod,    this->mp_mult);
+        save->write(save, "%d %d  ;    HP, XP\n",           this->getHp(),   this->getExperience());
+        save->write(save, "%d  ;    mana\n",        this->getMana()  );
+        save->write(save, "%d  ;    AP_per_round\n", this->AP_per_round );
+        save->write(save, "%d  ;    level\n",       this->getLevel() );
+        save->write(save, "#%c  ; dead?\n", isDead() ? 't' : 'f');
+
+        if (conv != NULL) {
+                conv_save(conv, save);
+        } else {
+                save->write(save, "nil  ; conv\n");
+        }
+
+        save->write(save, "%s  ; sched\n", sched? sched->tag : "nil");
+
+        if (ai != NULL) {
+                closure_save(ai, save);
+        } else
+                save->write(save, "nil  ; ai\n");
+
+        // Items in personal inventory.
+        if (!container) {
+                save->write(save, "nil  ; inventory\n");
+        } else {
+                container->save(save);
+        }
+
+        // Readied items. Subtle: if this character has a container then these
+        // items have already been saved.
+               int armsIndex=0;
+       arms = this->enumerateArms(&armsIndex);
+        if (! arms) {
+                save->write(save, "nil  ; readied arms\n");
+        } else {
+                save->enter(save, "(list\n");
+                while (arms != NULL) {
+                        save->write(save, "%s\n", arms->getTag());
+                        arms = this->getNextArms(&armsIndex);
+                }
+                save->exit(save, ")  ; readied arms\n\n");
+        }
+
+        // Hooks
+        Object::saveHooks(save);
+
+        // Close the <var-list> part of the 'let' block
+        save->exit(save, "))) ;; end ((kchar ...)\n");
+
+        if (isSubmerged()) {
+                save->write(save, "(kern-obj-set-submerged kchar #t)\n");
+        }
+
+        // Close the 'let' block
+        save->exit(save, "kchar) ;; end (let ...)\n");
+
+        if (getForceContainerDrop()) {
+                save->exit(save, "#t) ;; kern-char-force-drop\n");
+        }
+
+        if (getGob()) {
+
+                // save the gob list
+                gob_save(getGob(), save);
+
+                // end the bind call
+                save->exit(save, ") ;; bind\n");
+        }
+        
+        // close the args assignment section of the let block
+        save->write(save, ")) ");
+
+        if (isKnown()) {
+                save->write(save, "(kern-char-set-known kchar #t)\n");
+        }
+
+        // Only save AP debt, else when the game reloads and the character
+        // restarts its turn it will carry over what is saved as an unwarranted
+        // bonus.
+        if (getActionPoints() < 0) {
+            save->write(save, "(kern-obj-set-ap kchar %d)\n", getActionPoints());
+        }
+
+        // save the task, if any
+        if (taskproc) {
+            save->write(save, "(kern-char-task-continue kchar \"%s\" ", getTaskName());
+            closure_save(taskproc, save);
+            if (taskgob) {
+                gob_save(taskgob, save);
+            } else {
+                save->write(save, " nil");
+            }
+            save->write(save, ")\n");
+        }
+
+        // close the 'let' block
+        save->exit(save, "kchar)\n");
+}
+
+void Character::setSchedule(struct sched *val)
+{
+
+        sched = val;
+
+        if (sched) {
+                sched_chars_node = session_add_sched_char(Session, this);
+        } else {
+                // Bugfix: if a character is eating and the schedule is set to
+                // NULL then the character will be stuck eating (and doing
+                // nothing else!).
+                setActivity(NONE);
+        }
+
+        // Bugfix: if an npc with a schedule is added to the player party
+        // either during the game or on reload, and it has a schedule, then the
+        // next time the player enters a town the scheduling code will mess
+        // with the party member.
+        if (! sched && sched_chars_node) {
+                session_rm_sched_char(sched_chars_node);
+                sched_chars_node = 0;
+        }
+}
+
+bool Character::tryToRelocateToNewPlace(struct place *newplace, 
+                                        int newx, int newy,
+                                        struct closure *closure)
+{
+        // NPCs and charmed PCs are not allowed to change places because I
+        // don't want them dissappearing into the ether.
+        //
+        // Addendum: this needs to work for characters with multi-place
+        // schedules. If I only forbid entry to the wilderness this should work
+        // as originally intended.
+        if (place_is_wilderness(newplace)
+            && (! isPlayerControlled())) {
+                return false;
+        }
+
+        // -----------------------------------------------------------------
+        // At this point I know the character is player-controlled, so I can
+        // print informative messages.
+        // -----------------------------------------------------------------
+
+        if (player_party->get_num_living_members() == 1) {
+                // Force to follow mode to avoid the annoying case
+                // where only one member is in the party and the player
+                // wants to leave a combat map.
+                player_party->enableFollowMode();
+        }
+
+        if (player_party->getPartyControlMode() != PARTY_CONTROL_FOLLOW) {
+                log_msg("Exit - must be in follow mode!");
+                return false;
+        }
+
+        if (player_party->get_leader() != this)
+                return false;
+
+        if (!player_party->rendezvous(getPlace(), getX(), getY())) {
+                log_msg("Exit - party can't rendezvous!");
+                return false;
+        }
+
+        groupExitTo(newplace, newx, newy, closure);
+
+        return true;
+
+}
+
+void Character::addDefense(int val)
+{
+        defenseBonus += val;
+}
+
+struct mmode *Character::getMovementMode()
+{
+        if (currentMmode) {
+                return currentMmode;
+        } else {
+                return species->mmode;
+        }
+}
+
+void Character::setMovementMode(struct mmode *mmode)
+{
+        currentMmode = mmode;
+}
+
+void Character::setCurrentFaction(int faction)
+{
+#if 1
+    Being::setCurrentFaction(faction);
+
+    // We need to implement charm differently. This is the wrong place to do
+    // it.
+#else
+        if (! isPlayerPartyMember()) {
+                Being::setCurrentFaction(faction);
+        } else {
+                if (faction != player_party->getBaseFaction()) {
+                        // player party member charmed
+
+                        // Fix for [ 1425039 ] Solo mode + possession = lockup:
+                        // if in solo mode, switch party to follow mode
+                        if (isSolo()) {
+                                setSolo(false);
+                                player_party->enableFollowMode();
+                        }
+
+                        setControlMode(CONTROL_MODE_AUTO);
+                        
+                        // subtle: in this case, do this AFTER calling
+                        // setControlMode() (charmed character's ignore control
+                        // mode changes)
+                        Being::setCurrentFaction(faction);
+
+                } else {
+                        // subtle: in this case, do this BEFORE calling
+                        // setControlMode() (opposite of above)
+                        Being::setCurrentFaction(faction);
+
+                        // player party member uncharmed
+                        switch (player_party->getPartyControlMode()) {
+                        case PARTY_CONTROL_ROUND_ROBIN:
+                                setControlMode(CONTROL_MODE_PLAYER);
+                                break;
+                        case PARTY_CONTROL_SOLO:
+                                setControlMode(CONTROL_MODE_IDLE);
+                                break;
+                        case PARTY_CONTROL_FOLLOW:
+                                if (isLeader()) {
+                                        setControlMode(CONTROL_MODE_PLAYER);
+                                } else {
+                                        setControlMode(CONTROL_MODE_FOLLOW);
+                                }
+                                break;
+                        }
+                }
+        }
+#endif
+}
+
+class Container* Character::getInventoryContainer()
+{
+        /* for player-controlled maybe return party inventory? */
+        if (isPlayerControlled())
+                return player_party->inventory;
+        return container;
+}
+
+void Character::setInventoryContainer(class Container *val)
+{
+        // Blow away the old one
+        if (container) {
+                assert(container->isEmpty());
+                obj_dec_ref(container);
+        }
+
+        container = val;
+        if (container) {
+                obj_inc_ref(container);
+        }
+}
+
+void Character::setAI(struct closure *val)
+{
+        // out with the old
+        if (ai) {
+                closure_unref(ai);
+                ai = NULL;
+        }
+        
+        // in with the new
+        if (val) {
+                closure_ref(val);
+                ai = val;
+        }
+}
+
+struct closure *Character::getAI()
+{
+        return ai;
+}
+
+void Character::setDead(bool val)
+{
+        dead = val;
+}
+
+bool Character::getForceContainerDrop()
+{
+        return forceContainerDrop;
+}
+
+void Character::setForceContainerDrop(bool val)
+{
+        forceContainerDrop = val;
+}
+
+bool Character::isStationary()
+{
+        return species->stationary;
+}
+
+bool Character::isKnown()
+{
+        return known;
+}
+
+void Character::setKnown(bool val)
+{
+        known = val;
+}
+
+const char * Character::getTaskName()
+{
+    return taskname ? taskname : "a nameless task";
+}
+
+void Character::taskCleanup()
+{
+    if (taskname) {
+        free(taskname);
+        taskname = NULL;
+    }
+
+    if (taskproc) {
+        closure_unref(taskproc);
+        taskproc = NULL;
+    }
+
+    if (taskgob) {
+        gob_unref(taskgob);
+        taskgob = NULL;
+    }
+
+    if (isPlayerPartyMember()) {
+        class Character *oldLeader, *newLeader;
+        switch (player_party->getPartyControlMode()) {
+        case PARTY_CONTROL_FOLLOW:
+            oldLeader = player_party->get_leader();
+            player_party->chooseNewLeader();
+            newLeader = player_party->get_leader();
+            if (oldLeader != newLeader) {
+                oldLeader->setControlMode(CONTROL_MODE_FOLLOW);
+            }
+            if (newLeader != this) {
+                setControlMode(CONTROL_MODE_FOLLOW);
+            }
+            break;
+        case PARTY_CONTROL_SOLO:
+            setControlMode(CONTROL_MODE_IDLE);
+            break;
+        case PARTY_CONTROL_ROUND_ROBIN:
+            setControlMode(CONTROL_MODE_PLAYER);
+            break;
+        }
+    }
+}
+
+void Character::taskAbort()
+{
+    log_msg("%s aborts %s!", getName(), getTaskName());
+    taskCleanup();
+}
+
+void Character::taskSetup(char *name_arg, struct closure *proc_arg, struct gob *gob_arg)
+{
+    assert(! engagedInTask());
+
+    if (name_arg) {
+        taskname = strdup(name_arg);
+    }
+
+    assert(proc_arg);
+    taskproc = proc_arg;
+    closure_ref(taskproc);
+
+    if (gob_arg) {
+        taskgob = gob_arg;
+        gob_ref(gob_arg);
+    }
+
+    if (isPlayerPartyMember()) {
+        switch (player_party->getPartyControlMode()) {
+        case PARTY_CONTROL_FOLLOW:
+            if (isLeader()) {
+                player_party->chooseNewLeader();
+                assert(this != player_party->get_leader());
+            }
+            break;
+        case PARTY_CONTROL_SOLO:
+            if (isSolo()) {
+                setSolo(false); // sets CONTROL_MODE_IDLE
+                player_party->enableFollowMode();
+            }
+            break;
+        case PARTY_CONTROL_ROUND_ROBIN:
+            break;
+        }
+    }
+
+    setControlMode(CONTROL_MODE_TASK);
+    taskInterruptOnDamage = true;
+}
+
+void Character::taskBegin(char *name_arg, struct closure *proc_arg, struct gob *gob_arg)
+{
+    taskSetup(name_arg, proc_arg, gob_arg);
+    log_msg("%s begins %s.", getName(), getTaskName());
+    endTurn();
+}
+
+void Character::taskContinue(char *name_arg, struct closure *proc_arg, struct gob *gob_arg)
+{
+    if (isPlayerControlled()) {
+        log_msg("%s continues %s.", getName(), getTaskName());
+    }
+
+    taskSetup(name_arg, proc_arg, gob_arg);
+}
+
+void Character::taskEnd()
+{
+    log_msg("%s completes %s!", getName(), getTaskName());
+    taskCleanup();
+}
+
+bool Character::engagedInTask()
+{
+    return taskproc != NULL;
+}
diff --git a/src/character.h b/src/character.h
new file mode 100644 (file)
index 0000000..0bf4a1f
--- /dev/null
@@ -0,0 +1,353 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef character_h
+#define character_h
+
+#include "Being.h"
+#include "Arms.h"
+#include "species.h"
+#include "clock.h"
+#include "sound.h"
+
+#undef RAM_ATTACK
+
+// Weird C++-isms ensue at compile-time if I try to include combat.h directly
+// here...
+extern void combatKIA(class Character *);
+
+struct ready_spell {
+       struct list list;
+       struct spell *spell;
+};
+
+struct point {
+       int x, y;
+};
+
+struct TypicalObjectInfo {
+       int probability;
+       class ObjectType *type;
+       int n_max;
+};
+
+
+class Character:public Being {
+ public:
+
+       enum ReadyResult {
+               Readied,
+               NoAvailableSlot,
+               WrongType,
+               TooHeavy
+       };
+
+       Character();
+        Character(const char *tag, const char *name, 
+                  struct sprite *sprite,
+                  struct species *species, struct occ *occ,
+                  int str, int intl,
+                  int dex, int hpmod, int hpmult, 
+                  int mpmod, int mpmult, 
+                  int hp, int xp, int mp,
+                 int AP_per_round,
+                  int lvl);
+       virtual ~ Character();
+
+        virtual int getActivity();
+        int getArmor();
+        int getDefend();
+        int getToHitPenalty();
+        int getBaseAttackBonus(class ArmsType * weapon);
+        int getAttackBonus(class ArmsType * weapon);
+        int getDamageBonus(class ArmsType * weapon);
+        int getAvoidBonus();
+        virtual class Party * getParty();
+       virtual int getType();
+       int  getHp();
+       void setHp(int hp);
+       int  getMana();
+        void setMana(int mana);
+       int getMaxMana();
+        class Container *getInventoryContainer();
+       virtual int getMaxHp();
+       virtual int getOrder();
+        int getXpForLevel(int lvl);
+       virtual void addExperience(int delta);
+       virtual int getExperience();
+       virtual unsigned char getStrength();
+       virtual unsigned char getIntelligence();
+       virtual unsigned char getDexterity();
+       virtual unsigned char getBaseStrength();
+       virtual unsigned char getBaseIntelligence();
+       virtual unsigned char getBaseDexterity();
+       virtual void setStrength(unsigned char newstat);
+       virtual void setIntelligence(unsigned char newstat);
+       virtual void setDexterity(unsigned char newstat);
+       int getLevel();
+        void setLevel(int level);
+        virtual struct mmode *getMovementMode();
+        virtual void setMovementMode(struct mmode *mmode);
+       virtual int getArmourClass();
+       virtual const char *getWoundDescription();
+       virtual class Character *getAttackTarget(class ArmsType * weapon);
+       virtual class ArmsType *getNextArms(int * armsIndex);
+       virtual class ArmsType *getNextWeapon(int * armsIndex);
+       virtual int getLight();
+       virtual int getVisionRadius();
+       virtual int getSpeed();
+       virtual int setSpeed(int val);
+       virtual struct sprite *getSprite();
+        virtual sound_t *getDamageSound();
+        virtual sound_t *get_movement_sound();
+
+
+        virtual bool isCharmed();
+        virtual bool isCamping();
+        virtual bool isCompanionOf(class Object *other);
+        virtual bool isGuarding();
+        virtual bool isLeader();
+        virtual bool isResting();
+       virtual bool isType(int classID);
+       virtual bool isDead();
+       virtual bool isAsleep();
+       virtual bool isIncapacitated();
+       virtual bool isPlayerControlled();
+       virtual bool hasReadied(class ArmsType * arms);
+       virtual bool isSolo();
+       virtual int  hasAmmo(class ArmsType * weapon);
+        virtual bool hasInInventory(class ObjectType *type);
+       virtual bool isFleeing();
+       virtual bool isVisible();
+       virtual bool isShaded();
+        virtual bool isPlayerPartyMember();
+        virtual bool canWanderTo(int newx, int newy);
+
+        virtual void addDefense(int val);
+       virtual void changeArmourClass(int val);
+       virtual void changeSleep(bool val);
+       virtual void setLight(int delta);
+       virtual void addMana(int delta);
+
+        virtual void setActivity(int val);
+        virtual void setControlMode(enum control_mode mode);
+        virtual void setInventoryContainer(class Container *container);
+        virtual void setLeader(bool val);
+        virtual void setSchedule(struct sched *sched);
+        virtual void setSolo(bool val);
+       virtual void setOrder(int order);
+       virtual void setPlayerControlled(bool val);
+       virtual void setAttackTarget(class Character * target);
+       virtual void setFleeing(bool val);
+       virtual void setCombat(bool val);
+        virtual void ambushWhileCamping();
+       virtual void awaken(void);
+        virtual void beginCamping(int hours);
+        virtual void beginGuarding(int hours);
+        virtual void beginResting(int hours);        
+       virtual void damage(int amount);
+       virtual void inflictDamage(int amount,class Character *attacker);
+        virtual void endCamping(void);
+        virtual void endGuarding();
+        virtual void endResting(void);
+        virtual void exec();
+        virtual void groupExitTo(struct place *dest_place, 
+                                 int dest_x, int dest_y,
+                                 struct closure *closure);
+        virtual void heal(int amount);
+        bool joinPlayer(void);
+        void leavePlayer(void);
+       virtual void kill();
+       virtual void remove();
+       virtual enum ReadyResult ready(class ArmsType * arms);
+       virtual void synchronize();
+       virtual bool unready(class ArmsType * arms);
+       virtual enum MoveResult move(int dx, int dy);
+       virtual void armThyself();
+       virtual bool needToRearm();
+       virtual void resurrect();
+       virtual void rest(int hours);
+       virtual class Object *clone();
+       virtual void describe();
+       virtual void examine();
+       virtual void burn();
+        virtual void save(struct save *save);
+        virtual void sleep();
+        virtual bool tryToRelocateToNewPlace(struct place *place, 
+                                             int x, int y,
+                                             struct closure *closure);
+       virtual class ArmsType *enumerateArms(int *armsIndex);
+       virtual class ArmsType *enumerateWeapons(int *armsIndex);
+        class ArmsType *getArmsInSlot(int slot);
+        virtual bool addFood(int quantity);
+        virtual bool addGold(int quantity);
+        virtual bool add(ObjectType *type, int amount);
+        virtual bool takeOut(ObjectType *type, int amount);
+        virtual void setCurrentFaction(int faction);
+        virtual bool isStationary();
+
+        void charm(int faction);
+        void unCharm();
+       void useAmmo(class ArmsType *weapon);
+        bool canSee(class Object *obj);
+       bool commute();
+        int getExperienceValue();
+       bool initStock(struct species * species, struct occ * occ,
+                      struct sprite * sprite, char *name, int order);
+
+        bool canBeLeader();
+        void setAI(struct closure *val);
+        struct closure *getAI();
+        void setDead(bool val);
+        void introduce();
+        void setForceContainerDrop(bool val);
+        bool getForceContainerDrop();
+
+        void beginLoitering(int hours);
+        void endLoitering();
+        bool isLoitering();
+       bool flee();
+        bool isKnown();
+        void setKnown(bool val);
+
+        void taskAbort();
+        void taskBegin(char *taskname, struct closure *taskproc, struct gob *taskgob);
+        void taskContinue(char *taskname, struct closure *taskproc, struct gob *taskgob);
+        void taskEnd();
+        bool engagedInTask();
+        const char *getTaskName();
+
+        struct node *plnode; // pointer back to party list node
+       class Party *party;
+       struct species *species;
+       struct occ *occ;
+       bool is_clone;
+
+        int hp_mod;
+        int hp_mult;
+        int mp_mod;
+        int mp_mult;
+
+ protected:
+       bool initCommon(void);
+       bool isAttackTargetInRange(class ArmsType *weapon);
+        void getAppointment();
+        
+       int hm;
+
+        // -------------------------------------------------
+        // Custom attribute modifiers
+        // -------------------------------------------------
+
+
+       int xp;
+       int order;
+       bool sleeping;
+       int ac; // used by spells
+       int str;
+       int intl;
+       int dex;
+       int mana;
+       int AP_per_round;  // Action Points per round (speed)
+       int lvl;
+        int defenseBonus;
+       bool playerControlled;
+       bool solo;
+       class Character *target;
+       class ArmsType **rdyArms;
+       bool fleeing;
+       int burden;
+       bool inCombat;
+        sound_t *damage_sound;
+
+       // *** NPC fields
+       virtual void dropRdyArms();
+       virtual bool dropItems();
+       class Container *container;
+       bool rearm;
+
+       // *** PC fields
+       //struct sprite *sprite;
+
+        bool charmed;
+
+        // --------------------------------------------------------------------
+        // Stuff for resting/camping:
+        // --------------------------------------------------------------------
+        clock_alarm_t wakeup_alarm;
+        clock_alarm_t rest_alarm;
+        bool resting;
+        bool guarding;
+        bool loitering;
+
+       struct sched *sched;
+        int activity;
+        int appt;
+
+        bool is_leader;
+        void (*ctrl)(class Character *character);
+
+        int factionSwitch;
+        int tmpFaction;
+        bool ambushedWhileCamping;
+        struct closure *ai; // should be moved up to Being...
+        bool dead;
+
+        struct node *sched_chars_node;   /* for chars with multiplace scheds */
+        bool forceContainerDrop; // ensure the container is dropped on death
+        
+  protected:
+        virtual void switchPlaces(class Being *);
+
+ private:
+        bool atAppointment();
+        bool nextToAppointment();
+        bool playerIsInMyBed();
+        void kickPlayerOutOfMyBed();
+        void unreadyAll();
+        void getEvasionVector(int *dx, int *dy);
+        bool locationIsOk(int x2, int y2);
+        bool mapHasEdge();
+        bool followFleePath();
+        bool findFleePath();
+        bool pathfindToMapEdge();
+        bool fleeToMapEdge();
+        bool evade();
+        bool exitMap();
+        void taskCleanup();
+        void taskSetup(char *taskname, struct closure *taskproc, struct gob *taskgob);
+        void taskPromptToAbort();
+
+        bool fleePathFound;
+        int fleeX, fleeY, fleePathFlags;
+        struct mmode *currentMmode;
+        bool known;
+
+        char *taskname;
+        struct closure *taskproc;
+        struct gob *taskgob;
+        bool taskInterruptOnDamage;
+};
+
+extern void char_dtor(void *val);
+extern void char_save(struct save *save, void *val);
+
+#endif
diff --git a/src/clock.c b/src/clock.c
new file mode 100644 (file)
index 0000000..af82cfc
--- /dev/null
@@ -0,0 +1,391 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// Thi program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "sky.h"
+#include "clock.h"
+#include "screen.h"
+#include "common.h"
+#include "sprite.h"
+#include "place.h"
+#include "map.h"
+#include "player.h"
+#include "wq.h"
+#include "session.h"
+
+#include <assert.h>
+#include <math.h>
+
+#define Clock (Session->clock)
+
+int clock_year(void)
+{
+        return Clock.year;
+}
+
+int clock_month(void)
+{
+        return Clock.month;
+}
+
+int clock_week(void)
+{
+        return Clock.week;
+}
+
+int clock_day(void)
+{
+        return Clock.day;
+}
+
+int clock_hour(void)
+{
+        return Clock.hour;
+}
+
+int clock_minute(void)
+{
+        return Clock.min;
+}
+
+int clock_tick(void)
+{
+        return Clock.tick;
+}
+
+unsigned int clock_time_of_day(void)
+{
+        return (Clock.hour * 60 + Clock.min);
+}
+
+unsigned int clock_time(void)
+{
+        return Clock.total_minutes;
+}
+
+void clock_advance(int ticks)
+{
+        assert(Clock.tick < Clock.tick_to_change_time);
+
+        while (ticks-- > 0) {
+
+                Clock.tick++;
+                
+                if (Clock.tick == Clock.tick_to_change_time) {
+                        
+                        Clock.total_minutes++;
+                        Clock.tick = 0;
+                        Clock.tick_to_change_time = CLOCK_TICKS_PER_MINUTE;
+                        
+                        Clock.min++;
+                        if (Clock.min == MINUTES_PER_HOUR) {
+                                Clock.hour++;
+                                Clock.min = 0;
+                                if (Clock.hour == HOURS_PER_DAY) {
+                                        Clock.day++;
+                                        Clock.hour = 0;
+                                        if (Clock.day == DAYS_PER_WEEK) {
+                                                Clock.week++;
+                                                Clock.day = 0;
+                                                if (Clock.week == WEEKS_PER_MONTH) {
+                                                        Clock.month++;
+                                                        Clock.week = 0;
+                                                        if (Clock.month == MONTHS_PER_YEAR) {
+                                                                Clock.year++;
+                                                                Clock.month = 0;
+                                                        }
+                                                }
+                                        }
+                                }
+                        }
+                }
+        }
+                
+       mapRepaintClock();
+}
+
+char *time_HHMM_as_string(void)
+{
+       static char str[] = "HH:MMPM";
+       static int maxlen = strlen("HH:MMPM") + 1;
+       int hr = Clock.hour;
+       int min = Clock.min;
+       int n;
+
+       hr = (hr > 12) ? (hr - 12) : hr;
+       hr = (hr == 0) ? 12 : hr;
+
+       n = snprintf(str, maxlen, "%2d:%02d%2s",
+                    hr, min, (Clock.hour >= 12) ? "PM" : "AM");
+       assert(n != -1);
+       return str;
+}                              // time_HHMM_as_string()
+
+char *vague_time_as_string(void)
+{
+       static char str[] = "late afternoon";
+       static int maxlen = strlen("late afternoon") + 1;
+       int hr = Clock.hour;
+       int n;
+
+       if (hr < 4)
+       {
+               n = snprintf(str, maxlen, "night");
+       }
+       else if (hr < 7)
+       {
+               n = snprintf(str, maxlen, "early morning");     
+       }
+       else if (hr < 11)
+       {
+               n = snprintf(str, maxlen, "morning");   
+       }
+       else if (hr < 13)
+       {
+               n = snprintf(str, maxlen, "noon");      
+       }
+       else if (hr < 15)
+       {
+               n = snprintf(str, maxlen, "afternoon"); 
+       }
+       else if (hr < 18)
+       {
+               n = snprintf(str, maxlen, "late afternoon");    
+       }
+       else if (hr < 20)
+       {
+               n = snprintf(str, maxlen, "evening");   
+       }
+       else
+       {
+               n = snprintf(str, maxlen, "night");     
+       }
+       assert(n != -1);
+       return str;
+}                              // vague_time_as_string()
+
+char *time_YYYY_MM_DD_as_string(void)
+{
+       static char str[] = "YYYY/MM/DD";
+       static int maxlen = strlen("YYYY/MM/DD") + 1;
+       int n = snprintf(str, maxlen, "%04d/%02d/%02d",
+                        Clock.year, Clock.month, Clock.day);
+       assert(n != -1);
+       return str;
+}                              // time_YYYY_MM_DD_as_string()
+
+#ifdef OTHER_TIME_STRING_FUNCTIONS
+char *time_YYYY_as_string(void)
+{
+       static char str[] = "YYYY";
+       static int maxlen = strlen("YYYY") + 1;
+       int n = snprintf(str, maxlen, "%4d", Clock.year);
+       assert(n != -1);
+       return str;
+}
+
+char *time_MM_as_string(void)
+{
+       static char str[] = "MM";
+       static int maxlen = strlen("MM") + 1;
+       int n = snprintf(str, maxlen, "%2d", Clock.month);
+       assert(n != -1);
+       return str;
+}
+
+char *time_DD_as_string(void)
+{
+       static char str[] = "DD";
+       static int maxlen = strlen("DD") + 1;
+       int n = snprintf(str, maxlen, "%2d", Clock.day);
+       assert(n != -1);
+       return str;
+}
+#endif                         // OTHER_TIME_STRING_FUNCTIONS
+
+// SAM: 
+// A proper implementation of 
+// month_name(), week_name(), day_name()
+// will wait until we have GhulScript
+// for week and month names and such.
+// 
+const char *month_name(void)
+{
+       int month = Clock.month;
+       switch (month) {
+       case 0:
+               return "1st Month";
+       case 1:
+               return "2nd Month";
+       case 2:
+               return "3rd Month";
+       case 3:
+               return "4th Month";
+       case 4:
+               return "5th Month";
+       case 5:
+               return "6th Month";
+       case 6:
+               return "7th Month";
+       case 7:
+               return "8th Month";
+       case 8:
+               return "9th Month";
+       case 9:
+               return "10th Month";
+       case 10:
+               return "11th Month";
+       case 11:
+               return "12th Month";
+       default:
+               assert(0);
+       }
+}                              // month_name()
+
+const char *week_name(void)
+{
+       int week = Clock.week;
+       switch (week) {
+       case 0:
+               return "1st Week";
+       case 1:
+               return "2nd Week";
+       case 2:
+               return "3rd Week";
+       case 3:
+               return "4th Week";
+       default:
+               assert(0);
+       }
+}                              // week_name()
+
+const char *day_name(void)
+{
+       int day = Clock.day;
+       switch (day) {
+       case 0:
+               return "1st Day";
+       case 1:
+               return "2nd Day";
+       case 2:
+               return "3rd Day";
+       case 3:
+               return "4th Day";
+       case 4:
+               return "5th Day";
+       case 5:
+               return "6th Day";
+       case 6:
+               return "7th Day";
+       default:
+               assert(0);
+       }
+}                              // day_name()
+
+void clock_alarm_set(clock_alarm_t *alarm, unsigned int minutes)
+{
+        *alarm = Clock.total_minutes + minutes;
+}
+
+int clock_alarm_is_expired(clock_alarm_t *alarm)
+{
+        return (Clock.total_minutes >= *alarm);
+}
+
+int clock_alarm_remaining(clock_alarm_t *alarm)
+{
+       if (Clock.total_minutes >= *alarm) return 0;
+       return (*alarm - Clock.total_minutes);
+}
+
+int is_noon(void)
+{
+        return (Clock.hour == 12 && Clock.min == 0);
+}
+
+int is_midnight(void)
+{
+        return (Clock.hour == 0 && Clock.min == 0);
+}
+
+#ifdef INCLUDE_UNUSED_CLOCK_ROUTINES
+void clock_reset(struct clock *clock)
+{
+        memset(clock, 0, sizeof(*clock));
+}
+
+void clock_set_alarm(struct clock *clock, struct clock *offset)
+{
+
+        /* Copy the current time */
+        memcpy(clock, &Clock, sizeof(*clock));
+
+        /* Set the alarm to the current time plus the offset */
+        clock->min += offset->min;
+        if (clock->min >= MINUTES_PER_HOUR) {
+                offset->hour += clock->min / MINUTES_PER_HOUR;
+                clock->min %= MINUTES_PER_HOUR;
+        }
+
+        clock->hour += offset->hour;
+        if (clock->hour >= HOURS_PER_DAY) {
+                offset->day += clock->hour / HOURS_PER_DAY;
+                clock->hour %= HOURS_PER_DAY;
+        }
+
+        clock->day += offset->day;
+        if (clock->day >= DAYS_PER_WEEK) {
+                offset->week += clock->day / DAYS_PER_WEEK;
+                clock->day %= DAYS_PER_WEEK;
+        }
+
+        clock->week += offset->week;
+        if (clock->week >= WEEKS_PER_MONTH) {
+                offset->month += clock->week / WEEKS_PER_MONTH;
+                clock->week %= WEEKS_PER_MONTH;
+        }
+
+        clock->month += offset->month;
+        if (clock->month >= MONTHS_PER_YEAR) {
+                offset->year += clock->month / MONTHS_PER_YEAR;
+                clock->month %= MONTHS_PER_YEAR;
+        }
+        
+        clock->year += offset->year;
+
+        consolePrint("Set alarm for year %d, month %d, week %d, day %d, "
+                     "hour %d, min %d\n", clock->year, clock->month,
+                     clock->week, clock->day, clock->hour, clock->min);
+}
+
+int clock_alarm_expired(struct clock *clock)
+{
+        int total_minute;
+
+        total_minute  = (clock->year  - Clock.year)  * MINUTES_PER_YEAR;
+        total_minute += (clock->month - Clock.month) * MINUTES_PER_MONTH;
+        total_minute += (clock->week  - Clock.week)  * MINUTES_PER_WEEK;
+        total_minute += (clock->day   - Clock.day)   * MINUTES_PER_DAY;
+        total_minute += (clock->hour  - Clock.hour)  * MINUTES_PER_HOUR;
+        total_minute += (clock->min   - Clock.min);
+
+        return (total_minute <= 0);
+}
+#endif // INCLUDE_UNUSED_CLOCK_ROUTINES
diff --git a/src/clock.h b/src/clock.h
new file mode 100644 (file)
index 0000000..6eea57f
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef clock_h
+#define clock_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#define CLOCK_TICKS_PER_MINUTE TURNS_PER_MINUTE
+
+#define clock_alarm_save(clk,save) ((save)->write((save), "%d\n", (clk)))
+
+typedef unsigned int clock_alarm_t;
+
+struct clock {
+        int year;
+        int month;
+        int week;
+        int day_w;  // Day of week (0..6)
+        int day;    // Day of month (0..27)
+        int hour;
+        int min;
+        int baseTurn;
+
+        unsigned int total_minutes;
+        int tick;
+        int tick_to_change_time;
+        int set : 1;
+};
+
+extern void clock_advance(int ticks);
+extern void clock_alarm_set(clock_alarm_t *alarm, unsigned int minutes);
+extern int clock_alarm_is_expired(clock_alarm_t *alarm);
+extern int clock_alarm_remaining(clock_alarm_t *alarm);
+extern unsigned int clock_time_of_day(void);
+extern unsigned int clock_time(void);
+extern int is_noon(void);
+extern int is_midnight(void);
+extern int clock_year(void);
+extern int clock_month(void);
+extern int clock_week(void);
+extern int clock_day(void);
+extern int clock_hour(void);
+extern int clock_minute(void);
+extern int clock_tick(void);
+
+extern char * vague_time_as_string       (void);
+extern char * time_HHMM_as_string       (void);
+extern char * time_YYYY_MM_DD_as_string (void);
+
+extern const char * month_name (void);
+extern const char * week_name  (void);
+extern const char * day_name   (void);
+
+
+#ifdef INCLUDE_UNUSED_CLOCK_ROUTINES
+extern void clock_reset(struct clock *clock);
+extern void clock_set_alarm(struct clock *clock, struct clock *offset);
+extern int clock_alarm_expired(struct clock *clock);
+#endif
+
+#ifdef OTHER_TIME_STRING_FUNCTIONS
+extern const char * time_YYYY_as_string (void);
+extern const char * time_MM_as_string   (void);
+extern const char * time_DD_as_string   (void);
+#endif // OTHER_TIME_STRING_FUNCTIONS
+        
+END_DECL
+
+#endif
diff --git a/src/closure.c b/src/closure.c
new file mode 100644 (file)
index 0000000..9b87574
--- /dev/null
@@ -0,0 +1,329 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2004 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "closure.h"
+#include "debug.h"
+#include "session.h"
+
+#include "scheme.h"
+#include "scheme-private.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+/* Defined in kern.c: */
+extern pointer vpack(scheme *sc, const char *fmt, va_list ap);
+
+/*
+ * closure_del - free a closure (external code should use closure_unref)
+ */
+static void closure_del(closure_t *closure)
+{
+        assert(0 == closure->ref);
+        closure->sc->vptr->unprotect(closure->sc, closure->code);
+        free(closure);
+}
+
+/**
+ * Evaluate a Scheme procedure with Scheme args. This is an internal helper
+ * function.
+ *
+ * @param closure The closure to invoke.
+ * @param args A scheme list of parameters.
+ * @returns The result of evaluating the closure.
+ */
+static pointer closure_exec_with_scheme_args(closure_t *closure, pointer args)
+{
+        pointer result;
+
+        /* Lock the closure against deletion while it is being called. */
+        closure_ref(closure);
+
+        /* Straight procedure call? */
+        if (scm_is_closure(closure->sc, closure->code)) {
+                result = scheme_call(closure->sc, closure->code, args);
+        }
+
+        /* Need to lookup it up first? */
+        else if (scm_is_sym(closure->sc, closure->code)) {
+
+                pointer pair;
+                pointer proc;
+
+                /* The 'code' pointer is a pointer to a scheme symbol. Looking
+                 * it up in the scheme environment will return a (symbol,
+                 * value) pair. We then take the cdr of the pair to get the
+                 * actual procedure we want to call. */
+                pair = closure->sc->vptr->find_slot_in_env(closure->sc, 
+                                                           closure->sc->envir, 
+                                                           closure->code, 
+                                                           1);
+                assert(scm_is_pair(closure->sc, pair));
+                proc = closure->sc->vptr->pair_cdr(pair);
+                result = scheme_call(closure->sc, proc, args);
+
+        }
+
+        /* Invalid or garbage-collected closure? */
+        else {
+                /* There's a bug somewhere. Happy hunting. */
+                assert(false);
+        }
+
+        closure_unref(closure);
+        return result;
+}
+
+/** 
+ * Evaluate a Scheme procedure with C-style varargs.
+ * @param closure The procedure to evaluate.
+ * @param fmt Character encoding for the args, similar to printf, but the codes
+ * are different. See kern.c's vpack() function.
+ * @returns The Scheme result of evaluation.
+ */
+pointer closure_execv(closure_t *closure, const char *fmt, va_list args)
+{
+        pointer head;
+
+        /* Convert the C args to Scheme. */
+        if (fmt) {
+                head = vpack(closure->sc, fmt, args);
+        } else {
+                head = closure->sc->NIL;
+        }
+
+        return closure_exec_with_scheme_args(closure, head);
+}
+
+/* Do our best to translate a Scheme evaluation result into a C integer. */
+int closure_translate_result(scheme *sc, pointer result)
+{
+        if (result == sc->NIL ||
+            result == sc->F) {
+                return 0;
+        } 
+        
+        if (sc->vptr->is_number(result)) {
+                if (sc->vptr->is_integer(result)) {
+                        return sc->vptr->ivalue(result);
+                }
+                /* coerce it */
+                return (int)sc->vptr->rvalue(result);
+        }
+        
+        if (scm_is_sym(sc, result)) {
+                pointer pair;
+                pair = sc->vptr->find_slot_in_env(sc, 
+                                                  sc->envir, 
+                                                  result, 
+                                                  1);
+                assert(scm_is_pair(sc, pair));
+                result = sc->vptr->pair_cdr(pair);
+                /* recursive call... */
+                return closure_translate_result(sc, result);
+        }
+        
+        if (scm_is_ptr(sc, result)) {
+                return (long)sc->vptr->ffvalue(result);
+        }
+
+        return 1;
+}
+
+closure_t *closure_new(scheme *sc, pointer code)
+{
+        closure_t *clx = (closure_t*)calloc(1, sizeof(*clx));
+        assert(clx);
+        clx->sc = sc;
+        clx->code = code;
+        sc->vptr->protect(sc, code);
+        return clx;
+}
+
+closure_t *closure_new_ref(scheme *sc, pointer code)
+{
+        closure_t *clx = closure_new(sc, code);
+        closure_ref(clx);
+        return clx;
+}
+
+void closure_init(closure_t *clx, scheme *sc, pointer code)
+{
+        clx->sc = sc;
+        clx->code = code;
+}
+
+int closure_exec(closure_t *closure, const char *fmt, ...)
+{
+        pointer result;
+        va_list ap;
+        int ret = 1;
+
+        closure_ref(closure);
+
+        va_start(ap, fmt);
+        result = closure_execv(closure, fmt, ap);
+        va_end(ap);
+
+        ret = closure_translate_result(closure->sc, result);
+
+        closure_unref(closure);
+        return ret;
+}
+
+void closure_save(closure_t *closure, struct save *save)
+{
+        char *proc_name;
+
+        assert(scm_is_sym(closure->sc, closure->code));
+
+        /* The 'code' pointer is a pointer to a scheme symbol. To save the
+         * closure we only need to write this symbol out with a leading
+         * tick. */
+        proc_name = closure->sc->vptr->symname(closure->code);
+        save->write(save, "'%s\n", proc_name);
+}
+
+void closure_ref(closure_t *closure)
+{
+        closure->ref++;
+}
+
+void closure_unref(closure_t *closure)
+{
+        assert(closure->ref > 0);
+        closure->ref--;
+        if (! closure->ref)
+                closure_del(closure);
+}
+
+int closure_execlpv(closure_t *closure, pointer cell, void *ptr, 
+                    const char *fmt, va_list args)
+{
+        pointer head, tmp, result;
+        scheme *sc = closure->sc;
+
+        /* Convert the C args to Scheme. */
+        if (fmt) {
+                head = vpack(sc, fmt, args);
+        } else {
+                head = sc->NIL;
+        }
+
+        /* Protect the list while allocating cells. */
+        tmp = head;
+        if (tmp != sc->NIL) {
+                sc->vptr->protect(sc, tmp);
+        }
+
+        /* Prepend the cell and ptr to the arg list. */
+        head = _cons(sc, scm_mk_ptr(sc, ptr), head, 0);
+        head = _cons(sc, cell, head, 0);
+
+        /* Unprotect the list now that we're done allocating. */
+        if (tmp != sc->NIL) {
+                sc->vptr->unprotect(sc, tmp);
+        }
+
+        /* Evaluate the closure. */
+        result = closure_exec_with_scheme_args(closure, head);
+
+        /* Translate the result to an int. */
+        return closure_translate_result(closure->sc, result);
+}
+
+int closure_execlpiv(closure_t *closure, pointer cell, void *ptr, int id,
+                    const char *fmt, va_list args)
+{
+        pointer head, tmp, result;
+        scheme *sc = closure->sc;
+
+        /* Convert the C args to Scheme. */
+        if (fmt) {
+                head = vpack(sc, fmt, args);
+        } else {
+                head = sc->NIL;
+        }
+
+        /* Protect the list while allocating cells. */
+        tmp = head;
+        if (tmp != sc->NIL) {
+                sc->vptr->protect(sc, tmp);
+        }
+
+        /* Prepend the cell, ptr and id to the arg list. */
+        head = _cons(sc, scm_mk_integer(sc, id), head, 0);
+        head = _cons(sc, scm_mk_ptr(sc, ptr), head, 0);
+        head = _cons(sc, cell, head, 0);
+
+        /* Unprotect the list now that we're done allocating. */
+        if (tmp != sc->NIL) {
+                sc->vptr->unprotect(sc, tmp);
+        }
+
+        /* Evaluate the closure. */
+        result = closure_exec_with_scheme_args(closure, head);
+
+        /* Translate the result to an int. */
+        return closure_translate_result(closure->sc, result);
+}
+
+int closure_execvl(closure_t *closure, const char *fmt, va_list args, pointer cell)
+{
+        pointer head, result;
+        scheme *sc = closure->sc;
+
+        /* Convert the C args to Scheme. */
+        if (fmt) {
+                head = vpack(sc, fmt, args);
+        } else {
+                head = sc->NIL;
+        }
+
+        /* Append args to the list */
+        if (head == sc->NIL) {
+                /* args is the only thing on the list */
+                head = _cons(sc, cell, sc->NIL, 0);
+        } else {
+
+                /* Protect the list while allocating for _cons */
+                sc->vptr->protect(sc, head);
+
+                /* Find the end of the list */
+                pointer tail = head;
+                while (scm_cdr(sc, tail) != sc->NIL) {
+                        tail = scm_cdr(sc, tail);
+                }
+
+                /* Append the args to the tail of the list */
+                tail->_object._cons._cdr = _cons(sc, cell, sc->NIL, 0);
+                
+                /* Unprotect the list now that we're done allocating. */
+                sc->vptr->unprotect(sc, head);
+        }
+
+        /* Evaluate the closure. */
+        result = closure_exec_with_scheme_args(closure, head);
+
+        /* Translate the result to an int. */
+        return closure_translate_result(closure->sc, result);
+}
diff --git a/src/closure.h b/src/closure.h
new file mode 100644 (file)
index 0000000..98473b2
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2004 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef closure_h
+#define closure_h
+
+#include "macros.h"
+#include "scheme.h"
+
+#include <stdarg.h>
+
+BEGIN_DECL
+
+typedef struct closure {
+        scheme *sc;
+        pointer env;
+        pointer code;
+        int ref;
+} closure_t;
+
+#define closure_unref_safe(clx) if ((clx)) closure_unref(clx)
+
+extern closure_t *closure_new(scheme *interp, pointer code);
+extern closure_t *closure_new_ref(scheme *interp, pointer code);
+extern void closure_init(closure_t *closure, scheme *interp, pointer code);
+extern int closure_exec(closure_t *closure, const char *fmt, ...);
+extern pointer closure_execv(closure_t *closure, const char *fmt, va_list args);
+extern int closure_translate_result(scheme *sc, pointer result);
+extern  void closure_save(closure_t *closure, struct save *save);
+extern void closure_ref(closure_t *closure);
+extern void closure_unref(closure_t *closure);
+
+/* Special form of closure_exec() made for running object hooks. */
+int closure_execlpv(closure_t *closure, pointer gob, void *obj, 
+                     const char *fmt, va_list args);
+
+/* Special form of closure_exec() made for running object hooks where an effect
+ * is attached to more than one hook. */
+int closure_execlpiv(closure_t *closure, pointer gob, void *obj, int hook_id,
+                     const char *fmt, va_list args);
+
+/* Another special form - for session_run_hook */
+int closure_execvl(closure_t *closure, const char *fmt, va_list args, pointer cell);
+
+END_DECL
+
+#endif
diff --git a/src/cmd.c b/src/cmd.c
new file mode 100644 (file)
index 0000000..5140acb
--- /dev/null
+++ b/src/cmd.c
@@ -0,0 +1,4080 @@
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "cmd.h"
+#include "../config.h" /* for USE_SKILLS */
+#include "conv.h"
+#include "place.h"
+#include "constants.h"
+#include "file.h"
+#include "foogod.h"
+#include "images.h"
+#include "sprite.h"
+#include "los.h"
+#include "astar.h"
+#include "common.h"
+#include "screen.h"
+#include "status.h"
+#include "player.h"
+#include "sky.h"
+#include "map.h"
+#include "wq.h"
+#include "foogod.h"
+#include "combat.h"
+#include "cursor.h"
+#include "Arms.h"
+#include "event.h"
+#include "wind.h"
+#include "Container.h"
+#include "dup_constants.h"
+#include "cmdwin.h"
+#include "vehicle.h"
+#include "terrain.h"
+#include "vmask.h"
+#include "session.h"
+#include "sched.h"
+#include "conv.h"
+#include "log.h"
+#include "factions.h"
+#include "result.h"
+#include "dice.h"
+#include "menus.h"
+#include "kern_intvar.h"
+#include "skill.h"
+#include "skill_set.h"
+#include "skill_set_entry.h"
+#include "templ.h"
+#include "occ.h"
+#include "nazghul.h"  // for DeveloperMode
+#include "ztats.h"
+#include "terrain_editor.h"
+
+#define DEBUG
+#include "debug.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+#include <unistd.h>     // getpid()
+#include <errno.h>
+
+#define ESCAPE_CHARACTER 110
+
+/* Disabling the '>' command when standing over a subplace. This is generally
+ * not useful and can be abused for some towns. */
+#ifndef ENABLE_TOWN_ZOOM_IN
+#define ENABLE_TOWN_ZOOM_IN 0
+#endif
+
+/* SAM: Using this typedef below */
+typedef void (*v_fncptr_iiv_t) (struct place *, int x, int y, void * v);
+typedef int (*i_fncptr_iiv_t) (struct place *, int x, int y, void * v);
+
+
+/**
+ * Struct used by the movecursor function and it's mouse-handling counterparts
+ * for commands which prompt the player to select a target from the map. 
+ */
+struct movecursor_data {
+        v_fncptr_iiv_t each_tile_func;   /* called when cursor moves         */
+        i_fncptr_iiv_t each_target_func; /* called on 'enter' or leftclick   */
+        struct list *loc_list;           /* quick target list                */
+        struct list *cur_loc;            /* current target from list         */
+        int jump;                        /* distance to jump cursor          */
+        void *data;                      /* caller data passed to callbacks  */
+        char abort : 1;                  /* command was aborted              */
+};
+
+/* fwd decls */
+
+#ifdef USE_SKILLS
+static class Character *cmd_front_end(class Character *pc, const char *cmdstr);
+#endif
+static int cmd_eval_and_log_result(int result);
+static int select_target_rlcb(struct place *place,
+                              int ox, int oy, int *x, int *y,
+                              int range,
+                              struct list *suggest,
+                              v_fncptr_iiv_t each_tile_func,
+                              i_fncptr_iiv_t each_target_func);
+
+/* functions */
+
+static class Character * cmdAnyPartyMemberEngagedInTask(void)
+{
+    int num_pcs = player_party->getSize();
+    for (int i = 0; i < num_pcs; i++) {
+        class Character *pc = player_party->getMemberAtIndex(i);
+        if (pc->engagedInTask()) {
+            return pc;
+        }
+    }
+    return NULL;
+}
+
+int dirkey(struct KeyHandler *kh, int key, int keymod)
+{
+       int *dir = (int *) kh->data;
+
+       if (key >= KEY_SOUTHWEST && key <= KEY_NORTHEAST) {
+               *dir = keyToDirection(key);
+               return 1;
+       }
+
+       if (key == SDLK_ESCAPE) {
+               *dir = key;
+               return 1;
+       }
+
+        /* Special case: let '.' mean KEY_HERE for the numeric keypad
+         * challenged. */
+        if (key == '.') {
+                *dir = keyToDirection(KEY_HERE);
+                return 1;
+        }
+
+       return 0;
+}
+
+int cardinaldirkey(struct KeyHandler *kh, int key, int keymod)
+{
+       int *dir = (int *) kh->data;
+
+       switch (key) {
+       case KEY_NORTH:
+       case KEY_SOUTH:
+       case KEY_EAST:
+       case KEY_WEST:
+               *dir = keyToDirection(key);
+               return 1;
+       }
+
+       if (key == SDLK_ESCAPE) {
+               *dir = key;
+               return 1;
+       }
+
+       return 0;
+}
+
+int yesnokey(struct KeyHandler * kh, int key, int keymod)
+{
+       int *yesno = (int *) kh->data;
+
+       switch (key) {
+       case 'y':
+       case 'Y':
+               *yesno = 'y';
+               return 1;
+       case 'n':
+       case 'N':
+       case CANCEL:
+               *yesno = 'n';
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+enum get_number_state {
+       GN_ALL,
+       GN_ZERO,
+       GN_SOME,
+       GN_CANCEL
+};
+
+/* Max number getnum() will accept */
+const int MAX_GETNUM = 999999999;
+
+struct get_number_info {
+       int digit;
+       int state;
+       char *prompt;
+};
+
+struct get_char_info {
+        const char *string;
+        char c;
+       int state;
+       char *prompt;
+};
+
+struct get_spell_name_data {
+       char spell_name[MAX_WORDS_IN_SPELL_NAME + 1];
+        const char *prompt;
+       char *ptr;
+       int n;
+        int state;
+};
+
+int getnum(struct KeyHandler *kh, int key, int keymod)
+{
+       struct get_number_info *info;
+
+       info = (struct get_number_info *) kh->data;
+
+       switch (info->state) {
+       case GN_ALL:
+               if (key == CANCEL) {
+                        cmdwin_pop();
+                       info->digit = 0;
+                       info->state = GN_CANCEL;
+                       return 1;
+               }
+               if (key == '\n') {
+                        cmdwin_pop();
+                       return 1;
+               }
+               if (key == '0') {
+                        cmdwin_pop();
+                       cmdwin_push("0");
+                       info->digit = 0;
+                       info->state = GN_ZERO;
+                       return 0;
+               }
+               if (isdigit(key)) {
+                        cmdwin_pop();
+                       info->digit = info->digit * 10 + key - '0';
+                       cmdwin_push("%c", key);
+                       info->state = GN_SOME;
+                       return 0;
+               }
+               break;
+       case GN_ZERO:
+               if (key == CANCEL) {
+                       info->digit = 0;
+                       info->state = GN_CANCEL;
+                       return 1;
+               }
+               if (key == '\n') {
+                       return 1;
+               }
+               if (key == '\b') {
+                       cmdwin_pop();
+                       if (info->prompt)
+                               cmdwin_spush(info->prompt);
+                       info->state = GN_ALL;
+                       return 0;
+               }
+               if (key == '0')
+                       return 0;
+               if (isdigit(key)) {
+                       cmdwin_pop();
+                       info->digit = info->digit * 10 + key - '0';
+                       cmdwin_push("%c", key);
+                       info->state = GN_SOME;
+                       return 0;
+               }
+               break;
+       case GN_SOME:
+               if (key == CANCEL) {
+                       info->digit = 0;
+                       info->state = GN_CANCEL;
+                       return 1;
+               }
+               if (key == '\n') {
+                       return 1;
+               }
+               if (key == '\b') {
+                       info->digit = info->digit - (info->digit % 10);
+                       info->digit /= 10;
+                       cmdwin_pop();
+                       if (info->digit == 0) {
+                               info->state = GN_ALL;
+                               if (info->prompt)
+                                       cmdwin_spush(info->prompt);
+                       }
+                       return 0;
+               }
+               if (isdigit(key)) {
+                        int keyval = key - '0';
+                        if ((MAX_GETNUM - keyval) >= info->digit) {
+                                info->digit = info->digit * 10 + keyval;
+                                cmdwin_push("%c", key);
+                        }
+                       return 0;
+               }
+               break;
+       }
+
+       return 0;
+}
+
+int getdigit(struct KeyHandler * kh, int key, int keymod)
+{
+        struct get_number_info *info;
+
+        info = (struct get_number_info *) kh->data;
+        
+        if (key == CANCEL) {
+                cmdwin_pop();
+                info->digit = 0;
+                return 1;
+        }
+
+        if (isdigit(key)) {
+                cmdwin_pop();
+                info->digit = key - '0';
+                if (info->digit != 0)
+                        cmdwin_push("%c", key);
+                return 1;
+        }
+        
+        return 0;
+}
+
+static int cmd_getchar(struct KeyHandler * kh, int key, int keymod)
+{
+        struct get_char_info *info;
+
+        info = (struct get_char_info *) kh->data;
+        
+        if (key == CANCEL) {
+                cmdwin_pop();
+                info->c = 0;
+                return 1;
+        }
+
+        if (strchr(info->string, key)) {
+                cmdwin_pop();
+                info->c = key;
+                cmdwin_push("%c", key);
+                return 1;
+        }
+        
+        return 0;        
+}
+
+int anykey(struct KeyHandler * kh, int key, int keymod)
+{
+       return 1;
+}
+
+int scroller(struct KeyHandler * kh, int key, int keymod)
+{
+       struct ScrollerContext *context;
+       context = (struct ScrollerContext *) kh->data;
+
+       switch (key) {
+       case KEY_NORTH:
+               statusScroll(ScrollUp);
+               break;
+       case KEY_SOUTH:
+               statusScroll(ScrollDown);
+               break;
+       case KEY_EAST:
+               statusScroll(ScrollRight);
+               break;
+       case KEY_WEST:
+               statusScroll(ScrollLeft);
+               break;
+       case SDLK_PAGEUP:
+               statusScroll(ScrollPageUp);
+               break;
+       case SDLK_PAGEDOWN:
+               statusScroll(ScrollPageDown);
+               break;
+       case SDLK_RETURN:
+       case SDLK_SPACE:
+        case KEY_HERE:
+       case '\n':
+               if (context != NULL) {
+                       context->selection =
+                                statusGetSelected(context->selector);
+               }
+               return 1;
+       case SDLK_ESCAPE:
+       case 'q':
+               if (context)
+                       context->abort = 1;
+               return 1;
+       case 'm':
+               if (context && context->mixing) {
+                       context->done = 1;
+                       return 1;
+               }
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+bool mouse_button_cursor(struct MouseButtonHandler *mh, SDL_MouseButtonEvent *event)
+{
+        struct movecursor_data * data
+                = (struct movecursor_data *) mh->data;
+        int mx = event->x;
+        int my = event->y;
+
+        /* Off-map? */
+        if (mapScreenToPlaceCoords(&mx, &my)) {
+                return false;
+        }
+
+        /* Did the crosshair move? */
+        if (Session->crosshair->getX() != mx
+            || Session->crosshair->getY() != my) {
+
+                /* turn on range shading after the first move */
+                Session->crosshair->shadeRange(true);
+
+                /* Move the crosshair */
+                Session->crosshair->move(mx - Session->crosshair->getX(),
+                                         my - Session->crosshair->getY());
+                mapSetDirty();
+
+                /* Need to run our visitor function on each tile? */
+                if (data->each_tile_func) {
+                        data->each_tile_func(Session->crosshair->getPlace(),
+                                             Session->crosshair->getX(),
+                                             Session->crosshair->getY(),
+                                             data->data);
+                }
+
+        }
+
+        /* target selected? */
+        if (event->button == SDL_BUTTON_LEFT) {
+                if (data->each_target_func) {
+                        return data->each_target_func(Session->crosshair->getPlace(),
+                                                      Session->crosshair->getX(),
+                                                      Session->crosshair->getY(),
+                                                      data->data);
+                }
+                return 1; /* target selected */
+        }
+
+
+        return false;
+}
+
+bool mouse_motion_cursor(struct MouseMotionHandler *mh, SDL_MouseMotionEvent *event)
+{
+        struct movecursor_data * data
+                = (struct movecursor_data *) mh->data;
+        int mx = event->x;
+        int my = event->y;
+
+        /* Off-map? */
+        if (mapScreenToPlaceCoords(&mx, &my)) {
+                return false;
+        }
+        
+        /* Did the crosshair NOT move? */
+        if (Session->crosshair->getX() == mx
+            && Session->crosshair->getY() == my) {
+                return false;
+        }
+
+        /* turn on range shading after the first move */
+        Session->crosshair->shadeRange(true);
+
+        /* Move the crosshair */
+        Session->crosshair->move(mx - Session->crosshair->getX(),
+                                 my - Session->crosshair->getY());
+        mapSetDirty();
+
+        /* Need to run our visitor function on each tile? */
+        if (data->each_tile_func) {
+                data->each_tile_func(Session->crosshair->getPlace(),
+                                     Session->crosshair->getX(),
+                                     Session->crosshair->getY(),
+                                     data->data);
+        }
+
+        /* Mouse dragging? */
+        if (event->state & SDL_BUTTON(1)
+            && data->each_target_func) {
+                return data->each_target_func(Session->crosshair->getPlace(),
+                                              Session->crosshair->getX(),
+                                              Session->crosshair->getY(),
+                                              data->data);
+        }
+
+
+        return false;
+}
+
+/**
+ * movecursor - move the crosshair around, possibly running a function on each
+ * tile entered by the crosshair or on each tile selected
+ */
+int movecursor(struct KeyHandler * kh, int key, int keymod)
+{
+        int moved = 0;
+        struct movecursor_data * data
+                = (struct movecursor_data *) kh->data;
+  
+        /* target selected? */
+        switch (key) {
+       case SDLK_RETURN:
+       case SDLK_SPACE:
+        case KEY_HERE:
+       case '\n':
+                if (data->each_target_func) {
+                        return data->each_target_func(Session->crosshair->getPlace(),
+                                                      Session->crosshair->getX(),
+                                                      Session->crosshair->getY(),
+                                                      data->data);
+                }
+                return 1; /* target selected */
+        default:
+                break;
+        }
+  
+        /* crosshairs moved? */
+        if (keyIsDirection(key)) {
+                int dir = keyToDirection(key);
+                int dx = directionToDx(dir);
+                int dy = directionToDy(dir);
+                
+                /* Brain-dead but simple way to clamp the jump distance to
+                 * range: iteratively back-off until it's ok. */
+                while (OutOfRange == Session->crosshair->move(dx * data->jump, 
+                                                              dy * data->jump)
+                        && data->jump > 1) {
+                        data->jump--;
+                }
+                moved = 1;
+        } else if (isdigit(key)) {
+                data->jump = key - '0';
+                if (! data->jump)
+                        data->jump = 1; /* disallow zero */
+        } else {
+  
+                struct list *old_loc = data->cur_loc;
+
+                switch (key) {
+                        
+                case SDLK_ESCAPE:
+                        /* Abort */
+                        data->abort = 1;
+                        return 1;   /* done */
+                        
+                case '+':
+                case '=':
+                case 'n':
+                        /* Next target */
+                        if (data->loc_list
+                            && ! list_empty(data->loc_list)) {
+                                data->cur_loc = data->cur_loc->next;
+                                if (data->cur_loc == data->loc_list) {
+                                        /* wrap around */
+                                        data->cur_loc = 
+                                                data->cur_loc->next;
+                                }
+                        }
+                        break;
+                        
+                case '-':
+                case 'p':
+                        /* Previous target */
+                        if (data->loc_list
+                            && ! list_empty(data->loc_list)) {
+                                data->cur_loc = data->cur_loc->prev;
+                                if (data->cur_loc == data->loc_list) {
+                                        /* wrap around */
+                                        data->cur_loc = 
+                                                data->cur_loc->prev;
+                                }
+                        }
+                        break;
+                default:
+                        break;
+                }
+
+                /* Target changed? */
+                if (old_loc != data->cur_loc) {
+                        struct location_list *loc = 
+                                (struct location_list*)data->cur_loc;
+                        Session->crosshair->move(loc->x - 
+                                                 Session->crosshair->getX(),
+                                                 loc->y - 
+                                                 Session->crosshair->getY());
+                        moved = 1;
+                }
+        }
+
+        /* Cursor was moved? */
+        if (moved) {
+                data->jump = 1;
+                mapSetDirty();
+                if (data->each_tile_func) {
+                        data->each_tile_func(Session->crosshair->getPlace(),
+                                             Session->crosshair->getX(),
+                                             Session->crosshair->getY(),
+                                             data->data);
+                }
+
+                /* turn on range shading after the first move */
+                Session->crosshair->shadeRange(true);
+        }
+
+        return 0;   /* not done */
+}
+
+struct inv_entry *ui_select_item(void)
+{
+       struct inv_entry *ie;
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+
+        foogodSetHintText(SCROLLER_HINT);
+        foogodSetMode(FOOGOD_HINT);        
+
+       sc.selector = InventoryItem;
+       sc.selection = NULL;
+       kh.fx = scroller;
+       kh.data = &sc;
+
+       eventPushKeyHandler(&kh);
+       cmdwin_push("<select>");
+       eventHandle();
+       cmdwin_pop();
+       eventPopKeyHandler();
+
+        foogodSetMode(FOOGOD_DEFAULT);
+
+       ie = (struct inv_entry *) sc.selection;
+       if (ie == NULL) {
+               cmdwin_push("none!");
+               return NULL;
+       }
+
+       cmdwin_spush(ie->type->getName());
+
+       return ie;
+}
+
+class Character *select_party_member(void)
+{
+       enum StatusMode omode;
+       class Character *character;
+
+        if (1 == player_party->getSize()) {
+                character = player_party->getMemberByOrder(0);
+                /* fixme: move to cmd_front_end? */
+               cmdwin_spush("%s", character->getName());
+                return character;
+        }
+
+        foogodSetHintText(SCROLLER_HINT);
+        foogodSetMode(FOOGOD_HINT);        
+       omode = statusGetMode();
+       statusSetMode(SelectCharacter);
+
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+       sc.selector = Character;
+       sc.selection = NULL;
+       kh.fx = scroller;
+       kh.data = &sc;
+
+       eventPushKeyHandler(&kh);
+       cmdwin_push("<select>");
+       eventHandle();
+       cmdwin_pop();
+       eventPopKeyHandler();
+
+       statusRepaint();
+
+       character = (class Character *) sc.selection;
+
+       if (character == NULL) {
+               cmdwin_push("none!"); /* fixme: move to cmd_front_end? */
+               /* Hack alert: this saves the caller from having to remember to
+                * do this. Doing it unconditionally is undesirable because it
+                * can cause status screen flashes if the old mode requires a
+                * short status window and the next mode requires a tall
+                * one. */
+       } else {
+                /* fixme: move to cmd_front_end? */
+               cmdwin_spush("%s", character->getName());
+       }
+
+       statusSetMode(omode);
+        foogodSetMode(FOOGOD_DEFAULT);
+
+       return character;
+}
+
+void getkey(void *data, int(*handler) (struct KeyHandler * kh, int key, int keymod))
+{
+       struct KeyHandler kh;
+       kh.fx = handler;
+       kh.data = data;
+
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+}
+
+int ui_get_direction(void)
+{
+       int dir;
+       cmdwin_push("<direction>");
+       getkey(&dir, dirkey);
+       cmdwin_pop();
+       if (dir == CANCEL) {
+               cmdwin_push("none!");
+       } else {
+               cmdwin_spush(directionToString(dir));
+       }
+       return dir;
+}
+
+static void search_visitor(class Object *obj, void *arg)
+{
+        class ObjectType *type = obj->getObjectType();
+        /* Caution: searching can destroy the object if it triggers traps; the
+         * arg should be protected by the caller. */
+        if (type && type->canSearch()) {
+                type->search(obj, (class Object*)arg);
+        }
+}
+
+bool cmdSearch(class Character *pc)
+{
+       int dir;
+        bool old_reveal;
+        int x, y, x2,  y2;
+        struct place *place = 0;
+
+       cmdwin_clear();
+       cmdwin_spush("Search");
+
+        /* FIXME: this is duplicated in cmdHandle(), these command functions
+         * all need to be cleaned up to ensure consistency. */
+        if (! pc) {
+                if (player_party->get_num_living_members() == 1) {
+                       pc = player_party->get_first_living_member();
+                       cmdwin_spush("%s", pc->getName());
+               } else {
+                       pc = select_party_member();
+                       if (pc == NULL) {
+                               return false;
+                       }
+               }
+        }
+
+        assert(pc);
+        place = pc->getPlace();
+        x = pc->getX();
+        y = pc->getY();
+
+       dir = ui_get_direction();
+       if (dir == CANCEL)
+               return false;
+
+        x2 = x + directionToDx(dir);
+        y2 = y + directionToDy(dir);
+
+        /* Caution: searching can destroy the pc if it triggers traps. The
+         * following is iterative, so protect the pc from destruction until it
+         * completes. */
+        obj_inc_ref(pc);
+        place_for_each_object_at(place, x2, y2, search_visitor, pc);
+        obj_dec_ref(pc);
+
+       log_begin("You find ");
+        old_reveal = Reveal;
+        Reveal = true;
+       place_describe(place, x2, y2, PLACE_DESCRIBE_ALL);
+        log_end(".");
+        Reveal = old_reveal;
+        pc->decActionPoints(kern_intvar_get("AP_COST:search"));  // SAM: We may want a '-1' value here, to signify "all remaining AP"...
+       
+       return true;
+}
+
+static int cmdGetFilter(class Object *obj)
+{
+        return (int)(obj->getObjectType() && 
+                     obj->getObjectType()->canGet());
+}
+
+bool cmdGet(class Object *actor)
+{
+       class Object *item;
+       int dir;
+       int x, y;
+       
+       cmdwin_clear();
+       cmdwin_spush("Get");
+       
+       dir = ui_get_direction();
+       
+       if (dir == CANCEL)
+               return false;
+       
+       x = actor->getX() + directionToDx(dir);
+       y = actor->getY() + directionToDy(dir);
+       
+       item = place_get_filtered_object(actor->getPlace(), x, y, 
+       cmdGetFilter);
+       if (!item) {
+               log_msg("Get - nothing there!");
+               return false;
+       }
+       
+       log_begin_group();
+       
+       while (NULL != (item = place_get_filtered_object(
+                               actor->getPlace(), 
+                               x, y, cmdGetFilter)))
+       {
+               item->getObjectType()->get(item, actor);
+               //do not allow too much AP debt if in combat
+               if ((combat_get_state() == COMBAT_STATE_FIGHTING)
+                                       && ((2 * actor->getActionPoints()) + actor->getSpeed() < 0))
+               {
+                       break;   
+               }
+       }
+       
+       log_end_group();
+       
+       mapSetDirty();
+       actor->runHook(OBJ_HOOK_GET_DONE, 0);
+       actor->decActionPoints(kern_intvar_get("AP_COST:get_item"));  // SAM: Better to have a number of AP by item type...
+       
+       
+       return true;
+}
+
+static void cmd_describe_inv_entry(struct inv_entry *ie, void *unused)
+{
+        log_begin("...");
+        ie->type->describeType(ie->count);
+        log_end(NULL);
+}
+
+bool cmdOpen(class Character * pc)
+{
+       int dir, x, y;
+       class Object *mech;
+       class Container *container;
+
+       cmdwin_clear();
+       cmdwin_spush("Open");
+
+       // Get the party member who will open the container (in combat mode
+       // this is passed in as a parameter).
+       if (pc) {
+               cmdwin_spush(pc->getName());
+       } else {
+               pc = select_party_member();
+               if (pc == NULL) {
+                       return false;
+               }
+       }
+
+       dir = ui_get_direction();
+       if (dir == CANCEL)
+               return false;
+
+       if (pc) {
+               x = place_wrap_x(pc->getPlace(), 
+                                 pc->getX() + directionToDx(dir));
+               y = place_wrap_y(pc->getPlace(), 
+                                 pc->getY() + directionToDy(dir));
+       } else {
+               x = place_wrap_x(player_party->getPlace(),
+                                 player_party->getX() + directionToDx(dir));
+               y = place_wrap_y(player_party->getPlace(),
+                                 player_party->getY() + directionToDy(dir));
+       }
+
+        /* Check for a mechanism */
+         mech = place_get_object(pc->getPlace(), x, y, mech_layer);
+
+         /* Check for a container */
+         container = (class Container *) place_get_object(Place, x, y, 
+                                                          container_layer);
+
+         /* ignore invisible objects unless Reveal is in effect */
+         if (! Reveal) {
+                 if (mech && ! mech->isVisible())
+                         mech = 0;
+                 if (container && ! container->isVisible())
+                         container = 0;
+         }
+
+         /* If both are present the user must select one */
+         if (mech && mech->getObjectType()->canOpen() && container) {
+
+                 enum StatusMode omode;
+                 struct stat_list_entry statlist[2];
+                 struct KeyHandler kh;
+                 struct ScrollerContext data;
+
+                 cmdwin_push("<select>");
+
+                 statlist[0].sprite = mech->getSprite();
+                 snprintf(statlist[0].line1, sizeof(statlist[0].line1), "%s",
+                          mech->getName());
+                 statlist[0].line2[0] = 0;
+                 statlist[0].data = mech;
+
+                 statlist[1].sprite = container->getSprite();
+                 snprintf(statlist[1].line1, sizeof(statlist[1].line2), "%s",
+                          container->getName());
+                 statlist[1].line2[0] = 0;
+                 statlist[1].data   = container;
+
+                 foogodSetHintText(SCROLLER_HINT);
+                 foogodSetMode(FOOGOD_HINT);        
+                 omode = statusGetMode();
+                 statusSetGenericList("Choose Target", 2, statlist);
+                 statusSetMode(GenericList);
+                 
+                 data.selection = NULL;
+                 data.selector  = Generic;
+                 kh.fx   = scroller;
+                 kh.data = &data;
+                 eventPushKeyHandler(&kh);
+                 eventHandle();
+                 eventPopKeyHandler();
+                 
+                 statusSetMode(omode);
+                 foogodSetMode(FOOGOD_DEFAULT);
+                 
+                 /* Disqualify the object NOT selected */
+                 if (data.selection == mech)
+                         container = NULL;
+                 else
+                         mech = NULL;
+
+                 cmdwin_pop();
+         }
+
+         /* Open a mechanism */
+         if (mech && mech->getObjectType()->canOpen()) {
+                 cmdwin_push("%s!", mech->getName());
+                 mech->getObjectType()->open(mech, pc);
+                 mapSetDirty();
+                 pc->runHook(OBJ_HOOK_OPEN_DONE, "p", mech);
+                 pc->decActionPoints(kern_intvar_get("AP_COST:open_mechanism"));
+                 return true;
+         }
+
+         /* Nothing to open */
+         if (NULL == container) {
+                 cmdwin_push("abort!");
+                 log_msg("Open - nothing there!");
+                 return false;
+         }
+
+       /* Open Container */
+
+        log_begin_group();
+
+        pc->runHook(OBJ_HOOK_OPEN_DONE, "p", container);
+        pc->decActionPoints(kern_intvar_get("AP_COST:open_container"));
+        cmdwin_push("%s!", container->getName());
+
+        // Describe the contents of the container.
+        log_msg("You find:");
+        container->forEach(cmd_describe_inv_entry, NULL);
+
+       // Open the container (automagically spills all the contents onto the
+       // map).
+       container->open();
+
+        // --------------------------------------------------------------------
+        // Delete container automatically on the combat map because if
+        // containers are stacked (and they frequently are) then the top one
+        // always gets selected and the player can't get at the ones
+        // underneath. On the other hand, in towns I don't want to delete
+        // people's furniture.
+        //
+        // Addendum: everything stated above still holds, but now corpse loot
+        // can also get dropped on town maps outside, so I can no longer decide
+        // whether or not to delete a container based on context. Furthermore,
+        // I want all containers to behave the same way as much as
+        // possible. This is an open issue and it may take some time and user
+        // feedback to decide what best to do, so for now I'll simply always
+        // remove containers after opening them.
+        // --------------------------------------------------------------------
+
+        container->remove();
+
+        log_end_group();
+
+       mapSetDirty();
+       return true;
+}
+
+static bool cmd_nop_qh(struct QuitHandler *kh)
+{
+        return false;
+}
+
+
+bool cmdQuit(void)
+{
+       int yesno;
+       struct QuitHandler qh;
+
+        /* Bugfix: if the player tries to close the window while we're in one
+         * of our getkey() calls, we'll enter this function recursively,
+         * messing up the prompts. So push a nop quit handler to prevent
+         * that. Kind of a hack: why should this function "know" it is called
+         * by the default quit handler? */
+       qh.fx = cmd_nop_qh;
+       eventPushQuitHandler(&qh);
+        
+       cmdwin_clear();
+       cmdwin_spush("Quit");
+        cmdwin_spush("<y/n>");
+       getkey(&yesno, yesnokey);
+       cmdwin_pop();
+
+        /* Cancel quit? */
+       if (yesno == 'n') {
+                cmdwin_spush("abort!");
+                Quit = false;
+                goto pop_qh;
+        }
+
+        cmdwin_spush("save");
+        cmdwin_spush("<y/n>");
+        getkey(&yesno, yesnokey);
+        cmdwin_pop();
+
+        /* Don't save? */
+        if (yesno == 'n') {
+                cmdwin_spush("not saving!");
+                Quit = true;
+                goto pop_qh;
+        }
+
+        if (cmdSave()) {
+            cmdwin_spush("saved!");
+            log_msg("Goodbye!\n");
+            Quit = true;
+        } else {
+            Quit = false;
+        }
+
+ pop_qh:
+        eventPopQuitHandler();
+
+       return Quit;
+}
+
+void cmdAttack(void)
+{
+        int dir;
+        struct move_info info;
+        struct combat_info cinfo;
+
+        // Initialize data structures.
+        memset(&info, 0, sizeof(info));
+        memset(&cinfo, 0, sizeof(cinfo));
+        cinfo.move = &info;
+        cinfo.defend = false;
+               
+        // Get the direction
+       cmdwin_clear();
+       cmdwin_spush("Attack");
+        cmdwin_spush("<direction>");
+       getkey(&dir, cardinaldirkey);
+       cmdwin_pop();
+       if (dir == CANCEL) {
+               cmdwin_spush("none!");
+               return;
+       }
+       cmdwin_spush("%s", directionToString(dir));
+
+        // Get the npc party being attacked
+        info.dx = directionToDx(dir);
+        info.dy =  directionToDy(dir);;
+        info.place = player_party->getPlace();
+        info.x = place_wrap_x(info.place, player_party->getX() + info.dx);
+        info.y = place_wrap_y(info.place, player_party->getY() + info.dy);
+        info.npc_party = place_get_Party(info.place, info.x, info.y);
+                               
+        if (info.npc_party == NULL) {
+                cmdwin_spush("nobody there!");
+                log_msg("Attack - nobody there!");
+                return;
+        } 
+        info.px = player_party->getX();
+        info.py = player_party->getY();
+
+        cmdwin_spush("%s", info.npc_party->getName());
+
+        // If the npc is not hostile then get player confirmation.
+        if (! are_hostile(info.npc_party, player_party)) {
+                int yesno;
+                cmdwin_spush("attack non-hostile");
+                cmdwin_spush("<y/n>");
+                getkey(&yesno, yesnokey);
+                cmdwin_pop();
+                if (yesno == 'n') {
+                        cmdwin_spush("no");
+                        return;
+                }
+                cmdwin_spush("yes");
+
+                make_hostile(info.npc_party, player_party);
+        }
+
+        // Log the attack.
+        log_begin("You attack ");
+        info.npc_party->describe();
+        log_end(".");
+
+        // Enter combat
+        combat_enter(&cinfo);
+}
+
+void cmdDeveloperEval(struct session *session)
+{
+        unsigned int len = 1024;
+        char *buf = (char*)calloc(len, sizeof(char));
+        if (!buf) {
+                log_msg("Eval: not enough memory!");
+                return;
+        }
+
+        cmdwin_clear();
+        cmdwin_push("Eval:");
+
+        if (!ui_getline_filtered(buf, len, NULL)) {
+                log_msg("Eval: abort");
+                cmdwin_push("abort!");
+                goto cleanup;
+        }
+
+        log_msg("Eval: %s", buf);
+        session_eval(session, buf);
+
+ cleanup:
+        free(buf);
+}
+
+void cmdFire(void)
+{
+       int dir;
+
+       cmdwin_clear();
+       cmdwin_spush("Fire");
+
+        class Vehicle *vehicle = player_party->getVehicle();
+       if ((!vehicle ||
+             !vehicle->getOrdnance())) {
+                // SAM: 
+                // In future, we may check for adjacent "cannon" 
+                // mechanisms here (as in U5).
+               cmdwin_spush("No cannons available!");
+                log_msg("Fire - no cannons!");
+               return;
+       }
+
+       cmdwin_spush("%s", vehicle->getOrdnance()->getName());
+        cmdwin_spush("<direction>");
+       getkey(&dir, dirkey);
+       cmdwin_pop();
+
+       if (dir == CANCEL) {
+               cmdwin_spush("none!");
+               return;
+       }
+
+       cmdwin_spush("%s", directionToString(dir));
+       if (! vehicle->fire_weapon(directionToDx(dir), 
+                                                 directionToDy(dir), 
+                                                 player_party)) {
+               cmdwin_spush("Not a broadside!");
+                log_msg("Fire - not a broadside!");
+               return;
+        }
+}
+
+bool cmdReady(class Character * member)
+{
+       bool committed = false;
+       struct inv_entry *ie;
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+       const char *msg = 0;
+
+       cmdwin_clear();
+       cmdwin_spush("Ready");
+
+        // Select user
+        if (member) {
+               cmdwin_spush("%s", member->getName());                
+        } else {
+                member = select_party_member();
+                if (member == NULL)
+                        return false;       
+
+                if (member->isCharmed()) {
+                        cmdwin_push("Charmed!");
+                        log_msg("Ready - charmed!");
+                        return false;
+                }
+
+        }
+
+        log_begin_group();
+        log_msg("%s readies arms:", member->getName());
+
+       statusSelectCharacter(member->getOrder());
+
+       player_party->sortReadiedItems(member);
+        foogodSetHintText(SCROLLER_HINT);
+        foogodSetMode(FOOGOD_HINT);        
+       statusSetMode(Ready);
+       sc.selector = InventoryItem;
+       kh.fx = scroller;
+       kh.data = &sc;
+       eventPushKeyHandler(&kh);
+
+        cmdwin_spush("<select/ESC>");
+
+       for (;;) {
+
+               sc.selection = NULL;
+
+               eventHandle();
+                cmdwin_pop();
+
+               ie = (struct inv_entry *) sc.selection;
+               if (ie == NULL) {
+                       cmdwin_spush("done!");
+                       break;
+               }
+
+               committed = true;
+
+               class ArmsType *arms = (class ArmsType *) ie->type;
+
+                log_begin("%s - ", arms->getName());
+
+               if (ie->ref && member->unready(arms)) {
+                       msg = "unreadied!";
+                       member->decActionPoints(arms->getRequiredActionPoints());
+                       statusRepaint();
+               } else {
+
+                       switch (member->ready(arms)) {
+                       case Character::Readied:
+                               statusRepaint();
+                               msg = "readied!";
+                               member->decActionPoints(arms->getRequiredActionPoints());
+           /* Move the readied item to the front of the
+            * list for easy access next time, and to
+            * percolate frequently-used items up to the
+            * top. */
+           //player_party->inventory->moveToFront(ie);
+           /* After re-ordering the list, reset the status
+            * viewer to synch it back up with the new
+            * list. */
+           //statusSetMode(Ready);
+                               break;
+                       case Character::NoAvailableSlot:
+                               msg = "all full!";
+                               break;
+                       case Character::WrongType:
+                               msg = "can't use!";
+                               break;
+                       case Character::TooHeavy:
+                               msg = "too heavy!";
+                               break;
+                       default:
+                               assert(false);
+                               break;
+                       }
+               }
+
+               cmdwin_spush("%s %s", arms->getName(), msg);
+                log_end(msg);
+      
+       //do not allow too much AP debt if in combat
+               if ((combat_get_state() == COMBAT_STATE_FIGHTING)
+                                       && ((2 * member->getActionPoints()) + member->getSpeed() < 0))
+               {
+                       break;   
+               }
+      
+       }
+
+       eventPopKeyHandler();
+       statusSetMode(ShowParty);
+        foogodSetMode(FOOGOD_DEFAULT);
+
+        if (committed) {
+                player_party->sortReadiedItems(member);
+                member->runHook(OBJ_HOOK_READY_DONE, 0);
+        }
+
+        log_end_group();
+
+       return committed;
+}
+
+static void cmd_init_movecursor_data(struct movecursor_data *data, 
+                                     struct list *suggest)
+{
+        struct list *entry = 0;
+
+        memset(data, 0, sizeof(*data));
+        data->jump = 1;
+
+        if (! suggest)
+                return;
+
+        /* Copy the head of the list. */
+        data->loc_list = suggest;
+        data->cur_loc = data->loc_list;
+
+        /* Look for the crosshair in the suggest list. */
+        list_for_each(suggest, entry) {
+                struct location_list *loc = 
+                        (struct location_list*)entry;
+                if (loc->x == Session->crosshair->getX()
+                    && loc->y == Session->crosshair->getY()) {
+                        data->cur_loc = &loc->list;
+                        break;
+                }
+        }
+}
+
+int select_target(int ox, int oy, int *x, int *y, int range, 
+                  struct list *suggest)
+{
+        return select_target_rlcb(Place, ox, oy, x, y, range, suggest, 0, 0);
+}
+
+void ui_select_target_req_init(ui_select_target_req_t *req)
+{
+        memset(req, 0, sizeof(*req));
+        list_init(&req->suggest);
+}
+
+static int select_target_rlcb(struct place *place, 
+                              int ox, int oy, 
+                              int *x, int *y,
+                              int range,
+                              struct list *suggest,
+                              v_fncptr_iiv_t each_tile_func,
+                              i_fncptr_iiv_t each_target_func)
+{
+        ui_select_target_req_t req;
+        int ret;
+
+        /* convert args to a targeting request */
+        ui_select_target_req_init(&req);
+        req.place = place;
+        req.x1 = ox;
+        req.y1 = oy;
+        req.x2 = *x;
+        req.y2 = *y;
+        req.move = each_tile_func;
+        req.select = each_target_func;
+        req.tiles = templ_new_from_range(range);
+        templ_set_origin(req.tiles, ox, oy);
+        if (suggest) {
+                list_move(&req.suggest, suggest);
+        }
+        
+        /* call generic target selection */
+        ret = ui_select_target_generic(&req);
+
+        /* convert back */
+        *x = req.x2;
+        *y = req.y2;
+        if (suggest) {
+                list_move(suggest, &req.suggest);
+        }
+        templ_unref(req.tiles);
+
+        return ret;
+}
+
+int ui_select_target_generic(ui_select_target_req_t *req)
+{
+        struct movecursor_data data;
+        struct KeyHandler kh;
+        struct MouseButtonHandler mbh;
+        struct MouseMotionHandler mmh;
+
+        Session->crosshair->setZone(req->tiles);
+        Session->crosshair->setViewportBounded(1);
+        Session->crosshair->setOrigin(req->x1, req->y1);
+        Session->crosshair->relocate(req->place, req->x2, req->y2);
+        Session->show_boxes=1;
+        mapSetDirty();
+
+        cmd_init_movecursor_data(&data, &req->suggest);
+        data.each_tile_func   = req->move;
+        data.each_target_func = req->select;
+        data.data = req->data;
+
+        kh.fx   = movecursor;
+        kh.data = &data;
+  
+        mbh.fx = mouse_button_cursor;
+        mbh.data = &data;
+
+        mmh.fx = mouse_motion_cursor;
+        mmh.data = &data;
+
+        eventPushMouseButtonHandler(&mbh);
+        eventPushKeyHandler(&kh);
+        cmdwin_spush("<target> (ESC to exit)");
+        eventHandle();
+        cmdwin_pop();
+        eventPopKeyHandler();
+        eventPopMouseButtonHandler();
+  
+        Session->show_boxes=0;
+        req->x2 = Session->crosshair->getX();
+        req->y2 = Session->crosshair->getY();
+        Session->crosshair->remove();
+        Session->crosshair->setZone(0);
+        mapSetDirty();
+  
+        if (data.abort) {
+                cmdwin_spush("Done.");
+                return -1;
+        }
+  
+        return 0;
+}
+
+int select_target_with_doing(int ox, int oy, int *x, int *y,
+                             int range,
+                             v_fncptr_iiv_t each_tile_func,
+                             i_fncptr_iiv_t each_target_func)
+{
+        return select_target_rlcb(Place, ox, oy, x, y, range, 0, 
+                                  each_tile_func, 
+                                  each_target_func);
+}
+
+bool cmdHandle(class Character * pc)
+{
+       // SAM: Adding (H)andle command...
+       int x;
+       int y;
+
+       cmdwin_clear();
+       cmdwin_spush("Handle");
+
+       if (pc) {
+               // A party member was specified as a parameter, so this must be
+               // combat mode. Use the party member's location as the origin.
+               x = pc->getX();
+               y = pc->getY();
+               cmdwin_spush("%s", pc->getName());
+       } else {
+               // Must be party mode. Use the player party's location as the
+               // origin.
+               x = player_party->getX();
+               y = player_party->getY();
+
+               // And find out what the party member is Handling (so we can
+               // print the name). If only one party member then select the
+               // only one.
+               if (player_party->get_num_living_members() == 1) {
+                       pc = player_party->get_first_living_member();
+                       cmdwin_spush("%s", pc->getName());
+               } else {
+                       pc = select_party_member();
+                       if (pc == NULL) {
+                               return false;
+                       }
+               }
+       }
+
+       // *** Pick a target ***
+
+       if (select_target(x, y, &x, &y, 1, 0) == -1)
+               return false;
+
+        // Try to find a mech
+       class Object *mech;
+       mech = place_get_object(Place, x, y, mech_layer);
+       if (! mech 
+            || ! mech->getObjectType()->canHandle()
+            || (! mech->isVisible()            
+                && ! Reveal)) {
+                cmdwin_spush("nothing!");
+                log_msg("Handle - nothing there to handle!");
+                return false;
+        }
+
+        // Handle it (sometimes mechs are intentionally nameless so that they
+        // remain hidden from x)amine and s)earch commands)
+        const char *mechName=mech->getName();
+        if (!mechName) {
+                mechName = "a hidden mechanism";
+        }
+        cmdwin_spush("%s", mechName);
+        log_msg("%s handles %s", pc->getName(), mechName);
+        mech->getObjectType()->handle(mech, pc);
+        pc->runHook(OBJ_HOOK_HANDLE_DONE, "p", mech);
+        pc->decActionPoints(kern_intvar_get("AP_COST:handle_mechanism"));
+        mapSetDirty();
+
+        // I think the following was added to update LOS in cases where the
+        // mech changed state and changed LOS. Not sure what happens in
+        // character mode.
+        //player_party->updateView();
+
+       return true;
+}
+
+bool cmdUse(class Character * member, int flags)
+{
+       struct inv_entry *ie;
+       class ObjectType *item;
+        int result;
+
+       cmdwin_clear();
+       cmdwin_spush("Use");
+
+        // Select user
+        if (flags & CMD_SELECT_MEMBER) {
+                member = select_party_member();
+                if (member == NULL)
+                        return false;       
+        } else {
+                assert(member);
+                cmdwin_spush("%s", member->getName());
+        }
+       statusSelectCharacter(member->getOrder());
+
+        // select item to use
+       statusSetMode(Use);
+       ie = ui_select_item();
+       statusSetMode(ShowParty);
+       if (ie == NULL) {
+               return false;
+        }
+
+        /* warning: assume usable item came from player inventory; move it to
+         * the front of the list so that frequently-used items percolate to the
+         * top for easy selection by the player. Oh, and do this *before* using
+         * it, since using it may delete the ie if it is a consumable item and
+         * the last one in inventory. */
+        player_party->inventory->moveToFront(ie);
+
+       item = ie->type;
+        assert(item->isUsable());
+
+        // Use the item
+        log_begin("%s: %s - ", member->getName(), item->getName());
+       result = item->use(member);
+        cmd_eval_and_log_result(result);
+        log_end(0);
+
+        member->runHook(OBJ_HOOK_USE_DONE, "p", item);
+
+        // Item's appear to decrement AP in the script...
+        //member->decActionPoints(kern_intvar_get("AP_COST:use_item"));
+       statusRepaint();
+
+       return true;
+}
+
+/* Helper function called by cmdNewOrder: */
+static void cmd_switch_party_leader(class Character *old_leader,
+                                    class Character *new_leader)
+{
+        new_leader->setLeader(true);
+        old_leader->setLeader(false);
+        old_leader->endTurn();
+        old_leader->setControlMode(CONTROL_MODE_FOLLOW);
+        player_party->setLeader(new_leader);
+}
+
+void cmdNewOrder(void)
+{
+       class Character *pc1, *pc2;
+
+        switch (player_party->getSize()) {
+        case 0:
+                assert(0);
+                break;
+        case 1:
+                log_msg("New Order - only one party member!");
+                return;
+        case 2:
+                pc1 = player_party->getMemberByOrder(0);
+                pc2 = player_party->getMemberByOrder(1);
+                goto swap;
+        }
+
+       cmdwin_clear();
+       cmdwin_spush("Switch");
+
+        // Set the mode now - before calling select_party_member - so that the
+        // screen will not flash back to a short status window between the two
+        // calls to select_party_member.
+        statusSetMode(SelectCharacter);
+
+       pc1 = select_party_member();
+       if (pc1 == NULL) {
+                statusSetMode(ShowParty);
+               return;
+        }
+
+       cmdwin_spush("with");
+
+       pc2 = select_party_member();
+       if (pc2 == NULL) {
+                statusSetMode(ShowParty);
+               return;
+       }
+
+        statusSetMode(ShowParty);
+ swap:
+        player_party->switchOrder(pc1, pc2);
+
+       log_msg("New Order: %s switched with %s\n", pc1->getName(),
+                    pc2->getName());
+
+        // If one of the switched members was the party leader then make the
+        // other one the new leader (unless the other one is dead or otherwise
+        // incapable of being a party leader).
+        if (pc1->isLeader() && pc2->canBeLeader()) {
+                cmd_switch_party_leader(pc1, pc2);
+        } else if (pc2->isLeader() && pc1->canBeLeader()) {
+                cmd_switch_party_leader(pc2, pc1);
+        }
+
+       statusRepaint();
+}
+
+static void run_combat(bool camping, class Character * guard, int hours,
+                       class Object *foe)
+{
+       struct move_info minfo;
+       struct combat_info cinfo;
+
+        assert(!foe || foe->isType(PARTY_ID));
+
+       memset(&minfo, 0, sizeof(minfo));
+       minfo.place = Place;
+       minfo.x = player_party->getX();
+       minfo.y = player_party->getY();
+        minfo.px = minfo.x;
+        minfo.py = minfo.y;
+        minfo.npc_party = (class Party*)foe;
+
+       memset(&cinfo, 0, sizeof(cinfo));
+       cinfo.camping = camping;
+       cinfo.guard = guard;
+       cinfo.hours = hours;
+       cinfo.move = &minfo;
+
+        // Is there an enemy?
+        if (foe) {
+                // Yes, so I assume the player party is being attacked
+                // (currently this happens as a result of conversation). To
+                // setup the proper orientation of the parties I need to get
+                // the direction vector. The direction should be from the foe
+                // to the player.
+                cinfo.defend = true;
+                place_get_direction_vector(minfo.place, 
+                                           foe->getX(), foe->getY(),
+                                           minfo.x, minfo.y, 
+                                           &minfo.dx, &minfo.dy);
+        } else {
+                // No, so we're camping or zooming in. Party values are fine
+                // here.
+                minfo.dx = player_party->getDx();
+                minfo.dy = player_party->getDy();
+        } 
+
+       combat_enter(&cinfo);
+}
+
+struct talk_info {
+        class Object *origin;
+        class Object *nearest;
+        int min_distance;
+        int range;
+        struct list suggest;
+};
+
+/* cmd_talk_info_visitor - called on each object in the current place. Used by
+ * cmdTalk() to find the nearest conversant and build a list of other available
+ * conversants. */
+static void cmd_talk_info_visitor(class Object *obj, void *data)
+{
+        struct location_list *entry = 0;
+        int dist = 0;
+        struct talk_info *info = 
+                (struct talk_info*)data;
+
+        if (! obj->getConversation())
+                return;
+
+        if (obj->isPlayerControlled())
+                return;
+
+        if (TimeStop)
+                return;
+        
+        if (! obj->isVisible() && ! Reveal)
+                return;
+
+        /* Filter out objects not in los of the subject */
+        if (! place_in_los(info->origin->getPlace(),
+                           info->origin->getX(),
+                           info->origin->getY(),
+                           obj->getPlace(),
+                           obj->getX(),
+                           obj->getY()))
+                return;
+        
+
+        /* Filter out objects not in range of conversation. */
+        dist = place_flying_distance(info->origin->getPlace(),
+                                     info->origin->getX(),
+                                     info->origin->getY(),
+                                     obj->getX(),
+                                     obj->getY());
+
+        if (dist > info->range)
+                return;
+
+        /* Add this conversant to the suggestion list. */
+        entry = (struct location_list*)malloc(sizeof(*entry));
+        assert(entry);
+        entry->x = obj->getX();
+        entry->y = obj->getY();
+        list_add_tail(&info->suggest, &entry->list);
+
+        /* Remember the nearest conversant. */
+        if (! info->nearest
+            || dist < info->min_distance) {
+                info->nearest = obj;
+                info->min_distance = dist;
+        }
+}
+
+/* cmd_get_talk_info - find the nearest conversant and build the
+ * 'suggest' list. */
+static class Object *cmd_get_talk_info(struct talk_info *info,
+                                             class Object *member, 
+                                             int range)
+{
+        memset(info, 0, sizeof(info));
+        info->origin = member;
+        info->nearest = NULL;
+        info->min_distance = 0;
+        info->range = range;
+        list_init(&info->suggest);
+
+        place_for_each_object(member->getPlace(), 
+                              cmd_talk_info_visitor,
+                              info);
+
+        return info->nearest;
+}
+
+/* cmd_cleanup_talk_info - free the 'suggest' list. */
+static void cmd_cleanup_talk_info(struct talk_info *info)
+{
+        struct list *entry;
+        for (entry = info->suggest.next; entry != &info->suggest; ) {
+                struct location_list *loc = (struct location_list*)entry;
+                entry = entry->next;
+                list_remove(&loc->list);
+                free(loc);
+        }
+}
+
+void cmdTalk(Object *member)
+{
+       struct conv *conv = NULL;
+        class Object *obj, *conversant = NULL;
+        int x, y;
+        struct talk_info info;
+        const int max_distance = 5;
+
+       // *** Prompt user & check if valid ***
+
+       cmdwin_clear();
+       cmdwin_spush("Talk");
+
+        if (! member) {
+                member = select_party_member();
+                if (! member)
+                        return;
+        }
+
+        // start cursor on nearest object with a conversation
+        conversant = cmd_get_talk_info(&info, member, max_distance);
+        if (! conversant) {
+                conversant = member;
+        }
+
+        x = conversant->getX();
+        y = conversant->getY();
+
+       if (select_target(member->getX(), member->getY(), 
+                          &x, &y, max_distance, &info.suggest) == -1) {
+                goto cleanup;
+       }
+
+       obj = place_get_object(Place, x, y, being_layer);
+
+       if (!obj) {
+                cmdwin_spush("nobody there!");
+                log_msg("Try talking to a PERSON.");
+                goto cleanup;
+        }
+
+        // This next bit was added to support talking to parties, where the
+        // speaker is not the party itself.
+        obj = obj->getSpeaker();
+        if (! obj) {
+                cmdwin_spush("cancel");
+                goto cleanup;
+        }
+
+        if (TimeStop && !obj->isPlayerPartyMember()) {
+                cmdwin_spush("time stopped!");
+                log_msg("This person seems frozen in time.");
+                goto cleanup;
+        }
+
+        conv = obj->getConversation();
+        if (!conv) {
+               cmdwin_spush("no response!");
+                log_begin("No response from ");
+                obj->describe();
+                log_end(".");
+                goto cleanup;
+        }
+
+       cmdwin_spush(obj->getName());
+
+       if (((obj->getLayer() == being_layer) 
+             && ((class Character*)obj)->isAsleep())) {
+               log_msg("Zzzz...\n");
+                goto cleanup;
+       }
+
+        conv_enter(obj, member, conv);
+       mapSetDirty();
+
+ cleanup:
+        
+        cmd_cleanup_talk_info(&info);
+
+        return;
+}
+
+bool cmdZtats(class Character * pc)
+{
+       statusRunApplet(ztats_get_applet()); /* runs until user ESC */
+       statusSetMode(ShowParty); /* restore default status mode */
+       return false;
+}
+
+static int select_hours(int allow_sunrise)
+{
+       struct get_char_info info;
+
+        if (allow_sunrise) {
+                cmdwin_spush("<hours[0-9]/[s]unrise>");
+                info.string = "0123456789sS";
+        } else {
+                cmdwin_spush("<hours[0-9]>");
+                info.string = "0123456789";
+        }
+
+       info.c = '0';
+
+       getkey(&info, &cmd_getchar);
+
+       if (! info.c || info.c == '0') {
+                cmdwin_pop();
+               cmdwin_spush("none!");
+                return 0;
+        }
+        else if (allow_sunrise
+                 && (info.c == 's' ||
+                     info.c == 'S')) {
+                int hour;
+                int sunrise;
+
+                cmdwin_pop();
+                cmdwin_push("until sunrise");
+                hour = clock_time_of_day() / 60;
+                sunrise = SUNRISE_HOUR + 1;
+                if (hour < sunrise)
+                        return sunrise - hour;
+                return HOURS_PER_DAY - hour + sunrise;
+        }
+       else if (info.c == '1') {
+               cmdwin_push(" hour");
+                return 1;
+        }
+       else {
+               cmdwin_push(" hours");
+                return info.c - '0';
+        }
+}
+
+int ui_get_quantity(int max)
+{
+       struct get_number_info info;
+        char prompt[64];
+
+        /* Push the prompt but remember it for use within getnum() */
+       if (max == -1) {
+                snprintf(prompt, sizeof(prompt), "<quantity>");
+       } else {
+                snprintf(prompt, sizeof(prompt), 
+                         "<quantity[0-%d]/RET=%d>", max, max);
+       }
+
+       info.digit = 0;
+       info.state = GN_ALL;
+       info.prompt = prompt;
+
+        cmdwin_spush(info.prompt);
+       getkey(&info, getnum);
+
+       if (info.state == GN_ALL) {
+               if (max == -1)
+                       info.digit = 0;
+               else
+                       info.digit = max;
+       } else if (info.state == GN_CANCEL)
+               cmdwin_spush("none!");
+
+       return info.digit;
+}
+
+int cmd_camp_in_wilderness(class Party *camper)
+{
+       int hours, yesno;
+       class Character *guard = 0;
+
+       cmdwin_clear();
+       cmdwin_spush("Camp");
+
+       if (!place_is_passable(camper->getPlace(), camper->getX(), 
+                               camper->getY(), camper, PFLAG_IGNOREVEHICLES)) {
+               cmdwin_spush("not here!");
+                log_msg("Camp - not here!");
+               return 0;
+       }
+
+        if (place_get_subplace(camper->getPlace(), 
+                               camper->getX(), 
+                               camper->getY())) {
+               cmdwin_spush("not here!");
+                log_msg("Camp - not here!");
+                return 0;
+        }
+
+       hours = select_hours(1);
+       if (hours == 0)
+               return 0;
+
+        cmdwin_spush(""); /* for the '-' */
+       cmdwin_spush("set a watch");
+        cmdwin_spush("<y/n>");
+       getkey(&yesno, &yesnokey);
+
+       if (yesno == 'y') {
+
+               cmdwin_pop();
+               guard = select_party_member();
+               if (!guard) {
+                        cmdwin_pop();
+                       cmdwin_push("no watch");
+               }
+                else if (guard->isDead()) {
+                        log_msg("You prop up the corpse and wave off "
+                                "the flies...");
+                }
+                // else select_party_member() prints the name
+
+       } else {
+               cmdwin_pop();
+               cmdwin_spush("no watch");
+       }
+
+       player_party->beginCamping(guard, hours);
+        camper->endTurn();
+       run_combat(true, guard, hours, NULL);
+
+        return 0;
+}
+
+void cmdLoiter(class Being *subject)
+{
+    int hours = 0;
+
+        cmdwin_clear();
+        cmdwin_spush("Loiter");
+
+        /* Check if enemies are around. */
+        if (place_contains_hostiles(subject->getPlace(), subject)) {
+                cmdwin_spush("foes nearby!");
+                log_msg("Loiter - foes nearby!");
+                return;
+        }
+        
+        /* Check if any party members are engaged in a task. */
+        class Character *pc;
+        if ((pc = cmdAnyPartyMemberEngagedInTask())) {
+            log_msg("Loiter - %s engaged in task!", pc->getName());
+            cmdwin_spush("busy with tasks!");
+            return;
+        }
+
+        /* Prompt for the number of hours. */
+        hours = select_hours(0);
+        if (!hours) {
+                return;
+        }
+
+        /* Tell the party to start loitering. */
+        cmdwin_spush("loitering...");
+        player_party->beginLoitering(hours);
+
+        /* End the turn. */
+        subject->endTurn();
+        
+}
+
+int cmd_camp_in_town(class Character *camper)
+{
+        int hours;
+
+        cmdwin_clear();
+        cmdwin_spush("Rest");
+
+        // Party must be in follow mode.
+        if (player_party->getPartyControlMode() != PARTY_CONTROL_FOLLOW) {
+                cmdwin_spush("must be in follow mode!");
+                log_begin_group();
+                log_msg("Camp - party not in follow mode!");
+                log_msg("(Hint: hit 'f' to enter follow mode)");
+                log_end_group();
+                return 0;
+        }
+                
+        // Check for an object that will serve as a bed.
+        if (place_get_object(camper->getPlace(), camper->getX(), 
+                             camper->getY(),  bed_layer) == NULL) {
+                cmdwin_spush("no bed!");
+                log_msg("Camp - no bed here!");
+                return 0;
+        }
+
+        // Rendezvous the party around the bed.
+        if (! player_party->rendezvous(camper->getPlace(), camper->getX(), 
+                                       camper->getY())) {
+                log_msg("Camp - party can't rendezvous!");
+                return 0;
+        }
+
+        // Prompt for the number of hours to sleep.
+        hours = select_hours(! camper->getPlace()->underground);
+        if (hours == 0)
+                return 0;
+
+        // Put the party in "sleep" mode before returning back to the main
+        // event loop.
+        cmdwin_spush("resting...");
+        player_party->beginResting(hours);
+        camper->endTurn();
+
+        return TURNS_PER_HOUR;
+}
+
+int get_spell_name(struct KeyHandler *kh, int key, int keymod)
+{
+       struct get_spell_name_data *ctx;
+       char *word, letter;
+
+       ctx = (struct get_spell_name_data *) kh->data;
+
+        switch (ctx->state) {
+
+        case GN_ZERO: /* No spell words are entered yet and the prompt is
+                       * sitting there. */
+
+                /* Done? */
+                if (key == '\n') {
+                        cmdwin_pop();
+                        return 1;
+                }
+
+                /* Abort? */
+                if (key == CANCEL) {
+                        cmdwin_pop();
+                        ctx->spell_name[0] = 0;
+                        return 1;
+                }
+
+                /* A letter? */
+                if (isalpha(key)) {
+                        
+                        /* Lookup the word that goes with the letter. */
+                        letter = toupper(key);
+                        word = magic_lookup_word(&Session->magic, letter);
+
+                        /* Valid word? */
+                        if (word) {
+
+                                /* Clear prompt, show the word and advance. */
+                                cmdwin_pop();
+                                cmdwin_push(word);
+                                *ctx->ptr = letter;
+                                ctx->ptr++;
+                                ctx->n++;
+                                ctx->state = GN_SOME;
+                        }
+                }
+                return 0;
+
+        case GN_SOME: /* One or more words are already entered. */
+
+                /* Done? Ensure null-termination. */
+                if (key == '\n') {
+                        /* Segment-push a null string to force a '-' following
+                         * the spell name. */
+                        cmdwin_spush(0);
+                        *ctx->ptr = 0;
+                        return 1;
+                }
+
+                /* Abort? Terminate string at beginning. */
+                if (key == CANCEL) {
+                        ctx->spell_name[0] = 0;
+                        return 1;
+                }
+
+                /* Backspace? */
+                if (key == '\b' && ctx->n) {
+                        cmdwin_pop();
+                        ctx->ptr--;
+                        *ctx->ptr = 0;
+                        ctx->n--;
+
+                        /* Back to empty? Re-prompt. */
+                        if (!ctx->n) {
+                                cmdwin_spush(ctx->prompt);
+                                ctx->state = GN_ZERO;
+                        }
+                        return 0;
+                }
+
+                /* Out of space? */
+                if (ctx->n == MAX_WORDS_IN_SPELL_NAME) {
+                        return 0;
+                }
+
+                /* Not a letter? */
+                if (!isalpha(key))
+                        return 0;
+
+                /* Lookup the word that goes with the letter. */
+                letter = toupper(key);
+                word = magic_lookup_word(&Session->magic, letter);
+                if (!word) {
+                        return 0;
+                }
+                
+                /* Accept the word and print it. After the first word separate words
+                 * with a space. */
+                cmdwin_push(" %s", word);
+                *ctx->ptr = letter;
+                ctx->ptr++;
+                ctx->n++;
+                return 0;
+
+        default: /* Invalid state */
+                assert(0);
+                return 0;
+        }
+
+}
+
+int select_spell(struct get_spell_name_data *context)
+{
+       struct KeyHandler kh;
+
+       memset(context, 0, sizeof(*context));
+       context->ptr = context->spell_name;
+        context->prompt = "<spell name>";
+        context->state = GN_ZERO;
+
+       kh.fx = get_spell_name;
+       kh.data = context;
+
+        cmdwin_spush(context->prompt);
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+       if (strlen(context->spell_name) == 0) {
+               cmdwin_spush("none!");
+               return -1;
+       }
+
+       return 0;
+}
+
+/**
+ * Log console messages describing the results of a closure call and return
+ * whether or not it succeeded.
+ *
+ * @param result is what closure_exec() returned. It should be one of the
+ * standard result codes.
+ *
+ * @returns non-zero iff the closure call was successful. "Succesful" means it
+ * actually did something; whereas "unsuccesful" means the request was
+ * effectively aborted in the script, so the caller should skip post-processing
+ * like mp or ap reduction, etc.
+ */
+static int cmd_eval_and_log_result(int result)
+{
+        static struct {
+                const char *string;
+                int success;
+        } tbl[] = {
+                { "^c+gok^c-!",               1 },
+                { "^c+Gno target^c-!",        0 },
+                { "^c+yno effect^c-!",        1 },
+                { "^c+yno hostiles here^c-!", 1 },
+                { "^c+Glacks skill^c-!",      0 },
+                { "^c+rfailed^c-!",           1 },
+                { "^c+Gnot here^c-!",         0 },
+                { "^c+rcritical fail^c-!!!",  1 },
+                { "^c+ynot now^c-!",          0 },
+        };
+
+        if (result < 0 || result >= array_sz(tbl)) {
+                warn("result code '%d' unknown\n", result);
+                return 1;
+        }
+
+        log_continue(tbl[result].string);
+        return tbl[result].success;
+}
+
+bool cmdCastSpell(class Character * pc)
+{
+       struct get_spell_name_data context;
+       struct inv_entry *ie = NULL;
+       struct spell *spell;
+       bool mixed = false;
+       bool natural = false;
+       int i, cast = 0, result = 0;
+        char spell_name[MAX_SPELL_NAME_LENGTH];
+
+        if (MagicNegated) {
+                log_msg("Cast - magic negated!\n");
+                return false;
+        }
+
+       cmdwin_clear();
+       cmdwin_spush("Cast");
+
+       /* If the pc is null then we are in non-combat mode and need to promp
+         * the user. */
+       if (pc == NULL) {
+               pc = select_party_member();
+               if (pc == NULL) {
+                       return false;
+               }
+               statusSetMode(ShowParty);
+       }
+
+        /* Make sure the PC is not asleep, dead, etc. */
+        if (pc->isDead()) {
+                cmdwin_spush("unable right now!");
+                log_msg("Cast - %s is too dead!", pc->getName());
+                return false;
+        }
+
+        if (pc->isAsleep()) {
+                cmdwin_spush("unable right now!");
+                log_msg("Cast - %s is asleep!", pc->getName());
+                return false;
+        }
+
+       /* Prompt to select a spell */
+       if (select_spell(&context) == -1)
+               return false;
+
+        /* The code for the spell is stored in the context, but not the full
+         * name. I want the full name for log msgs. */
+        magic_spell_code_to_name(&Session->magic, spell_name, 
+                                 MAX_SPELL_NAME_LENGTH, 
+                                 context.spell_name);
+
+        log_begin("%s: %s - ", pc->getName(), spell_name);
+
+       /* Lookup the spell in the list of valid spells. */
+       spell = magic_lookup_spell(&Session->magic, context.spell_name);
+       if (!spell) {
+                /* Bugfix for SF1564255: don't let player guess at spells. */
+               cmdwin_spush("none mixed!");
+                log_end("none mixed!");
+               return false;
+       }
+
+       /* Check if the spell can be used in this context. */
+       if (!(player_party->getContext() & spell->context)) {
+               cmdwin_spush("not here!");
+                log_end("not here!");
+               return false;
+       }
+
+       /* Check if the character comes by this spell naturally. */
+       for (i = 0; i < pc->species->n_spells; i++) {
+               if (! strcmp(pc->species->spells[i], spell->code)) {
+                       natural = true;
+                       break;
+               }
+       }
+
+        /* Check if the caster is of sufficient level. */
+        /*
+         * FIXME: what if the spell is natural? cast An Xen Exe on a snake and
+         * try to cast In Nox Por to see what I mean...
+         */
+       if (!natural && pc->getLevel() < spell->level) {
+               cmdwin_spush("need more experience!");
+                log_end("must be level %d!", spell->level);
+               return false;
+       }
+
+       /* Check party inventory for a mixed spell. */
+       if (!natural) {
+               ie = player_party->inventory->search(spell->type);
+               if (ie && ie->count)
+                       mixed = true;
+       }
+
+       if (!natural && !mixed) {
+               cmdwin_spush("none mixed!");
+                log_end("none mixed!");
+               return false;
+       }
+
+       /* Check if the character has enough mana to cast the spell. */
+       if (pc->getMana() < spell->cost) {
+               cmdwin_spush("need more mana!");
+                log_end("need more mana!");
+               return false;
+       }
+
+        /* Cast the spell. */
+        result = spell->type->cast(pc);
+        cast = cmd_eval_and_log_result(result);
+
+        if (! cast) {
+                log_end(NULL);
+                return false;
+        }
+
+        /* Decrement the caster's mana. */
+        pc->runHook(OBJ_HOOK_CAST_DONE, 0);
+        pc->addMana(0 - spell->cost);
+        pc->decActionPoints(spell->action_points);
+        pc->addExperience(spell->cost);
+
+       /* If the spell was mixed then remove it from inventory. */
+       if (mixed) {
+                int count = ie->count - 1;
+               player_party->takeOut(ie->type, 1);
+                log_msg("%d %s remaining", count, spell_name);
+        }
+
+        /* Some spells have status in the foogod window, so repaint it now. */
+        foogodRepaint();
+
+        log_end(NULL);
+
+       return true;
+
+}
+
+bool cmdMixReagents(class Character *character)
+{
+       struct spell *spell;
+       struct get_spell_name_data context;
+       struct list reagents, *elem;
+       int quantity, max_quantity;
+       struct inv_entry *ie, *ie_spell = 0;
+       bool mistake = false;
+        char spell_name[MAX_SPELL_NAME_LENGTH];
+
+       list_init(&reagents);
+
+       cmdwin_clear();
+       cmdwin_spush("Mix");
+
+       // Select a spell...
+       if (select_spell(&context) == -1)
+               return false;
+
+        // The code for the spell is stored in the context, but not the full
+        // name. I want the full name for log msgs.
+        magic_spell_code_to_name(&Session->magic, spell_name, 
+                                 MAX_SPELL_NAME_LENGTH, 
+                                 context.spell_name);
+
+       // Lookup the spell. If null then keep going and bomb when done.
+       spell = magic_lookup_spell(&Session->magic, context.spell_name);
+
+        // Show the player how many he already has mixed...
+        ie_spell = 0;
+        if (spell) {
+                ie_spell = player_party->inventory->search(spell->type);
+        }
+        if (ie_spell && ie_spell->count) {
+                cmdwin_spush("%d mixed", ie_spell->count);
+        } else {
+                cmdwin_spush("0 mixed");
+        }
+
+       // Prompt for reagents 
+       cmdwin_spush("<select, then M)ix>");
+
+        foogodSetHintText("\005\006=scroll ENT=add/remove ESC=abort M=done");
+        foogodSetMode(FOOGOD_HINT);
+
+       // Show the reagents in the status window
+       statusSetMode(MixReagents);
+
+       struct ScrollerContext sc;
+       sc.selector = Reagents;
+       sc.done = false;
+       sc.abort = false;
+       sc.mixing = true;
+
+       struct KeyHandler kh;
+       kh.fx = scroller;
+       kh.data = &sc;
+
+       eventPushKeyHandler(&kh);
+
+       for (;;) {
+               sc.selection = NULL;
+               eventHandle();
+
+               if (sc.abort) {
+                       // u5 silently aborts here
+                        cmdwin_pop();
+                       eventPopKeyHandler();
+                       cmdwin_spush("none!");
+                       goto done;
+               }
+
+               if (sc.done)
+                       break;
+
+               ie = (struct inv_entry *) sc.selection;
+                if (! ie) {
+                        /* This happens when the player has no reagents
+                         * whatsoever. */
+                       cmdwin_pop();
+                       eventPopKeyHandler();
+                       cmdwin_spush("none!");
+                       goto done;
+                }
+
+               if (ie->ref) {
+                       // unselect
+                       ie->ref = 0;
+                       list_remove(&ie->auxlist);
+               } else {
+                       // select
+                       ie->ref = 1;
+                       list_add(&reagents, &ie->auxlist);
+               }
+
+               statusRepaint();
+       }
+
+       cmdwin_pop();
+       eventPopKeyHandler();
+
+       if (list_empty(&reagents)) {
+               cmdwin_spush("none!");
+               goto done;
+       }
+
+       // Determine the max number of mixtures the player can make.
+       max_quantity = 0x7fffff;
+       list_for_each(&reagents, elem) {
+               ie = outcast(elem, struct inv_entry, auxlist);
+               if (ie->count < max_quantity) {
+                       max_quantity = ie->count;
+               }
+       }
+
+       // Prompt for the number of mixtures to make
+       for (;;) {
+
+               int dummy;
+
+                cmdwin_push_mark();
+               quantity = ui_get_quantity(max_quantity);
+
+               if (quantity == 0) {
+                       goto done;
+               }
+
+               if (quantity <= max_quantity)
+                       break;
+
+                cmdwin_spush(0); /* for the '-' after the quantity */
+               cmdwin_spush("not enough reagents!");
+               getkey(&dummy, anykey);
+               cmdwin_pop_to_mark();
+       }
+
+        cmdwin_push("-");
+       log_begin("Mix: %s - ", spell_name);
+
+       // For each reagent required by the spell, check if it is in the list
+       // of reagents given by the player. If not then remember this fact. If
+       // the reagent is found then remove it from player inventory and remove
+       // it from the list.
+       if (spell) {
+               for (int i = 0; i < spell->n_reagents; i++) {
+                       bool found = false;
+                       list_for_each(&reagents, elem) {
+                               ie = outcast(elem, struct inv_entry, auxlist);
+                               if (ie->type ==
+                                   (class ObjectType *) spell->reagents[i]) {
+                                        // The following line is safe only
+                                       // because this is the end of the
+                                       // list_for_each loop!
+                                       list_remove(elem);
+                                       ie->ref--;
+                                       player_party->takeOut(ie->type, 
+                                                              quantity);
+                                       found = true;
+                                       break;
+                               }
+                       }
+                       if (!found)
+                               mistake = true;
+               }
+       }
+
+       // Now, if any reagents remain leftover then remember this fact and
+       // remove the remaining reagents from inventory.
+       if (!list_empty(&reagents)) {
+               mistake = true;
+               elem = reagents.next;
+               while (elem != &reagents) {
+                       struct list *tmp = elem->next;
+                       ie = outcast(elem, struct inv_entry, auxlist);
+                       list_remove(elem);
+                       elem = tmp;
+                       ie->ref--;
+                       player_party->takeOut(ie->type, quantity);
+               }
+       }
+
+        statusSetMode(ShowParty);
+        foogodSetMode(FOOGOD_DEFAULT);
+
+        // committed to action now, so decrement AP
+        if (character) {
+                character->runHook(OBJ_HOOK_MIX_DONE, 0);
+                
+                if (!spell)
+                {
+                   // Failed attempt (mixing a spell which does not exist)
+                   int num  = kern_intvar_get("AP_COST:mix_reagents_nospell_num");
+                   int dice = kern_intvar_get("AP_COST:mix_reagents_nospell_dice");
+                   int plus = kern_intvar_get("AP_COST:mix_reagents_nospell_plus");
+                   int AP_wasted = dice_roll_numeric(num, dice, plus);
+                   character->decActionPoints(AP_wasted);
+                   // was 3d50+20 -- dice_roll_numeric(3, 50, 20)
+                }
+                else if (mistake)
+                {
+                   int level = spell->level;
+                   int num  = kern_intvar_get("AP_COST:mix_reagents_badmix_num");
+                   int dice = kern_intvar_get("AP_COST:mix_reagents_badmix_dice");
+                   int plus = kern_intvar_get("AP_COST:mix_reagents_badmix_plus");
+                   int AP_wasted = dice_roll_numeric(level * num, dice, plus);
+                   character->decActionPoints(AP_wasted);
+                   // was 1d(2*AP)+100 -- dice_roll_numeric(1 ,(2 * spell->action_points) , 100)
+                }
+               else
+               {
+                   // mixing should be SLOW
+                   int base      = kern_intvar_get("AP_COST:mix_reagents_base");
+                   int per_mix   = kern_intvar_get("AP_COST:mix_reagents_per_mix");
+                   int per_level = kern_intvar_get("AP_COST:mix_reagents_per_level");
+                   int AP_spent  = base + (quantity * per_mix) + (spell->level * per_level);
+                   character->decActionPoints(AP_spent);
+                   // was 100 + 2 * spell->action_points
+               }
+        }
+
+       // If the spell is invalid or the reagents are incorrect then punish
+       // the player.
+       if (!spell) {
+                cmdwin_spush("oops!");
+                player_party->damage(DAMAGE_ACID);
+                log_end("ACID!");
+                goto done;
+
+        } else if (mistake) {
+                cmdwin_spush("ouch!");
+                player_party->damage(DAMAGE_BOMB);
+                log_end("BOMB!");
+                goto done;
+       }
+
+       // All is well. Add the spell to player inventory.
+        cmdwin_spush("ok");
+       player_party->add(spell->type, quantity);
+        log_end("ok!");
+
+ done:
+       // In case of cancellation I need to unselect all the reagents.
+       elem = reagents.next;
+       while (elem != &reagents) {
+               struct list *tmp = elem->next;
+               ie = outcast(elem, struct inv_entry, auxlist);
+               list_remove(elem);
+               elem = tmp;
+               ie->ref--;
+       }
+       statusSetMode(ShowParty);
+        foogodSetMode(FOOGOD_DEFAULT);
+       return true;
+}
+
+void look_at_XY(struct place *place, int x, int y, void *unused)
+{
+        if (DeveloperMode) {
+                log_begin("At XY=(%d,%d): ", x, y);
+        } else {
+                log_begin("");
+        }
+
+        if ( mapTileIsVisible(x, y) ) {
+                if (mapTileLightLevel(x,y) < MIN_XAMINE_LIGHT_LEVEL) {
+                        log_continue("Too dark!");
+                } else {
+                        log_continue("You see ");
+                        place_describe(place, x, y, PLACE_DESCRIBE_ALL);
+                }
+        } else if (ShowAllTerrain || XrayVision) {
+                log_continue("You see (via xray) ");
+                place_describe(place, x, y, PLACE_DESCRIBE_TERRAIN);
+        } else {
+                log_continue("You can't see!");
+        }
+
+        log_end(NULL);
+}
+
+int detailed_examine_XY(struct place *place, int x, int y, void *unused)
+{
+       if (DeveloperMode) {
+                       log_begin("At XY=(%d,%d): ", x, y);
+       } else {
+                       log_begin("");
+       }
+
+       if ( mapTileIsVisible(x, y) ) {
+                       if (mapTileLightLevel(x,y) < MIN_XAMINE_LIGHT_LEVEL) {
+                                       log_continue("You can't see!");
+                       } else {
+                                       log_continue("You see:\n");
+                                       place_examine(place, x, y);
+                       }
+       } else if (ShowAllTerrain || XrayVision) {
+                       log_continue("You see (via xray):\n");
+                       place_examine(place, x, y);
+       } else {
+                       log_continue("You can't see!");
+       }
+
+       #if 0
+       // SAM: 
+       // Hmmm...how best to print more info about
+       // the objects on this tile?
+        if ( mapTileIsVisible(x, y) ) {
+                log_msg("DETAIL XY=(%d,%d) TODO - print detailed view\n", x, y);
+                // For each object/terrain on the tile, print the name (and
+                // perhaps show the sprite in a Status Window mode), and also
+                // show:
+                //
+                //     o whether this object blocks LOS (alpha)
+                //     o whether this object blocks movement (pmask)
+                //     o whether this object causes some effect when stepped
+                //       upon (hazardous terrain effects, pressure plate
+                //       triggers)
+                //     o information specific to the object type, such as:
+                //     o Triggers: current state, and perhaps what it is 
+                //       connected to?
+                //     o NpcParties: faction, movement mode 
+                //       (pmask), ...
+                //     o Vehicles: movement mode, armament, current HP
+                //     o Portable items: weapon/armor stats, (U)se effects, 
+                //       etc...
+                // Hmmm...what else?
+                return;
+        }
+        log_msg("DETAIL XY=(%d,%d) out of LOS\n", x, y);
+       #endif
+       
+       log_end(NULL);
+
+        return 0; /* keep on targeting */
+}
+
+bool cmdXamine(class Object * pc)
+{
+       // SAM: Working on an improved (L)ook command,
+       // which works as a "Look Mode" rather than a 
+       // "look at 1 tile" command...
+       int x, y;
+        bool ret = true;
+
+       cmdwin_clear();
+       cmdwin_spush("Xamine");
+
+        x = pc->getX();
+        y = pc->getY();
+
+        log_begin_group();
+
+        if (pc)
+                log_msg("%s examines around...", pc->getName());
+        else
+                log_msg("You examine around...");
+
+        look_at_XY(pc->getPlace(), x, y, 0);  // First look at the current tile
+       if (select_target_with_doing(x, y, &x, &y, pc->getVisionRadius(),
+                                    look_at_XY, detailed_examine_XY) == -1) {
+               ret = false;
+       }
+
+        log_end_group();
+
+       return ret;
+} // cmdXamine()
+
+const char * name_of_context (void)
+{
+        // SAM: Perhaps this function belongs in common.c?
+        switch (player_party->getContext()) {
+        case CONTEXT_WILDERNESS:
+                return "Party Context";
+                break;
+        default:
+                return "Character Context";
+                break;
+        }
+} // name_of_context()
+
+bool cmdAT (class Character * pc)
+{
+       int x, y;
+        const char * who = "";
+        const char * place_name = "";
+
+       cmdwin_clear();
+
+        // Should I check player_party->context
+        // for the context info below, 
+        // rather than the current method?
+       if (pc) {
+               // A party member was specified as a parameter, so this must be
+               // combat mode. Use the party member's location as the origin.
+                who = pc->getName();
+                place_name =  Place->name;
+               x = pc->getX();
+               y = pc->getY();
+       }
+        else {
+               // Must be party mode. 
+               // Use the player party's location as the origin.
+                who = "The party";
+                place_name = player_party->getPlace()->name;
+                x = player_party->getX();
+                y = player_party->getY();
+       }
+        // SAM: Why is this line not safe in combat mode?
+        //      Would it be The Right Thing (TM) 
+        //      for it to be made safe in all contexts?
+        // place_name = player_party->getPlace()->name;
+    
+        log_begin_group();
+        log_msg("This is %s.", name_of_context() );
+        log_msg("%s is in %s.", who, place_name);
+               if (Place->underground) {
+                       log_msg("It is %s, %s of %s in the year %d.",
+                day_name(), week_name(), month_name(), Session->clock.year );
+        }
+               else
+               {
+                       log_msg("It is %s on %s, "
+                "%s of %s in the year %d.",
+                vague_time_as_string(), day_name(), 
+                week_name(), month_name(), Session->clock.year );
+               }
+        // SAM: Is this really interesting though, I wonder?
+        log_msg("%d game turns have passed.", Turn);
+
+        log_msg("The wind is blowing from the %s.",
+                directionToString(windGetDirection()) );
+
+        if (Place->underground) {
+                log_msg("%s is underground, and cannot see the sky.", 
+                        who);
+        } // underground
+        else {
+                struct list *elem;
+                
+                // SAM: 
+                // This message won't be true if you are under 
+                // a roof in a town.  In future there should be 
+                // logic querying the (future) roof-ripping code here.
+                log_msg("%s is beneath the open sky.", who);
+
+                // The kernel no longer has any special knowledge about which
+                // astral body is the sun, so we have to deal with all astral
+                // bodies generically now. I mean, a game may have two or even
+                // more suns. The time runs independently and isn't cued off
+                // the sun.
+                if (is_noon())
+                        log_msg("It is noon.");
+                else if (is_midnight())
+                        log_msg("It is midnight.");
+
+                // Report on each astral body generically.
+                list_for_each(&Session->sky.bodies, elem) {
+                        struct astral_body *body;
+                        body = outcast(elem, struct astral_body, list);
+                        if (astral_body_is_visible(body->arc)) {
+                                log_begin("%s is up at arc %d", body->name, 
+                                        body->arc);
+                                if (body->n_phases > 1) {
+                                        char *phase_name = 
+                                                body->phases[body->phase].
+                                                name;
+                                        if (phase_name)
+                                                log_continue(" in its %s "
+                                                             "phase", 
+                                                             phase_name);
+                                        else
+                                                log_continue(" in phase %d", 
+                                                             body->phase);
+                                }
+                                log_end(".");
+                        }
+                }
+
+        } // open air, under the sky
+
+        if (player_party->getVehicle()) {
+                log_msg("%s is %s a %s.", 
+                        who, "using", player_party->getVehicle()->getName() );
+                // SAM:
+                // In future, we shall want GhulScript to specify 
+                // whether one is to be
+                //     "riding" "driving" "piloting" "sailing"
+                // a particular vehicle type.
+                // The existing 'mv_desc' field (Ride, Sail)
+                // is related, but we need the gerund of the verb.
+        }
+        else {
+                // SAM: Not true for a party of Gazers or Nixies.
+                // Similar GhulScript for party / character movement mode
+                // descriptions and gerunds?
+                log_msg("%s is on foot.", who);
+        }
+
+        log_end_group();
+
+        /*
+          Information reported shall include:
+          X the current place,X,Y
+          X the in-game time in game time units (HH:MM, YYYY/MM/DD)
+          X the in-game time in elapased turns (this is of less interest)
+          X the current weather status (wind)
+          X the current astronomy (day/night, sun, moons)
+          X the UI mode of the party (Wilderness,Town,Dungeon,Combat)
+          X whether the party is on foot or in a vehicle (and what type)
+          . the number of party members, names, order, and basic vital stats
+          . global party stats such as food and gold
+          . any special effects (buffs/nerfs) currently affecting the party,
+          . such as haste/quickness/slow, time stop, protection, etc.
+          . Xamine type information about the tile the party is standing on.
+        */
+
+        return true;
+} // cmdAT()
+
+/**
+ * cmd_terraform - edit terrain interactively
+ */
+bool cmd_terraform(struct place *place, int x, int y)
+{
+    terrain_editor_run(place, x, y);
+    return true;
+}
+
+bool cmd_save_current_place (struct place * place)
+{
+    FILE *   file;
+    const char *   file_path;
+    save_t * save;
+    int ret;
+
+    //log_msg("cmd_save_current_place");
+    //printf("cmd_save_current_place()\n");
+
+    file_path = "_test_save_place";
+
+    file = file_open_in_save_dir(file_path, "w");
+    if (file == NULL) {
+       log_msg("Save place to file '%s' failed.", file_path);
+       printf("Error on fopen() for file '%s': '%s'\n", file_path, strerror(errno));
+       return 0;
+    }
+    Session->session_id++;  // Must increment to cause saving.
+
+    save = save_new(file);
+    save->indent     = 0;
+    save->session_id = Session->session_id;
+
+    //terrain_map_print(file, 0, place->terrain_map);
+    terrain_map_save(save, place->terrain_map);
+    log_msg("Saved map to file:\n'%s'", file_path);
+    printf( "Saved map to file '%s'\n", file_path);
+
+    save_del(save);
+
+    ret = fclose(file);
+    if (ret != 0) {
+       // SAM: Not sure what we can do about it, 
+       //      and this seems kind of low-level to log_msg() about...
+       printf("Error on fclose() for file '%s': '%s'\n", file_path, strerror(errno));
+       // It seems that the save method should return non-void, 
+       // so that we know success/failure in this and other cases...
+       return 0;
+    }
+    return 1;
+}
+
+void cmdZoomIn(void)
+{
+        struct place *subplace = 0;
+        // 
+        // SAM: Curently no "Enter" message is printed.  It turns out to be
+        // moderately complicated to do so properly, as a distinct message for
+        // each enter_combat() case might be desired...
+        // 
+        // For now, I print a placeholder message for each case here:
+        
+        if ((subplace = place_get_subplace(player_party->getPlace(),
+                                                  player_party->getX(),
+                                                  player_party->getY()))) {
+                if (ENABLE_TOWN_ZOOM_IN) {
+                        // Standing over a subplace. Try to enter with no
+                        // direction, this will prompt the player to provide a
+                        // direction.
+                        log_msg("Enter-%s", subplace->name);
+                        player_party->try_to_enter_subplace_from_edge(subplace,
+                                                                      0, 0);
+                } else {
+                        log_msg("Enter-Use a side entrance!");
+                }
+
+        } else if (!place_is_passable(player_party->getPlace(),
+                                      player_party->getX(),
+                                      player_party->getY(),
+                                      player_party,
+                                      PFLAG_IGNOREVEHICLES)) {
+
+                // Currently zooming in to impassable terrain is not doable;
+                // since the party might not be placeable on the default map,
+                // which would be a solid grid of that impassable terrain.
+                // Also, if somehow placed, the party could not escape unless
+                // on an edge.  There would be no harm in it otherwise,
+                // however.
+                struct terrain * tt = 
+                        place_get_terrain(player_party->getPlace(),
+                                          player_party->getX(),
+                                          player_party->getY() );
+                log_msg("Enter-Cannot zoom-in to %s!", tt->name);
+        } else {
+                // If standing on ordinary terrain, zoom in:
+                struct terrain * tt = 
+                        place_get_terrain(player_party->getPlace(),
+                                          player_party->getX(),
+                                          player_party->getY() );
+                log_msg("Enter-%s", tt->name);
+                run_combat(false, 0, 0, NULL);
+        }
+}
+
+bool cmdSave(void)
+{
+    bool ret = true;
+    class Character *pc;
+    if ((pc = cmdAnyPartyMemberEngagedInTask())) {
+        log_msg("Denied - %s engaged in task!", pc->getName());
+        cmdwin_spush("busy with tasks!");
+        return false;
+    }
+
+    char *fname = save_game_menu();
+    if (!fname) {
+        cmdwin_spush("abort!");
+        return false;
+    }
+    
+    log_begin("Saving to %s...", fname);
+    if (session_save(fname)) {
+        log_end("^c+rfailed!^c-");
+        cmdwin_spush("failed!");
+        ret = false;
+    } else {
+        cmdwin_spush("ok!");
+        log_end("^c+gok!^c-");
+    }
+    session_save(fname);
+    free(fname);
+    return ret;
+}
+
+void cmdReload(void)
+{
+        Reload = 1;        
+}
+
+/****** New UI ******/
+
+#define MARKUP 4
+
+
+int ui_get_yes_no(const char *name)
+{
+       int yesno;
+       cmdwin_clear();
+       cmdwin_spush("Reply");
+        cmdwin_spush("<y/n>");
+       getkey(&yesno, yesnokey);
+       cmdwin_pop();
+       if (yesno == 'y') {
+               cmdwin_spush("yes");
+               log_msg("^c+%c%s:^c- Yes", CONV_PC_COLOR, name);
+                return 1;
+       } else {
+               cmdwin_spush("no");
+               log_msg("^c+%c%s:^c- No", CONV_PC_COLOR, name);
+                return 0;
+       }
+}
+
+typedef struct ui_getline_data {
+        char *ptr;
+        char *buf;
+        int room;
+        int (*filter)(int key);
+} getline_t;
+
+static int ui_getline_handler(struct KeyHandler *kh, int key, int keymod)
+{
+        getline_t *data = (getline_t*)kh->data;
+
+       if (key == CANCEL) {
+               while (data->ptr > data->buf) {
+                       data->ptr--;
+                       *data->ptr = 0;
+                       cmdwin_pop();
+                       data->room++;
+               }
+               return 1;
+       }
+
+       if (key == '\n') {
+               return 1;
+       }
+
+       if (key == '\b') {
+               if (data->ptr != data->buf) {
+                       data->ptr--;
+                       *data->ptr = 0;
+                       data->room++;
+                       cmdwin_pop();
+               }
+               return 0;
+       }
+
+        if (data->filter
+            && data->filter(key)) {
+                return 0;
+        }
+
+       if (isprintable(key) 
+            && data->room) {
+               cmdwin_push("%c", key);
+               *data->ptr++ = key;
+               data->room--;
+       }
+
+       return 0;
+}
+
+int ui_getline_filtered(char *buf, int len, int (*filter)(int key))
+{
+        struct KeyHandler kh;
+        getline_t data;
+
+        data.buf  = buf;
+        data.ptr  = buf;
+        data.room = len - 1;
+        data.filter = filter;
+
+        memset(buf, 0, len);
+
+        kh.fx   = ui_getline_handler;
+        kh.data = &data;
+
+        eventPushKeyHandler(&kh);
+        eventHandle();
+        eventPopKeyHandler();
+
+        return len - (data.room + 1);        
+}
+
+int ui_getline_plain(char *buf, int len)
+{
+        return ui_getline_filtered(buf, len, 0);
+}
+
+int ui_getline(char *buf, int len)
+{
+        cmdwin_clear();
+        cmdwin_push("Say: ");
+        return ui_getline_plain(buf, len);
+}
+
+int ui_buy(struct merchant *merch)
+{
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+       struct trade_info *trade;
+       int quantity, cost, max_q, bought = 0;
+
+       statusSetTradeInfo(merch->n_trades, merch->trades);
+       statusSetMode(Trade);
+
+       sc.selector = TradeItem;
+       kh.fx = scroller;
+       kh.data = &sc;
+
+       for (;;) {
+
+               // *** selection ***
+
+               sc.selection = NULL;
+
+               cmdwin_clear();
+               cmdwin_spush("Buy");
+                cmdwin_spush("<select/ESC>");
+               eventPushKeyHandler(&kh);
+               eventHandle();
+               eventPopKeyHandler();
+               cmdwin_pop();
+
+               trade = (struct trade_info *) sc.selection;
+
+               if (!trade) {
+                       cmdwin_spush("none!");
+                       break;
+               }
+
+                /* Print the sales pitch to the console, if one exists */
+                if (trade->sales_pitch) {
+                        log_msg("^c+%c%s:^c- %s", CONV_NPC_COLOR, merch->name,
+                                trade->sales_pitch);
+                }
+
+               cmdwin_spush("%s", trade->name);
+
+               if (player_party->gold < trade->cost) {
+                       int dummy;
+                       cmdwin_spush("not enough gold! <hit any key>");
+                       getkey(&dummy, anykey);
+                       continue;
+               }
+               // *** quantity ***
+
+                cmdwin_push_mark();
+               max_q = player_party->gold / trade->cost;
+               quantity = ui_get_quantity(max_q);
+                cmdwin_pop_to_mark();
+
+               if (quantity == 0) {
+                       cmdwin_spush("none!");
+                       continue;
+               }
+
+               quantity = min(quantity, max_q);
+               cmdwin_spush("%d", quantity);
+
+               cost = quantity * trade->cost;
+
+               // *** trade ***
+
+                class ObjectType *type = (class ObjectType*)trade->data;
+               cmdwin_spush("ok");
+               log_msg("You buy %d %s%s for %d gold\n", quantity,
+                            trade->name, quantity > 1 ? "s" : "", cost);
+
+               player_party->gold -= cost;
+                if (type->canBuy()) {
+                        type->buy(player_party->get_leader(), quantity);
+                } else {
+                        player_party->add(type, quantity);
+                }
+                trade->quantity = player_party->inventory->numAvail(type);
+                statusRepaint();
+               foogodRepaint();
+                bought++;
+       }
+
+       statusSetMode(ShowParty);
+        return bought;
+}
+
+static bool conv_filter_trade(struct inv_entry *ie, void *fdata)
+{
+        struct trade_info *trade = (struct trade_info*)fdata;
+        return (ie->type == trade->data && ie->count > ie->ref);
+}
+
+static int fill_sell_list(struct merchant *merch, struct trade_info *trades)
+{
+       struct inv_entry *ie = NULL;
+        struct filter filter;
+       int i, j = 0;
+
+        filter.fx = conv_filter_trade;
+
+        for (i = 0; i < merch->n_trades; i++) {
+
+                if (merch->trades[i].cost / MARKUP == 0)
+                        continue;
+                
+                filter.fdata = &merch->trades[i];
+                ie = player_party->inventory->first(&filter);
+                if (!ie)
+                        continue;
+
+                /* Why don't aren't we setting show_sprite here, too? */
+                trades[j] = merch->trades[i];
+                trades[j].cost /= MARKUP;
+                trades[j].quantity = ie->count - ie->ref;
+                trades[j].show_quantity = 1;
+                j++;
+        }
+
+       return j;
+}
+
+int ui_sell(struct merchant *merch)
+{
+       // A bit trickier than the "Buy" scenario. A merchant will only buy
+       // items that it is willing to turn around and sell at a profit. When
+       // it comes time to select an item to sell the user should only see the
+       // list of items in player inventory which the merchant is willing to
+       // buy. So here we need to build that list and feed it to the status
+       // viewer.
+
+       int n_trades = 0;
+       struct trade_info *trades;
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+       struct trade_info *trade;
+        int sold = 0;
+
+       // Allocate the trade list.
+       trades = new struct trade_info[merch->n_trades];
+       if (!trades) {
+               log_msg("^c+%c%s:^c- I don't need anything.\n", 
+                        CONV_NPC_COLOR, merch->name);                
+               return 0;
+       }
+       // Fill out the list
+       n_trades = fill_sell_list(merch, trades);
+       statusSetTradeInfo(n_trades, trades);
+       statusSetMode(Trade);
+
+       sc.selector = TradeItem;
+       kh.fx = scroller;
+       kh.data = &sc;
+
+       for (;;) {
+
+               struct inv_entry *ie;
+               int quantity, max_q;
+
+               sc.selection = NULL;
+
+               cmdwin_clear();
+               cmdwin_spush("Sell");
+                cmdwin_spush("<select or ESC>");
+               eventPushKeyHandler(&kh);
+               eventHandle();
+               eventPopKeyHandler();
+               cmdwin_pop();
+
+               trade = (struct trade_info *) sc.selection;
+
+               if (!trade) {
+                       cmdwin_spush("none!");
+                       break;
+               }
+
+               cmdwin_spush("%s", trade->name);
+
+               ie = player_party->inventory->search((class ObjectType *) 
+                                                     trade->data);
+               assert(ie);
+               assert(ie->ref < ie->count);
+
+               // quantity
+
+               max_q = ie->count - ie->ref;
+
+               cmdwin_push_mark();
+               quantity = ui_get_quantity(max_q);
+                cmdwin_pop_to_mark();
+
+               if (quantity == 0) {
+                       cmdwin_spush("none!");
+                       continue;
+               }
+
+               quantity = min(quantity, max_q);
+               cmdwin_spush("%d", quantity);
+
+               // make the trade
+               player_party->takeOut(ie->type, quantity);
+               player_party->gold += quantity * trade->cost;
+               foogodRepaint();
+
+               cmdwin_spush("ok");
+               log_msg("You sell %d %s%s for %d gold\n", quantity,
+                            trade->name, quantity > 1 ? "s" : "",
+                            quantity * trade->cost);
+
+               // refresh the sell list
+               n_trades = fill_sell_list(merch, trades);
+               statusSetTradeInfo(n_trades, trades);
+               statusUpdateTradeInfo(n_trades, trades);
+                sold++;
+       }
+
+       statusSetMode(ShowParty);
+
+       delete trades;
+        return sold;
+}
+
+static int get_buy_or_sell_key(struct KeyHandler *kh, int key, int keymod)
+{
+       int *val = (int *) kh->data;
+
+       switch (key) {
+       case 'b':
+       case 'B':
+               *val = 'b';
+               return 1;
+       case 's':
+       case 'S':
+               *val = 's';
+               return 1;
+       case CANCEL:
+               *val = 'x';
+               return 1;
+       default:
+               return 0;
+       }
+}
+
+int ui_trade(struct merchant *merch)
+{
+       int key, traded = 0;
+
+       for (;;) {
+               cmdwin_clear();
+               cmdwin_spush("Buy or sell");
+                cmdwin_spush("<B/S/ESC>");
+               getkey(&key, get_buy_or_sell_key);
+
+               switch (key) {
+               case 'b':
+                       traded += ui_buy(merch);
+                       break;
+               case 's':
+                       traded += ui_sell(merch);
+                       break;
+               default:
+                       cmdwin_pop();
+                       cmdwin_spush("none!");
+                       return traded;
+               }
+       }
+}
+
+static const char *cmd_help_text =
+"Use the arrow keys to indicate direction.\n"
+"Use the ESC key to cancel commands.\n"
+"Use the first letter to start a command.\n"
+"\n"
+"A)ttack something\n"
+"B)oard a ship or other vehicle\n"
+"C)ast a spell\n"
+"E)nter a town or dungeon\n"
+"F)ire a ship's cannon or other ordnance\n"
+"G)et something on the ground\n"
+"H)andle a lever or mechanism\n"
+"K)amp in a bed or the wilderness\n"
+"L)oiter for a while\n"
+"N)ew-Order (rearrange party order)\n"
+"O)pen a chest, door or other closed object\n"
+"Q)uit and save the game\n"
+"R)eady weapons or armor\n"
+"S)earch for hidden stuff\n"
+"T)alk to somebody\n"
+"U)se an item in inventory\n"
+"Z)tats (show party status)\n"
+"X)amine around\n"
+"@)AT (info about place & time)\n"
+"<space> (pass a turn)\n"
+"CTRL-Q)uit without saving\n"
+"CTRL-S)ave without quitting\n"
+"CTRL-R)eload the last saved game\n"
+"\n"
+"When talking to people, enter a keyword.\n"
+"Most people reply to NAME, JOB, TRADE and\n"
+"JOIN. Their replies will give you hints\n"
+"about more keywords.\n"
+;
+
+void cmdHelp(void)
+{
+        struct KeyHandler kh;
+
+        foogodSetHintText(PAGER_HINT);
+        foogodSetMode(FOOGOD_HINT);
+        statusSetPageText("Commands", cmd_help_text);
+        statusSetMode(Page);
+
+        kh.fx = scroller;
+        kh.data = NULL;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+        statusSetMode(ShowParty);
+        foogodSetMode(FOOGOD_DEFAULT);
+}
+
+void ui_name_vehicle(class Vehicle *vehicle)
+{
+        int yesno;
+        char buf[64];
+
+        log_begin("Do you want to name your ");
+        vehicle->describe();
+        log_end("?");
+
+        cmdwin_spush("Name");
+        cmdwin_spush("<y/n>");
+        getkey(&yesno, yesnokey);
+        cmdwin_pop();
+        cmdwin_pop();
+
+        if (yesno == 'n') {
+                cmdwin_spush("no!");
+                log_msg("It's likely to be stolen!");
+                return;
+        }
+
+        if (!ui_getline(buf, sizeof(buf))) {
+                log_msg("It's likely to be stolen!");
+                return;
+        }
+
+        vehicle->setName(buf);
+
+        log_begin("You christen ");
+        vehicle->describe();
+        log_end(".");
+}
+
+void cmdSettings(void)
+{
+        StatusMode omode = statusGetMode();
+        options_menu();
+        statusSetMode(omode);
+}
+
+void cmdDrop(class Character *actor)
+{
+        enum StatusMode omode;
+        struct inv_entry *ie;
+        class Object *obj;
+        int maxq, quantity, dir, x, y;
+
+        assert(actor);
+
+        cmdwin_clear();
+        cmdwin_spush("Drop");
+
+        omode = statusGetMode();
+        statusBrowseContainer(actor->getInventoryContainer(), "Drop");
+        ie = ui_select_item();
+        statusSetMode(omode);
+
+        if (!ie) {
+                return;
+        }
+
+        maxq = ie->count - ie->ref;
+        assert(maxq);
+
+        /* Don't drop quest items in temporary places! */
+        if (place_is_wilderness_combat(actor->getPlace())
+            && ie->type->isQuestItem()) {
+                log_msg("%s seems important, it might get lost here!", 
+                        ie->type->getName());
+                return;
+        }
+
+        /* prompt for a count (unless there is only one) */
+        if (ie->count == 1) {
+                quantity = 1;
+        } else {
+                quantity = ui_get_quantity(maxq);
+                if (!quantity) {
+                        return;
+                }
+        }
+
+        /* prompt for location */
+        dir = ui_get_direction();
+       if (dir == CANCEL) {
+               return;
+        }
+        x = actor->getX() + directionToDx(dir);
+        y = actor->getY() + directionToDy(dir);
+
+        /* put it on the map */
+        obj = ie->type->createInstance();
+        assert(obj);
+        obj->setCount(quantity);
+        if (place_get_movement_cost(actor->getPlace(), x, y, 
+                            obj, 0) < PTABLE_NO_DROP)
+        {
+               obj->relocate(actor->getPlace(), x, y,
+                          REL_NOSTEP, /* FIXME: really? */
+                       NULL);
+               actor->takeOut(ie->type, quantity);
+               actor->runHook(OBJ_HOOK_DROP_DONE, "pd", ie->type, quantity);
+         }
+         else if (place_get_movement_cost(actor->getPlace(), actor->getX(), actor->getY(), 
+                            obj, 0) < PTABLE_IMPASSABLE)
+        {
+                       obj->relocate(actor->getPlace(), actor->getX(), actor->getY(),
+                          REL_NOSTEP, /* FIXME: really? */
+                       NULL);
+               actor->takeOut(ie->type, quantity);
+               actor->runHook(OBJ_HOOK_DROP_DONE, "pd", ie->type, quantity);
+               log_msg("%s wouldnt fit!", ie->type->getName());
+                }
+                else
+                {
+                        log_msg("Couldnt drop %s!", ie->type->getName());
+                }
+        /* remove from party inventory */
+        actor->decActionPoints(kern_intvar_get("AP_COST:drop_item"));
+
+        statusRepaint();
+        mapUpdate(REPAINT_IF_DIRTY);
+        return;
+}
+
+#ifdef USE_SKILLS
+
+static const void *cmd_select_generic()
+{
+       struct KeyHandler kh;
+       struct ScrollerContext sc;
+
+        foogodSetHintText(SCROLLER_HINT);
+        foogodSetMode(FOOGOD_HINT);        
+
+       sc.selector = SelectSuperGeneric;
+       sc.selection = NULL;
+       kh.fx = scroller;
+       kh.data = &sc;
+
+       eventPushKeyHandler(&kh);
+       cmdwin_push("<select>");
+       eventHandle();
+       cmdwin_pop();
+       eventPopKeyHandler();
+
+        foogodSetMode(FOOGOD_DEFAULT);
+        return sc.selection;
+}
+
+
+/* Do common front-end processing. Migrate all commands to start using this. */
+static class Character *cmd_front_end(class Character *pc, const char *cmdstr)
+{
+        cmdwin_clear();
+        cmdwin_spush(cmdstr);
+
+        /* prompt user? */
+        if (!pc) {
+
+                /* only one choice? */
+                if (player_party->get_num_living_members() == 1) {
+                        pc = player_party->get_first_living_member();
+                        cmdwin_spush(pc->getName());
+                } else {
+                        pc = select_party_member();
+                }
+
+        } else {
+                cmdwin_spush(pc->getName());
+        }
+
+        /* user abort? */
+        if (!pc) {
+                return 0;
+        }
+
+        /* dead actor? */
+        if (pc->isDead()) {
+                log_msg("%s - %s is too dead!", cmdstr, pc->getName());
+                cmdwin_push("can't!");
+                return 0;
+        }
+
+        /* sleeping actor? */
+        if (pc->isAsleep()) {
+                log_msg("%s - %s rolls over and snores!", cmdstr, 
+                        pc->getName());
+                cmdwin_push("can't!");
+                return 0;
+        }
+
+        /* tell status who the actor is (sometimes it matters) */
+        statusSelectCharacter(pc->getOrder());
+
+        return pc;
+}
+
+static void cmd_add_skill_set(struct node *head, class Character *pc, 
+                              struct skill_set *skset)
+{
+        struct list *elem;
+        int pclvl = pc->getLevel();
+
+        /* for each skill in the skill set */
+        list_for_each(&skset->skills, elem) {
+
+                struct skill_set_entry *ssent;
+                struct node *node;
+                ssent = list_entry(elem, struct skill_set_entry, list);
+
+                /* is it a passive skill? */
+                if (ssent->skill->passive) {
+                        continue;
+                }
+
+                /* is the character is of sufficient level? */
+                if (pclvl < ssent->level) {
+                        continue;
+                }
+
+                /* add it to the list */
+                node = node_new(ssent);
+                node_add_tail(head, node);
+        }
+}
+
+static void cmd_build_skill_list(struct node *head, class Character *pc)
+{
+        node_init(head);
+
+        /* add species skills */
+        if (pc->species
+            && pc->species->skills) {
+                cmd_add_skill_set(head, pc, pc->species->skills);
+        }
+
+        /* add occupation skills */
+        if (pc->occ
+            && pc->occ->skills) {
+                cmd_add_skill_set(head, pc, pc->occ->skills);
+        }
+
+        /* add bonus skills? */
+}
+
+static int cmd_paint_skill(struct stat_super_generic_data *self, 
+                            struct node *node, 
+                            SDL_Rect *rect)
+{
+        struct skill_set_entry *ssent = (struct skill_set_entry *)node->ptr;
+        struct skill *skill = ssent->skill;
+        const char *requires = "Requires:";
+        struct node *tnode;
+        struct list *elem;
+        SDL_Rect orect;
+        int complete = 0;
+
+        /* remember original rect */
+        orect = *rect;
+
+        /* name */
+        if (rect->h < ASCII_H) {
+                return -1;
+        }
+        screenPrint(rect, 0, "^c+m%s^c-", skill->name);
+
+        /* level, ap, mp */
+        screenPrint(rect, SP_RIGHTJUSTIFIED, 
+                    "^c+GLvl:^c+y%d^c- MP:^c+b%d^c- AP:^c+r%d^c-^c-",
+                    ssent->level, 
+                    skill->mp, 
+                    skill->ap);
+        rect->y += ASCII_H;
+        rect->h -= ASCII_H;
+
+        /* check for required items */
+        if (! node_list_empty(&skill->tools)
+            || ! list_empty(&skill->materials)) {
+
+                if (rect->h < ASCII_H) {
+                        complete = -1;
+                } else {
+
+                        /* print "requires:" */
+                        screenPrint(rect, 0, " ^c+G%s^c-", requires);
+                        
+                        /* temporarily change x to print to right of "requires" */
+                        rect->x += (strlen(requires) + 1) * ASCII_W;
+                        
+                        /* list tools */
+                        node_for_each(&skill->tools, tnode) {
+
+                                if (rect->h < ASCII_H) {
+                                        complete = -1;
+                                        break;
+                                }
+
+                                class ObjectType *tool = (class ObjectType*)tnode->ptr;
+                                struct inv_entry *ie=player_party->inventory->
+                                        search(tool);
+                                char tool_clr=(ie&&ie->count)?'g':'r';
+                                screenPrint(rect, 0, "^c+%c%s^c-", tool_clr, 
+                                            tool->getName());
+
+                                rect->y += ASCII_H;
+                                rect->h -= ASCII_H;
+                        }
+
+                        /* list materials */
+                        list_for_each(&skill->materials, elem) {
+
+                                if (rect->h < ASCII_H) {
+                                        complete = -1;
+                                        break;
+                                }
+
+                                struct skill_material *mat =
+                                        list_entry(elem, struct skill_material, list);
+                                class ObjectType *objtype = 
+                                        (class ObjectType*)mat->objtype;
+                                struct inv_entry *ie=player_party->inventory->
+                                        search(objtype);
+                                char mat_clr=ie?'g':'r';
+                                char q_clr=(ie&&(ie->count>=mat->quantity))?'g':'r';
+                                screenPrint(rect, 0, "^c+%c%s^c+%c (%d/%d)^c-^c-", 
+                                            mat_clr,
+                                            objtype->getName(), 
+                                            q_clr,
+                                            mat->quantity,
+                                            ie?ie->count:0);
+
+                                rect->y += ASCII_H;
+                                rect->h -= ASCII_H;
+                        }
+
+                        /* restore rect x */
+                        rect->x = orect.x;
+                }
+        }
+        
+        /* figure out how much area we used */
+        orect.h = rect->y - orect.y;
+
+        /* if this is not the currently selected item then shade it */
+        if (self->selected != node) {
+                screenShade(&orect, 128);
+        }
+
+        return complete;
+}
+
+static void cmd_skill_list_unref(struct stat_super_generic_data *self)
+{
+        struct node *node;
+
+        /* Decrement the refcount. */
+        assert(self->refcount > 0);
+        self->refcount--;
+        if (self->refcount > 0) {
+                return;
+        }
+
+        /* Cleanup if no more refs. */
+        node = node_next(&self->list);
+        while (node != &self->list) {
+                struct node *tmp = node;
+                node = node_next(node);
+                node_unref(tmp);
+        }
+}
+
+static struct skill_set_entry *cmd_select_skill(class Character *pc)
+{
+        struct skill_set_entry *ssent;
+        struct node *selected;
+        struct stat_super_generic_data data;
+
+        /* setup the status browser data */
+        memset(&data, 0, sizeof(data));
+        cmd_build_skill_list(&data.list, pc);
+        data.title = "Yuse";
+        data.paint = cmd_paint_skill;
+        data.unref = cmd_skill_list_unref;
+
+        /* put the status browser in selection mode */
+        statusSetSuperGenericData(&data);
+        statusPushMode(SuperGeneric);
+
+        /* wait for user selection */
+        selected = (struct node*)cmd_select_generic();
+
+        /* extract result */
+        if (selected) {
+                ssent = (struct skill_set_entry *)selected->ptr;
+                cmdwin_push(ssent->skill->name);
+        } else {
+                ssent = 0;
+                cmdwin_push("none");
+        }
+
+        /* restore browser status mode */
+        statusPopMode();
+
+        assert(! data.refcount);
+
+        return ssent;
+}
+
+void cmdYuse(class Character *actor)
+{
+        struct skill_set_entry *ssent;
+        struct skill *skill;
+        int cant = 0, result = 0, yused = 0;
+
+        /* select/verify the actor */
+        if (!(actor = cmd_front_end(actor, "Yuse"))) {
+                return;
+        }
+
+        /* select the skill to yuse */
+        if (!(ssent = cmd_select_skill(actor))) {
+                return;
+        }
+        skill = ssent->skill;
+        log_begin("%s: %s - ", actor->getName(), skill->name);
+
+        /* check wilderness */
+        if (! skill->wilderness_ok
+            && place_is_wilderness(actor->getPlace())) {
+                cant = 1;
+                log_msg("Not in the wilderness!");
+        }
+
+        /* check level */
+        if (actor->getLevel() < ssent->level) {
+                cant = 1;
+                log_msg("Must be level %d!", ssent->level);
+        }
+
+        /* check mana */
+        if (actor->getMana() < skill->mp) {
+                cant = 1;
+                log_msg("Not enough mana!");
+        }
+
+        /* check tools */
+        if (!node_list_empty(&skill->tools)) {
+                struct node *tnode;
+                node_for_each(&skill->tools, tnode) {
+                        class ObjectType *tool = (class ObjectType*)tnode->ptr;
+                        struct inv_entry *ie=player_party->inventory->
+                                search(tool);
+                        if (!ie || !ie->count) {
+                                log_msg("Need %s!", tool->getName());
+                                cant = 1;
+                        }
+                }
+
+        }
+
+        /* check material */
+        if (! list_empty(&skill->materials)) {
+                struct list *elem;
+                struct skill_material *mat;
+                class ObjectType *objtype;
+                struct inv_entry *ie;
+                list_for_each(&skill->materials, elem) {
+                        mat = list_entry(elem, struct skill_material, list);
+                        objtype = (class ObjectType*)mat->objtype;
+                        ie = player_party->inventory->search(objtype);
+                        if (!ie || ie->count < mat->quantity) {
+                                cant = 1;
+                                log_msg("Need %d %s!", mat->quantity, 
+                                        objtype->getName());
+                        }
+                }
+        }
+
+        /* check special */
+        if (skill->can_yuse
+            && ! closure_exec(skill->can_yuse, "p", actor)) {
+                cant = 1;
+        }
+
+        /* cant? */
+        if (cant) {
+                cmdwin_push("failed!");
+                log_end("^c+rFailed!^c-");
+                return;
+        }
+
+        /* yuse the skill */
+        result = closure_exec(skill->yuse, "p", actor);
+        yused = cmd_eval_and_log_result(result);
+        
+        /* change ap/mp/xp and consume materials */
+        if (yused) {
+                actor->runHook(OBJ_HOOK_YUSE_DONE, 0);
+                actor->addMana(0 - skill->mp);
+                actor->decActionPoints(skill->ap);
+                actor->addExperience(ssent->level);
+
+                if (! list_empty(&skill->materials)) {
+                        struct list *elem;
+                        struct skill_material *mat;
+                        list_for_each(&skill->materials, elem) {
+                                mat = list_entry(elem, struct skill_material, 
+                                                 list);
+                                player_party->takeOut((class ObjectType*)
+                                                      mat->objtype, 
+                                                      mat->quantity);
+                        }
+                }
+        }       
+
+        log_end(0);
+}
+#endif /* USE_SKILLS */
+
+bool cmdSetSoloMode(int party_member_index)
+{
+    class Character *solo_member = player_party->getMemberAtIndex(party_member_index);
+    if (solo_member
+        && ! solo_member->isIncapacitated() 
+        && solo_member->isOnMap()
+        && solo_member->isPlayerControlled()
+        ) {
+
+        if (solo_member->engagedInTask()) {            
+            log_msg("%s is engaged in %s, abort?", solo_member->getName(), solo_member->getTaskName());
+            if (! ui_get_yes_no(solo_member->getName())) {
+                return false;
+            }
+        }
+
+        player_party->enableSoloMode(solo_member);
+        return true;
+    }
+    return false;
+}
+
+bool cmdToggleFollowMode(void)
+{
+    log_begin("Follow mode ");
+    if (player_party->getPartyControlMode() == PARTY_CONTROL_FOLLOW) {
+        log_end("OFF");
+        player_party->enableRoundRobinMode();
+        return false;
+    } else {
+        log_end("ON");
+        player_party->enableFollowMode();
+        return true;
+    }   
+}
+
diff --git a/src/cmd.h b/src/cmd.h
new file mode 100644 (file)
index 0000000..e3ce7cc
--- /dev/null
+++ b/src/cmd.h
@@ -0,0 +1,211 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef cmd_h
+#define cmd_h
+
+#include "macros.h"
+#include "event.h" /* for v_funcpointer_ii */
+
+#define MIN_XAMINE_LIGHT_LEVEL 32
+
+class Character;
+class Object;
+class Party;
+
+BEGIN_DECL;
+
+// I really shouldn't pollute this interface with these, but they don't really
+// fit anywhere else right now, either.
+#include "status.h"
+struct ScrollerContext {
+        enum StatusSelection selector;
+        const void *selection;
+        bool abort;
+        bool done;
+        bool mixing; // for mix reagents
+};
+
+/**
+ * Request format for select_target_generic().
+ */
+typedef struct ui_select_target_req 
+{
+        struct place *place;   /* place this is happening in       */
+        int x1, y1;            /* center of target zone            */
+        int x2, y2;            /* initial/final cursor position    */
+        struct templ *tiles;   /* template of tiles in target zone */
+        struct list suggest;   /* quick-target tiles               */
+        void *data;            /* caller context                   */
+
+        /* called when the cursor moves over a new tile */
+        void (*move)(struct place *, int, int, void *);
+
+        /* Called when user hits 'enter' or otherwise selects a tile. Returns
+         * non-zero to end the targeting session, zero otherwise. */
+        int (*select)(struct place *, int, int, void *);
+
+} ui_select_target_req_t;
+
+#define SCROLLER_HINT "\005\006=scroll ENT=select ESC=exit"
+#define PAGER_HINT  "\005\006=scroll ESC=exit"
+
+extern int dirkey(struct KeyHandler *kh, int key, int keymod);
+extern int cardinaldirkey(struct KeyHandler *kh, int key, int keymod);
+extern int yesnokey(struct KeyHandler *kh, int key, int keymod);
+extern int anykey(struct KeyHandler *kh, int key, int keymod);
+extern int scroller(struct KeyHandler *kh, int key, int keymod);
+extern int movecursor(struct KeyHandler *kh, int key, int keymod);
+extern int getnum(struct KeyHandler *kh, int key, int keymod);
+extern void getkey(void *data, int(*handler) (struct KeyHandler * kh,
+                                               int key, int keymod));
+#define CMD_SELECT_MEMBER (1 << 0)
+#define CMD_PRINT_MEMBER  (1 << 1)
+  
+extern void cmdAttack(void);
+extern int cmd_camp_in_town(class Character *camper);
+extern int cmd_camp_in_wilderness(class Party *camper);
+extern void cmdFire(void);
+extern void cmdHelp(void);
+extern void cmdLoiter(class Being *subject);
+extern bool cmdMixReagents(class Character *mixer);
+extern void cmdNewOrder(void);
+extern bool cmdSave(void);
+extern void cmdReload(void);
+extern bool cmdSearch(class Character *pc);
+extern void cmdTalk(Object *member);
+extern void cmdZoomIn(void);
+extern bool cmdUse(class Character * pc, int flags);
+extern bool cmdHandle(class Character * pc);
+extern bool cmdReady(class Character * pc);
+extern bool cmdZtats(class Character * pc);
+extern bool cmdXamine (class Object *examiner);
+extern bool cmdAT(class Character * pc);
+extern bool cmdGet(class Object *actor);
+extern bool cmdOpen(class Character * pc);
+extern bool cmdCastSpell(class Character * pc);
+extern bool cmdQuit(void);
+extern bool cmdLook(int x, int y);
+extern bool cmd_terraform(struct place *place, int x, int y);
+extern bool cmd_save_current_place (struct place * place);
+extern bool cmdSaveTerrainMap(class Character * pc);
+extern bool cmdSetSoloMode(int party_member_index);
+extern bool cmdToggleFollowMode(void);
+extern void cmdSettings(void);
+extern void cmdDrop(class Character *pc);
+extern void cmdYuse(class Character *pc);
+extern void cmdDeveloperEval(struct session *);
+  
+extern class Character *select_party_member(void);
+    
+struct location_list {
+        struct list list;
+        int x;
+        int y;
+};
+
+extern int select_target(int ox, int oy, int *x, int *y, int range, 
+                         struct list *suggest);
+
+extern const char * name_of_context (void);
+
+extern int ui_get_quantity(int max);
+  
+// the new ui api
+extern int ui_get_direction(void);
+extern int ui_get_yes_no(const char *asked_persons_name);
+extern int ui_getline(char *buf, int len);
+extern int ui_getline_plain(char *buf, int len);
+extern void ui_name_vehicle(class Vehicle *vehicle);
+
+/**
+ * The merchant information for a trading session.
+ */
+struct merchant {
+        const char *name;                /* The merchant's name */
+        int n_trades;              /* Num entries in the array of items */
+        struct trade_info *trades; /* The array of trade items */
+};
+
+/**
+ * These three functions all engage in the trading UI with a merchant. ui_trade
+ * will allow the player to choose between buying and selling, and will call
+ * the other two functions.
+ *
+ * @param merch is the merchant info
+ * @returns the quantity of items traded
+ */
+extern int ui_trade(struct merchant *merch);
+extern int ui_buy(struct merchant *merch);
+extern int ui_sell(struct merchant *merch);
+
+/**
+ * Prompt the player to enter a line. By default (no filter provided) this will
+ * accept all printable characters as valid input from the player. Especially
+ * the ESC, '\n' and '\b' characters are taken to mean control characters and
+ * aren't considered printable.
+ *
+ * @param buf The string buffer to fill with the response. On success this
+ * contains a null-terminated string. The NULL will be there, and the buffer
+ * length will not be exceeded. The user reply will be truncated if necessary.
+ *
+ * @param len The length of buf.
+ *
+ * @param filter An optional filter function. This function should return
+ * non-zero to reject a key. Note that all non-printable characters are already
+ * filtered automatically; this param let's you filter even more. The filter is
+ * applied after checking for ESC, '\n' and '\b', which are processed as
+ * control characters and never appear in the result anyway.
+ *
+ * @returns The actual number of characters stored. Note that if the player
+ * hits ESC this will be zero as if no keys were pressed.
+ */
+extern int ui_getline_filtered(char *buf, int len, int (*filter)(int key));
+
+/**
+ * More general version of select_target(). Prompts the player to select a tile
+ * within a range or template of tiles.
+ *
+ * @parm req tells the function how to carry out its business.
+ *
+ * @returns zero iff the (x2, y2) fields of the req hold the player-selected
+ * target location. The only time it won't is if the player aborts the prompt.
+ */
+extern int ui_select_target_generic(ui_select_target_req_t *req);
+
+/**
+ * Initialize a target request to safe defaults. Note that this is for a new
+ * request, if you try to re-init without doing some manual cleanup first
+ * you'll get a memory leak.
+ *
+ * @parm req will be initialized.
+ */
+extern void ui_select_target_req_init(ui_select_target_req_t *req);
+
+/**
+ * Prompt the player to select something from inventory. This assumes that the
+ * status mode has already been set by the caller.
+ */
+extern struct inv_entry *ui_select_item(void);
+
+END_DECL;
+
+#endif
diff --git a/src/cmdwin.c b/src/cmdwin.c
new file mode 100644 (file)
index 0000000..118549f
--- /dev/null
@@ -0,0 +1,300 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "cmdwin.h"
+
+#include "cfg.h"
+#include "common.h"
+#include "console.h"
+#include "dimensions.h"
+#include "images.h"
+#include "log.h"
+#include "screen.h"
+#include "sprite.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#define CMDWIN_FRAG_MAX_LEN 64
+#define CMDWIN_BUF_SZ       256
+
+/* Fragment flags */
+#define CMDWIN_FRAG_SEP     (1<<0)
+#define CMDWIN_FRAG_MARK    (1<<1)
+
+struct cmdwin_frag {
+        struct list list;
+        int flags;
+        char buf[CMDWIN_FRAG_MAX_LEN];
+};
+
+static struct {
+       SDL_Rect srect; /* screen rectangle (pixels) */
+       char *buf;      /* string buffer */
+       char *ptr;      /* next empty spot in buffer */
+       int blen;       /* buffer length, this should be bigger than slen and
+                         * is the max expected total size of any prompt (the
+                         * longest prompts may be too big for the window) */
+       int room;       /* empty space in buffer */
+        int slen;       /* printable string length (blen >= slen), this is
+                         * limited by the cmdwin UI size */
+        struct sprite *cursor_sprite;
+        struct list frags;
+} cmdwin;
+
+#ifdef DEBUG
+static FILE *log = NULL;
+#endif
+
+static inline void cmdwin_clear_no_repaint()
+{
+       memset(cmdwin.buf, 0, cmdwin.blen);
+       cmdwin.ptr = cmdwin.buf;
+       cmdwin.room = cmdwin.blen;
+}
+
+static void cmdwin_cursor_sprite_init()
+{
+        char *fname = cfg_get("cursor-image-filename");
+        struct images *ss_cursor = 0;
+
+        assert(fname);
+        ss_cursor = images_new(0, 8, 16, 1, 4, 0, 0, fname);
+        assert(ss_cursor);
+        cmdwin.cursor_sprite = sprite_new(0, 4, 0, 0, 0, ss_cursor);
+        assert(cmdwin.cursor_sprite);
+}
+
+static void cmdwin_clear_frag_stack(void)
+{
+        struct list *entry;
+        
+        entry = cmdwin.frags.next;
+        while (entry != &cmdwin.frags) {
+                struct cmdwin_frag *frag = (struct cmdwin_frag*)entry;
+                entry = entry->next;
+                list_remove(&frag->list);
+                free(frag);
+        }
+}
+
+static struct cmdwin_frag *cmdwin_top()
+{
+        if (list_empty(&cmdwin.frags))
+                return 0;
+        return (struct cmdwin_frag*)cmdwin.frags.prev;
+}
+
+static void cmdwin_reprint_buffer(void)
+{
+        struct list *entry;
+
+        /* Erase the buffer */
+        cmdwin_clear_no_repaint();
+
+        /* Loop over the fragments until out of room or out of fragments */
+        list_for_each(&cmdwin.frags, entry) {
+                struct cmdwin_frag *frag = (struct cmdwin_frag*)entry;
+                int n = 0;
+
+                /* Append the fragment to the buffer. */
+                if ((frag->flags & CMDWIN_FRAG_SEP)
+                    && (entry->next != &cmdwin.frags)) {
+                        /* Print a '-' after this fragment. */
+                        n = snprintf(cmdwin.ptr, cmdwin.room, "%s-", frag->buf);
+                } else {
+                        /* No '-' afterwards. */
+                        n = snprintf(cmdwin.ptr, cmdwin.room, "%s", frag->buf);
+                }
+                n = min(n, cmdwin.room);
+                cmdwin.room -= n;
+                cmdwin.ptr += n;
+
+                /* If out of room then stop, and backup the ptr to the last
+                 * entry in the buffer */
+                if (!cmdwin.room) {
+                        cmdwin.ptr--;
+                        break;
+                }
+
+        }
+}
+
+int cmdwin_init(void)
+{
+        cmdwin_cursor_sprite_init();
+
+        list_init(&cmdwin.frags);
+
+       cmdwin.srect.x = CMD_X;
+       cmdwin.srect.y = CMD_Y;
+       cmdwin.srect.w = CMD_W;
+       cmdwin.srect.h = CMD_H;
+       cmdwin.slen = (CMD_W / ASCII_W) - 1; /* leave one space for the
+                                              * cursor */
+        cmdwin.blen = CMDWIN_BUF_SZ;
+        assert(cmdwin.blen >= cmdwin.slen);
+
+       cmdwin.buf = (char *) malloc(cmdwin.blen);
+       if (!cmdwin.buf)
+               return -1;
+
+#ifdef DEBUG
+       log = fopen(".cmdwin", "w+");
+       if (!log) {
+               err(strerror(errno));
+               return -1;
+       }
+#endif
+
+        cmdwin_clear_no_repaint();
+       return 0;
+}
+
+static void cmdwin_vpush(int flags, const char *fmt, va_list args)
+{
+        /* Allocate a new fragment */
+        struct cmdwin_frag *frag = (struct cmdwin_frag*)malloc(sizeof(*frag));
+        if (!frag) {
+                warn("allocation failed");
+                return;
+        }
+
+        frag->flags = flags;
+
+        /* default to empty string */
+        frag->buf[0] = 0;
+
+        /* Store the string in the fragment */
+        if (fmt != NULL) {
+                vsnprintf(frag->buf, sizeof(frag->buf), fmt, args);
+        }
+
+        /* Push the fragment onto the stack */
+        list_add_tail(&cmdwin.frags, &frag->list);
+
+        /* Reprint the buffer with the new fragment */
+        cmdwin_reprint_buffer();
+
+        /* Update the display */
+       cmdwin_repaint();        
+}
+
+void cmdwin_spush(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+        cmdwin_vpush(CMDWIN_FRAG_SEP, fmt, args);
+       va_end(args);
+        
+}
+
+void cmdwin_push(const char *fmt, ...)
+{
+       va_list args;
+
+       va_start(args, fmt);
+        cmdwin_vpush(0, fmt, args);
+       va_end(args);
+}
+
+void cmdwin_push_mark()
+{
+        cmdwin_vpush(CMDWIN_FRAG_MARK, 0, 0);
+}
+
+void cmdwin_pop(void)
+{
+        struct cmdwin_frag *frag;
+
+        /* Fragment stack should not be empty. */
+        assert(! list_empty(&cmdwin.frags));
+
+        /* Remove the last fragment and free it. */
+        frag = (struct cmdwin_frag*)cmdwin.frags.prev;
+        list_remove(&frag->list);
+        free(frag);
+
+        /* Reprint the buffer without the fragment */
+        cmdwin_reprint_buffer();
+
+        /* Update the display */
+       cmdwin_repaint();
+}
+
+void cmdwin_pop_to_mark()
+{
+        struct cmdwin_frag *frag = cmdwin_top();
+        while (frag && frag->flags != CMDWIN_FRAG_MARK) {
+                cmdwin_pop();
+                frag = cmdwin_top();
+        }
+
+        /* DON'T pop the mark itself */
+}
+
+void cmdwin_clear(void)
+{
+        cmdwin_clear_frag_stack();
+        cmdwin_clear_no_repaint();
+        cmdwin_repaint();
+}
+
+void cmdwin_repaint_cursor(void)
+{
+       SDL_Rect rect;
+
+       rect.x = cmdwin.srect.x;
+       rect.y = cmdwin.srect.y;
+       rect.w = ASCII_W;
+       rect.h = ASCII_H;
+
+        /* If the string is too big, show the last part of it (in other words,
+         * right-justify it) */
+        char *start = max(cmdwin.buf, cmdwin.ptr - cmdwin.slen);
+       rect.x += (cmdwin.ptr - start) * ASCII_W;
+
+       sprite_paint(cmdwin.cursor_sprite, 0, rect.x, rect.y);
+       screenUpdate(&rect);
+}
+
+void cmdwin_repaint(void)
+{
+        /* If the string is too big, show the last part of it (in other words,
+         * right-justify it) */
+        char *start = max(cmdwin.buf, cmdwin.ptr - cmdwin.slen);
+       screenErase(&cmdwin.srect);
+       screenPrint(&cmdwin.srect, 0, start);
+       screenUpdate(&cmdwin.srect);
+       cmdwin_repaint_cursor();
+}
+
+void cmdwin_flush(void)
+{
+        if (!strlen(cmdwin.buf))
+                return;
+
+        log_msg("%s\n", cmdwin.buf);
+        cmdwin_clear();
+}
diff --git a/src/cmdwin.h b/src/cmdwin.h
new file mode 100644 (file)
index 0000000..27dec74
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef cmdwin_h
+#define cmdwin_h
+
+/* The command window is the little window below the map that displays all the
+ * command prompts. It's very interactive. The gist of the API is that
+ * multi-step commands that want to prompt the user will "push" a prompt, pop
+ * it and push the reply, push the next prompt, etc. */
+
+/* cmdwin_init -- startup init */
+extern int cmdwin_init(void);
+
+/* cmdwin_clear -- erase the contents */
+extern void cmdwin_clear(void);
+
+/* cmdwin_repaint_cursor -- repaint just the cursor prompt (used to animate the
+ * cursor sprite) */
+extern void cmdwin_repaint_cursor(void);
+
+/* cmdwin_repaint -- repaint the cmdwin window (cmdwin_push and _spush do this
+ * automatically, so this is rarely necessary) */
+extern void cmdwin_repaint(void);
+
+/* cmdwin_flush -- write the contents of the cmdwin to the console */
+extern void cmdwin_flush(void);
+
+/* cmdwin_push -- append a string to the cmdwin prompt (this can be undone with
+ * cmdwin_pop). Works just like printf for string formatting. */
+extern void cmdwin_push(const char *fmt, ...);
+
+/* cmdwin_spush -- same as push, but print a '-' after it if anything else is
+ * pushed (the 's' is for 'segment', you're pushing a prompt segment) */
+extern void cmdwin_spush(const char *fmt, ...);
+
+/* cmdwin_pop -- remove a string appended by one of the push commands */
+extern void cmdwin_pop(void);
+
+/* cmdwin_push_mark -- a mark is invisible, but when pop_to_mark is called any
+ * string appended after the last mark is popped. */
+extern void cmdwin_push_mark();
+
+/* cmdwin_pop_to_mark -- pop all strings appended since the last mark. This
+ * does not pop the mark itself (use cmdwin_pop for that). */
+extern void cmdwin_pop_to_mark();
+
+#endif
diff --git a/src/combat.c b/src/combat.c
new file mode 100644 (file)
index 0000000..d2ee791
--- /dev/null
@@ -0,0 +1,1814 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "combat.h"
+#include "dice.h"
+#include "node.h"
+#include "Party.h"
+#include "place.h"
+#include "player.h"
+#include "object.h"
+#include "common.h"
+#include "map.h"
+#include "hash.h"
+#include "wq.h"
+#include "sound.h"
+#include "status.h"
+#include "cursor.h"
+#include "Container.h"
+#include "terrain.h"
+#include "Field.h"
+#include "event.h"
+#include "play.h"
+#include "foogod.h"
+#include "wind.h"
+#include "dup_constants.h"
+#include "cmdwin.h"
+#include "terrain_map.h"
+#include "vehicle.h"
+#include "formation.h"
+#include "pinfo.h"
+#include "cmd.h"
+#include "formation.h"
+#include "session.h"
+#include "log.h"
+#include "vmask.h"
+#include "factions.h"
+#include "blender.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <time.h>
+#include <unistd.h>
+#include <math.h>
+
+#define FORMATION_H     (formation[array_sz(formation) - 1].y)
+#define N_MAX_NPCS      256      /* arbitrary limit */
+#define MAX_DEPTH       64
+#define MAX_PLACEMENT_RECTANGLE_W 32
+#define MAX_PLACEMENT_RECTANGLE_H 16
+#define SEARCH_QUEUE_SZ 100
+
+/* Formation pattern -- party facing north (dx=0,dy=-1), origin at the leader's
+ * position */
+
+enum combat_faction_status {
+        COMBAT_FACTION_EXISTS,
+        COMBAT_FACTION_GONE,
+        COMBAT_FACTION_CHARMED,
+        COMBAT_FACTION_CAMPING
+};
+
+static struct {
+        struct place *place;
+        void *session_handle;
+        enum combat_state state;
+        char vmap[7 * 7];       // visited map (used to search for positions)
+        class Vehicle *enemy_vehicle;
+        sound_t *sound_enter;
+        sound_t *sound_defeat;
+        sound_t *sound_victory;
+        int round;
+} Combat;
+
+struct v2 {
+        struct place *place;
+        int dx, dy;
+};
+
+// Search alg data
+static char rmap[MAX_PLACEMENT_RECTANGLE_W * MAX_PLACEMENT_RECTANGLE_H];
+static int x_q[SEARCH_QUEUE_SZ];
+static int y_q[SEARCH_QUEUE_SZ];
+static int q_head;
+static int q_tail;
+
+enum combat_state combat_get_state(void)
+{
+        return Combat.state;
+}
+
+void combat_set_state(enum combat_state new_state)
+{
+        // --------------------------------------------------------------------
+        // Interesting state transitions:
+        //
+        // ====================================================================
+        // old state              | new state              | result
+        // ====================================================================
+        // COMBAT_STATE_DONE      | COMBAT_STATE_FIGHTING  | entry to combat
+        // COMBAT_STATE_DONE      | COMBAT_STATE_LOOTING   | non-hostile
+        // COMBAT_STATE_DONE      | COMBAT_STATE_CAMPING   | entry to camping
+        // COMBAT_STATE_FIGHTING  | COMBAT_STATE_DONE      | defeat
+        // COMBAT_STATE_FIGHTING  | COMBAT_STATE_LOOTING   | victory
+        // COMBAT_STATE_LOOTING   | COMBAT_STATE_FIGHTING  | hostiles entered
+        // COMBAT_STATE_LOOTING   | COMBAT_STATE_DONE      | exit normally
+        // COMBAT_STATE_CAMPING   | COMBAT_STATE_FIGHTING  | ambush
+        // COMBAT_STATE_CAMPING   | COMBAT_STATE_DONE      | exit camping
+        // ====================================================================
+        //
+        // --------------------------------------------------------------------
+
+        if (Combat.state == new_state)
+                return;
+
+
+        switch (Combat.state) {
+
+        case COMBAT_STATE_DONE:
+                switch (new_state) {
+                case COMBAT_STATE_FIGHTING:
+                        log_banner("^c+mCOMBAT^c-");
+                        sound_play(Combat.sound_enter, SOUND_MAX_VOLUME);
+                        break;
+                case COMBAT_STATE_LOOTING:
+                        break;
+                case COMBAT_STATE_CAMPING:
+                        log_banner("CAMPING");
+                        break;
+                default:
+                        assert(false);
+                        break;
+                }
+                break;
+
+        case COMBAT_STATE_FIGHTING:
+                switch (new_state) {
+                case COMBAT_STATE_LOOTING:
+                        log_banner("^c+gVICTORY^c-");
+                        sound_play(Combat.sound_victory, SOUND_MAX_VOLUME);
+                        player_party->addExperience(COMBAT_VICTORY_XP);
+                        break;
+                case COMBAT_STATE_DONE:
+                        log_banner("^c+rDEFEAT^c-");
+                        sound_play(Combat.sound_defeat, SOUND_MAX_VOLUME);
+                        break;
+                default:
+                        assert(false);
+                        break;
+                }
+                break;
+
+        case COMBAT_STATE_LOOTING:
+                switch (new_state) {
+                case COMBAT_STATE_FIGHTING:
+                        log_banner("^c+mCOMBAT^c-");
+                        sound_play(Combat.sound_enter, SOUND_MAX_VOLUME);
+                        break;
+                case COMBAT_STATE_DONE:
+                        break;
+                default:
+                        assert(false);
+                        break;
+                }
+                break;
+
+        case COMBAT_STATE_CAMPING:
+                switch (new_state) {
+                case COMBAT_STATE_FIGHTING:
+                        log_banner("^c+mCOMBAT^c-");
+                        sound_play(Combat.sound_enter, SOUND_MAX_VOLUME);
+                        break;
+                case COMBAT_STATE_LOOTING:
+                case COMBAT_STATE_DONE:
+                        break;
+                default:
+                        assert(false);
+                        break;
+                }
+                break;
+
+        default:
+                assert(false);
+                break;
+        }
+
+        Combat.state = new_state;
+        session_run_hook(Session, combat_change_hook, "p", Session->player);
+}
+
+// returns 0 for ok position, -1 for no position, or a PFLAG type for fallback positions with problems
+// input includes current best case problemness
+static int location_is_safe(struct position_info *info, int current)
+{
+        struct astar_node *path;
+        struct astar_search_info as_info;
+        struct terrain *terrain;
+        int returntype=0;
+
+        // Is it passable?
+        if (!place_is_passable(info->place, info->px, info->py, 
+                               info->subject, 0)) {
+                dbg("impassable\n");
+                return -1;
+        }
+        // Is it occupied?
+        if (place_is_occupied(info->place, info->px, info->py)) {
+                dbg("occupied\n");
+                returntype= PFLAG_IGNOREBEINGS;
+                if (current & (PFLAG_IGNOREHAZARDS || PFLAG_IGNOREBEINGS || PFLAG_IGNOREFIELDS))
+                       return -1;
+        }
+
+        // I added the next two checks because a character was getting
+        // positioned over the firepit while camping, and I thought it was
+        // damaging him. Turns out firepits weren't setup to cause fire damage
+        // (oddly), and the character was just starving. I'll leave this here
+        // for now anyway.
+
+        // Is it dangerous? Hack: check for a field and dangerous terrain
+        if (place_get_object(info->place, info->px, info->py, field_layer)) {
+                dbg("possibly dangerous field\n");
+                returntype= PFLAG_IGNOREFIELDS;
+                if (current & (PFLAG_IGNOREHAZARDS || PFLAG_IGNOREFIELDS))
+                       return -1;
+        }
+        terrain = place_get_terrain(info->place, info->px, info->py);
+        if (terrain->effect) {
+                dbg("possibly dangerous terrain\n");
+                returntype= PFLAG_IGNOREHAZARDS;
+                if (current & (PFLAG_IGNOREHAZARDS ))
+                       return -1;
+        }
+
+        memset(&as_info, 0, sizeof (as_info));
+        if (info->find_party) {
+                // Each member should be able to find a path back to the
+                // party's originating location on the map.
+                dbg("searching for path to party [%d %d]...",
+                       info->x, info->y);
+
+                as_info.x0 = info->px;
+                as_info.y0 = info->py;
+                as_info.x1 = info->x;
+                as_info.y1 = info->y;
+                as_info.flags = PFLAG_IGNOREBEINGS;
+                as_info.limit_depth = true;
+                as_info.max_depth = 5;
+
+                path = place_find_path(info->place, &as_info, info->subject);
+
+                if (!path)
+                        dbg("no path back to party\n");
+        }
+        else {
+                // skip the pathfinding check
+                return returntype;
+        }
+
+        if (path) {
+                astar_path_destroy(path);
+                return returntype;
+        }
+
+        return -1;
+}
+
+// returns 0 for ok position, -1 for no position, or a PFLAG type for fallback positions with problems
+// input includes current best case problemness
+static int combat_search_for_safe_position(struct position_info *info, int currentsafety)
+{
+        unsigned int i;
+        int index;
+        static int x_offsets[] = { -1, 1, 0, 0 };
+        static int y_offsets[] = { 0, 0, -1, 1 };
+        int locationsafety=-1;
+
+        dbg("checking [%d %d]...", info->px, info->py);
+
+        // translate the map coords into an rmap index
+        index = info->py - info->ry;
+        index *= info->rw;
+        index += (info->px - info->rx);
+
+        // If the current location is off-map, outside of the placement
+        // rectangle or already visited then discontinue the search.  
+        if (rmap[index]) {
+                dbg("already visited [%d]\n", index);
+                return -1;      // already visited
+        }
+        if (info->px < info->rx || info->px >= info->rx + info->rw ||
+            info->py < info->ry || info->py >= info->ry + info->rh) {
+                dbg("outside the placement area\n");
+                return -1;      // outside the placement rect
+        }
+        if (place_off_map(info->place, info->px, info->py)) {
+                dbg("off-map\n");
+                // return -1; // off map
+                goto enqueue_neighbors;
+        }
+        // Mark this location as visited.
+        rmap[index] = 1;
+
+        // If the current location is safe then the search succeeded.
+        locationsafety = location_is_safe(info,currentsafety);
+        if (locationsafety == 0) {
+                dbg("OK!\n");
+                return 0;
+        }
+
+      enqueue_neighbors:
+        // Enqueue the adjacent neighbors onto the search queue.
+        for (i = 0; i < array_sz(x_offsets) && q_tail < SEARCH_QUEUE_SZ; i++) {
+                assert(q_tail < SEARCH_QUEUE_SZ);
+                x_q[q_tail] = info->px + x_offsets[i];
+                y_q[q_tail] = info->py + y_offsets[i];
+                q_tail++;
+        }
+
+        // Return still not found.
+        return locationsafety;
+}
+
+// returns 0 for ok position, -1 for no position, or a PFLAG type for fallback positions with problems
+static int combat_find_safe_position(struct position_info *info)
+{
+        // Here's my new definition of a safe place: a safe place is a tile
+        // within the placement rectangle which is passable to the character in
+        // question and from which the character in question can pathfind to
+        // the edge from which the party entered.
+
+         // store data on a fallback not-so-safe position
+         int currentsafety = 0;
+         int cur_x = 0, cur_y = 0;
+         int newsafety = -1;
+         
+        // Clear the search queue.
+        q_head = q_tail = 0;
+
+        // Push the preferred position onto the search queue.
+        x_q[q_tail] = info->px;
+        y_q[q_tail] = info->py;
+        q_tail++;
+
+        // Run through the search queue until it is exhausted or a safe
+        // position has been found.
+        while (q_head != q_tail) {
+
+                // Dequeue the next location to check.
+                info->px = x_q[q_head];
+                info->py = y_q[q_head];
+                q_head++;
+
+                // If it is ok then we're done.
+                newsafety = combat_search_for_safe_position(info, currentsafety);
+                if (newsafety == 0)
+                        return 0;
+                else if (newsafety != -1)
+                {
+                       currentsafety = newsafety;
+                       cur_x = info->px;
+                       cur_y = info->py;
+                }
+        }
+
+        if (currentsafety != 0)
+        {
+                info->px = cur_x;
+                info->py = cur_y;  
+                return currentsafety;
+        }
+        
+        return -1;
+}
+
+static bool myPutNpc(class Character * pm, void *data)
+{
+        int tmp;
+        struct position_info *info;
+
+
+        info = (struct position_info *) data;
+
+        if (pm->isDead())
+                return false;
+
+        // In the case where there is more than one NPC party entering combat
+        // this might be called more than once for an NPC. I want to ignore all
+        // but the first call, so check if the NPC is already on the map.
+        if (pm->isOnMap())
+                return false;
+
+        // Make sure we don't index beyond the end of the formation array.
+        if (pm->getOrder() >= info->formation->n)
+                return false;
+
+        pm->setCombat(true);
+
+        pm->setX(info->formation->entry[pm->getOrder()].x);
+        pm->setY(info->formation->entry[pm->getOrder()].y);
+
+        /* Counterclockwise rotations: x = x * cos - y * sin y = x * sin + y *
+         * cos */
+        if (info->dx < 0) {
+                /* Rotate +90 degrees */
+                tmp = pm->getX();
+                pm->setX(pm->getY());
+                pm->setY(tmp);
+        }
+        else if (info->dx > 0) {
+                /* Rotate -90 degrees */
+                tmp = pm->getX();
+                pm->setX(-pm->getY());
+                pm->setY(tmp);
+        }
+        else if (info->dy > 0) {
+                /* Rotate 180 degrees */
+                pm->setX(-pm->getX());
+                pm->setY(-pm->getY());
+        }
+
+        /* If dy > 1 then the formation is ok as-is. */
+        pm->changeX(info->x);
+        pm->changeY(info->y);
+
+        // Check if that location will really work. If not then do a DFS
+        // starting from the desired location and see if we can find someplace
+        // that WILL work.
+
+        // initialize the position info for a new search
+        info->subject = pm;
+        memset(rmap, 0, sizeof (rmap));
+
+        // set the preferred location
+        info->px = pm->getX();
+        info->py = pm->getY();
+
+        dbg("Placing %s\n", pm->getName());
+
+        if (combat_find_safe_position(info) == -1) {
+                // If I can't place a member then I can't place it.
+                dbg("*** Can't place %s ***\n", pm->getName());
+                return false;
+        }
+
+        pm->setX(info->px);
+        pm->setY(info->py);
+        dbg("Put '%s' at [%d %d]\n", pm->getName(), info->px, info->py);
+        pm->setPlace(Place);
+        place_add_object(Place, pm);
+        pm->setOnMap(true);
+        info->placed++;
+
+        /* Check if we need to go back to fighting */
+        if (combat_get_state() != COMBAT_STATE_FIGHTING &&
+            are_hostile(pm, player_party)) {
+                combat_set_state(COMBAT_STATE_FIGHTING);
+        }
+
+        return false;
+}
+
+static void set_party_initial_position(struct position_info *pinfo, int x, int y)
+{
+        pinfo->x = x;
+        pinfo->y = y;
+
+        // Set the bounds of the placement rectangle. For now I don't care if
+        // it overlaps the edge of the map because the search algorithm will
+        // check for off-map locations.
+        pinfo->rw = MAX_PLACEMENT_RECTANGLE_W;
+        pinfo->rh = MAX_PLACEMENT_RECTANGLE_H;
+        pinfo->rx = pinfo->x - pinfo->rw / 2;
+        pinfo->ry = pinfo->y - pinfo->rh / 2;
+
+        dbg("Moved party start position to [%d %d]\n", pinfo->x, pinfo->y);;
+
+}
+
+void combat_fill_position_info(struct position_info *info, struct place *place, int x, int y, int dx, int dy, bool defend)
+{
+        // 
+        // This function will:
+        // * determine the party's coordinates upon entry to combat
+        // * turn the defending party to face the attacker
+        // * specify the placement rectangle for the party members
+        // * set the flags for the placement algorithm
+        // 
+
+        info->place = place;
+        info->dx = dx;
+        info->dy = dy;
+
+        if (info->place != Combat.place) {
+                // Occupy the same location and face the same way
+                info->x = x;
+                info->y = y;
+
+        }
+        else {
+
+                if (defend) {
+                        // Reverse facing
+                        info->dx = -dx;
+                        info->dy = -dy;
+                        dx = -dx;
+                        dy = -dy;
+                }
+                // Occupy an edge facing the opponent
+                if (dx < 0) {
+                        // facing west, occupy east half
+                        info->x = place_w(info->place) - place_w(info->place) / 4;
+                }
+                else if (dx > 0) {
+                        // facing east, occupy west half
+                        info->x = place_w(info->place) / 4;
+                }
+                else {
+                        // facing north or south, center on east-west
+                        info->x = place_w(info->place) / 2;
+                }
+
+                if (dy < 0) {
+                        // facing north, occupy south
+                        info->y = place_h(info->place) - place_h(info->place) / 4;
+                }
+                else if (dy > 0) {
+                        // facing south, occupy north
+                        info->y = place_h(info->place) / 4;
+                }
+                else {
+                        // facing east or west, center on north-south
+                        info->y = place_h(info->place) / 2;
+                }
+        }
+
+        set_party_initial_position(info, info->x, info->y);
+
+        // clear the pmask and search map before first use
+        info->subject = NULL;
+        memset(rmap, 0, sizeof (rmap));
+
+        info->placed = 0;
+}
+
+bool combat_place_character(class Character * pm, void *data)
+{
+        // Put a party member on the combat map
+
+        int tmp;
+        struct position_info *info;
+
+        info = (struct position_info *) data;
+
+        if (pm->isDead())
+                return false;
+
+        if (pm->getOrder() >= info->formation->n)
+                return false;
+
+        pm->setX(info->formation->entry[pm->getOrder()].x);
+        pm->setY(info->formation->entry[pm->getOrder()].y);
+
+        /* Counterclockwise rotations: x = x * cos - y * sin y = x * sin + y *
+         * cos */
+        if (info->dx < 0) {
+                /* Rotate +90 degrees */
+                tmp = pm->getX();
+                pm->setX(pm->getY());
+                pm->setY(tmp);
+        }
+        else if (info->dx > 0) {
+                /* Rotate -90 degrees */
+                tmp = pm->getX();
+                pm->setX(-pm->getY());
+                pm->setY(tmp);
+        }
+        else if (info->dy > 0) {
+                /* Rotate 180 degrees */
+                pm->setX(-pm->getX());
+                pm->setY(-pm->getY());
+        }
+
+        /* If dy > 1 then the formation is ok as-is. */
+        pm->changeX(info->x);
+        pm->changeY(info->y);
+
+        // Check if that location will really work. If not then do a DFS
+        // starting from the desired location and see if we can find someplace
+        // that WILL work.
+
+        // init the position info for a new search
+        info->subject = pm;
+        memset(rmap, 0, sizeof (rmap));
+        info->px = pm->getX();
+        info->py = pm->getY();
+        dbg("Placing %s\n", pm->getName());
+
+        if (combat_find_safe_position(info) != 0) {
+
+                // Ok, so that didn't work. This can happen when the party
+                // leader is right on the map border facing towards the map
+                // center. In this case the find-safe-place alg won't handle
+                // followers that are too deep off the map. If this IS the
+                // party leader, or if upon retry we STILL can't find a safe
+                // place, then screw it - we'll place this character on the
+                // start location (even if we have to end up stacking the whole
+                // party there!).
+
+                // Corner case: a portal leads from one lake to another. A
+                // hostile npc party is sitting right on the destination. The
+                // party enters the portal on foot, upon arrival the npc party
+                // attacks. Party members which are on foot get stacked on the
+                // entry point and cannot move or flee. This is an unfriendly
+                // situation, but something of a corner case. Map hackers can
+                // skirt the issue and player's can expect that entering
+                // portals involves an element of danger :). The engine won't
+                // crash and the player can usually get out of the fix by
+                // defeating the npc's.
+
+                class Character *leader = player_party->get_leader();
+
+                if (!leader) {
+                        dbg("Putting %s on start location [%d %d]\n",
+                               pm->getName(), info->x, info->y);
+                        info->px = info->x;
+                        info->py = info->y;
+                }
+                else {
+                        // init the position info to search again
+                        memset(rmap, 0, sizeof (rmap));
+                        info->px = leader->getX();
+                        info->py = leader->getY();
+                        dbg("Retrying %s\n", pm->getName());
+
+                        if (combat_find_safe_position(info) != 0) {
+                                dbg("Putting %s on start location "
+                                       "[%d %d]\n",
+                                       pm->getName(), info->x, info->y);
+                                info->px = info->x;
+                                info->py = info->y;
+                        }
+                }
+        }
+
+        pm->relocate(info->place, info->px, info->py);
+        
+        return false;
+}
+
+static bool mySetInitialCameraPosition(class Character * pm, void *data)
+{
+        if (pm->isOnMap()) {
+                mapCenterCamera(pm->getX(), pm->getY());
+                return true;
+        }
+        return false;
+}
+
+static void combat_overlay_vehicle(Vehicle *vehicle, int dx, int dy,
+                                   struct position_info *pinfo)
+{
+
+       assert(pinfo->dx || pinfo->dy);
+       assert(!pinfo->dx || !pinfo->dy);       
+       
+       int dst_x = 0, dst_y = 0;
+               
+       if (dx < 0) {
+               // facing west, fill east half
+               dst_x = COMBAT_MAP_W / 2;
+               set_party_initial_position(pinfo, (COMBAT_MAP_W*3)/4,COMBAT_MAP_H/2);
+       }
+       else if (dx > 0) {
+               // facing east, fill west half
+               dst_x = COMBAT_MAP_W / 2 - COMBAT_MAP_W;
+               set_party_initial_position(pinfo, COMBAT_MAP_W/4,COMBAT_MAP_H/2);
+       }
+       else if (dy < 0) {
+               // facing north, fill south half
+               dst_y = COMBAT_MAP_H / 2;
+               set_party_initial_position(pinfo, COMBAT_MAP_W/2,(COMBAT_MAP_H*3)/4);
+       }
+       else if (dy > 0) {
+               // facing south, fill north half
+               dst_y = COMBAT_MAP_H / 2 - COMBAT_MAP_H;
+               set_party_initial_position(pinfo, COMBAT_MAP_W/2,COMBAT_MAP_H/4);
+       }
+       else
+       {
+               set_party_initial_position(pinfo, COMBAT_MAP_W/2,COMBAT_MAP_H/2);
+       }
+       
+       closure_exec(vehicle->getObjectType()->renderCombat, "ppdd", 
+       Place, vehicle, dst_x, dst_y);
+      
+}
+                                   
+
+static void combat_overlay_map(struct terrain_map *map, 
+                               struct position_info *pinfo, int broadside)
+{
+        int x = 0, y = 0;
+
+        assert(pinfo->dx || pinfo->dy);
+        assert(!pinfo->dx || !pinfo->dy);
+
+        // Clone the map so we can make a rotated copy.
+        map = terrain_map_clone(map, "combat_overlay_map");
+        if (!map) {
+                err("Failed to allocate temporary terrain map");
+                return;
+        }
+        // Rotate the map so that north faces the opponent.
+        if (broadside) {
+                terrain_map_rotate(map, vector_to_rotation(pinfo->dy, pinfo->dx));
+
+                // Position the map against the boundary dividing the map.
+                if (pinfo->dx < 0) {
+                        // facing west, shift map west toward edge
+                        x = (place_w(Place)) / 2;
+                        y = (place_h(Place) - map->h) / 2;
+                }
+                else if (pinfo->dx > 0) {
+                        // facing east, shift map east toward edge
+                        x = (place_w(Place)) / 2 - map->w;
+                        y = (place_h(Place) - map->h) / 2;
+                }
+                else if (pinfo->dy < 0) {
+                        // facing north, shift map north toward edge
+                        x = (place_w(Place) - map->w) / 2;
+                        y = (place_h(Place)) / 2;
+                }
+                else if (pinfo->dy > 0) {
+                        // facing south, shift map south toward edge
+                        x = (place_w(Place) - map->w) / 2;
+                        y = (place_h(Place)) / 2 - map->h;
+                }
+        }
+        else {
+                terrain_map_rotate(map, vector_to_rotation(pinfo->dx, 
+                                                           pinfo->dy));
+                // center the overlayed map
+                x = (place_w(Place) - map->w) / 2;
+                y = (place_h(Place) - map->h) / 2;
+        }
+
+        assert(x >= 0);
+        assert(y >= 0);
+
+        // Adjust the party's starting position to be centered on the overlap
+        // map.
+        set_party_initial_position(pinfo, 
+                                   x + (map->w /*+ 1*/) / 2, 
+                                   y + (map->h /*+ 1*/) / 2);
+
+        // Blit the rotated map centered on the given coordinates.
+        terrain_map_blit(Place->terrain_map, x, y, map, 0, 0, map->w, map->h);
+        // terrain_map_print(stdout, INITIAL_INDENTATION, Place->terrain_map);
+
+        // Cleanup.
+        terrain_map_unref(map);
+}
+
+static void myPutEnemy(class Party * foe, struct position_info *pinfo)
+{
+        foe->forEachMember(myPutNpc, pinfo);
+}
+
+/*
+ * combat_position_enemy - put an NPC party on the combat map
+ */
+static int combat_position_enemy(class Party * foe, int dx, int dy, 
+                                 int defend, 
+                                 struct place *place)
+{
+        int positioned = 0;
+
+        assert(foe->getSize());
+
+        combat_fill_position_info(&foe->pinfo, place, foe->getX(), foe->getY(),
+                                  dx, dy, defend);
+        foe->pinfo.formation = foe->get_formation();
+        if (!foe->pinfo.formation)
+                foe->pinfo.formation = formation_get_default();
+
+        Combat.enemy_vehicle = foe->getVehicle();
+
+        /* Bugfix SF1412060 "NPC attacks while on (but not aboard) ship" */
+        /* Addendum: the foe may not have a place if it is being introduced
+         * into combat "from scratch" (ie, it did not exist on the wilderness
+         * as a party before being imported into combat). */
+        if (! Combat.enemy_vehicle && foe->getPlace()) {
+                Combat.enemy_vehicle = place_get_vehicle(foe->getPlace(),
+                                                         foe->getX(),
+                                                         foe->getY());
+        }
+        /* Check for a map overlay. */
+        if (Combat.enemy_vehicle
+            && Combat.enemy_vehicle->getObjectType()->renderCombat 
+            && Place == Combat.place) {
+                combat_overlay_vehicle(Combat.enemy_vehicle, 
+                                       defend ? -dx : dx, 
+                                       defend ? -dy : dy,
+                                       &foe->pinfo);
+          }
+
+        foe->disembark();
+        obj_inc_ref(foe);
+        foe->remove();
+        myPutEnemy(foe, &foe->pinfo);
+        positioned = foe->pinfo.placed;
+
+        obj_dec_ref(foe);
+
+        return positioned;
+}
+
+
+/*****************************************************************************
+ * combat_npc_status_visitor - determine the status of the npc faction(s)
+ *
+ * This is a "visitor" function applied to each object in a list of nodes. It's
+ * meant to be applied to every object in a place. It checks for any npc
+ * party members and whether or not they're charmed, and sets the combat status
+ * of the npc faction.
+ *
+ * This routine does not distinguish between different NPC factions, it just
+ * looks for anybody hostile to the player.
+ *
+ *****************************************************************************/
+static void combat_hostile_status_visitor(struct node *node, void *data)
+{
+        enum combat_faction_status *status;
+        class Object *obj;
+
+        /* Extract the typed variables from the generic parms */
+        status = (enum combat_faction_status *)data;
+        obj = (class Object*)node->ptr;
+
+        /* If we already know a hostile faction exists then skip the rest */
+        if (*status == COMBAT_FACTION_EXISTS)
+                return;
+
+        /* Skip non-beings */
+        if (! obj_is_being(obj))
+                return;
+
+        /* Skip player party members */
+        if (obj->isPlayerPartyMember())
+                return;
+
+        /* A hostile npc means a hostile faction still exists */
+        if (are_hostile((Being*)obj, player_party)) {
+                *status = COMBAT_FACTION_EXISTS;
+                return;
+        }
+
+        /* Check for a charmed hostile */
+        if (are_natively_hostile((Being*)obj, player_party)) {
+                *status = COMBAT_FACTION_CHARMED;
+        }
+}
+
+/*****************************************************************************
+ * combat_get_hostile_faction_status - check hostile combat status
+ *
+ * This is literally a dupe of combat_get_player_faction_status() below.
+ *
+ *****************************************************************************/
+static enum combat_faction_status combat_get_hostile_faction_status(void)
+{
+        enum combat_faction_status stat;
+
+        /* Assume until proven otherwise that the player faction is gone. */
+        stat = COMBAT_FACTION_GONE;
+
+        /* Check each object in the current place to determine the status of
+         * the player faction. */
+        node_foldr(place_get_all_objects(Place),
+                   combat_hostile_status_visitor,
+                   &stat);
+
+        /* Return the discovered status. */
+        return stat;
+}
+
+/*****************************************************************************
+ * combat_player_status_visitor - determine the status of the player faction
+ *
+ * This is a "visitor" function applied to each object in a list of nodes. It's
+ * meant to be applied to every object in a place. It checks for any player
+ * party members and whether or not they're charmed, and sets the combat status
+ * of the player party based on the cumulative results.
+ *
+ *****************************************************************************/
+static void combat_player_status_visitor(struct node *node, void *data)
+{
+        enum combat_faction_status *status;
+        class Object *obj;
+
+        /* Extract the typed variables from the generic parms */
+        status = (enum combat_faction_status *)data;
+        obj = (class Object*)node->ptr;
+
+        /* If we already know the player is still fighting then skip the rest
+         * of this. */
+        if (*status == COMBAT_FACTION_EXISTS)
+                return;
+
+        /* Skip non-beings */
+        if (! obj_is_being(obj))
+                return;
+
+        /* Skip non-party-members */
+        if (! obj->isPlayerPartyMember())
+                return;
+
+        /* A non-hostile party member means the player is still fighting. */
+        if (! are_hostile((Being*)obj, player_party)) {
+                *status = COMBAT_FACTION_EXISTS;
+                return;
+        }
+
+        /* Check if a player party members has been charmed */
+        if (are_natively_hostile((Being*)obj, player_party)) {
+                *status = COMBAT_FACTION_CHARMED;
+        }
+}
+
+/*****************************************************************************
+ * combat_get_player_faction_status - check player combat status
+ *
+ * Loops over all objects to check if any player party members are still around
+ * and whether or not they're charmed.
+ *
+ * FIXME: why not just check the player party directly? Or at least merge this
+ * with the combat_get_hostile_faction_status() function above?
+ *
+ *****************************************************************************/
+static enum combat_faction_status combat_get_player_faction_status(void)
+{
+        enum combat_faction_status stat;
+
+        /* Assume until proven otherwise that the player faction is gone. */
+        stat = COMBAT_FACTION_GONE;
+
+        /* Check each object in the current place to determine the status of
+         * the player faction. */
+        node_foldr(place_get_all_objects(Place),
+                   combat_player_status_visitor,
+                   &stat);
+
+        /* Return the discovered status. */
+        return stat;
+}
+
+void combat_analyze_results_of_last_turn()
+{
+
+        enum combat_faction_status hostile_faction_status;
+        enum combat_faction_status player_faction_status;
+
+        // ---------------------------------------------------------------------
+        // Now check for changes in the combat state as a result of the last
+        // turn. Check the status of the hostile party or parties and the
+        // player party. The following table shows the outcome with all
+        // possible combinations of status:
+        //
+        // =====================================================
+        // hostiles | player party | result
+        // ===================================================== 
+        // exist    | exist        | continue combat
+        // exist    | gone         | exit combat
+        // exist    | charmed      | uncharm, continue combat
+        // gone     | exist        | looting
+        // gone     | gone         | exit combat
+        // gone     | charmed      | uncharm, looting
+        // charmed  | exist        | continue combat
+        // charmed  | gone         | exit combat
+        // charmed  | charmed      | uncharm, continue combat
+        // =====================================================
+        //
+        // ---------------------------------------------------------------------
+        
+        hostile_faction_status = combat_get_hostile_faction_status();
+        player_faction_status  = combat_get_player_faction_status();
+                        
+        switch (player_faction_status) {
+                
+        case COMBAT_FACTION_EXISTS:
+                
+                switch (hostile_faction_status) {
+                        
+                case COMBAT_FACTION_EXISTS:
+                        // -----------------------------------------------------
+                        // Both factions exist. Continue or restart fighting.
+                        // -----------------------------------------------------                        
+                        combat_set_state(COMBAT_STATE_FIGHTING);
+                        break;
+
+                case COMBAT_FACTION_CHARMED:
+                        // -----------------------------------------------------
+                        // The hostile faction are all charmed. Tough luck for
+                        // them. Make sure we are fighting.  Addendum: can't
+                        // attack them without degrading diplomacy with own
+                        // faction, so declare combat over. When charm wears
+                        // off we'll go back to fighting.
+                        // -----------------------------------------------------
+                        //combat_set_state(COMBAT_STATE_FIGHTING);
+                        combat_set_state(COMBAT_STATE_LOOTING);
+                        break;
+
+                case COMBAT_FACTION_GONE:
+                        // -----------------------------------------------------
+                        // No hostiles around. Loot at will.
+                        // -----------------------------------------------------
+                        if (Combat.state != COMBAT_STATE_DONE)
+                        {
+                               combat_set_state(COMBAT_STATE_LOOTING);
+                       }
+                        break;
+
+                default:
+                        assert(false);
+                        break;
+                }
+                
+                break;
+
+        case COMBAT_FACTION_CHARMED:
+
+                // -------------------------------------------------------------
+                // In all of these cases I uncharm the party members. If I
+                // don't, then I'm risking a deadlock situation where the
+                // hostiles can't or won't finish off the charmed members, in
+                // which case the game gets stuck running all the npc's forever
+                // while the player helplessly watches.
+                // -------------------------------------------------------------
+
+                player_party->unCharmMembers();
+
+                switch (hostile_faction_status) {
+                        
+                case COMBAT_FACTION_EXISTS:
+                        combat_set_state(COMBAT_STATE_FIGHTING);
+                        break;
+
+                case COMBAT_FACTION_GONE:
+                        // ----------------------------------------------------
+                        // No hostiles around. Loot at will. Uncharm or we'll
+                        // definitely deadlock.
+                        // ----------------------------------------------------
+                        combat_set_state(COMBAT_STATE_LOOTING);
+                        break;
+
+                default:
+                        assert(false);
+                        break;
+                }
+
+                break;
+
+        case COMBAT_FACTION_GONE:
+
+                // ------------------------------------------------------------
+                // In all of these cases combat is over. Simple. If combat is
+                // ocurring in the special combat place then we need to clean
+                // it up by calling combat_exit().
+                // ------------------------------------------------------------
+                
+                combat_set_state(COMBAT_STATE_DONE);
+
+//                if (Place == Combat.place)
+                combat_exit();
+
+                break;
+                
+        case COMBAT_FACTION_CAMPING:
+
+                switch (hostile_faction_status) {
+                        
+                case COMBAT_FACTION_EXISTS:
+                        // ----------------------------------------------------
+                        // Ambush!
+                        // ----------------------------------------------------                        
+                        combat_set_state(COMBAT_STATE_FIGHTING);
+                        break;
+
+                case COMBAT_FACTION_GONE:
+                        // ----------------------------------------------------
+                        // No hostiles around. Change nothing.
+                        // ----------------------------------------------------
+                        break;
+
+                default:
+                        assert(false);
+                        break;
+                }
+
+                break;
+
+        }
+        
+
+}
+
+/*
+ * combat_find_and_position_enemy - if this object is a hostile NPC party then
+ * place it on the combat map
+ */
+static void combat_find_and_position_enemy(class Object * obj, void *data)
+{
+        struct v2 *info;
+
+        if (!obj->isType(PARTY_ID))
+                return;
+
+        info = (struct v2 *) data;
+        assert(obj_is_being(obj));
+        if (are_hostile((Being*)obj, player_party))
+                combat_set_state(COMBAT_STATE_FIGHTING);        
+        combat_position_enemy((class Party *) obj, info->dx, info->dy, false, 
+                        info->place);
+}
+
+int combatInit(void)
+{
+        // This is called once at the beginning of the game
+        memset(&Combat, 0, sizeof (Combat));
+
+        /* Initialize the place to safe defaults */
+        Combat.state = COMBAT_STATE_DONE;
+
+        return 0;
+}
+
+void combat_reset_state(void)
+{
+        /* Initialize the place to safe defaults */
+        fprintf(stderr,"combatreset\n");
+        Combat.state = COMBAT_STATE_DONE;
+}
+
+static void fill_map_half(struct terrain_map *map, int dx, int dy,
+                          struct terrain *terrain)
+{
+        assert(dx || dy);
+
+        if (dx < 0) {
+                // facing west, fill east half
+                terrain_map_fill(map, map->w / 2, 0, (map->w+1) / 2, map->h,
+                                 terrain);
+        }
+        else if (dx > 0) {
+                // facing east, fill west half
+                terrain_map_fill(map, 0, 0, map->w / 2, map->h, terrain);
+        }
+        else if (dy < 0) {
+                // facing north, fill south half
+                terrain_map_fill(map, 0, map->h / 2, map->w, (map->h+1) / 2,
+                                 terrain);
+        }
+        else if (dy > 0) {
+                // facing south, fill north half
+                terrain_map_fill(map, 0, 0, map->w, map->h / 2, terrain);
+        }
+}
+
+
+static void fill_temporary_terrain_map(struct terrain_map *map,
+                                       struct place *place, int x, int y,
+                                       int dx, int dy)
+{
+        struct terrain_map *tile_map;
+        struct terrain *terrain;
+        int dst_x = 0, dst_y = 0, src_x = 0, src_y = 0, src_w = 0, src_h = 0;
+
+        assert(dx || dy);
+        assert(!(dx && dy));
+
+        if (dx < 0) {
+
+                // facing west, fill east half
+                dst_x = map->w / 2;
+                dst_y = 0;
+                src_x = 0;
+                src_y = 0;
+                src_w = (map->w + 1) / 2;
+                src_h = map->h;
+
+        }
+        else if (dx > 0) {
+
+                // facing east, fill west half
+                dst_x = 0;
+                dst_y = 0;
+                src_x = map->w / 2;
+                src_y = 0;
+                src_w = (map->w) / 2;
+                src_h = map->h;
+
+        }
+        else if (dy < 0) {
+
+                // facing north, fill south half
+                dst_x = 0;
+                dst_y = map->h / 2;
+                src_x = 0;
+                src_y = 0;
+                src_w = map->w;
+                src_h = (map->h + 1) / 2;
+
+        }
+        else if (dy > 0) {
+
+                // facing south, fill north half
+                dst_x = 0;
+                dst_y = 0;
+                src_x = 0;
+                src_y = map->h / 2;
+                src_w = map->w;
+                src_h = (map->h)/ 2;
+        }
+
+        tile_map = place_get_combat_terrain_map(place, x, y);
+
+        if (tile_map) {
+
+                // fixme -- instead of crashing at runtime, check for properly
+                // sized combat maps at load time (this will require the combat
+                // map dimensions to be also specified at load time or at least
+                // well-documented for map developers)
+                assert(tile_map->w >= (src_x + src_w));
+                assert(tile_map->h >= (src_y + src_h));
+
+                // Use the combat map associated with the terrain type.
+                terrain_map_blit(map, dst_x, dst_y, tile_map, src_x, src_y,
+                                 src_w, src_h);
+        }
+        else {
+                // Fill with the terrain type.
+                terrain = place_get_terrain(place, x, y);
+                terrain_map_fill(map, dst_x, dst_y, src_w, src_h, terrain);
+        }
+}
+
+
+static void setup_combat_place_part(struct place *place, 
+               struct terrain* our_terrain, struct terrain* other_terrain,
+               int dx, int dy, int mapx, int mapy)
+{
+       int dst_x = 0, dst_y = 0;
+       
+       if (our_terrain->renderCombat)
+       {       
+               fprintf(stderr,"rc\n");
+               if (dx < 0) {
+                       // facing west, fill east half
+                       dst_x = COMBAT_MAP_W / 2;
+               }
+               else if (dx > 0) {
+                       // facing east, fill west half
+                       dst_x = COMBAT_MAP_W / 2 - COMBAT_MAP_W;
+               }
+               else if (dy < 0) {
+                       // facing north, fill south half
+                       dst_y = COMBAT_MAP_H / 2;
+               }
+               else if (dy > 0) {
+                       // facing south, fill north half
+                       dst_y = COMBAT_MAP_H / 2 - COMBAT_MAP_H;
+               }
+               
+               closure_exec(our_terrain->renderCombat, "pppdddd", 
+                                                       place, our_terrain, other_terrain,
+                                                       dst_x, dst_y, mapx, mapy);
+       }
+       else if (dx || dy)
+       {
+               fill_map_half(place->terrain_map, dx, dy, our_terrain); 
+       }
+       else
+       {
+               terrain_map_fill(place->terrain_map, 0, 0, COMBAT_MAP_W, COMBAT_MAP_H, our_terrain);
+       }
+}
+       
+
+static void setup_combat_place(struct place *place, struct combat_info
+                                                        *info)
+{
+       struct terrain *player_terrain;
+       struct terrain *npc_terrain;
+       
+       // Determine orientation for both parties
+       // Also get true locations (after parties have moved to go from diagonal to adjacent)
+       if (!info->move->npc_party)
+       {
+               info->pc_dx = 0;
+               info->pc_dy = 0;
+               info->pc_x = player_party->getX();
+               info->pc_y = player_party->getY();
+       }
+       else if (info->defend)
+       {
+               info->pc_dx = -info->move->dx;
+               info->pc_dy = -info->move->dy;
+               info->pc_x = player_party->getX();
+               info->pc_y = player_party->getY();
+               info->npc_x = info->pc_x - info->move->dx;
+               info->npc_y = info->pc_y - info->move->dy;
+       }
+       else
+       {
+               info->pc_dx = info->move->dx;
+               info->pc_dy = info->move->dy;
+               info->npc_x = info->move->npc_party->getX();
+               info->npc_y = info->move->npc_party->getY();
+               info->pc_x = info->npc_x - info->move->dx;
+               info->pc_y = info->npc_y - info->move->dy;
+       }
+       
+       // get terrains for each
+       player_terrain=place_get_terrain(player_party->getPlace(), info->pc_x, info->pc_y);
+       
+       if (info->move->npc_party)      
+       {
+               npc_terrain=place_get_terrain(info->move->npc_party->getPlace(), info->npc_x, info->npc_y);
+       }
+       else
+       {
+               npc_terrain=player_terrain; // some sensible definition makes like easier...
+       }
+       
+       setup_combat_place_part(place, player_terrain, npc_terrain, info->pc_dx, info->pc_dy, info->pc_x, info->pc_y);
+       if (info->move->npc_party)      
+       {
+               setup_combat_place_part(place, npc_terrain, player_terrain, -info->pc_dx, -info->pc_dy, info->npc_x, info->npc_y);
+       }
+       
+}
+
+
+static struct terrain_map *create_temporary_terrain_map(struct combat_info
+                                                        *info)
+{
+        struct terrain_map *map;
+        int player_dx, player_dy, npc_dx, npc_dy,pcmap_x,pcmap_y,npcmap_x,npcmap_y;
+        struct list *elem;
+
+        // Create a map derived partially from the enemy's tile and
+        // partially from the player's tile.
+
+        map = terrain_map_new("tmp_combat_map", COMBAT_MAP_W, COMBAT_MAP_H,
+                       player_party->getPlace()->terrain_map->palette);
+        assert(map);
+        
+        terrain_map_fill(map, 0, 0, COMBAT_MAP_W, COMBAT_MAP_H, 
+                       place_get_terrain(player_party->getPlace(),player_party->getX(),player_party->getY()));
+        return map;
+        
+        // Determine orientation for both parties.
+
+        
+        if (info->defend) {
+                player_dx = -info->move->dx;
+                player_dy = -info->move->dy;
+                npc_dx = info->move->dx;
+                npc_dy = info->move->dy;
+                pcmap_x = player_party->getX();
+                pcmap_y = player_party->getY();
+                npcmap_x = pcmap_x - info->move->dx;
+                npcmap_y = pcmap_y - info->move->dy;
+        }
+        else {
+                player_dx = info->move->dx;
+                player_dy = info->move->dy;
+                npc_dx = -info->move->dx;
+                npc_dy = -info->move->dy;
+                npcmap_x = info->move->npc_party->getX();
+                npcmap_y = info->move->npc_party->getY();
+                pcmap_x = npcmap_x - info->move->dx;
+                pcmap_y = npcmap_y - info->move->dy;
+        }
+
+        // Fill the player's half of the combat map
+        fill_temporary_terrain_map(map,
+                                   player_party->getPlace(),
+                                   pcmap_x, pcmap_y,
+                                   player_dx, player_dy);
+
+        // Fill the npc party's half of the combat map
+        fill_temporary_terrain_map(map,
+                                   info->move->npc_party->getPlace(),
+                                   npcmap_x, npcmap_y,
+                                   npc_dx, npc_dy);
+
+        struct terrain_map *party_map =
+            place_get_combat_terrain_map(player_party->getPlace(),
+                                         player_party->getX(),
+                                         player_party->getY());
+        struct terrain_map *npc_party_map =
+            place_get_combat_terrain_map(info->move->npc_party->getPlace(),
+                                         info->move->npc_party->getX(),
+                                         info->move->npc_party->getY());
+
+        // SAM: It seems that, until we can think of something 
+        //      more clever, (palette merging code?  yech...)
+        //      that all combat maps will have to have a palette
+        //      in common.  It may be more restrictive than I have
+        //      stated, but I would need to research the question...
+        // 
+        // SAM:
+        // Hmmm...ship-to-shore blits a map with a different palette 
+        // onto a map with 'pal_standard', and this code has no way of seeing that.
+        // Possibly the map blitting should merge the palettes after all...
+        if (party_map && npc_party_map) {
+                dbg("maps '%s' '%s', palettes '%s' '%s'\n",
+                       party_map->tag, npc_party_map->tag,
+                       party_map->palette->tag, npc_party_map->palette->tag);
+                int palette_tags_match = !strcmp(party_map->palette->tag,
+                                                 npc_party_map->palette->tag);
+                if (!palette_tags_match) {
+                        dbg("create_temporary_terrain_map() warning: \n"
+                               "  Two combat maps (tags '%s' and '%s') \n"
+                               "  merging with dissimilar palettes (tags '%s' and '%s').\n"
+                               "  (This should work OK now, but be aware...)\n",
+                               party_map->tag, npc_party_map->tag,
+                               party_map->palette->tag,
+                               npc_party_map->palette->tag);
+                        // SAM: New code in palette_print() should enable us to carry on.
+                        // assert(0);
+                }
+        }
+        struct terrain_map *the_map;
+        if (party_map)
+                the_map = party_map;
+        else if (npc_party_map)
+                the_map = npc_party_map;
+        else {
+                // No combat map for either location?
+                // Use the parent map (wilderness, or whatever) to get a palette.
+                // Since the terrain fill for each half is based on 
+                // some terrain in the parent map, that palette should be appropriate.
+                assert(player_party->getPlace()->terrain_map);
+                the_map = player_party->getPlace()->terrain_map;
+        }
+        map->palette = the_map->palette;
+        //terrain_map_print(stdout, INITIAL_INDENTATION, map);
+
+
+        /* run all registered terrain blenders on the new map */
+        list_for_each(&Session->blenders, elem) {
+                blender_t *blender=outcast(elem, blender_t, list);
+                terrain_map_blend(map, blender->inf, blender->n_nonsup,
+                                  blender->nonsup, blender->range);
+        }
+
+        return map;
+}
+
+static bool position_player_party(struct combat_info *cinfo)
+{
+        class Vehicle *vehicle;
+
+        combat_fill_position_info(&player_party->pinfo, Place,
+                                  cinfo->move->x, cinfo->move->y,
+                                  cinfo->move->dx, cinfo->move->dy, 
+                                  cinfo->defend);
+
+        player_party->pinfo.formation = player_party->get_formation();
+        if (!player_party->pinfo.formation)
+                player_party->pinfo.formation = formation_get_default();
+
+        // Check for map overlays. First check if the player is in a vehicle
+        // with a map.
+        vehicle = player_party->getVehicle();
+        if (vehicle &&
+            vehicle->getObjectType()->renderCombat &&
+            Place == Combat.place) {
+                combat_overlay_vehicle(vehicle, cinfo->pc_dx, cinfo->pc_dy,
+                                   &player_party->pinfo);
+        }
+
+        // Next check if the player is OVER (on the map) but not in a vehicle
+        // on the map. Note: this only applies to non-dungeon combat, and in a
+        // series of dungeon combats the player party may not have a place
+        // (because we remove it just below and the calling code does not
+        // relocate the player party until it returns to a town or wilderness.
+        else if (player_party->getPlace() &&
+                 (vehicle = place_get_vehicle(player_party->getPlace(),
+                                              player_party->getX(),
+                                              player_party->getY())) &&
+                 vehicle->getObjectType()->renderCombat) {
+                // dbg("party overlay, party over vehicle\n");
+               combat_overlay_vehicle(vehicle, cinfo->pc_dx, cinfo->pc_dy,
+                                   &player_party->pinfo);
+        }
+        // Finally, since there is no vehicle map check for a camping map.
+        else if (cinfo->camping && player_party->campsite_map) {
+                // dbg("party overlay, party is camping\n");
+                combat_overlay_map(player_party->campsite_map, 
+                                   &player_party->pinfo, 0);
+        }
+
+        if (player_party->isLoitering())
+        {
+                       player_party->forceAbortLoitering();   
+         }
+        player_party->remove();
+        player_party->forEachReverseMember(combat_place_character, 
+                                           &player_party->pinfo);
+                                           
+        return true;
+}
+
+bool combat_enter(struct combat_info * info)
+{
+        struct location loc;
+
+        if (player_party->allDead()) {
+                /* Yes, this can happen in some rare circumstances... */
+                return false;
+        }
+
+        /* Our map-building code assumes 4-neighbor adjacency. If attacking on
+         * a diagonal, randomly choose a cardinal direction. */
+        if (info->move->dx && info->move->dy)
+        {
+                if (rand() % 2) {
+                        info->move->dx = 0;
+                } else {
+                        info->move->dy = 0;
+                }
+        }
+
+        // --------------------------------------------------------------------
+        // Default to the entry point as the combat exit location for the
+        // player party.
+        // --------------------------------------------------------------------
+
+        loc.place = info->move->place;
+        loc.x     = info->move->x;
+        loc.y     = info->move->y;
+
+
+        // *** Initialize Combat Globals ***
+
+        Combat.enemy_vehicle = NULL;
+        Combat.round = 0;
+        Session->crosshair->remove();
+
+        if (! info->move->place->wilderness) {
+
+                // ------------------------------------------------------------
+                // When not in the wilderness use the current place for combat.
+                // ------------------------------------------------------------
+                Place = info->move->place;
+        }
+        else {
+
+                // ------------------------------------------------------------
+                // Create a temporary place for combat in the wilderness. It's
+                // parent will be the wilderness. We have to set a special flag
+                // to indicate that it's wilderness combat (used for things
+                // like exit policy).
+                // ------------------------------------------------------------
+
+                Combat.place = place_new("p_wilderness_combat", 
+                                         "Wilderness Combat",
+                                         0, // sprite
+                                         create_temporary_terrain_map(info),
+                                         0, // ! wrapping
+                                         info->move->place->underground, 
+                                         0, // ! wilderness
+                                         1  // wilderness combat
+                                         );
+
+                Combat.place->is_wilderness_combat = 1;
+                Combat.place->location.place = info->move->place;
+                Combat.place->location.x = info->move->px;
+                Combat.place->location.y = info->move->py;
+
+                setup_combat_place(Combat.place,info);
+                
+                place_add_subplace(info->move->place, Combat.place, 
+                                   info->move->px, info->move->py);
+
+                Place = Combat.place;
+        }
+
+        mapSetPlace(Place);
+
+        // *** Position the Player Companions ***
+
+        // This is where the map overlays on the player side of the map get
+        // placed, if any.
+        if (!position_player_party(info))
+                return false;
+               
+        // *** Position the Enemy Party Members ***
+
+        if (info->move->npc_party) {
+                
+
+                /* combat_position_enemy() will decrement most of the refcounts
+                 * ont he party, keep it alive until we're done */
+                obj_inc_ref(info->move->npc_party);
+
+                if (!combat_position_enemy(info->move->npc_party, 
+                                           info->move->dx, info->move->dy, 
+                                           !info->defend, Place)) {
+                        log_begin("*** FORFEIT ***");
+                        log_msg("Your opponent slips away!");
+                        log_end(NULL);
+                        combat_set_state(COMBAT_STATE_LOOTING);
+                }
+                else
+                {
+                       combat_set_state(COMBAT_STATE_FIGHTING);   
+                }
+
+                /* done with it now */
+                obj_dec_ref(info->move->npc_party);
+                info->move->npc_party = NULL;
+
+        }
+        else if (info->camping) {
+
+                combat_set_state(COMBAT_STATE_CAMPING);
+                log_msg("Zzzz...");
+        }
+        else {
+                struct v2 v2;
+                v2.dx = info->move->dx;
+                v2.dy = info->move->dy;
+                v2.place = Place;
+                combat_set_state(COMBAT_STATE_DONE);
+                place_for_each_object(Place, combat_find_and_position_enemy,
+                                      &v2);
+        }
+
+        player_party->forEachMember(mySetInitialCameraPosition, 0);
+
+        if (combat_get_state() == COMBAT_STATE_FIGHTING) {
+                player_party->enableRoundRobinMode();
+                sound_play(Combat.sound_enter, SOUND_MAX_VOLUME);
+        }
+        else if (combat_get_state() != COMBAT_STATE_CAMPING) {
+                player_party->enableFollowMode();
+        }
+
+        // ---------------------------------------------------------------------
+        // Force a map update. If an npc initiates combat then the event
+        // handler will not run and do a repaint until the next event.
+        // ---------------------------------------------------------------------
+
+        mapUpdate(0);
+        foogodRepaint();
+
+        // ---------------------------------------------------------------------
+        // Return to the main loop. Combat will continue from there.
+        // ---------------------------------------------------------------------
+        return true;
+}
+
+char combatGetState(void)
+{
+        switch (Combat.state) {
+        case COMBAT_STATE_FIGHTING:
+                return 'Y';
+                break;
+        case COMBAT_STATE_DONE:
+                return 'N';
+                break;
+        case COMBAT_STATE_LOOTING:
+                return 'V';
+                break;
+        case COMBAT_STATE_CAMPING:
+                return 'K';
+                break;
+        }
+
+        return 'N';
+}
+
+int combat_add_party(class Party * party, int dx, int dy, int located,
+                     struct place *place, int x, int y)
+{
+        int added = 0;
+
+        obj_inc_ref(party);
+
+        if (!located) {
+                // Caller has not specified a location so use the normal
+                // procedure.
+                added = combat_position_enemy(party, dx, dy, false, place);
+                obj_dec_ref(party);
+                return added;
+        }
+
+        // Special case: caller wants to put the party at (x, y). Duplicate the
+        // code in combat_position_enemy except fill out the position info
+        // based on caller's request.
+        party->disembark();
+        party->remove();
+
+        memset(&party->pinfo, 0, sizeof (party->pinfo));
+        party->pinfo.place = place;
+        party->pinfo.x = x;
+        party->pinfo.y = y;
+        party->pinfo.dx = dx;
+        party->pinfo.dy = dy;
+        party->pinfo.formation = party->get_formation();
+        party->pinfo.find_party = true;
+        if (!party->pinfo.formation)
+                party->pinfo.formation = formation_get_default();
+        set_party_initial_position(&party->pinfo, x, y);
+        myPutEnemy(party, &party->pinfo);
+
+        added = party->pinfo.placed;
+
+        obj_dec_ref(party);
+
+        return added;
+
+}
+
+void combat_exit(void)
+{
+        struct place *parent = 0;
+        int x, y;
+
+        // Clean up the temporary combat place, if we used one. If we started
+        // off in combat when we loaded this session then we need to remove
+        // the temp place and temp map from the session's list of objects
+        // to save. We can tell that we need to remove them if they have
+        // non-null handles (those handles are only set by the loader, if
+        // we create the tmp place during normal game play we don't set them).
+        //
+        // Before destroying the place I have to memorize it's location for the
+        // next step.
+        if (Place->is_wilderness_combat) {
+
+                //assert(! Place->handle); // should not be top-level
+                assert(place_get_parent(Place));
+
+                if (Place->terrain_map->handle)
+                        session_rm(Session, Place->terrain_map->handle);
+
+                place_remove_and_destroy_all_objects(Place);
+                parent = place_get_parent(Place);
+                x = place_get_x(Place);
+                y = place_get_y(Place);
+                place_remove_subplace(parent, Place);
+
+                // Bugfix: Invalidate the entire map from the vmask cache. If
+                // you don't do this, then the next time the player enters
+                // combat and we start looking up vmasks we will find old,
+                // stale ones from this place, resulting in LOS bugs. That's
+                // because the keys used by the vmask are built from the name
+                // of the place, and for the combat map it is always the same
+                // name.
+                vmask_invalidate(Place, 0, 0, place_w(Place), place_h(Place));
+
+                // If this place has a handle it's in the session list and
+                // needs to be removed before we destroy it, otherwise on
+                // session reload it will be deleted again.
+                if (Place->handle)
+                        session_rm(Session, Place->handle);
+
+                place_del(Place); // map deleted in here
+                Combat.place = 0;
+
+                // ------------------------------------------------------------
+                // Relocate the player party back to the wilderness. This will
+                // handle the place switch implicitly by setting the global
+                // 'Place' pointer to the wilderness.
+                // ------------------------------------------------------------
+
+                player_party->relocate(parent, x, y);                
+
+        }
+
+        assert(NULL != player_party->getPlace());
+
+        // --------------------------------------------------------------------
+        // Force a map update. Although the map has been marked dirty by now,
+        // we will not see a repaint until the next event if we do not act
+        // now. This routine is called from the context of the main play loop,
+        // not the event loop.
+        // --------------------------------------------------------------------
+
+        //mapUpdate(0);
+        
+}
diff --git a/src/combat.h b/src/combat.h
new file mode 100644 (file)
index 0000000..5623be3
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef combat_h
+#define combat_h
+
+#define COMBAT_MAP_W    19
+#define COMBAT_MAP_H    19
+
+class Character;
+
+extern int combatInit(void);
+extern int combatLoad(class Loader *loader);
+extern char combatGetState(void);
+
+/* This is needed for walking around while zoomed out. Currently only the
+   special ^Z command (which is intended for map editing) uses it. */
+extern void combatGetCameraCenter(int *x, int *y);
+
+
+#include "player.h"            // for struct move_info
+struct combat_info {
+       int hours;              // for moving into camping
+       class Character *guard; // for moving into camping
+       bool defend;            // for moving into combat- true if PC is defending
+       bool camping;           // for moving into combat
+       struct move_info *move;
+       int pc_x;       // cache for final location of player party
+       int pc_y;
+       int npc_x;      // cache for final location of npc party
+       int npc_y;
+       int pc_dx;  // cache for final delta
+       int pc_dy;
+};
+
+enum combat_state {
+        COMBAT_STATE_FIGHTING,
+        COMBAT_STATE_LOOTING,
+        COMBAT_STATE_CAMPING,
+        COMBAT_STATE_DONE
+};
+
+extern enum combat_state combat_get_state(void);
+extern void combat_set_state(enum combat_state);
+extern void combat_reset_state(void);
+extern bool combat_enter(struct combat_info *info);
+extern bool combat_rendezvous_party(int max_path_len);
+extern void combat_exit(void);
+extern void combat_analyze_results_of_last_turn(void);
+extern void combat_fill_position_info(struct position_info *info, struct place *place, int x, int y, int dx, int dy, bool defend);
+extern bool combat_place_character(class Character * pm, void *data);
+extern int combat_add_party(class Party *party, int dx, int dy, int located,
+                            struct place *place, int x, int y);
+
+#endif
diff --git a/src/common.c b/src/common.c
new file mode 100644 (file)
index 0000000..de6db29
--- /dev/null
@@ -0,0 +1,242 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "common.h"
+#include "sky.h"
+#include "screen.h"
+#include "player.h"
+#include "foogod.h"
+#include "place.h"
+#include "event.h"
+#include "console.h"
+
+#include <stdlib.h>
+#include <time.h>
+
+int Turn;
+int Tick;
+int AnimationTicks;
+int TickMilliseconds;
+// int WindDirection;
+int ShowAllTerrain = 0;
+
+struct los *LosEngine;
+
+
+int commonInit(void)
+{
+       Turn = 0;
+       Tick = 0;
+       srand(0);
+        return 0;
+}
+
+// fixme -- obsolete, use the next one
+static const char *dir_str[] = {
+       "Northwest", "North", "Northeast",
+       "West", "Here", "East",
+       "Southwest", "South", "Southeast", 
+        "Up", "Down"
+};
+
+static unsigned char dir_facing[] = {
+       WEST, NORTH, EAST,
+       WEST, NORTH, EAST,
+       WEST, SOUTH, EAST,
+};
+
+static unsigned char dir_8facing[] = {
+       NORTHWEST, NORTH, NORTHEAST,
+       WEST, NORTH, EAST,
+       SOUTHWEST, SOUTH, SOUTHEAST,
+};
+
+static int direction_to_rotation_tbl[] = {
+       315, 0, 45,
+       270, 0, 90,
+       225, 180, 135,
+};
+
+static int directionToDxTable[] = {
+       -1, 0, +1,
+       -1, 0, +1,
+       -1, 0, +1,
+       0, 0,
+};
+
+static int directionToDyTable[] = {
+       -1, -1, -1,
+       0, 0, 0,
+       +1, +1, +1,
+       0, 0,
+};
+
+static int keyToDirectionTable[] = {
+       SOUTHWEST, SOUTH, SOUTHEAST,
+       WEST, HERE, EAST,
+       NORTHWEST, NORTH, NORTHEAST
+};
+
+const char *directionToString(int dir)
+{
+        if (dir < 0 || dir >= array_sz(dir_str))
+                return "*** invalid direction ***";
+       return dir_str[dir];
+}
+
+int stringToDirection(char *str)
+{
+       unsigned int i;
+       for (i = 0; i < array_sz(dir_str); i++) {
+               if (!strncasecmp(dir_str[i], str, strlen(dir_str[i])))
+                       return i;
+       }
+       return -1;
+}
+
+int directionToOpposite(int dir)
+{
+        static int tbl[] = {
+                SOUTHEAST,
+                SOUTH,
+                SOUTHWEST,
+                EAST,
+                HERE,
+                WEST,
+                NORTHEAST,
+                NORTH,
+                NORTHWEST,
+                DOWN,
+                UP
+        };
+
+        if (dir < 0 || dir >= array_sz(tbl))
+                return DIRECTION_NONE;
+
+        return tbl[dir];
+}
+
+int keyToDirection(int key)
+{
+       return keyToDirectionTable[key - KEY_SOUTHWEST];
+}
+
+int directionToDx(int dir)
+{
+       return directionToDxTable[dir];
+}
+
+int directionToDy(int dir)
+{
+       return directionToDyTable[dir];
+}
+
+const char *get_dir_str(int dx, int dy)
+{
+       clamp(dx, -1, 1);
+       clamp(dy, -1, 1);
+       return dir_str[(dy + 1) * 3 + dx + 1];
+}
+
+int vector_to_facing(int dx, int dy)
+{
+       clamp(dx, -1, 1);
+       clamp(dy, -1, 1);
+       return dir_facing[(dy + 1) * 3 + dx + 1];
+}
+
+int vector_to_8facing(int dx, int dy)
+{
+       if (abs(dx) > 2* (abs(dy)))
+       {
+               dy = 0; 
+       }
+       else if (abs(dy) > 2* (abs(dx)))
+       {
+               dx = 0; 
+       }
+       clamp(dx, -1, 1);
+       clamp(dy, -1, 1);
+       return dir_8facing[(dy + 1) * 3 + dx + 1];
+}
+
+int vector_to_rotation(int dx, int dy)
+{
+       clamp(dx, -1, 1);
+       clamp(dy, -1, 1);
+       return direction_to_rotation_tbl[(dy + 1) * 3 + dx + 1];
+}
+
+int vector_to_dir(int dx, int dy)
+{
+       int adx = abs(dx);
+       int ady = abs(dy);
+
+       // Note: north is in the negative x direction, south in the positive
+
+       if (ady > adx) {
+               if (dy > 0)
+                       return SOUTH;
+               else
+                       return NORTH;
+       } else {
+               if (dx > 0)
+                       return EAST;
+               else
+                       return WEST;
+       }
+}
+
+bool isvowel(char c)
+{
+       return (c == 'a' || c == 'A' ||
+               c == 'e' || c == 'E' ||
+               c == 'i' || c == 'I' ||
+               c == 'o' || c == 'O' ||
+               c == 'u' || c == 'U' || c == 'y' || c == 'Y');
+}
+
+bool point_in_rect(int x, int y, SDL_Rect *rect)
+{
+        return (x >= rect->x && 
+                y >= rect->y &&
+                x < (rect->x + rect->w) &&
+                y < (rect->y + rect->h));
+}
+
+int logBase2(int val)
+{
+        int ret = 0;
+
+        if (val<=0)
+                return 0; /* incorrect but safe */
+
+        val -= 1;
+
+        while (val) {
+                val>>=1;
+                ret++;
+        }
+
+        return ret;
+}
+
+
diff --git a/src/common.h b/src/common.h
new file mode 100644 (file)
index 0000000..c93ee43
--- /dev/null
@@ -0,0 +1,337 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef common_h
+#define common_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "list.h"
+#include "debug.h"
+#include "los.h"
+#include "dup_constants.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <SDL.h>
+
+/* Constants *****************************************************************/
+
+/* Directions */
+#define DIRECTION_NONE -1
+#define NORTHWEST 0
+#define NORTH     1
+#define NORTHEAST 2
+#define WEST      3
+#define HERE      4
+#define EAST      5
+#define SOUTHWEST 6
+#define SOUTH     7
+#define SOUTHEAST 8
+#define UP        9
+#define DOWN      10
+#define NUM_DIRECTIONS 11
+#define NUM_PLANAR_DIRECTIONS 9
+#define NUM_WIND_DIRECTIONS 9 
+#define IS_LEGAL_DIRECTION(dir) ((dir)>=0 && (dir)<NUM_DIRECTIONS)
+
+#define CANCEL    SDLK_ESCAPE
+
+/* Time -- In future, these likely come from GhulScript */
+#define TURNS_PER_MINUTE        20
+#define MINUTES_PER_HOUR        60
+#define HOURS_PER_DAY           24
+#define TURNS_PER_HOUR          (TURNS_PER_MINUTE * MINUTES_PER_HOUR)
+#define TURNS_PER_DAY           (TURNS_PER_HOUR   * HOURS_PER_DAY)
+
+#define MINUTES_PER_DAY         (MINUTES_PER_HOUR * HOURS_PER_DAY)
+#define MINUTES_PER_WEEK        (MINUTES_PER_DAY * DAYS_PER_WEEK)
+#define MINUTES_PER_MONTH       (MINUTES_PER_WEEK * WEEKS_PER_MONTH)
+#define MINUTES_PER_YEAR        (MINUTES_PER_MONTH * MONTHS_PER_YEAR)
+
+#define DAYS_PER_WEEK           7
+#define WEEKS_PER_MONTH         4
+#define MONTHS_PER_YEAR         13
+#define DAYS_PER_MONTH          (DAYS_PER_WEEK  * WEEKS_PER_MONTH)
+#define DAYS_PER_YEAR           (DAYS_PER_MONTH * MONTHS_PER_YEAR)
+#define TURNS_PER_WEEK          (DAYS_PER_WEEK  * TURNS_PER_DAY)
+#define TURNS_PER_MONTH         (DAYS_PER_MONTH * TURNS_PER_DAY)
+#define TURNS_PER_YEAR          (DAYS_PER_YEAR  * TURNS_PER_DAY)
+
+#define HOURS_OF_NIGHT          8
+#define HOURS_OF_SUNLIGHT       (HOURS_PER_DAY - HOURS_OF_NIGHT)
+#define SUNRISE_HOUR            4
+#define SUNSET_HOUR             (SUNRISE_HOUR + HOURS_OF_SUNLIGHT)
+#define NOON_HOUR               12
+#define MIDNIGHT_HOUR_LATE      24
+#define MIDNIGHT_HOUR_EARLY     0
+
+#define DEGREES_PER_HOUR        (360 / HOURS_PER_DAY)
+#define DEGREES_PER_MINUTE      (360 / MINUTES_PER_DAY)
+#define MINUTES_PER_DEGREE      (MINUTES_PER_DAY / 360)
+#define SUNRISE_DEGREE          (SUNRISE_HOUR * DEGREES_PER_HOUR)
+#define SUNSET_DEGREE           (SUNSET_HOUR  * DEGREES_PER_HOUR)
+#define NOON_DEGREE             (NOON_HOUR    * DEGREES_PER_HOUR)
+#define MIDNIGHT_DEGREE_LATE    (MIDNIGHT_HOUR_LATE  * DEGREES_PER_HOUR)
+#define MIDNIGHT_DEGREE_EARLY   (MIDNIGHT_HOUR_EARLY * DEGREES_PER_HOUR)
+
+/* Moons */
+#define NUM_MOONS                       0 /*2*/
+#define MOON_WINDOW_DEGREES             (HOURS_OF_SUNLIGHT * DEGREES_PER_HOUR)
+#define MOON_WINDOW_PIXELS_PER_DEGREE   1      /* needs to be an integer */
+#define MOON_WINDOW_W     (MOON_WINDOW_PIXELS_PER_DEGREE *      \
+                                         MOON_WINDOW_DEGREES)
+#define MOON_HOURS_PER_REVOLUTION       (HOURS_PER_DAY - 1)
+#define MOON_DEGREES_PER_HOUR           (360 / MOON_HOURS_PER_REVOLUTION)
+#define MOON_DEGREES_PER_MINUTE         (MOON_DEGREES_PER_HOUR * 60)
+#define MOON_MINUTES_PER_DEGREE         ((MOON_HOURS_PER_REVOLUTION * 60) / 360)
+#define MOON_PIXELS_PER_HOUR            (MOON_DEGREES_PER_HOUR *              \
+                                         MOON_WINDOW_PIXELS_PER_DEGREE)
+#define TURNS_PER_MOON_CYCLE            (TURNS_PER_DAY * 30)
+#define MOON_TURNS_PER_DEGREE           (TURNS_PER_HOUR /                     \
+                                         MOON_DEGREES_PER_HOUR)
+#define SUN_DEGREES_PER_HOUR            (360 / 24)
+#define SUN_TURNS_PER_DEGREE            (TURNS_PER_HOUR /                     \
+                                         SUN_DEGREES_PER_HOUR)
+
+/* Font info */
+#define FONT_FILENAME   "fonts/cour.ttf"
+#define FONT_PTSIZE      14
+#define FONT_STYLE       TTF_STYLE_NORMAL
+
+/* Timing */
+#define ANIMATION_TICKS  10    /* Ticks between animation frame changes */
+#define MS_PER_TICK      100
+
+/* Misc */
+#define TURNS_TO_FIRE_VEHICLE_WEAPON    2
+#define APPLICATION_NAME        "Nazghul"
+#define WIND_CHANGE_PROBABILITY 5
+#define PLAYER_MAX_PROGRESS     100
+#define STAT_TEXT_LEN           ((STAT_W - TILE_W) / ASCII_W)
+#define MAX_NAME_LEN            STAT_TEXT_LEN
+#define MIN_VISION_RADIUS       1
+#define HP_PER_LVL              30
+#define MAX_ATTRIBUTE_VALUE     999
+
+// MAX_VISION_RADIUS must be <= MAX_SIGHT in angband.c, but it cannot be
+// greater than the map viewer. The reason it can't be greater than the map
+// viewer is because we set our visibility mask to be the same dimensions as
+// the map viewer, and if we let the LOS alg exceed these dimensions it will
+// produce artifacts on the vmask.
+//#define MAX_VISION_RADIUS       (MAP_TILE_W / 2)
+#define MAX_VISION_RADIUS       (MAP_TILE_W)
+#define MAX_VIEWPORT_RANGE      (MAX_VISION_RADIUS + (MAX_VISION_RADIUS / 2))
+
+#define FRAME_IMAGE             "images/frame.bmp"
+#define SPLASH_IMAGE            "images/splash.bmp"
+#define MAX_WORDS_IN_SPELL_NAME  4
+
+/* The maximum intensity of ambient sunlight. No point making it more than 255
+ * because the lightmap only allows tiles to have a max value of 255.*/
+#define MAX_AMBIENT_LIGHT       255
+#define MAX_SUNLIGHT            255
+#define MAX_MOONLIGHT           128
+
+/* The minimum amount of light the player generates. This is so that the user
+       * can at least see the player icon in total darkness. */
+#define MIN_PLAYER_LIGHT        8 /*128*/
+
+// The sun sprite is SKY_SPRITE_W pixels wide, and it advances
+// MOON_WINDOW_PIXELS_PER_DEGREE every time it moves, and I want its luminence
+// to drop to zero by the time it passes out of sight of the sky window.
+#define DELTA_SUNLIGHT          (MAX_SUNLIGHT / \
+                                 (SKY_SPRITE_W * MOON_WINDOW_PIXELS_PER_DEGREE))
+
+#define TURNS_PER_FOOD          (TURNS_PER_DAY/3)
+#define MAX_SPEED               100
+#define WILDERNESS_SCALE        32
+#define NON_WILDERNESS_SCALE     1
+#define MAX_N_REAGENTS          32
+
+/* Resting */
+#define HP_RECOVERED_PER_HOUR_OF_REST   3
+#define MANA_RECOVERED_PER_HOUR_OF_REST 10
+#define PROB_AWAKEN                     25
+
+/* My events */
+#define TICK_EVENT              1
+
+/* Damages */
+#define DAMAGE_FIRE       10
+#define DAMAGE_POISON     1
+#define DAMAGE_STARVATION 1
+#define DAMAGE_ACID       10
+#define DAMAGE_BOMB       25
+
+/* Targets */
+#define TARG_NONE       0
+#define TARG_SELF       1
+#define TARG_FRIEND     2
+
+/* Type ID's (TIDs) */
+#define OBJECT_ID               1
+#define VEHICLE_ID              (OBJECT_ID + 1)
+#define CHARACTER_ID            (OBJECT_ID + 2)
+#define MOONGATE_ID             (OBJECT_ID + 3)
+#define PORTAL_ID               (OBJECT_ID + 4)
+#define PARTY_ID                (OBJECT_ID + 5)
+
+#define SPRITE_ID               (OBJECT_ID + 7)
+#define OBJECT_TYPE_ID          100
+#define ARMS_TYPE_ID            101
+#define ITEM_TYPE_ID            102
+#define VEHICLE_TYPE_ID         103
+#define ORDNANCE_TYPE_ID        104
+#define CHARACTER_TYPE_ID       105
+#define ENTITY_TYPE_ID          106
+#define MOONGATE_TYPE_ID        107
+#define REAGENT_TYPE_ID         108
+#define SPELL_TYPE_ID           109
+#define MISSILE_TYPE_ID         110 //repurposed from unused AMMO_TYPE_ID
+#define FIELD_TYPE_ID           111
+#define FOOD_TYPE_ID            112
+#define TRAP_TYPE_ID            113
+#define PARTY_TYPE_ID           114
+
+#define RESPONSE_TYPE_ID        116
+#define CONVERSATION_TYPE_ID    117
+#define OCC_ID                  118
+#define SPECIES_ID              119
+#define SCHEDULE_ID             120
+#define PLACE_ID                121
+#define MAP_ID                  122
+
+#define TERRAIN_PALETTE_ID      124
+#define TERRAIN_ID              125
+#define MECH_TYPE_ID            126
+#define MECH_ID                 127
+#define IMAGES_ID               128
+#define FORMATION_TYPE_ID       129
+
+/* Services (loadfile must match) */
+#define SRV_HEAL        1
+#define SRV_CURE        2
+#define SRV_RESURRECT   3
+#define SRV_MIN         SRV_HEAL
+#define SRV_MAX         SRV_RESURRECT
+
+/* Contexts */
+#define CONTEXT_WILDERNESS 1
+#define CONTEXT_TOWN       2
+
+/* Spells (loadfile must match) */
+#define SPELL_TARGET_NONE              0
+#define SPELL_TARGET_CHARACTER         1
+#define SPELL_TARGET_MECH              2
+#define SPELL_TARGET_DIRECTION         3
+#define SPELL_TARGET_LOCATION          4
+#define SPELL_TARGET_UP                5
+#define SPELL_TARGET_DOWN              6
+#define SPELL_TARGET_ALL_PARTY_MEMBERS 7
+#define SPELL_TARGET_CASTER_LOCATION   8
+#define SPELL_TARGET_PARTY_MEMBER      9
+
+// Compile-time configuration parameters
+#define CONFIG_MOVEMENT_COST_FOR_CHARACTERS false
+
+/* Action point values (temporary - should be moved to the load file) */
+// #define NAZGHUL_BASE_ACTION_POINTS  50 // SAM: should be obsolete now, with the use of kern_intvar_get()
+
+/* Hard-coded experience point values */
+#define COMBAT_VICTORY_XP 5
+
+/* Hard-coded drop probabilities */
+#define ITEM_DROP_PROB    25   /* 25% chance to drop readied items */
+#define CHEST_DROP_PROB   25   /* 25% chance to drop container     */
+
+/* Macros ********************************************************************/
+
+#define perror_sdl(msg) err("%s: %s\n", (msg), SDL_GetError())
+// #define perror_sdl(msg) fprintf(stderr, "%s:%s\n", (msg), SDL_GetError())
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#define clamp(v,a,b) ((v) = (v) < (a) ? (a) : ((v) > (b) ? (b) : (v)))
+#define array_sz(a) (int)(sizeof((a))/sizeof((a)[0]))
+#define outcast(ptr,type,field) \
+        ((type*)((char*)(ptr)-(unsigned long)(&((type *)0)->field)))
+#define CREATE(ptr,type,err) \
+  (ptr) = (type*)malloc(sizeof(type)); \
+  if (!(ptr)) \
+    return (err); \
+  memset((ptr), 0, sizeof(type));
+#define distance(dx,dy) (((dx)>(dy)) ? ((dx)+((dy)>>1)) : ((dy)+ (dx)>>1)))
+
+
+// SAM: The below are used by palette_print(), terrain_map_print(), etc.
+#define INITIAL_INDENTATION   0
+#define INDENTATION_FACTOR    2
+#define INDENT fprintf(fp, "%*s", indent, "")
+
+/* Enums *********************************************************************/
+
+typedef enum {
+        UI_SIZE_NORMAL = 0,
+        UI_SIZE_SMALL = 1
+} ui_size_t;
+
+/* Structures ****************************************************************/
+
+/* Global Functions **********************************************************/
+
+char * version_as_string(void);  // From nazghul.c
+
+extern int commonInit(void);
+extern const char *get_dir_str(int dx, int dy);
+extern void turnAdvance(int turns);
+extern int vector_to_dir(int dx, int dy);
+extern int vector_to_facing(int dx, int dy);
+extern int vector_to_rotation(int dx, int dy);
+extern int vector_to_8facing(int dx, int dy);
+
+extern int stringToDirection(char *str);
+extern int keyToDirection(int key);
+extern int directionToDx(int dir);
+extern int directionToDy(int dir);
+extern const char *directionToString(int dir);
+extern bool isvowel(char c);
+extern bool point_in_rect(int x, int y, SDL_Rect *rect);
+extern int directionToOpposite(int dir);
+
+#define keyIsDirection(key) ((key) >= KEY_SOUTHWEST && (key) <= KEY_NORTHEAST)
+
+/* Global Variables **********************************************************/
+
+extern int Turn;
+extern int AnimationTicks;
+extern int Tick;
+extern int TickMilliseconds;
+extern bool Quit;
+extern struct los *LosEngine;
+extern int ShowAllTerrain;
+extern int logBase2(int val);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/console.c b/src/console.c
new file mode 100644 (file)
index 0000000..49c2fd7
--- /dev/null
@@ -0,0 +1,460 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "console.h"
+#include "screen.h"
+#include "common.h"
+#include "sprite.h"
+#include "play.h"
+#include "event.h"
+#include "cmd.h" // for getkey()
+#include "foogod.h"  // for foogod_get_y()
+
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+
+#define MAX_MSG_SZ 512
+#define CONS_BUF_SIZE (CONS_LINES * (CONSOLE_MAX_MSG_SZ + 1))
+
+static struct console {
+        SDL_Rect screenRect;
+        char *buf;             /* text buffer */
+        char **lines;          /* pointers into buf, one per line */
+        int line;              /* current line index */
+        char *cursor;          /* next byte on current line */
+        int room;              /* bytes left on current line */
+        int numLines;          /* num lines filled + current line */
+
+        int firstLine;         // index into 'lines' array of the first filled
+                               // line (the lines array is a circular buffer, *
+                               // so once all the lines are filled this value *
+                               // advances every time the 'line' value *
+                               // advances)
+
+        int repeat;           // counts number of times last line repeats
+
+#ifdef DEBUG
+        FILE *log;
+#endif
+} Console;
+
+static char console_scratch_buf[MAX_MSG_SZ + 1];
+static char console_last_msg[MAX_MSG_SZ + 1];
+
+static void consoleNewline(void);
+
+static int consolePage(void)
+{
+        int yesno = 1;
+
+        consolePrint("---More-Y/N?");
+        consoleRepaint();
+        getkey(&yesno, yesnokey);
+        consoleBackspace(12);
+        return yesno == 'y';
+}
+
+int consoleInit(void)
+{
+        int i;
+
+        Console.screenRect.x = CONS_X;
+        Console.screenRect.w = CONS_W;
+
+        //console_set_y(foogod_get_y() + FOOGOD_H + BORDER_H);
+
+        Console.buf = (char *)malloc(CONS_BUF_SIZE);
+        if (! Console.buf)
+                return -1;
+        memset(Console.buf, 0, CONSOLE_MAX_MSG_SZ + 1);
+
+        Console.cursor = Console.buf;
+        Console.room = CONSOLE_MAX_MSG_SZ;
+        Console.line = 0;
+        Console.firstLine = 0;
+        Console.repeat = 0;
+
+        /* Unintuitively, numLines must begin with 1. I only advance it for
+         * newlines, and if someone prints text on the very first line without
+         * issuing a newline then it needs to be rendered in the repaint
+         * routine. In other words, I always pretend that the current line has
+         * something on it. */
+        Console.numLines = 1;
+        Console.lines = (char**)malloc(CONS_LINES * sizeof(char*));
+        if (!Console.lines)
+                return -1;
+        for (i = 0; i < CONS_LINES; i++)
+                Console.lines[i] = &Console.buf[i * (CONSOLE_MAX_MSG_SZ + 1)];
+
+#ifdef DEBUG
+       /* Open the console log file. */
+       Console.log = fopen(".console", "w");
+       if (Console.log == NULL) {
+               perror(".console");
+       }
+#endif
+
+        return 0;
+}
+
+static int console_handle_repeated_msg(void)
+{
+
+        // Is this a repeat?
+        if (strchr(console_scratch_buf, '\n') == 0 ||
+            (strcmp(console_scratch_buf, console_last_msg) != 0) ||
+            (strcmp(console_scratch_buf, "\n") == 0)) {
+
+                // No. Was the previous message a repeat?
+                if (Console.repeat != 0) {
+                        // Yes, So we need to advance past the 'repeat' msg
+                        // which occupies its own line
+                        consoleNewline();
+                }
+                // Setup for new msg.
+                Console.repeat = 0;
+                strcpy(console_last_msg, console_scratch_buf);
+                return 0;
+        }
+
+        // Yes, this is a repeat.
+        Console.repeat++;
+
+        // Is this the first repeat for the msg?
+        if (Console.repeat == 1) {
+                // Yes. Are we at the beginning of a new line?
+                if (Console.room != CONSOLE_MAX_MSG_SZ) {
+                        // No. So advance to a new line.
+                        consoleNewline();
+                }
+                // Print the repeat notice for the first time.
+                snprintf(Console.lines[Console.line], CONSOLE_MAX_MSG_SZ, 
+                         "[again]");
+                Console.room -= strlen(Console.lines[Console.line]);
+                Console.cursor += strlen(Console.lines[Console.line]);
+
+        } else {
+                // No. This is not the first time we've repeated this
+                // msg. Erase the previous 'repeat' notice and print a new one
+                // with the updated repeat count.
+                memset(Console.lines[Console.line], 0, CONSOLE_MAX_MSG_SZ + 1);
+                snprintf(Console.lines[Console.line], CONSOLE_MAX_MSG_SZ,
+                         "[%d times]", Console.repeat);
+        }
+
+        consoleRepaint();
+
+        return 1;
+}
+
+void consolePrint(const char *fmt, ...)
+{
+        int printed;
+        va_list args;
+        char *ptr, *eow;
+        int n_lines = 0, wlen;
+        int words = 0;
+        int wrapped;
+
+        /* Print message to the scratch buffer */
+        va_start(args, fmt);
+        printed = vsnprintf(console_scratch_buf, MAX_MSG_SZ, fmt, args);
+        va_end(args);
+
+#ifdef DEBUG
+        if (Console.log != NULL)
+                vfprintf(Console.log, fmt, args);
+#endif
+
+        /* Check if message was truncated to fit. Note that I discard anything
+         * that will not fit. */
+        if (printed == -1)
+                printed = MAX_MSG_SZ;
+
+        // Is this a repeat of the last msg?
+        if (console_handle_repeated_msg())
+                // Yes. Already handled.
+                return;
+
+        /* 
+         * Now transfer the contents of the scratch buffer to the line
+         * buffers. I use the following rules:
+         * 
+         * 1. A word is a run of non-ws chars.
+         * 
+         * 2. When starting a new line after wrapping discard FIRST initial ws.
+         * 
+         * 3. When starting a new line print the first word. If the first will
+         * not fit on the line then print as much as possible and start a new
+         * line with the remainder.
+         * 
+         * 4. After printing a word print all whitespace up to the next word or
+         * the end of the current line.
+         * 
+         * 5. After printing ws probe the next word to find it's length. If the
+         * word will not fit then start a new line and apply rule 3. Otherwise
+         * print the word and apply rule 4.
+         * 
+         * 6. After starting a new line check if the message window is full. If
+         * so then prompt the user before continuing. This gives the user a
+         * chance to read everything printed thus far.
+         * 
+         * 7. All but the first newline are indented by a space to help make
+         * visual blocks of text.
+         * 
+         */
+        ptr = console_scratch_buf;
+
+        wrapped = 0;
+
+        /* copy from the super buffer to the line buffer(s) */
+        while (printed) {
+
+                /* Check if this is the start of a new line and if so then
+                 * apply rules 2 and 3. */
+                if (Console.room == CONSOLE_MAX_MSG_SZ) {
+
+                        /* Rule 2 */
+                        while (isspace(*ptr) && printed) {
+
+                                if (!wrapped) {
+                                        if (*ptr == '\n') {
+                                                ptr++;
+                                                printed--;
+                                                goto newline;
+                                        }
+
+                                        /* copy the char */
+                                        *Console.cursor = *ptr;
+                                        Console.room--;
+                                        Console.cursor++;
+                                }
+                                wrapped = 0;
+                                ptr++;
+                                printed--;
+                        }
+
+                        /* Rule 3 */
+                        while (!isspace(*ptr) && printed && Console.room) {
+
+                                /* copy the char */
+                                *Console.cursor = *ptr;
+
+                                /* advance source and destination */
+                                printed--;
+                                ptr++;
+                                Console.room--;
+                                Console.cursor++;
+                        }
+
+                        words++;
+
+                        /* Check for end-of-line */
+                        if (!Console.room) {
+                                wrapped = 1;
+                                goto newline;
+                        }
+
+                }
+
+                /* Ok. We have already printed at least one word on this line
+                 * and now need to apply Rule 4: print all ws up to end-of-line
+                 * or start-of-word. */
+
+                wrapped = 0;
+
+                while (isspace(*ptr) && Console.room && printed) {
+
+                        if (*ptr == '\n') {
+                                ptr++;
+                                printed--;
+                                goto newline;
+                        }
+
+                        /* copy the char */
+                        *Console.cursor = *ptr;
+
+                        /* advance source and destination */
+                        printed--;
+                        ptr++;
+                        Console.room--;
+                        Console.cursor++;
+                }
+
+                if (!Console.room) {
+                        wrapped = 1;
+                        goto newline;
+                }
+
+                if (!printed)
+                        break;
+
+                /* All right. At this point I know I have space left and
+                 * another word to print. Rule 5. */
+                eow = strpbrk(ptr, " \t\n\r");
+                if (eow)
+                        wlen = eow - ptr;
+                else
+                        wlen = printed;
+
+                if (wlen > Console.room) {
+                        wrapped = 1;
+                        goto newline;
+                }
+
+                while (wlen) {
+                        /* copy the char */
+                        *Console.cursor = *ptr;
+
+                        /* advance source and destination */
+                        printed--;
+                        ptr++;
+                        Console.room--;
+                        Console.cursor++;
+                        wlen--;
+                }
+
+                words++;
+
+                continue;
+
+              newline:
+
+                /* advance to the next line */
+                consoleNewline();
+                n_lines++;
+
+                /* Rule 6 */
+                if (n_lines == (CONS_LINES - 1)) {
+                        if (!consolePage())
+                                return;
+                        n_lines = 0;
+                }
+
+                /* Start of new line so go back to top-of-loop so I can run the
+                 * start-of-line code. */
+                continue;
+        }
+
+        consoleRepaint();
+}
+
+void consoleBackspace(int n)
+{
+        int len;
+
+        /* Don't allow backspace beyond end of prompt */
+        len = CONSOLE_MAX_MSG_SZ - Console.room;
+        if (len > n)
+                len = n;
+
+        /* Backup */
+        Console.cursor -= len;
+        Console.room += len;
+
+        /* Erase everything beyond the Console.cursor */
+        memset(Console.cursor, 0, Console.room);
+        // *Console.cursor = 0;
+
+#ifdef DEBUG
+        if (Console.log != NULL)
+                fprintf(Console.log, "\b");
+#endif
+}
+
+static void consoleNewline(void)
+{
+  Console.line = (Console.line + 1) % CONS_LINES;
+
+  if (Console.numLines < (CONS_LINES))
+          Console.numLines++;
+  else
+          Console.firstLine = (Console.firstLine + 1) % CONS_LINES;
+
+  Console.cursor = Console.lines[Console.line];
+  
+  memset(Console.cursor, 0, CONSOLE_MAX_MSG_SZ + 1);
+  Console.room = CONSOLE_MAX_MSG_SZ;
+  
+#ifdef DEBUG
+  if (Console.log != NULL)
+          fprintf(Console.log, "\n");
+#endif
+  
+  //consoleRepaint();
+}
+
+void consoleRepaint(void)
+{
+        SDL_Rect rect;
+        int n_lines;
+        int max_lines;
+        int line;
+
+        //screenErase(&Console.screenRect);
+
+        rect.x = Console.screenRect.x;
+        rect.w = Console.screenRect.w;
+        rect.y = console_get_y();
+        rect.h = console_get_h();
+
+        screenErase(&rect);
+
+        max_lines = rect.h / ASCII_H;
+        n_lines = min(Console.numLines, max_lines);
+
+        /* Find the first visible line in the line buffer by backing up from
+         * the current line. If I need to back up past the beginning then wrap
+         * around to the end. */
+        if (n_lines > (Console.line + 1)) {
+                line = CONS_LINES - (n_lines - (Console.line + 1));
+        } else {
+                line = (Console.line + 1) - n_lines;
+        }
+
+        while (n_lines--) {
+                screenPrint(&rect, 0, Console.lines[line]);
+                line = (line + 1) % CONS_LINES;
+                rect.y += ASCII_H;
+        }
+
+        screenUpdate(&Console.screenRect);
+}
+
+int console_get_y(void)
+{
+        return (foogod_get_y() + foogod_get_h());
+}
+
+int console_get_h(void)
+{
+        return (SCREEN_H - BORDER_H - console_get_y());
+}
+
+int console_max_lines (void) {
+        int max_lines;
+
+        max_lines = Console.screenRect.h / ASCII_H;
+        return min(Console.numLines, max_lines);
+}
diff --git a/src/console.h b/src/console.h
new file mode 100644 (file)
index 0000000..d3b7995
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef console_h
+#define console_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       extern int consoleInit(void);
+       extern void consolePrint(const char *fmt, ...);
+       extern void consoleBackspace(int n);
+       //extern void consoleNewline(void);
+       extern void consoleRepaint(void);
+       //extern void console_set_y(int y);
+       extern int console_get_y(void);
+       extern int console_get_h(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/constants.h b/src/constants.h
new file mode 100644 (file)
index 0000000..47b703a
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef constants_h
+#define constants_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 
+ * User-defined event types
+ */
+
+/*
+ * Defaults for configurable parameters.
+ */
+#define DEFAULT_SCREEN_WIDTH          640
+#define DEFAULT_SCREEN_HEIGHT         480
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/conv.c b/src/conv.c
new file mode 100644 (file)
index 0000000..bce92b1
--- /dev/null
@@ -0,0 +1,1015 @@
+#ifndef TEST_PORTRAITS
+
+
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+#include "character.h"
+//
+
+#include "bitset.h"
+#include "conv.h"
+#include "cfg.h"
+#include "event.h"
+#include "cmdwin.h"
+#include "common.h"
+#include "object.h"
+#include <string.h>
+#include "closure.h"
+#include "log.h"
+#include "scheme-private.h" /* for keyword processing */
+#include "session.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define MAX_KEYWORD_SZ 16
+
+/**
+ * Conversation structure.
+ */
+struct conv {
+    struct closure *proc; /* Closure which responds to keywords. */
+    int ref; /* Reference count. */
+    int n_keywords; /* Size of the keywords array. */
+    char **keywords; /* Keyword array. */
+    bitset_t *marked; /* Used keywords */
+};
+
+static int conv_room, conv_len;
+static char conv_query[64], *conv_ptr;
+static int conv_done;
+static int conv_keyword_highlighting = 1;
+
+/**
+ * Keyhandler callback for processing player keystrokes while collecting the
+ * query string. This stores typed characters into the conv_query buffer.
+ *
+ * @param kh is the keyhandler pushed for input handling.
+ * @param key is the key the player just typed.
+ * @returns 1 if the player is done entering the query, else 0.
+ */
+static int conv_get_player_query(struct KeyHandler *kh, int key, int keymod)
+{
+       if (key == CANCEL) {
+               while (conv_ptr > conv_query) {
+                       conv_ptr--;
+                       *conv_ptr = 0;
+                       cmdwin_pop();
+                       conv_room++;
+               }
+               return 1;
+       }
+
+       if (key == '\n') {
+               return 1;
+       }
+
+       if (key == '\b') {
+               if (conv_ptr != conv_query) {
+                       conv_ptr--;
+                       *conv_ptr = 0;
+                       conv_room++;
+                       cmdwin_pop();
+               }
+               return 0;
+       }
+
+       if (isprintable(key) 
+            && conv_room) {
+               cmdwin_push("%c", key);
+               *conv_ptr++ = key;
+               conv_room--;
+       }
+
+       return 0;
+}
+
+
+/**
+ * Force the player query to a value. This is mainly done to start the
+
+ * conversation off with the "HAIL" keyword.
+ *
+ * @param str is the query value to set.
+ */
+static void conv_set_query(const char *str)
+{
+       snprintf(conv_query, sizeof(conv_query) - 1, "%s", str);
+       conv_query[MAX_KEYWORD_SZ] = 0;
+       conv_len = strlen(conv_query);
+}
+
+/**
+ * Internal destructor for a conversation struct.
+ *
+ * @param conv is the conversation to delete.
+ */
+static void conv_del(struct conv *conv)
+{
+        if (conv->proc) {
+                closure_unref(conv->proc);
+        }
+
+        if (conv->keywords) {
+
+                int i;
+
+                for (i = 0; i < conv->n_keywords; i++) {
+                        if (conv->keywords[i]) {
+                                free(conv->keywords[i]);
+                        }
+                }
+
+                free(conv->keywords);
+        }
+
+        if (conv->marked) {
+                bitset_free(conv->marked);
+        }
+
+        free(conv);
+}
+
+/**
+ * Callback used by the sort function to compare two values.
+ *
+ * @param p1 is one value.
+ * @param p2 is the other value.
+ * @returns 1 if p1>p2, 0 if p1==p2, -1 if p1<p2.
+ */
+static int conv_sort_cmp(const void *p1, const void *p2)
+{
+   return strcmp(*(char* const*)p1, *(char* const*)p2);
+}
+
+/**
+ * Function used by the binary search in conv_is_keyword.
+ *
+ * @param wptr is the word to look for.
+ * @param cptr is the keyword to compare against.
+ * @returns 0 is cptr is a prefix of wptr; -1 if wptr < cptr; 1 if wptr > cptr.
+ */
+static int conv_prefix_cmp(char *wptr, char *cptr)
+{
+        int len = 0;
+
+        while (*wptr && *cptr) {
+                char wc = tolower(*wptr++);
+                char cc = tolower(*cptr++);
+                len++;
+                int d = wc - cc;
+                if (d != 0) {
+                        return d;
+                }
+        }
+
+        if (*cptr && ! *wptr) {
+                /* candidate is longer than word */
+                return -1;
+        }
+
+        if (*wptr && !isspace(*wptr) && !ispunct(*wptr) && len < 4) {
+                /* candidate is short but word is not */
+                return 1;
+        }
+
+        return 0;
+}
+
+/**
+ * Check if a word is a keyword.
+ *
+ * @conv is the conversation to check.
+ * @word is the word to look for in the keywords.
+ * @returns the index of the matching keyword, else -1 if not found.
+ */
+static int conv_lookup_keyword(struct conv *conv, char *word)
+{
+        int min = 0, max = conv->n_keywords, pivot;
+
+        while (max > min) {
+
+                /**
+                 * apricot
+                 *
+                 * aardvark
+                 * abacus
+                 *
+                 * zoo
+                 * zebra
+                 */
+
+                pivot = ((max-min)/2) + min;
+                
+                int d = conv_prefix_cmp(word, conv->keywords[pivot]);
+                
+                if (d > 0) {
+                        /* word > pivot => search higher */
+                        min = pivot + 1;
+                } else if (d < 0) {
+                        /* word < pivot => search lower */
+                        max = pivot;
+                } else {
+                        return pivot;
+                }
+        }
+
+        return -1;
+}
+
+/**
+ * Check if a word is a keyword and, if so, to mark it (marking is used to show
+ * the player which keywords have already been used in a conversation).
+ *
+ * @conv is the conversation to check.
+ * @word is the word to look for in the keywords.
+ */
+static void conv_mark_if_keyword(struct conv *conv, char *word)
+{
+        int index = conv_lookup_keyword(conv, word);
+        if (index != -1) {
+                bitset_set(conv->marked, index);
+        }
+}
+
+static int conv_add_keyword(struct conv *conv, char *keyword, int key_index)
+{
+    assert(key_index < conv->n_keywords);
+    if (!(conv->keywords[key_index] = strdup(keyword))) {
+        warn("%s: strdup failed on %s", __FUNCTION__, keyword);
+        return -1;
+    }
+    return 0;
+}
+
+static void conv_sort_keywords(struct conv *conv)
+{
+        qsort(conv->keywords, conv->n_keywords, sizeof(char*), conv_sort_cmp);
+}
+
+static void conv_highlight_keywords(struct conv *conv)
+{
+    int key_index = 0;
+    scheme *sc = conv->proc->sc;
+    pointer sym = conv->proc->code;
+    
+    assert(sc);
+    assert(sym);
+
+    if (sym == sc->NIL) {
+        warn("%s: conv proc not a symbol", __FUNCTION__);
+        return;
+    }
+
+    pointer ifc = sc->vptr->find_slot_in_env(sc, sc->envir, sym, 1);
+    if (! scm_is_pair(sc, ifc)) {
+        warn("%s: conv '%s' has no value", __FUNCTION__, scm_sym_val(sc, sym));
+        return;
+    }
+
+    pointer clos = scm_cdr(sc, ifc);
+    if (! scm_is_closure(sc, clos)) {
+        warn("%s: conv '%s' not a closure", __FUNCTION__, scm_sym_val(sc, sym));
+        return;
+    }
+
+    pointer env = scm_cdr(sc, clos);
+    pointer vtable = scm_cdr(sc, scm_car(sc, scm_car(sc, env)));
+
+    conv->n_keywords = scm_len(sc, vtable);
+
+    if (!(conv->keywords = (char**)calloc(conv->n_keywords, sizeof(char*)))) {
+        warn("%s: failed to allocate keyword array size %d", __FUNCTION__, conv->n_keywords);
+        return;
+    }
+
+    if (!(conv->marked = bitset_alloc(conv->n_keywords))) {
+        warn("%s: failed to allocate bitset array size %d", __FUNCTION__, conv->n_keywords);
+        return;
+    }
+
+    while (scm_is_pair(sc, vtable)) {
+        pointer binding = scm_car(sc, vtable);
+        vtable = scm_cdr(sc, vtable);
+        pointer var = scm_car(sc, binding);
+        if (conv_add_keyword(conv, scm_sym_val(sc, var), key_index)) {
+            return;
+        }
+        key_index++;
+    }
+
+    conv_sort_keywords(conv);
+}
+
+struct conv *conv_new(struct closure *proc)
+{
+        struct conv *conv;
+
+        if (!(conv = (struct conv*)calloc(1, sizeof(*conv)))) {
+                return NULL;
+        }
+
+        conv->ref = 1;
+        conv->proc = proc;
+        closure_ref(proc);
+
+        return conv;
+}
+
+void conv_save(struct conv *conv, struct save *save)
+{
+        closure_save(conv->proc, save);
+}
+
+void conv_unref(struct conv *conv)
+{
+        assert(conv->ref>0);
+        conv->ref--;
+        if (!conv->ref) {
+                conv_del(conv);
+        }
+}
+
+void conv_ref(struct conv *conv)
+{
+        conv->ref++;
+}
+
+void conv_end()
+{
+        conv_done = 1;
+}
+
+void conv_enter(Object *npc, Object *pc, struct conv *conv)
+{
+       struct KeyHandler kh;
+
+        assert(conv);
+
+        if (! conv->keywords && conv_keyword_highlighting) {
+            conv_highlight_keywords(conv);
+        }
+
+        /* If NPC initiates conversation, make sure we have a valid session
+         * subject, else describe() will crash when determining if unknown NPC
+         * is hostile or not. */
+        if (! Session->subject) {
+            Session->subject = (class Being*)pc;
+        }
+
+       log_banner("^c+yCONVERSATION^c-");
+
+        session_run_hook(Session, conv_start_hook, "pp", pc, npc);
+
+        conv_done = 0;
+       kh.fx = conv_get_player_query;
+       conv_set_query("hail");
+
+       for (;;) {
+
+                /* Truncate the query to 4 characters */
+                conv_query[4] = 0;
+
+                conv_mark_if_keyword(conv, conv_query);
+
+                /* If query was NAME, assume the NPC is now known */
+                if (!strcasecmp(conv_query, "NAME")) {
+                        ((class Character*)npc)->setKnown(true);
+                }
+
+                /* Query the NPC */
+                closure_exec(conv->proc, "ypp", conv_query, npc, pc);
+
+               if (conv_done)
+                       break;
+
+               /*** Setup for next query ***/
+
+               memset(conv_query, 0, sizeof(conv_query));
+               conv_room = sizeof(conv_query) - 1;
+               conv_ptr = conv_query;
+
+               cmdwin_clear();
+               cmdwin_push("Say: ");
+
+               /*** Get next query ***/
+
+               eventPushKeyHandler(&kh);
+               eventHandle();
+               eventPopKeyHandler();
+
+               conv_query[MAX_KEYWORD_SZ] = 0;
+               conv_len = strlen(conv_query);
+                if (! conv_len)
+                        sprintf(conv_query, "bye");
+               log_msg("^c+%c%s:^c- %s", CONV_PC_COLOR, 
+                        pc->getName(), conv_query);
+
+               /*** Check if player ended conversation ***/
+
+               if (Quit)
+                       break;
+
+               if (strlen(conv_query) == 0)
+                       conv_set_query("BYE");
+
+               if (!strcasecmp(conv_query, "BYE")) {
+                       conv_end();
+               }
+
+       }
+
+       cmdwin_clear();
+       cmdwin_repaint();
+
+        session_run_hook(Session, conv_end_hook, "pp", pc, npc);
+        
+}
+
+int isprintable(int c)
+{
+        /* Looks like ctype's isprint() doesn't always behave the same way. On
+         * some systems it was letting c<32 go through, causing an assert in
+         * ascii.c. */
+        return ((c >= 32)
+                && (c < 127)
+                && (c != '%') /* printf special char */
+                && (c != '^') /* ascii.c special char */
+                );
+}
+
+int conv_get_word(char *instr, char **beg, char **end)
+{
+        char *inp = instr;
+
+        while (*inp && !isalpha(*inp)) {
+                inp++;
+        }
+
+        if (!*inp) {
+                return 0;
+        }
+
+        *beg = inp;
+
+        while (*inp && isalpha(*inp)) {
+                inp++;
+        }
+
+        *end = inp;
+
+        return 1;
+}
+
+int conv_is_keyword(struct conv *conv, char *word)
+{
+        int index;
+
+        if (! conv_keyword_highlighting) {
+                return 0;
+        }
+
+        index = conv_lookup_keyword(conv, word);
+        if (index == -1) {
+                return 0;
+        }
+        return CONV_IS_KEYWORD | (bitset_tst(conv->marked, index) ? CONV_IS_MARKED : 0);
+}
+
+int conv_init(void)
+{
+        char *val = cfg_get("keyword-highlighting");
+        if (!val || strcasecmp(val, "yes")) {
+                conv_keyword_highlighting = 0;
+        }
+        return 0;
+}
+
+void conv_enable_keyword_highlighting(int enable)
+{
+        conv_keyword_highlighting = !!enable;
+}
+
+#else /* TEST_PORTRAITS */
+
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "applet.h"
+#include "bitset.h"
+#include "conv.h"
+#include "event.h"
+#include "cmdwin.h"
+#include "common.h"
+#include "object.h"
+#include "closure.h"
+#include "log.h"
+#include "session.h"
+#include "sprite.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_KEYWORD_SZ 16
+
+#define PORTRAIT_H 192
+#define PORTRAIT_W 184
+
+/**
+ * Conversation structure.
+ */
+struct conv {
+        struct closure *proc; /* Closure which responds to keywords. */
+        int ref; /* Reference count. */
+        int n_keywords; /* Size of the keywords array. */
+        int key_index; /* Index of next empty keyword slot. */
+        char **keywords; /* Keyword array. */
+        bitset_t *marked; /* Used keywords */
+};
+
+struct conv_applet {
+        struct applet base;
+        struct sprite *portrait;
+        Object *npc, *pc; 
+        struct conv *conv;
+        int conv_room, conv_len;
+        char conv_query[16], *conv_ptr;
+};
+
+static int conv_done;
+
+static void conv_op_run(struct applet *applet, SDL_Rect *dims, struct session *session);
+static void conv_op_paint(struct applet *applet);
+static int conv_op_get_height(struct applet *applet);
+
+static struct applet_ops conv_applet_ops = {
+        conv_op_run,
+        conv_op_paint,
+        conv_op_get_height
+};
+
+
+/**
+ * Keyhandler callback for processing player keystrokes while collecting the
+ * query string. This stores typed characters into the ca->conv_query buffer.
+ *
+ * @param kh is the keyhandler pushed for input handling.
+ * @param key is the key the player just typed.
+ * @returns 1 if the player is done entering the query, else 0.
+ */
+static int conv_get_player_query(struct KeyHandler *kh, int key, int keymod)
+{
+        DECL_CAST(struct conv_applet, ca, kh->data);
+
+       if (key == CANCEL) {
+               while (ca->conv_ptr > ca->conv_query) {
+                       ca->conv_ptr--;
+                       *ca->conv_ptr = 0;
+                       cmdwin_pop();
+                       ca->conv_room++;
+               }
+               return 1;
+       }
+
+       if (key == '\n') {
+               return 1;
+       }
+
+       if (key == '\b') {
+               if (ca->conv_ptr != ca->conv_query) {
+                       ca->conv_ptr--;
+                       *ca->conv_ptr = 0;
+                       ca->conv_room++;
+                       cmdwin_pop();
+               }
+               return 0;
+       }
+
+       if (isprintable(key) 
+            && ca->conv_room) {
+               cmdwin_push("%c", key);
+               *ca->conv_ptr++ = key;
+               ca->conv_room--;
+       }
+
+       return 0;
+}
+
+/**
+ * Force the player query to a value. This is mainly done to start the
+ * conversation off with the "HAIL" keyword.
+ *
+ * @param ca is the conv_applet context to modify.
+ * @param str is the query value to set.
+ */
+static void conv_set_query(struct conv_applet *ca, char *str)
+{
+       snprintf(ca->conv_query, sizeof(ca->conv_query) - 1, "%s", str);
+       ca->conv_query[MAX_KEYWORD_SZ] = 0;
+       ca->conv_len = strlen(ca->conv_query);
+}
+
+/**
+ * Internal destructor for a conversation struct.
+ *
+ * @param conv is the conversation to delete.
+ */
+static void conv_del(struct conv *conv)
+{
+        if (conv->proc) {
+                closure_unref(conv->proc);
+        }
+
+        if (conv->keywords) {
+
+                int i;
+
+                for (i = 0; i < conv->key_index; i++) {
+                        if (conv->keywords[i]) {
+                                free(conv->keywords[i]);
+                        }
+                }
+
+                free(conv->keywords);
+        }
+
+        if (conv->marked) {
+                bitset_free(conv->marked);
+        }
+
+        free(conv);
+}
+
+/**
+ * Callback used by the sort function to compare two values.
+ *
+ * @param p1 is one value.
+ * @param p2 is the other value.
+ * @returns 1 if p1>p2, 0 if p1==p2, -1 if p1<p2.
+ */
+static int conv_sort_cmp(const void *p1, const void *p2)
+{
+   return strcmp(*(char* const*)p1, *(char* const*)p2);
+}
+
+/**
+ * Function used by the binary search in conv_is_keyword.
+ *
+ * @param wptr is the word to look for.
+ * @param cptr is the keyword to compare against.
+ * @returns 0 is cptr is a prefix of wptr; -1 if wptr < cptr; 1 if wptr > cptr.
+ */
+static int conv_prefix_cmp(char *wptr, char *cptr)
+{
+        int len = 0;
+
+        while (*wptr && *cptr) {
+                char wc = tolower(*wptr++);
+                char cc = tolower(*cptr++);
+                len++;
+                int d = wc - cc;
+                if (d != 0) {
+                        return d;
+                }
+        }
+
+        if (*cptr && ! *wptr) {
+                /* candidate is longer than word */
+                return 1;
+        }
+
+        if (*wptr && len < 4) {
+                /* candidate is short but word is not */
+                return -1;
+        }
+
+        return 0;
+}
+
+/**
+ * Check if a word is a keyword.
+ *
+ * @conv is the conversation to check.
+ * @word is the word to look for in the keywords.
+ * @returns the index of the matching keyword, else -1 if not found.
+ */
+static int conv_lookup_keyword(struct conv *conv, char *word)
+{
+        int min = 0, max = conv->key_index, pivot;
+
+        while (max > min) {
+
+                /**
+                 * apricot
+                 *
+                 * aardvark
+                 * abacus
+                 *
+                 * zoo
+                 * zebra
+                 */
+
+                pivot = ((max-min)/2) + min;
+                
+                int d = conv_prefix_cmp(word, conv->keywords[pivot]);
+                
+                if (d > 0) {
+                        /* word > pivot => search higher */
+                        min = pivot + 1;
+                } else if (d < 0) {
+                        /* word < pivot => search lower */
+                        max = pivot;
+                } else {
+                        return pivot;
+                }
+        }
+
+        return -1;
+}
+
+/**
+ * Check if a word is a keyword and, if so, to mark it (marking is used to show
+ * the player which keywords have already been used in a conversation).
+ *
+ * @conv is the conversation to check.
+ * @word is the word to look for in the keywords.
+ */
+static void conv_mark_if_keyword(struct conv *conv, char *word)
+{
+        int index = conv_lookup_keyword(conv, word);
+        if (index != -1) {
+                bitset_set(conv->marked, index);
+        }
+}
+
+/**
+ * 
+ */
+static int conv_op_get_height(struct applet *applet)
+{
+        DECL_CAST(struct conv_applet, ca, applet);
+        if (ca->portrait) {
+                return PORTRAIT_H;
+        }
+        return ASCII_H;
+}
+
+struct conv *conv_new(struct closure *proc, int n_keywords)
+{
+        struct conv *conv;
+
+        if (!(conv = (struct conv*)calloc(1, sizeof(*conv)))) {
+                return NULL;
+        }
+
+        if (!(conv->keywords = (char**)calloc(n_keywords, sizeof(char*)))) {
+                conv_del(conv);
+                return NULL;
+        }
+
+        if (!(conv->marked = bitset_alloc(n_keywords))) {
+                conv_del(conv);
+                return NULL;
+        }
+
+        conv->n_keywords = n_keywords;
+        conv->ref = 1;
+        conv->proc = proc;
+        closure_ref(proc);
+
+        return conv;
+}
+
+void conv_save(struct conv *conv, struct save *save)
+{
+        closure_save(conv->proc, save);
+}
+
+int conv_add_keyword(struct conv *conv, char *keyword)
+{
+        assert(conv->key_index < conv->n_keywords);
+        if (!(conv->keywords[conv->key_index] = strdup(keyword))) {
+                return -1;
+        }
+        conv->key_index++;
+        return 0;
+}
+
+void conv_sort_keywords(struct conv *conv)
+{
+        qsort(conv->keywords, conv->key_index, sizeof(char*), conv_sort_cmp);
+}
+
+void conv_unref(struct conv *conv)
+{
+        assert(conv->ref>0);
+        conv->ref--;
+        if (!conv->ref) {
+                conv_del(conv);
+        }
+}
+
+void conv_ref(struct conv *conv)
+{
+        conv->ref++;
+}
+
+char *conv_highlight_keywords(struct conv *conv, char *orig)
+{
+        return NULL;
+}
+
+
+void conv_end()
+{
+        conv_done = 1;
+}
+
+void conv_enter(Object *npc, Object *pc, struct conv *conv)
+{
+        struct conv_applet conv_applet;
+
+        memset(&conv_applet, 0, sizeof(&conv_applet));
+        conv_applet.base.ops = &conv_applet_ops;
+        conv_applet.npc = npc;
+        conv_applet.pc = pc;
+        conv_applet.conv = conv;
+        conv_applet.portrait = npc->getPortrait();
+
+        session_run_hook(Session, conv_start_hook, "pp", pc, npc);
+        
+        statusRunApplet(&conv_applet.base);
+       statusSetMode(ShowParty); /* restore default status mode */
+
+        session_run_hook(Session, conv_end_hook, "pp", pc, npc);
+
+}
+
+int isprintable(int c)
+{
+        /* Looks like ctype's isprint() doesn't always behave the same way. On
+         * some systems it was letting c<32 go through, causing an assert in
+         * ascii.c. */
+        return ((c >= 32)
+                && (c < 127)
+                && (c != '%') /* printf special char */
+                && (c != '^') /* ascii.c special char */
+                );
+}
+
+int conv_get_word(char *instr, char **beg, char **end)
+{
+        char *inp = instr;
+
+        while (*inp && !isalpha(*inp)) {
+                inp++;
+        }
+
+        if (!*inp) {
+                return 0;
+        }
+
+        *beg = inp;
+
+        while (*inp && isalpha(*inp)) {
+                inp++;
+        }
+
+        *end = inp;
+
+        return 1;
+}
+
+int conv_is_keyword(struct conv *conv, char *word)
+{
+        int index = conv_lookup_keyword(conv, word);
+        if (index == -1) {
+                return 0;
+        }
+        return CONV_IS_KEYWORD | (bitset_tst(conv->marked, index) ? CONV_IS_MARKED : 0);
+}
+
+static void conv_op_paint(struct applet *applet)
+{
+        DECL_CAST(struct conv_applet, ca, applet);
+
+        screenErase(&applet->dims);
+        if (ca->portrait) {
+                int x = (applet->dims.w - PORTRAIT_W)/2 + applet->dims.x;
+                sprite_paint(ca->portrait, 0, x, applet->dims.y);
+        } else {
+                screenPrint(&applet->dims, SP_CENTERED, "No portrait");
+        }
+        screenUpdate(&applet->dims);
+
+        status_repaint_title();
+}
+
+static void conv_op_run(struct applet *applet, SDL_Rect *dims, struct session *session)
+{
+        DECL_CAST(struct conv_applet, ca, applet);
+        
+        applet->dims = *dims;
+        applet->session = session;
+
+        status_set_title(ca->npc->getName());
+        conv_op_paint(applet);
+
+       conv_set_query(ca, "hail");
+        conv_done = 0;
+
+       for (;;) {
+
+                /* Truncate the query to 4 characters */
+                ca->conv_query[4] = 0;
+
+                conv_mark_if_keyword(ca->conv, ca->conv_query);
+
+                /* Query the NPC */
+                closure_exec(ca->conv->proc, "ypp", ca->conv_query, ca->npc, ca->pc);
+
+               if (conv_done) {
+                       break;
+                }
+
+               /*** Setup for next query ***/
+
+               memset(ca->conv_query, 0, sizeof(ca->conv_query));
+               ca->conv_room = sizeof(ca->conv_query) - 1;
+               ca->conv_ptr = ca->conv_query;
+
+               cmdwin_clear();
+               cmdwin_push("Say: ");
+
+               /*** Get next query ***/
+
+                eventRunKeyHandler(conv_get_player_query, ca);
+
+               ca->conv_query[MAX_KEYWORD_SZ] = 0;
+               ca->conv_len = strlen(ca->conv_query);
+                if (! ca->conv_len)
+                        sprintf(ca->conv_query, "bye");
+               log_msg("^c+%c%s:^c- %s", CONV_PC_COLOR, 
+                        ca->pc->getName(), ca->conv_query);
+
+               /*** Check if player ended conversation ***/
+
+               if (Quit)
+                       break;
+
+               if (strlen(ca->conv_query) == 0)
+                       conv_set_query(ca, "BYE");
+
+               if (!strcasecmp(ca->conv_query, "BYE")) {
+                       conv_end();
+               }
+
+       }
+
+       cmdwin_clear();
+       cmdwin_repaint();
+
+}
+
+
+#endif /* TEST_PORTRAITS */
diff --git a/src/conv.h b/src/conv.h
new file mode 100644 (file)
index 0000000..4a88942
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003, 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef conv_h
+#define conv_h
+
+#define CONV_PC_COLOR  'g'
+#define CONV_NPC_COLOR 'b'
+
+/**
+ * Flags for the return value of conv_is_keyword().
+ */
+#define CONV_IS_KEYWORD (1<<0) /* word is a keyword */
+#define CONV_IS_MARKED  (1<<1) /* keyword has been used */
+
+struct conv;
+
+/**
+ * Allocate a conversation struct and a fixed number of keywords slots.
+ *
+ * @param proc becomes the proc field with an added refcount.
+ * @returns a new converstation struct on success, else NULL if allocaition
+ * failed.
+ */
+struct conv *conv_new(struct closure *proc);
+
+/**
+ * Save a conversation to the session file.
+ *
+ * @param conv is the conversation to save. Only the closure is saved.
+ * @param save is the save object.
+ */
+void conv_save(struct conv *conv, struct save *save);
+
+/**
+ * Release a reference to a conversation. This may delete it.
+ *
+ * @param is the conversation.
+ */
+void conv_unref(struct conv *conv);
+
+/**
+ * Add a reference to a conversation. This prevents it from being destroyed.
+ *
+ * @param is the conversation.
+ */
+void conv_ref(struct conv *conv);
+
+/**
+ * Start a conversation. This will start the conversation session in the
+ * console, and return when and only when the conversation is over.
+ *
+ * @param npc is the NPC being spoken to.
+ * @param pc is the player party member doing the talking.
+ * @param conv is the conversation.
+ */
+void conv_enter(class Object *npc, class Object *pc, struct conv *conv);
+
+/**
+ * End a conversation. This is provided so that NPC scripts can end the
+ * conversation prematurely (before the player says 'bye').
+ */
+void conv_end(void);
+
+/**
+ * Substitute for ctype.h's isprint(), which does not work properly on all
+ * systems.
+ *
+ * @param c is the character to test.
+ * @returns non-zero if c is a printable character, else zero.
+ */
+int isprintable(int c);
+
+/**
+ * Given an input string get pointers to the beginning and end of the next
+ * word. The beginning of a word is any alphabetical character which either
+ * starts the string or follows whitespace or punctuation. 
+ *
+ * @param instr is the input string.  
+ *
+ * @param beg will point to the beginning of the next work on exit, iff one was
+ * found. If not its value is undefined.
+ * @param end likewise will point to the end of the next work in the string.
+ * @returns non-zero iff a word was found in the string.
+ */
+int conv_get_word(char *instr, char **beg, char **end);
+
+/**
+ * Check if a word is a keyword in a conversation (and, if so, if it has
+ * already been used in a conversation since the last session reload). This
+ * works by testing if any of the keywords are a prefix of the word.
+ *
+ * @param conv is the conversation with the keywords to check.
+ * @param word if the word to test for.
+ * @returns zero if the word is not a keyword, else a non-zero union of the
+ * flags CONV_IS_KEYWORD and CONV_IS_MARKED.
+ *
+ */
+int conv_is_keyword(struct conv *conv, char *word);
+
+/**
+ * Initialize module before using.
+ *
+ * @returns non-zero on error.
+ */
+int conv_init(void);
+
+/**
+ * Turn keyword highlighting on or off.
+ *
+ * @param enable is non-zero to turn it on.
+ */
+void conv_enable_keyword_highlighting(int enable);
+
+
+#endif
diff --git a/src/ctrl.c b/src/ctrl.c
new file mode 100644 (file)
index 0000000..e0ef26d
--- /dev/null
@@ -0,0 +1,1707 @@
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "../config.h" /* for USE_SKILLS */
+#include "ctrl.h"
+#include "dice.h"
+#include "event.h"
+#include "foogod.h"
+#include "cmd.h"
+#include "cmdwin.h"
+#include "map.h"
+#include "place.h"
+#include "player.h"
+#include "Party.h"
+#include "character.h"
+#include "combat.h"
+#include "terrain.h"
+#include "sched.h"
+#include "session.h"
+#include "log.h"
+#include "factions.h"
+#include "kern_intvar.h"
+#include "nazghul.h"  // for DeveloperMode
+
+#ifndef CONFIG_DIAGONAL_MOVEMENT
+#define CONFIG_DIAGONAL_MOVEMENT 1
+#endif
+
+int G_latency_start = 0;
+int G_turnaround_start = 0;
+int G_turnaround  = 0;
+
+static int ctrl_party_key_handler(struct KeyHandler *kh, int key, int keymod)
+{
+        int dir;
+
+        class PlayerParty *party = (class PlayerParty*)kh->data;
+
+        Session->subject = player_party;   
+        
+        G_latency_start = SDL_GetTicks();
+
+        /* Commands which are only enabled in developer mode */
+        if (DeveloperMode) {
+           switch (key) {
+                        
+                case KEY_CTRL_T:
+                   cmd_terraform(party->getPlace(), party->getX(), party->getY());
+                   break;
+
+               case KEY_CTRL_O:
+                   cmd_save_current_place(party->getPlace());
+                   break;
+
+                case KEY_CTRL_Z:
+                   mapTogglePeering();
+                   break;
+           }
+        }
+
+        switch (key) {
+                
+#if CONFIG_DIAGONAL_MOVEMENT
+        case KEY_NORTHWEST:
+        case KEY_NORTHEAST:
+        case KEY_SOUTHWEST:
+        case KEY_SOUTHEAST:
+#endif   /* CONFIG_DIAGONAL_MOVEMENT */
+        case KEY_NORTH:
+        case KEY_WEST:
+        case KEY_EAST:
+        case KEY_SOUTH:
+        {
+                dir = keyToDirection(key);
+                party->move(directionToDx(dir), directionToDy(dir));
+                mapSetDirty();
+                dir = keyToDirection(key);
+        }
+        break;
+
+#if CONFIG_DIAGONAL_MOVEMENT
+        case KEY_SHIFT_NORTHWEST:
+        case KEY_SHIFT_NORTHEAST:
+        case KEY_SHIFT_SOUTHWEST:
+        case KEY_SHIFT_SOUTHEAST:
+#endif   /* CONFIG_DIAGONAL_MOVEMENT */
+        case KEY_SHIFT_NORTH:
+        case KEY_SHIFT_EAST:
+        case KEY_SHIFT_SOUTH:
+        case KEY_SHIFT_WEST:
+
+                // ----------------------------------------------------
+                // Pan the camera.
+                // ----------------------------------------------------
+                        
+                key &= ~KEY_SHIFT; /* clear shift bit */
+                dir = keyToDirection(key);
+                mapMoveCamera(directionToDx(dir), directionToDy(dir));
+                mapSetDirty();
+                break;
+
+        case 'a':
+                cmdAttack();
+                break;
+        case 'b':
+                party->board_vehicle();
+                break;
+        case 'c':
+                cmdCastSpell(NULL);
+                break;
+        case 'f':
+                cmdFire();
+                break;
+        case 'g':
+                cmdGet(party);
+                break;
+        case 'h':
+                // SAM: Adding (H)andle command...
+                cmdHandle(NULL);
+                break;
+        case 'k':
+                cmd_camp_in_wilderness(party);
+                break;
+        case 'l':
+                cmdLoiter(party);
+                break;
+        case 'm':
+                cmdMixReagents(NULL);
+                break;
+        case 'n':
+                cmdNewOrder();
+                break;
+        case 'o':
+                cmdOpen(NULL);
+                break;
+        case 'q':
+                cmdQuit();
+                break;
+        case 'r':
+                cmdReady(NULL);
+                break;
+        case 's':
+                cmdSearch(0);
+                break;
+        case 't':
+                cmdTalk(NULL);
+                break;
+        case 'u':
+                cmdUse(NULL, CMD_SELECT_MEMBER|CMD_PRINT_MEMBER);
+                break;
+#ifdef USE_SKILLS
+        case 'y':
+                cmdYuse(NULL);
+                break;
+#endif
+        case 'x':
+                cmdXamine(party);
+                break;
+        case 'z':
+                cmdZtats(party->getMemberAtIndex(0));
+                break;
+        case '@':
+                // SAM: 'AT' command for party-centric information
+                cmdAT(NULL);
+                break;
+        case ' ':
+                party->endTurn();
+                log_msg("Pass");
+                break;
+        case '>':
+                // This key was chosen to be a cognate for '>' in
+                // NetHack and other roguelike games.
+                cmdZoomIn();
+                party->endTurn();
+                break;
+        case '?':
+                cmdHelp();
+                break;
+
+        case KEY_CTRL_S:
+                cmdSave();
+                break;
+                        
+        case KEY_CTRL_R:
+                cmdReload();
+                Session->subject = NULL;
+                return true;
+
+        case SDLK_F10:
+                cmdSettings();
+                break;
+                        
+        default:
+                break;
+        } // switch(key)
+
+        /* Prep cmdwin for next prompt */
+        cmdwin_clear();
+
+        Session->subject = NULL;
+        
+        party->absorbMemberAPDebt();
+
+        /* Return true when done processing commands. */
+               if(!party->isTurnEnded())
+                               cmdwin_push("Party [%d ap]:",party->getActionPoints());
+                
+        return party->isTurnEnded();
+
+}
+
+void ctrl_wander(class Object *object)
+{
+        // *** left off here ***
+
+       int dx = 0, dy = 0;
+
+        if (object->isStationary())
+                return;
+
+       /* Roll for direction */
+       dx = rand() % 3 - 1;
+       if (!dx)
+               dy = rand() % 3 - 1;
+
+       if (dx || dy) {
+
+                int newx, newy;
+                newx = object->getX() + dx;
+                newy = object->getY() + dy;
+
+                if (! object->canWanderTo(newx, newy))
+                        return;
+
+                // ------------------------------------------------------------
+                // Do a quick check here if this would take the character off
+                // the map. If so, then don't do it. Can't have NPC's wandering
+                // off out of town...
+                // ------------------------------------------------------------
+
+                if (place_off_map(object->getPlace(), object->getX() + dx, 
+                                  object->getY() + dy) ||
+                    place_is_hazardous(object->getPlace(), object->getX() + dx,
+                                       object->getY() + dy))
+                        return;
+
+               object->move(dx, dy);
+       }
+}
+
+void ctrl_party_ai(class Party *party)
+{
+       int d;
+
+        /* Check if this party is friendly to the player or if the player is
+         * not around */
+       if (! are_hostile(party, player_party) ||
+            Place != party->getPlace()) {
+               // This party is friendly to the player, so just wander for now
+               // (later I'll add schedules).
+               ctrl_wander(party);
+               return;
+       }
+
+        /* Check if the player is _on this spot_. Yes, this can happen under
+         * current game rules. If a player enters a portal and an npc is on the
+         * destination then... */
+       if (party->getX() == player_party->getX() && 
+            party->getY() == player_party->getY()) {
+                
+                struct move_info info;
+                struct combat_info cinfo;
+
+                memset(&info, 0, sizeof(info));
+                info.place = party->getPlace();
+                info.x = party->getX();
+                info.y = party->getY();
+                info.dx = party->getDx();
+                info.dy = party->getDy();
+                info.px = player_party->getX();
+                info.py = player_party->getY();
+                info.npc_party = party;
+                
+                if (!info.dx && !info.dy)
+                        info.dx = 1;
+                else if (info.dx && info.dy)
+                        info.dy = 0;
+
+                memset(&cinfo, 0, sizeof(cinfo));
+                cinfo.defend = true;
+                cinfo.move = &info;
+                
+                combat_enter(&cinfo);
+                party->endTurn();
+               return;
+       }
+
+       /* get distance to player */
+       d = place_walking_distance(party->getPlace(), party->getX(), 
+                                   party->getY(),
+                                  player_party->getX(), player_party->getY());
+
+        /* if adjacent attack */
+        if (1==d) {
+                int dx=0, dy=0;
+                place_get_direction_vector(party->getPlace(),
+                                           party->getX(), party->getY(),
+                                           player_party->getX(), player_party->getY(),
+                                           &dx, &dy);
+                if (party->attackPlayer(dx, dy)) {
+                        return;
+                }
+        }
+
+       if (d > party->getVisionRadius()) {
+               ctrl_wander(party);
+               return;
+       }
+
+       if (d > 1 && party->attack_with_ordnance(d)) {
+               return;
+       }
+
+       if (!party->gotoSpot(player_party->getX(), player_party->getY())) {
+               ctrl_wander(party);
+               return;
+       }
+}
+
+static int ctrl_calc_to_hit(class Character *character, 
+                            class ArmsType *weapon, 
+                            int penalty)
+{
+        int base        = dice_roll("1d20");
+        int weaponBonus = dice_roll(weapon->getToHitDice());
+        int attackBonus = character->getAttackBonus(weapon);
+        int val         = base + weaponBonus + attackBonus + penalty;
+
+        log_continue("to-hit: %d=%d+%d+%d", val, base, weaponBonus, 
+                     attackBonus);
+        if (penalty >= 0) {
+                log_continue("+");
+        }
+        log_continue("%d\n", penalty);
+
+        return val;
+}
+
+static int ctrl_calc_to_defend(class Character *target)
+{
+        int base  = target->getDefend();
+        int bonus = target->getAvoidBonus();
+        int val   = base + bonus;
+
+        log_continue("to-def: %d=%d+%d\n", val, base, bonus);
+        
+        return val;
+}
+
+static int ctrl_calc_damage(class Character *character, 
+                            class ArmsType *weapon, 
+                            char critical)
+{
+        int weaponDamage   = dice_roll(weapon->getDamageDice());
+        int characterBonus = character->getDamageBonus(weapon);
+        int memberBonus    = 0;
+        int criticalBonus  = 0;
+
+        if (character->isPlayerControlled()) {
+                memberBonus = dice_roll("1d4");
+        }
+
+        if (critical) {
+                criticalBonus = character->getDamageBonus(weapon);
+        }
+
+        int val = weaponDamage + characterBonus + criticalBonus + memberBonus;
+
+        log_continue("damage: %d=%d+%d", val, weaponDamage, characterBonus);
+        if (memberBonus) {
+                log_continue("+%d", memberBonus);
+        }
+        if (criticalBonus) {
+                log_continue("+%d", criticalBonus);
+        }
+        log_continue("\n");
+
+        return val;
+}
+
+static int ctrl_calc_armor(class Character *target, int critical)
+{
+        int armor = 0;
+
+        if (! critical) {
+                armor = target->getArmor();
+        }
+
+        log_continue(" armor: %d\n", armor);
+        
+        return armor;
+}
+
+static void ctrl_attack_done(class Character *character, class ArmsType *weapon, 
+                             class Character *target)
+{
+        character->runHook(OBJ_HOOK_ATTACK_DONE, "pp", weapon, target);
+        character->useAmmo(weapon);
+}
+
+void ctrl_do_attack(class Character *character, class ArmsType *weapon, 
+                    class Character *target, int to_hit_penalty)
+{
+        int hit;
+        int def;
+        int damage;
+        int armor;
+        int critical = 0;
+               int misx;
+               int misy;
+        bool miss;
+
+        /* Reduce the diplomacy rating between the attacker's and target's
+         * factions */
+        harm_relations(character, target);
+
+        log_begin("^c%c%s^cw attacks ^c%c%s^cw with %s: "
+                  , (are_hostile(character, player_party)?'r':'g')
+                  , character->getName()
+                  , (are_hostile(target, player_party)?'r':'g')
+                  , target->getName()
+                  , weapon->getName()
+                );
+
+        if (weapon->canOnAttack())
+        {
+               weapon->onAttack(NULL,character);  
+               }
+                
+        miss = ! weapon->fire(target, character->getX(), character->getY(), &misx, &misy);
+        ctrl_attack_done(character, weapon, target);
+
+        if (miss)
+        {
+                               log_end("obstructed!");
+                               weapon->fireHitLoc(character, NULL, character->getPlace(),misx,misy,-1);
+                               return;
+        }
+
+        /* Roll to hit. */
+        log_continue("\n");
+        hit = ctrl_calc_to_hit(character, weapon, to_hit_penalty);
+        def = ctrl_calc_to_defend(target);
+        if (hit < def)
+        {
+                               log_end("evaded!");
+                               weapon->fireHitLoc(character, NULL, character->getPlace(),misx,misy,-1);
+                               return;
+        }
+
+        /* roll for critical hit */
+        if (20 <= (dice_roll("1d20") 
+                   + logBase2(character->getBaseAttackBonus(weapon)))) {
+                critical = 1;
+                log_continue("^c+yCritical hit!^c-\n");
+        }
+
+        /* roll for damage */
+        damage = ctrl_calc_damage(character, weapon, critical);
+        armor = ctrl_calc_armor(target, critical);
+        damage -= armor;
+        damage = max(damage, 0);
+        
+        if (damage <= 0)
+        {
+                               log_end("blocked!");
+                               weapon->fireHitLoc(character, target, character->getPlace(),misx,misy,0);
+                               return;
+        }
+
+        // the damage() method may destroy the target, so bump the refcount
+        // since we still need the target through the end of this function
+        obj_inc_ref(target);
+        target->damage(damage);
+
+                       weapon->fireHitLoc(character, target, character->getPlace(),misx,misy,damage);
+
+        log_end("%s!", target->getWoundDescription());
+
+        /* If the target was killed then add xp to the attacker */
+        if (target->isDead()) {
+                character->addExperience(target->getExperienceValue());
+        }
+
+        obj_dec_ref(target);
+}
+
+
+static class Character *
+ctrl_get_interfering_hostile(class Character *character)
+{
+        static int dx_to_neighbor[] = { 0, -1, 0, 1 };
+        static int dy_to_neighbor[] = { -1, 0, 1, 0 };
+        class Character *near;
+        int i;
+
+        for (i = 0; i < 4; i++) {
+                near = (class Character*)place_get_object(
+                        character->getPlace(), 
+                        character->getX() + dx_to_neighbor[i], 
+                        character->getY() + dy_to_neighbor[i], 
+                        being_layer);
+                
+                if (near &&
+                    are_hostile(near, character) &&
+                    !near->isIncapacitated()) {
+                        return near;
+                }
+        }
+
+        return NULL;
+}
+
+struct nearest_hostile_info {
+        class Character *origin;
+        class Character *nearest;
+        int min_distance;
+        int range;
+        struct list suggest; /* for ctrl_attack_ui */
+};
+
+static void ctrl_suggest_visitor(class Object *obj, void *data)
+{
+        struct nearest_hostile_info *info = (struct nearest_hostile_info*)data;
+        class Character *npc = 0;
+        int dist = 0;
+        struct location_list *entry = 0;
+
+        if (being_layer!=obj->getLayer())
+                return;
+
+        npc = (class Character*)obj;
+
+        if (! are_hostile(npc, info->origin))
+                return;
+
+        if (! npc->isVisible() && ! Reveal)
+                return;
+        
+        if (! place_in_los(info->origin->getPlace(),
+                           info->origin->getX(),
+                           info->origin->getY(),
+                           info->origin->getPlace(),
+                           obj->getX(),
+                           obj->getY()))
+                return;
+
+        if (info->range < (dist = place_flying_distance(info->origin->getPlace(),
+                                                        info->origin->getX(),
+                                                        info->origin->getY(),
+                                                        obj->getX(),
+                                                        obj->getY())))
+                return;
+
+        /* Add it to the list */
+        entry = (struct location_list*)malloc(sizeof(*entry));
+        assert(entry);
+        entry->x = obj->getX();
+        entry->y = obj->getY();
+        list_add_tail(&info->suggest, &entry->list);
+
+        /* Keep track of the nearest as we go. */
+        if (! info->nearest
+            || (dist < info->min_distance)) {
+                info->min_distance = dist;
+                info->nearest = npc;
+        }
+
+        printf("Added %s at [%d %d]\n", obj->getName(), obj->getX(), obj->getY());        
+}
+
+static void ctrl_del_suggest_list(struct list *head)
+{
+        struct list *entry = head->next;
+        while (entry != head) {
+                struct location_list *tmp = 
+                        (struct location_list*)entry;
+                entry = entry->next;
+                list_remove(&tmp->list);
+                free(tmp);
+        }
+}
+
+
+static void ctrl_attack_ui(class Character *character)
+{
+        int x;
+        int y;
+        class ArmsType *weapon;
+        class Character *target;
+        struct terrain *terrain;
+        class Object *mech;
+               
+        // If in follow mode, when the leader attacks automatically switch to
+        // turn-based mode.
+        if (player_party->getPartyControlMode() == PARTY_CONTROL_FOLLOW &&
+            player_party->getSize() > 1) {
+                log_msg("Switching from Follow to Round Robin Mode.\n");
+                player_party->enableRoundRobinMode();
+        }
+
+        // Loop over all readied weapons
+        int armsIndex=0;
+       int this_is_nth_attack = 1;
+        int this_wpn_AP;
+        for (weapon = character->enumerateWeapons(&armsIndex); weapon != NULL; 
+             weapon = character->getNextWeapon(&armsIndex)) {
+           struct nearest_hostile_info info;
+                                               
+                // prompt the user
+                cmdwin_clear();
+                cmdwin_spush("Attack");
+
+               // Determine AP for this (potential) attack,
+               // as a discount may be applied for dual weapon attacks and such,
+               // and we need the discounted figure to display in the UI:
+                this_wpn_AP = weapon->getRequiredActionPoints();
+               if (this_is_nth_attack ==  1) {
+                   // 1st weapon attack (usual case), no AP cost adjustments
+               }
+               else if (this_is_nth_attack == 2) {
+                   // 2nd weapon attack (dual weapon, 2nd weapon)
+                   int mult = kern_intvar_get("AP_MULT12:second_wpn_attack");
+                   this_wpn_AP = (int) (this_wpn_AP * mult) / 12;
+               }
+               else if (this_is_nth_attack >= 3) {
+                   // 3rd+ weapon attack (unusual case for multi-limbed beings...)
+                   int mult = kern_intvar_get("AP_MULT12:third_plus_wpn_attack");
+                   this_wpn_AP = (int) (this_wpn_AP * mult) / 12;
+               }
+
+               //log_msg("DEBUG: wpn = %s (AP=%d-->%d), remaining AP=%d\n", 
+               //      weapon->getName(), weapon->getRequiredActionPoints(), this_wpn_AP,
+               //      character->getActionPoints() );
+
+                if (weapon->isMissileWeapon()) {
+                        // SAM: It would be nice to get ammo name, too...
+                        cmdwin_spush("%s (%d AP, range %d, %d ammo)", 
+                                     weapon->getName(), 
+                                    this_wpn_AP,
+                                    weapon->getRange(), 
+                                     character->hasAmmo(weapon));
+                }
+                else if (weapon->isThrownWeapon()) {
+                        // SAM: It would be nice to get ammo name, too...
+                        cmdwin_spush("%s (%d AP, range %d, %d left)",
+                                     weapon->getName(), 
+                                    this_wpn_AP,
+                                    weapon->getRange(), 
+                                     character->hasAmmo(weapon));
+                }
+                else {
+                        cmdwin_spush("%s (%d AP, reach %d)", 
+                                     weapon->getName(), 
+                                    this_wpn_AP,
+                                    weapon->getRange() );
+                }
+
+
+                // Check ammo
+                if (!character->hasAmmo(weapon)) {
+                        cmdwin_spush("no ammo!");
+                        log_msg("%s: %s - no ammo!\n",
+                                     character->getName(),
+                                     weapon->getName());
+                        continue;
+                }
+
+                /* Check the four adjacent tiles for hostiles who will
+                 * interfere with a missile weapon */
+                if (weapon->isMissileWeapon()) {
+                        class Character *near;
+                        near = ctrl_get_interfering_hostile(character);
+                        if (near) {
+                                cmdwin_spush("blocked!");
+                                log_msg("%s: %s - blocked by %s!\n",
+                                             character->getName(),
+                                             weapon->getName(),
+                                             near->getName());
+                                continue;
+                        }
+                }
+
+                /* Build the list of suggested targets. */
+                memset(&info, 0, sizeof(info));
+                info.origin = character;
+                info.range = weapon->getRange();
+                list_init(&info.suggest);
+                place_for_each_object(character->getPlace(),
+                                      ctrl_suggest_visitor,
+                                      &info);
+
+                /* Get the default target. It's important to do this every time
+                 * the loop because the last iteration may have killed the
+                 * previous target, or it may be out of range of the
+                 * weapon. The getAttackTarget routine will reevaluate the
+                 * current target. */
+                target = character->getAttackTarget(weapon);
+
+                /* If the target is the character that means there is no
+                 * default target now. Select the nearest one is the new
+                 * default. */
+                if (target==character) {
+                        if (! list_empty(&info.suggest)) {
+                                assert(info.nearest);
+                                target = info.nearest;
+                        }
+                }
+
+                assert(target);
+
+                // select the target location
+                x = target->getX();
+                y = target->getY();
+
+                // SAM:
+                // select_target() might be a more elegant place to put
+                // logic to prevent (or require confirm of) attacking self, 
+                // party members, etc.
+                if (-1 == select_target(character->getX(), 
+                                        character->getY(), 
+                                        &x, &y,
+                                        weapon->getRange(),
+                                        &info.suggest)) {
+                        cmdwin_spush("abort!");
+                        continue;
+                }
+
+                /* Cleanup the suggestion list */
+                ctrl_del_suggest_list(&info.suggest);
+
+                // Find the new target under the cursor
+                target = (class Character *) 
+                        place_get_object(character->getPlace(), x, y, 
+                                         being_layer);
+                character->setAttackTarget(target);
+                if (target == NULL) {
+                                               
+                        /* Attack the terrain */
+                        terrain = place_get_terrain(character->getPlace(),
+                                                    x, y);
+
+                        cmdwin_spush(" %s", terrain->name);                  
+                                                    
+                        log_begin("%s: %s - ", character->getName()
+                                  , weapon->getName()
+                                );
+                               
+                       int misx = x;
+                       int misy = y;
+                       
+                       this_is_nth_attack++;                           
+                       
+                               if (weapon->canOnAttack())
+                               {
+                                       weapon->onAttack(NULL,character);  
+                                       }
+                       
+                        bool miss = ! weapon->fire(character->getPlace(), 
+                                     character->getX(), 
+                                     character->getY(), 
+                                     &misx, 
+                                     &misy);
+
+                        if (miss)
+                        {
+                               log_end("obstructed!");
+                        }
+                                     
+                        weapon->fireHitLoc(character, NULL, character->getPlace(),misx,misy,-1);
+                                     
+                        ctrl_attack_done(character, weapon, NULL);
+
+                                                               if (!miss)
+                                                               {                     
+                               /* Check for a mech */
+                               mech = place_get_object(character->getPlace(), x, y, 
+                                                       mech_layer);
+                               if (mech && mech->getName()) {
+                                       log_end("%s hit!", mech->getName());
+                                       mech->attack(character);
+                               } else {
+                                       log_end("%s hit!", terrain->name);
+                               }
+                        }
+                                                       
+                }
+                else if (target == character) {
+                        /* Targeting the self is taken to mean "switch to my
+                         * next weapon". This allows players to quickly jump to
+                         * the next weapon if no target is in range and they
+                         * aren't interested in attacking the ground. */
+                        cmdwin_spush("skip weapon!");
+                       // no attack made, so don't increment this_is_nth_attack
+                        continue;
+                } else {
+                        // confirmed_attack_ally:
+
+                        // in combat all npc parties and the player party
+                        // should be removed, so only characters reside at the
+                        // being layer
+                        assert(target->isType(CHARACTER_ID));
+
+                        cmdwin_spush("%s", target->getName());
+
+
+                        // If the npc is not hostile then get player confirmation.
+                        if (! are_hostile(character, target)) {
+                                int yesno;
+                                cmdwin_spush("attack non-hostile");
+                                cmdwin_spush("<y/n>");
+                                getkey(&yesno, yesnokey);
+                                cmdwin_pop();
+                                if (yesno == 'n') {
+                                        cmdwin_spush("no");
+                                        continue;
+                                }
+                                cmdwin_spush("yes");
+                        }
+
+                        // Strike the target
+                       this_is_nth_attack++;
+                        ctrl_do_attack(character, weapon, target, character->getToHitPenalty());
+
+                        // If we hit a party member then show their new hit
+                        // points in the status window
+                        if (target->isPlayerControlled())
+                                statusRepaint();
+                }
+
+                /* Warn the user if out of ammo. Originally this code used
+                 * character->getCurrentWeapon() instead of weapon, that may
+                 * still be okay now that getToHitPenalty() is outside of this
+                 * loop, but not sure why it' would be preferred. */
+                if (! character->hasAmmo(weapon))
+                        log_msg("%s : %s now out of ammo\n", 
+                                     character->getName(), weapon->getName());
+                                
+               character->decActionPoints(this_wpn_AP);
+               //log_msg("DEBUG: after attack, used %d, remaining AP=%d\n", 
+               //      this_wpn_AP, character->getActionPoints() );
+        }
+        
+}
+
+static void ctrl_move_character(class Character *character, int dir)
+{
+        enum MoveResult move_result;
+        const char *result = NULL;
+        const char *dirstr = directionToString(dir);
+        int dx;
+        int dy;
+
+        dx = directionToDx(dir);
+        dy = directionToDy(dir);
+
+        /* try to move */
+        move_result = character->move(dx, dy);
+
+        /* recenter (harmless if move failed) */
+        mapCenterView(character->getView(), character->getX(),
+                      character->getY());
+
+        /* if moved ok then no message to print */
+        if (MovedOk == move_result) {
+                return;
+        }
+        
+        /* otherwise we'll print something */
+        log_begin("");
+
+        switch (move_result) {
+        case OffMap:
+                result = "no place to go!";
+                break;
+        case ExitedMap:
+                result = "exit!";
+                character->endTurn();
+                break;
+        case EngagedEnemy:
+                cmdwin_spush("enter combat!");
+                break;
+        case WasOccupied:
+                result = "occupied!";
+                break;
+        case WasImpassable:
+        {
+                /* If the move failed because something impassable is there
+                 * then check for a mech and try to handle it. This is good
+                 * enough to automatically open unlocked doors.
+                 */
+
+                class Object *mech;
+                int newx, newy;
+                
+                newx = character->getX() + dx;
+                newy = character->getY() + dy;
+                
+                mech = place_get_object(character->getPlace(), newx, newy, 
+                                        mech_layer);
+                
+                               if (mech && mech->getObjectType()->canHandle())
+                               {
+                                       mech->getObjectType()->handle(mech, character);
+                                       character->decActionPoints(kern_intvar_get("AP_COST:handle_mechanism"));
+                                       mapSetDirty();
+                                       result = "handled!";
+                               } 
+                               else if (mech && mech->getObjectType()->canBump())
+                               {
+                                       result = "";
+                                       mech->getObjectType()->bump(mech, character);
+                                       mapSetDirty();                  
+                               }
+                               else
+                               {                
+                                       result = "impassable!";
+                               }
+        }
+                break;
+        case SlowProgress:
+                result = "slow progress!";
+                break;
+        case SwitchedOccupants:
+                result = "switch!";
+                break;
+        case NotFollowMode:
+                result = "must be in follow mode!";
+                break;
+        case CantRendezvous:
+                result = "party can't rendezvous!";
+                break;
+        case CouldNotSwitchOccupants:
+                result = "can't switch places!";
+                break;
+        default:
+                break;
+        }
+
+        log_continue("%s: %s - %s", character->getName(), dirstr, result);
+        log_end("");
+}
+
+static int ctrl_character_key_handler(struct KeyHandler *kh, int key, 
+                                       int keymod)
+{
+        extern int G_latency_start;
+        int dir;
+
+        class Character *character = (class Character *) kh->data;
+        class Object *portal;
+
+        G_latency_start = SDL_GetTicks();
+
+        Session->subject = character;
+
+        /* First process commands which should not be affected by the keystroke
+         * hooks. */
+
+        /* Commands which are only enabled in developer mode */
+        if (DeveloperMode) {
+                switch (key) {
+
+                case KEY_CTRL_T:
+                        cmd_terraform(character->getPlace(), character->getX(),
+                                      character->getY());
+                        break;
+                        
+               case KEY_CTRL_O:
+                        cmd_save_current_place(character->getPlace() );
+                        break;
+                        
+                case KEY_CTRL_Z:
+                        mapTogglePeering();
+                        break;
+                        
+                case KEY_CTRL_E:
+                        cmdDeveloperEval(Session);
+                        break;
+                }
+        }
+
+        switch (key) {
+
+        case KEY_CTRL_S:
+                cmdSave();
+                break;
+
+        case KEY_CTRL_R:
+                cmdReload();
+                Session->subject = NULL;
+                return true;
+      
+        case SDLK_F10:
+                cmdSettings();
+                break;
+                        
+        case 'f':
+            if (cmdToggleFollowMode()) {
+                if (! character->isLeader()) {
+                    character->endTurn();
+                }
+            } else {
+                foogod_set_title("Round Robin: %s", character->getName());
+                foogodRepaint();
+            }
+            break;
+
+        case SDLK_1:
+        case SDLK_2:
+        case SDLK_3:
+        case SDLK_4:
+        case SDLK_5:
+        case SDLK_6:
+        case SDLK_7:
+        case SDLK_8:
+        case SDLK_9:                        
+            if (cmdSetSoloMode(key - SDLK_1)) {
+                character->endTurn();                        
+            }
+            break;
+
+        case SDLK_0:
+                // ----------------------------------------------------
+                // Exit solo mode.
+                // ----------------------------------------------------
+                player_party->enableRoundRobinMode();
+                //in general, switching to roundrobin mode means
+                //you need all the turns you gan get, so dont waste this one
+                //character->endTurn();
+                break;
+
+        default:
+                break;
+        }
+
+        // Don't run the keystroke hook until we get here. Keystroke
+        // effects should not affect the special ctrl charactes
+        // (otherwise something like being stuck in a web can prevent a
+        // user from reloading a game).
+        character->runHook(OBJ_HOOK_KEYSTROKE, 0);
+        if (character->isTurnEnded()) {
+                Session->subject = NULL;
+                return true;
+        }
+
+
+        switch (key) {
+
+#if CONFIG_DIAGONAL_MOVEMENT
+        case KEY_NORTHWEST:
+        case KEY_NORTHEAST:
+        case KEY_SOUTHWEST:
+        case KEY_SOUTHEAST:
+#endif   /* CONFIG_DIAGONAL_MOVEMENT */
+        case KEY_NORTH:
+        case KEY_WEST:
+        case KEY_EAST:
+        case KEY_SOUTH:
+                dir = keyToDirection(key);
+                ctrl_move_character(character, dir);
+                break;
+
+
+#if CONFIG_DIAGONAL_MOVEMENT
+        case KEY_SHIFT_NORTHWEST:
+        case KEY_SHIFT_NORTHEAST:
+        case KEY_SHIFT_SOUTHWEST:
+        case KEY_SHIFT_SOUTHEAST:
+#endif   /* CONFIG_DIAGONAL_MOVEMENT */
+        case KEY_SHIFT_NORTH:
+        case KEY_SHIFT_EAST:
+        case KEY_SHIFT_SOUTH:
+        case KEY_SHIFT_WEST:
+
+                // ----------------------------------------------------
+                // Pan the camera.
+                // ----------------------------------------------------
+                        
+                key &= ~KEY_SHIFT; /* clear shift bit */
+                dir = keyToDirection(key);
+                mapMoveCamera(directionToDx(dir), directionToDy(dir));
+                mapSetDirty();
+                break;
+
+
+        case 'a':
+                ctrl_attack_ui(character);
+                break;
+
+        case 'c':
+                cmdCastSpell(character);
+                break;
+
+        case 'd':
+                cmdDrop(character);
+                break;
+        case 'e':
+
+                // ----------------------------------------------------
+                // Enter a portal. For this to work a portal must exist
+                // here, the party must be in follow mode, and all the
+                // party members must be able to rendezvous at this
+                // character's position.
+                // ----------------------------------------------------
+
+                portal = place_get_object(character->getPlace(), 
+                                          character->getX(), 
+                                          character->getY(), 
+                                          mech_layer);
+                if (!portal || !portal->canEnter()) {
+                        break;
+                }
+                        
+                log_begin_group();
+                portal->enter(character);
+                log_end_group();
+
+                break;
+
+
+        case 'g':
+                cmdGet(character);
+                break;
+        case 'h':
+                cmdHandle(character);
+                break;
+        case 'k':
+                cmd_camp_in_town(character);
+                break;
+        case 'l':
+                cmdLoiter(character);
+                break;
+        case 'm':
+                cmdMixReagents(character);
+                break;
+        case 'n':
+                cmdNewOrder();
+                break;
+        case 'o':
+                cmdOpen(character);
+                break;
+        case 'q':
+                cmdQuit();
+                break;
+        case 'r':
+                if (player_party->getPartyControlMode()==PARTY_CONTROL_FOLLOW)
+                        cmdReady(NULL);
+                else
+                        cmdReady(character);
+                break;
+        case 's':
+                cmdSearch(character);
+                break;
+        case 't':
+                cmdTalk(character);
+                break;
+        case 'u':
+                cmdUse(character, 0);
+                break;
+        case 'x':
+                cmdXamine(character);
+                break;
+#ifdef USE_SKILLS
+        case 'y':
+                cmdYuse(character);
+                break;
+#endif
+        case 'z':
+                cmdZtats(character);
+                break;
+        case '@':
+                cmdAT(character);
+                break;
+        case ' ':
+                log_msg("Pass");
+                character->endTurn();
+                break;
+        case '?':
+                cmdHelp();
+                break;
+
+       case SDLK_ESCAPE:
+        // SAM: Removed the ESC-to-exit-combat keybinding.
+        //      Using ESC for both exit-from-UI-things and exit-combat-map
+        //      meant it was easy to exit, and miss your loot.
+        //      
+                if (!place_is_wilderness_combat(character->getPlace()))
+                {
+                   // log_msg("");
+                   break;
+                }
+
+                if (place_contains_hostiles(character->getPlace(), character))
+                {
+                   // log_msg("");
+                   break;
+                }
+               log_msg("To exit this combat map, use '<', \nor walk off the edge of the map.");
+               break;
+
+        case '<':
+        // case SDLK_ESCAPE // SAM: Removed the ESC-to-exit-combat keybinding, see above.
+                // ----------------------------------------------------
+                // Quick exit from wilderness combat. The current place
+                // must be the special wildernss combat place and it
+                // must be empty of hostile characters or this fails.
+                // ----------------------------------------------------
+
+                if (!place_is_wilderness_combat(character->getPlace()))
+                {
+                        log_msg("Must use an exit!");
+                        break;
+                }
+
+                if (place_contains_hostiles(character->getPlace(), 
+                                            character))
+                {
+                        log_msg("Not while foes remain!");
+                        break;
+                }
+
+                // ----------------------------------------------------
+                // This next call is to make sure the "Victory" and
+                // "Defeated" messages are printed properly. I don't
+                // *think* it has any other interesting side-effects in
+                // this case.
+                // ----------------------------------------------------
+
+                combat_analyze_results_of_last_turn();
+
+                // ----------------------------------------------------
+                // Remove all party members.
+                // ----------------------------------------------------
+
+                player_party->removeMembers();
+
+                character->endTurn();
+
+                break;
+
+        default:
+                break;
+        }
+
+        cmdwin_clear();
+
+        if (!character->isTurnEnded()) {
+                cmdwin_push("%s:", character->getName());
+        }
+
+        Session->subject = NULL;
+
+        return character->isTurnEnded();
+}
+
+static int ctrl_too_close_to_target(class Character *character, 
+                                    class Character *target)
+{
+        int distance;
+
+        distance = place_flying_distance(character->getPlace(), 
+                                         character->getX(), character->getY(), 
+                                         target->getX(), target->getY());
+
+        if (distance > 1)
+                return 0;
+
+               int armsIndex=0;
+        for (class ArmsType * weapon = character->enumerateWeapons(&armsIndex); 
+             weapon != NULL; weapon = character->getNextWeapon(&armsIndex)) {
+
+                /* if npc has at least one melee weapon then not too close */
+                if (character->hasAmmo(weapon) &&
+                    ! weapon->isMissileWeapon()) {
+                        return 0;
+                }
+        }
+
+        return 1;
+}
+
+#if 0
+static void ctrl_unready_all_weapons(class Character *character)
+{
+               int armsIndex = 0;
+        for (class ArmsType * weapon = character->enumerateWeapons(&armsIndex); 
+             weapon != NULL; weapon = character->getNextWeapon(&armsIndex)) {
+                character->unready(weapon);
+        }
+}
+
+static void ctrl_ready_melee_weapons(class Character *character)
+{
+        class Container *container = character->getContainer();
+        struct inv_entry *ie;
+}
+
+static int ctrl_switch_to_melee_weapon(class Character *character)
+{
+        /* unready all weapons */
+        ctrl_unready_all_weapons(character);
+
+        /* ready any melee weapons */
+        ctrl_ready_melee_weapons(character);
+
+        /* ready any shields if hands are left open */
+
+        /* ready any missile weapons if hands are left open */
+
+}
+#endif
+
+static int ctrl_try_move_toward(class Character *character, int dx, int dy)
+{
+        int x = character->getX() + dx;
+        int y = character->getY() + dy;
+        
+        if (place_is_passable(character->getPlace(), x, y, character, 0)) {
+                switch (character->move(dx, dy)) {
+                case MovedOk:
+                case ExitedMap:
+                case SwitchedOccupants:
+                        return 1;
+                default:
+                        return 0;
+                }
+        }
+
+        return 0;
+}
+
+static int ctrl_move_away_from_target(class Character *character, 
+                                      class Character *target)
+{
+        /* first try moving directly away from the target */
+        int dx = character->getX() - target->getX();
+        int dy = character->getY() - target->getY();
+
+        if (character->isStationary())
+                return 0;
+
+        /* normalize vector */
+        dx = dx > 0 ? 1 : (dx < 0 ? -1 : 0);
+        dy = dy > 0 ? 1 : (dy < 0 ? -1 : 0);
+
+        /* disallow diagonal moves */
+        if (dx == 0 || dy == 0) {
+                if (ctrl_try_move_toward(character, dx, dy))
+                        return 1;
+        }
+
+        /* try another vector */
+        if (dx != 0) {
+                if (ctrl_try_move_toward(character, 0, 1))
+                        return 1;
+                if (ctrl_try_move_toward(character, 0, -1))
+                        return 1;
+        }
+
+        if (dy != 0) {
+                if (ctrl_try_move_toward(character, 1, 0))
+                        return 1;
+                if (ctrl_try_move_toward(character, -1, 0))
+                        return 1;
+        }
+
+        return 0;
+}
+
+static bool ctrl_attack_target(class Character *character, 
+                               class Character *target)
+{
+        int distance;
+        bool attacked = false;
+
+        distance = place_flying_distance(character->getPlace(), 
+                                         character->getX(), character->getY(), 
+                                         target->getX(), target->getY());
+
+               int armsIndex = 0;
+               int this_is_nth_attack = 0;
+               int slowest_attack_AP = 0;
+               int total_AP = 0;
+               int this_wpn_AP;
+        for (class ArmsType * weapon = character->enumerateWeapons(&armsIndex);
+             weapon != NULL; weapon = character->getNextWeapon(&armsIndex)) {
+
+           // log_msg("DEBUG: wpn = %s (AP=%d), remaining AP=%d\n",
+           //         weapon->getName(), weapon->getRequiredActionPoints(), character->getActionPoints() );
+                if (distance > weapon->getRange()) {
+                        continue;
+                }
+
+                if (!character->hasAmmo(weapon)) {
+                        continue;
+                }
+
+                if (distance <= 1 && weapon->isMissileWeapon()) {
+                        // Handle missile weapon interference
+                        continue;
+                }
+
+               this_is_nth_attack++;
+                ctrl_do_attack(character, weapon, target, character->getToHitPenalty());
+                
+                // sum up AP requirement
+                this_wpn_AP = weapon->getRequiredActionPoints();
+                if (this_wpn_AP > slowest_attack_AP)
+                {
+                       slowest_attack_AP = this_wpn_AP;
+                }
+                total_AP += this_wpn_AP;
+                attacked = true;
+
+               if (this_is_nth_attack == 1) {
+                   // 1st weapon attack (usual case)
+               }
+               else if (this_is_nth_attack == 2) {
+                   // 2st weapon attack (dual weapon, 2nd weapon)
+                   int mult = kern_intvar_get("AP_MULT12:second_wpn_attack");
+                   this_wpn_AP = (int) (this_wpn_AP * mult) / 12;
+               }
+               else if (this_is_nth_attack >= 3) {
+                   // 3rd+ weapon attack (unusual case for multi-limbed beings...)
+                   int mult = kern_intvar_get("AP_MULT12:third_plus_wpn_attack");
+                   this_wpn_AP = (int) (this_wpn_AP * mult) / 12;
+               }
+               character->decActionPoints(this_wpn_AP);
+               //log_msg("DEBUG: after attack, used %d, remaining AP=%d\n",
+                //        this_wpn_AP, character->getActionPoints() );
+                statusRepaint();
+
+                if (target->isDead())
+                        break;
+
+               // If the AP use is not over the multi-weapon extra allowance, continue:
+               int threshold = kern_intvar_get("AP_THRESHOLD:multi_attack_overage");
+               if (character->getActionPoints() + threshold < 0) {
+                   //log_msg("DEBUG: AP = %d, threshold = %d -- breaking multi-attack\n",
+                   //    character->getActionPoints(), threshold );
+                   break;
+               }
+       }
+        
+        if (character->needToRearm())
+                character->armThyself();
+
+        return attacked;
+}
+
+/* Data structure used by the ctrl_is_valid_target visitor function below */
+struct ctrl_select_target_data {
+        class Character *target;    /* best target found so far */
+        class Character *attacker;  /* attacking character */
+        int distance;               /* distance to 'target' */
+};
+
+/*****************************************************************************
+ * ctrl_is_valid_target - check if 'obj' is a valid target for 'attacker'
+ *****************************************************************************/
+static int ctrl_is_valid_target(class Character *attacker, class Object *obj)
+{
+        /* Skip NULL */
+        if (! obj)
+                return 0;
+
+        /* Skip non-characters */
+        if (! obj->isType(CHARACTER_ID))
+                return 0;
+
+        /* Skip the attacker */
+        if (obj == attacker)
+                return 0;
+
+        /* Skip dead beings */
+        if (obj->isDead())
+                return 0;
+
+        /* Skip non-hostiles */
+        if (! are_hostile(attacker, (Being*)obj))
+                return 0;
+
+        /* Skip non-visible objects */
+        if (! attacker->canSee(obj))
+                return 0;
+
+        /* Skip off-map beings (is this even possible?) */
+        if (! obj->isOnMap())
+                return 0;
+
+        return 1;
+}
+
+/*****************************************************************************
+ * ctrl_select_target_visitor - find and remember the closest valid target for
+ * an attacker
+ *****************************************************************************/
+static void ctrl_select_target_visitor(struct node *node, void *parm)
+{
+        class Object *obj;
+        struct ctrl_select_target_data *data;
+        int distance;
+
+        /* Extract the typed variables from the generic parms */
+        obj = (class Object*)node->ptr;
+        data = (struct ctrl_select_target_data *)parm;
+
+        /* Check if this object makes a valid target */
+        if (! ctrl_is_valid_target(data->attacker, obj))
+                return;
+
+        /* Compute the distance from attacker to obj */
+        distance = place_flying_distance(data->attacker->getPlace(), 
+                                         data->attacker->getX(), 
+                                         data->attacker->getY(), 
+                                         obj->getX(), 
+                                         obj->getY());
+
+        /* Memoize the closest target and its distance */
+        if (distance < data->distance) {
+                data->distance = distance;
+                data->target = (class Character*)obj;
+        }
+}
+
+/*****************************************************************************
+ * ctrl_select_target - use a heuristic to pick a target for an attacker
+ *****************************************************************************/
+static class Character * ctrl_select_target(class Character *character)
+{
+        struct ctrl_select_target_data data;
+
+        /* Initialize the search data. */
+        data.attacker = character;
+        data.target = NULL;
+        data.distance = place_max_distance(character->getPlace()) + 1;
+
+        /* Search all objects in the current place for targets. */
+        node_foldr(place_get_all_objects(character->getPlace()),
+                   ctrl_select_target_visitor,
+                   &data);
+
+        /* Check if one was found */
+        if (data.target) {
+                character->setAttackTarget((class Character*)data.target);
+                return data.target;
+        }
+
+        /* Try the old one */
+        if (ctrl_is_valid_target(character,
+                                 character->getAttackTarget(NULL)))
+                return character->getAttackTarget(NULL);
+
+        /* No valid targets */
+        character->setAttackTarget(NULL);
+        return NULL;
+}
+
+
+static void ctrl_idle(class Character *character)
+{
+        class Character *target;
+
+        if (character->getAI()) {
+
+                /* closure returns true if it handled the turn, otherwise fall
+                 * through to standard AI */
+                if (closure_exec(character->getAI(), "p", character))
+                        return;
+
+                if (character->getActionPoints() <= 0)
+                        return;
+        }
+
+        // -------------------------------------------------------------------
+        // If they see an enemy they'll engage. Otherwise they just wander
+        // uselessly within the rectangular area imposed by their schedule (or
+        // freely if they have no schedule).
+        // -------------------------------------------------------------------
+
+        target = ctrl_select_target(character);
+        if (!target) {
+                ctrl_wander(character);
+                return;
+        }
+        
+        // -------------------------------------------------------------------
+        // A bit confusing here next. If the NPC can't see a target I still let
+        // them pathfind. Why? Because the target might be "remembered" - maybe
+        // they were visible last turn and they just stepped out of LOS.
+        // -------------------------------------------------------------------
+        
+        // note isOnMap checks so that if something has removed the character
+        // from the map (or killed it) as a result of its move attempt then
+        // you should quit having it wander around
+        
+                       if (!character->canSee(target))
+                       {
+                               if (! character->pathfindTo(target->getPlace(),
+                                               target->getX(),
+                                               target->getY()))
+                               {
+                                       if (character->isOnMap())
+                                       {
+                                               ctrl_wander(character);
+                                       }
+                                       return;
+                               }
+                       }
+                              
+        if (ctrl_too_close_to_target(character, target)) {
+                if (! ctrl_move_away_from_target(character, target))
+                        /*if (! ctrl_switch_to_melee_weapon(character))*/
+                        ctrl_wander(character);
+                return;
+        }
+
+        // -------------------------------------------------------------------
+        // Then try force.
+        // -------------------------------------------------------------------
+
+                       if (!ctrl_attack_target(character, target))
+                       {
+                               if ((! character->pathfindTo(target->getPlace(),
+                                                       target->getX(),
+                                                       target->getY()))
+                                               && character->isOnMap())
+                               {
+                                       ctrl_wander(character);
+                               }
+                       }
+}
+
+void ctrl_character_ai(class Character *character)
+{
+        if (character->isFleeing()
+            && character->flee()) {
+                return;
+        }
+        ctrl_idle(character);
+}
+
+void ctrl_character_ui(class Character *character)
+{
+        struct KeyHandler kh;
+        /* Setup cmdwin prompt for first entry to the control loop */
+        cmdwin_clear();
+        cmdwin_push("%s:", character->getName());
+
+        /* Push the key handler and enter the event loop until character is
+         * done with turn */
+        kh.fx = &ctrl_character_key_handler;
+        kh.data = character;
+        eventPushKeyHandler(&kh);
+        G_turnaround = SDL_GetTicks() - G_turnaround_start;
+        eventHandle();
+        G_turnaround_start = SDL_GetTicks();
+        eventPopKeyHandler();        
+        mapUpdate(REPAINT_IF_DIRTY);
+}
+
+void ctrl_party_ui(class PlayerParty *party)
+{
+        struct KeyHandler kh;
+
+        /* ready the cmdwin prompt */
+        cmdwin_clear();
+                 cmdwin_push("Party [%d ap]:",party->getActionPoints());
+                               
+        kh.fx = &ctrl_party_key_handler;
+        kh.data = party;
+        eventPushKeyHandler(&kh);
+        G_turnaround = SDL_GetTicks() - G_turnaround_start;
+        eventHandle();
+        G_turnaround_start = SDL_GetTicks();
+        eventPopKeyHandler();
+        mapUpdate(REPAINT_IF_DIRTY);
+}
diff --git a/src/ctrl.h b/src/ctrl.h
new file mode 100644 (file)
index 0000000..86f1f60
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef ctrl_h
+#define ctrl_h
+
+extern void ctrl_party_ui(class PlayerParty *party);
+extern void ctrl_party_ai(class Party *party);
+extern void ctrl_character_ui(class Character *character);
+extern void ctrl_character_ai(class Character *character);
+extern void ctrl_wander(class Object *obj);
+extern void ctrl_do_attack(class Character *character, class ArmsType *weapon, 
+                           class Character *target, int penalty);
+
+#endif
diff --git a/src/cursor.cpp b/src/cursor.cpp
new file mode 100644 (file)
index 0000000..10c8f61
--- /dev/null
@@ -0,0 +1,198 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "cursor.h"
+#include "place.h"
+#include "map.h"
+#include "templ.h"
+
+Cursor::Cursor()
+        : range(0)
+          , bounded(0)
+          , originX(0)
+          , originY(0)
+          , active(false)
+          , useRange(false)
+          , useZone(false)
+          , zone(0)
+{
+}
+
+Cursor::~Cursor()
+{
+}
+
+void Cursor::init(class ObjectType * type)
+{
+       Object::init(type);
+}
+
+bool Cursor::inRange(int x, int y)
+{
+        if (useRange) {
+                // this works on wrapping maps
+                int d = place_flying_distance(getPlace(), originX, originY, 
+                                              x, y);
+        
+                // Is the new location out of range?
+                if (d > range) {
+                        return false;
+                }
+        }
+
+        if (useZone) {
+                assert(zone);
+                if (! templ_get(zone, x, y)) {
+                        return false;
+                }
+        }
+
+        return true;
+}
+
+enum MoveResult Cursor::move(int dx, int dy)
+{
+        // SAM: Found a few things, noted below.
+        // 
+        // -- Cursor sometimes not drawn:
+        // If the cursor is moved out of LOS, it is not drawn.
+        // That is not desirable, methinks.
+        // 
+        // -- Cursor range "any range within viewport"
+        // Cursor::setViewportBounded() makes this possible.
+        // The caller need only set the range to some large value,
+        // and turn on 'bounded'.
+       int newx = getX() + dx;
+       int newy = getY() + dy;
+        
+        newx = place_wrap_x(getPlace(), newx);
+        newy = place_wrap_y(getPlace(), newy);
+        
+        // Is the new location off the map?
+        if (place_off_map(getPlace(), newx, newy))
+            return OffMap;
+        
+        // Is the new location out of the current viewport (without scrolling)?
+        if (bounded && !mapTileIsWithinViewport(newx,newy))
+                return OutOfRange;
+        
+        // Is the new location out of range?
+        if (! inRange(newx, newy))
+                return OutOfRange;
+
+        // move the cursor
+        relocate(getPlace(), newx, newy, REL_NOTRIG);
+
+        // Keep the cursor in view.
+        if (! mapIsInCameraView(getPlace(), getX(), getY())) {
+                mapCenterCamera(getX(), getY());
+        }
+        
+        return MovedOk;
+}
+
+void Cursor::setViewportBounded(bool val)
+{
+        bounded = val;
+}
+
+void Cursor::setRange(int val)
+{
+       range = val;
+        useRange = true;
+}
+
+void Cursor::setOrigin(int x, int y)
+{
+       originX = x;
+       originY = y;
+        if (zone) {
+                templ_set_origin(zone, x, y);
+        }
+}
+
+void Cursor::relocate(struct place *newplace, int newx, int newy, bool noStep,
+                      struct closure *place_switch_hook)
+{
+        Object::relocate(newplace, newx, newy, REL_NOTRIG, NULL);
+        active = true;
+}
+
+void Cursor::remove()
+{
+        Object::remove();
+        active = false;
+}
+
+bool Cursor::is_active(void)
+{
+        return active;
+}
+
+int Cursor::getRange()
+{
+        return range;
+}
+
+int Cursor::getOriginX()
+{
+        return originX;
+}
+
+int Cursor::getOriginY()
+{
+        return originY;
+}
+
+void Cursor::shadeRange(bool val)
+{
+        shade = val;
+}
+
+bool Cursor::isRangeShaded()
+{
+        return shade;
+}
+
+void Cursor::setZone(struct templ *val)
+{
+        if (zone) {
+                templ_unref(zone);
+                zone = 0;
+                useZone = false;
+        }
+        
+        if (val) {
+                templ_ref(val);
+                zone = val;
+                useZone = true;
+                templ_set_origin(zone, originX, originY);
+        }
+}
+
+void Cursor::reset()
+{
+        setZone(0);
+        setRange(0);
+        useRange = false;
+        shade    = false;
+        active   = false;
+}
diff --git a/src/cursor.h b/src/cursor.h
new file mode 100644 (file)
index 0000000..4281e20
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef cursor_h
+#define cursor_h
+
+#include "object.h"
+
+class Cursor:public Object {
+      public:
+       Cursor();
+
+       virtual ~ Cursor();
+       virtual void init(class ObjectType * type);
+       virtual enum MoveResult move(int dx, int dy);
+        virtual void relocate(struct place *newplace, int newx, int newy, 
+                              bool noStep = true, 
+                              struct closure *place_switch_hook = NULL);
+        virtual void remove();
+
+        bool is_active(void);
+        void setViewportBounded(bool val);
+        int getRange();
+        void setRange(int val);
+       void setOrigin(int x, int y);
+        int getOriginX();
+        int getOriginY();
+        bool inRange(int x, int y);
+        void shadeRange(bool val);
+        bool isRangeShaded();
+        void setZone(struct templ *zone);
+        void reset();
+
+      protected:
+       int range, bounded, originX, originY;
+        bool active;
+        bool shade;
+        bool useRange;
+        bool useZone;
+        struct templ *zone;
+};
+
+#endif // cursor_h
diff --git a/src/debug.c b/src/debug.c
new file mode 100644 (file)
index 0000000..3aa29dc
--- /dev/null
@@ -0,0 +1,52 @@
+#include "debug.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+// revisit: make these command-line options
+int DEBUG = 1;
+int VERBOSE = 1;
+
+void dbg(const char *fmt, ...)
+{
+        if (DEBUG) {
+                va_list args;
+                va_start(args, fmt);
+                vprintf(fmt, args);
+                va_end(args);
+        }
+}
+
+void err(const char *fmt, ...)
+{
+        va_list args;
+        va_start(args, fmt);
+        vfprintf(stderr, fmt, args);
+        va_end(args);
+        fprintf(stderr, "\n");
+        exit(-1);
+}
+
+void info(const char *fmt, ...)
+{
+        if (VERBOSE) {
+                va_list args;
+                va_start(args, fmt);
+                vprintf(fmt, args);
+                va_end(args);
+        }
+}
+
+void warn(const char *fmt, ...)
+{
+        va_list args;
+        va_start(args, fmt);
+        vprintf(fmt, args);
+        va_end(args);
+}
+
+void vwarn(const char *fmt, va_list args)
+{
+        vprintf(fmt, args);
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644 (file)
index 0000000..6194183
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+/* Ripped this off from linux/include/linux/usb.h
+ */
+#ifndef debug_h
+#define debug_h
+
+#include "macros.h"
+#include <stdarg.h>
+
+BEGIN_DECL
+
+extern int DEBUG;
+extern int VERBOSE;
+
+extern void dbg(const char *fmt, ...);
+extern void err(const char *fmt, ...);
+extern void info(const char *fmt, ...);
+extern void warn(const char *fmt, ...);
+extern void vwarn(const char *fmt, va_list args);
+
+END_DECL
+
+#endif
diff --git a/src/dice.c b/src/dice.c
new file mode 100644 (file)
index 0000000..af26aa5
--- /dev/null
@@ -0,0 +1,167 @@
+#include <assert.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+static int dice_parse(const char *ptr, int *num, int *faces, int *bias)
+{
+        int state = 0;
+        int val = 0;
+        int sign = 1;
+
+        *num = 0;
+        *faces = 0;
+        *bias = 0;
+
+        while (*ptr) {
+                switch (state) {
+
+                case 0:
+                        if (*ptr == '+') {
+                                sign = 1;
+                                state = 4;
+                        } else if (*ptr == '-') {
+                                sign = -1;
+                                state = 4;
+                        } else if (isdigit(*ptr)) {
+                                val = *ptr - '0';
+                                if (val)
+                                        state = 1;
+                        } else {
+                                goto error;
+                        }
+                        break;
+                        
+                case 1:
+                        if (*ptr == 'd') {
+                                *num = val * sign;
+                                val = 0;
+                                sign = 1;
+                                state = 2;
+                        } else if (isdigit(*ptr)) {
+                                val = (val * 10) + *ptr - '0';
+                        } else {
+                                goto error;
+                        }
+                        break;
+
+                case 2:
+                        if (isdigit(*ptr)) {
+                                val = *ptr - '0';
+                                if (val)
+                                        state = 3;
+                        } else {
+                                goto error;
+                        }
+                        break;
+
+                case 3:
+                        if (isdigit(*ptr)) {
+                                val = (val * 10) + *ptr - '0';
+                        } else if (*ptr == '+') {
+                                *faces = val;
+                                val = 0;
+                                state = 4;
+                                sign = 1;
+                        } else if (*ptr == '-') {
+                                *faces = val;
+                                val = 0;
+                                state = 4;
+                                sign = -1;
+                        } else {
+                                goto error;
+                        }
+                        break;
+
+                case 4:
+                        if (isdigit(*ptr)) {
+                                val = atoi(ptr);
+                                if (val)
+                                        state = 5;
+                        } else {
+                                goto error;
+                        }
+                        break;
+
+                case 5:
+                        if (isdigit(*ptr)) {
+                                val = (val * 10) + *ptr - '0';
+                        } else {
+                                goto error;
+                        }
+                        break;
+                default:
+                        assert(false); /* impossible state */
+                        goto error;
+                }
+
+                ptr++;
+        }
+
+        switch (state) {
+        case 0:
+                break;
+        case 1:
+                *bias = val * sign;
+                break;
+        case 2:
+                goto error;
+                break;
+        case 3:
+                *faces = val * sign;
+                break;
+        case 4:
+                *bias = val * sign;
+                break;
+        case 5:
+                *bias = val * sign;
+                break;
+        default:
+                assert(false); /* impossible state */
+                goto error;
+        }
+
+        return 0;
+
+ error:
+        return -1;
+}
+
+int dice_roll_numeric(int num, int faces, int bias)
+{
+       int val = 0;
+       while (num--) {
+              val += (rand() % faces) + 1;
+       }
+       val += bias;
+       return val;
+}
+
+int dice_roll(const char *ptr)
+{
+        int num = 0;
+        int faces = 0;
+        int bias = 0;
+
+        if (dice_parse(ptr, &num, &faces, &bias)) {
+                assert(false); /* if uncertain, caller should have checked
+                                * first */
+                return 0;
+        }
+        
+        return dice_roll_numeric(num,faces,bias);
+}
+
+int dice_valid(const char *fmt)
+{
+        int num, faces, bias;
+        if (!fmt) 
+                return 0;
+        return dice_parse(fmt, &num, &faces, &bias) ? 0 : 1;
+}
+
+int dice_average(const char *fmt)
+{
+        int num, faces, bias;
+        dice_parse(fmt, &num, &faces, &bias);
+        return ((faces / 2) + 1) * num + bias;
+}
diff --git a/src/dice.h b/src/dice.h
new file mode 100644 (file)
index 0000000..73ee81b
--- /dev/null
@@ -0,0 +1,23 @@
+
+/* A dice roll is specified by a string format. For example, "2d20+6". The
+ * legal formats are defined by a regular expression:
+ *
+ *      ([1-9][0-9]*]d[1-9][0-9]*)?([\+\-]?[1-9][0-9]*)?
+ *
+ * Which means the following are all legal examples:
+ *
+ *      "1d1"
+ *      "2"
+ *      "" (note: returns 0)
+ *      "5064d21023902-10909012"
+ *
+ * The result of the dice roll is returned. If the format is invalid then it
+ * will always return 0, but since 0 is a valid response you won't necessarily
+ * be able to tell. To check if a format is bad use the separate dice_valid()
+ * call, which returns non-zero if the format is ok and 0 otherwise.
+ *
+ */
+extern int dice_roll(const char *fmt);
+extern int dice_valid(const char *fmt);
+extern int dice_average(const char *fmt);
+extern int dice_roll_numeric(int num, int faces, int bias);
diff --git a/src/dimensions.c b/src/dimensions.c
new file mode 100644 (file)
index 0000000..33466d1
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "dimensions.h"
+#include "common.h" /* for MOON_WINDOW_W */
+#include "cfg.h"
+
+#include <string.h>
+
+int STATUS_MAX_MSG_SZ;
+int SCREEN_W;
+int SCREEN_H;
+int CONSOLE_MAX_MSG_SZ;
+int MAP_TILE_W;
+int MAP_TILE_H;
+int MAP_X;
+int MAP_Y;
+int MAP_W;
+int MAP_H;
+int CMD_X;
+int CMD_Y;
+int CMD_W;
+int CMD_H;
+int STAT_X;
+int STAT_Y;
+int STAT_W;
+int STAT_H;
+int STAT_H_MAX;
+int FOOGOD_X;
+int FOOGOD_Y;
+int FOOGOD_W;
+int FOOGOD_H;
+int WIND_X;
+int WIND_Y;
+int WIND_W;
+int WIND_H;
+int CONS_X;
+int CONS_Y;
+int CONS_W;
+int CONS_H;
+int CONS_LINES;
+int SKY_X;
+int SKY_Y;
+int SKY_W;
+int SKY_H;
+int SKY_SPRITE_W;
+
+/* dimensions_get_map_size -- figure out the biggest map window that will
+ * satisfy the screen dimensions.  */
+static int dimensions_get_map_size(char *dimstr)
+{
+        struct dimstr2mapsz {
+                const char *dimstr;
+                int map_sz;
+        };
+#       define ADD_SCREEN_DIM(dim,mapw) { (dim), (mapw) },
+        struct dimstr2mapsz tbl[] = {
+#               include "screen_dims.h"
+        };
+
+        int i;
+
+        if (!dimstr) {
+                warn("warn: NULL dimensions");
+                return -1;
+        }
+
+        for (i = 0; i < array_sz(tbl); i++) {
+                if (! strcmp(tbl[i].dimstr, dimstr)) {
+                        return tbl[i].map_sz;
+                }
+        }
+
+        warn("warn: screen res %s not found in table\n", dimstr);
+        return -1;
+}
+
+int dimensions_init()
+{
+        int map_size = dimensions_get_map_size(cfg_get("screen-dims"));
+        if (map_size < 0)
+                return -1;
+
+        MAP_TILE_W = map_size;
+        MAP_TILE_H = map_size;
+
+        MAP_X = BORDER_W;
+        MAP_Y = BORDER_H;
+        MAP_W = (TILE_W * MAP_TILE_W);
+        MAP_H = (TILE_H * MAP_TILE_H);
+
+        CMD_X = MAP_X;
+        CMD_Y = (MAP_Y + MAP_H + BORDER_H);
+        CMD_W = MAP_W;
+        CMD_H = ASCII_H;
+
+        SCREEN_H = (BORDER_H * 3 + MAP_H + CMD_H);
+
+        STATUS_MAX_MSG_SZ = 128;
+        STAT_X =  (MAP_X + MAP_W + BORDER_W);
+        STAT_Y =  BORDER_H;
+        STAT_W = (/*BORDER_W * 2*/ + ASCII_W * STAT_CHARS_PER_LINE);
+        STAT_H =  (3 * TILE_H);
+        STAT_H_MAX = (16 * TILE_H);
+
+        CONS_X =  STAT_X;
+        CONS_Y =  (FOOGOD_Y + FOOGOD_H + BORDER_H);
+        CONS_W =  STAT_W;
+        CONS_H =  (SCREEN_H - BORDER_H - CONS_Y);
+        CONS_LINES = (CONS_H / ASCII_H);
+
+        CONSOLE_MAX_MSG_SZ = (CONS_W / ASCII_W);
+
+        FOOGOD_X = STAT_X;
+        FOOGOD_Y = (STAT_Y + STAT_H + BORDER_H);
+        FOOGOD_W = STAT_W;
+        FOOGOD_H = (2 * ASCII_H);
+
+        WIND_W =  (strlen("wind:northeast") * ASCII_W);
+        WIND_H =  BORDER_H;
+        WIND_X =  (BORDER_W + (MAP_W - WIND_W) / 2);
+        WIND_Y =  (MAP_Y + MAP_H);
+
+        SKY_W =   MOON_WINDOW_W;
+        SKY_H =   BORDER_H;
+        SKY_X =   (MAP_X + (MAP_W - SKY_W) / 2);
+        SKY_Y =   0;
+        SKY_SPRITE_W = (TILE_W/2);
+
+        SCREEN_W = (BORDER_W * 3 + MAP_W + CONS_W);
+
+        return 0;
+}
diff --git a/src/dimensions.h b/src/dimensions.h
new file mode 100644 (file)
index 0000000..06787fa
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef dimensions_h
+#define dimensions_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#define STAT_CHARS_PER_LINE 46
+
+#define TILE_W   32
+#define TILE_H   32
+#define ASCII_W  8
+#define ASCII_H  16
+#define BORDER_W 16
+#define BORDER_H 16
+
+#define MIN_MAP_SIZE 11
+#define MAX_MAP_SIZE 19
+#define DEF_MAP_SIZE 19
+
+extern int STATUS_MAX_MSG_SZ;
+extern int SCREEN_W;
+extern int SCREEN_H;
+extern int CONSOLE_MAX_MSG_SZ;
+
+extern int MAP_TILE_W;
+extern int MAP_TILE_H;
+extern int MAP_X;
+extern int MAP_Y;
+extern int MAP_W;
+extern int MAP_H;
+
+extern int CMD_X;
+extern int CMD_Y;
+extern int CMD_W;
+extern int CMD_H;
+
+extern int STAT_X;
+extern int STAT_Y;
+extern int STAT_W;
+extern int STAT_H;
+extern int STAT_H_MAX;
+
+extern int FOOGOD_X;
+extern int FOOGOD_Y;
+extern int FOOGOD_W;
+extern int FOOGOD_H;
+
+extern int WIND_X;
+extern int WIND_Y;
+extern int WIND_W;
+extern int WIND_H;
+
+extern int CONS_X;
+extern int CONS_Y;
+extern int CONS_W;
+extern int CONS_H;
+extern int CONS_LINES;
+
+extern int SKY_X;
+extern int SKY_Y;
+extern int SKY_W;
+extern int SKY_H;
+extern int SKY_SPRITE_W;
+
+/* Set all the runtime-configurable UI dimensions */
+int dimensions_init();
+
+END_DECL
+
+#endif
diff --git a/src/dtable.c b/src/dtable.c
new file mode 100644 (file)
index 0000000..aa9d21f
--- /dev/null
@@ -0,0 +1,171 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "dtable.h"
+#include "debug.h"
+#include "session.h" /* for save */
+
+#include <assert.h>
+#include <stdlib.h>
+
+#define dtable_is_valid_faction(dtable,fac) \
+        ((fac) >= 0 && (fac) < (dtable)->n_factions)
+
+#define dtable_clamp_level(dtable,lvl) \
+        clamp((lvl), (dtable)->lower_bound, (dtable)->upper_bound)
+
+struct dtable *dtable_new(int n_factions)
+{
+        struct dtable *dtable;
+
+        /* allocate the "main" struct */
+        dtable = (struct dtable*)calloc(1, sizeof(*dtable));
+        assert(dtable);
+        
+        dtable->n_factions = n_factions;
+
+        /* allocate the table of stack pointers */
+        dtable->table = (int*)calloc(n_factions * n_factions, 
+                                     sizeof(dtable->table[0]));
+        assert(dtable->table);
+
+        /* For now, hardcode the table limits and settings. Note that we must
+         * set the upper and lower bounds before poking any entries into the
+         * table. */
+        dtable_set_hostile(dtable, DTABLE_DEFAULT_HOSTILE);
+        dtable_set_allies(dtable, DTABLE_DEFAULT_ALLIES);
+        dtable_set_upper_bound(dtable, DTABLE_DEFAULT_UPPER_BOUND);
+        dtable_set_lower_bound(dtable, DTABLE_DEFAULT_LOWER_BOUND);
+        
+        return dtable;        
+}
+
+static int dtable_check(struct dtable *dtable, int faction)
+{
+        if (! dtable_is_valid_faction(dtable, faction)) {
+                warn("dtable_check: invalid faction=%d\n", faction);
+                return -1;
+        }
+
+        return 0;
+}
+
+static int dtable_index(struct dtable *dtable, int f1, int f2)
+{
+        if (dtable_check(dtable, f1))
+                return -1;
+
+        if (dtable_check(dtable, f2))
+                return -1;
+
+        return f1 * dtable->n_factions + f2;
+        
+}
+
+void dtable_set(struct dtable *dtable, int f1, int f2, int level)
+{
+        int index;
+
+        dtable_clamp_level(dtable, level);
+
+        if ((index = dtable_index(dtable, f1, f2)) < 0)
+                return;
+
+        dtable->table[index] = level;
+        
+        /* mirror the change on the other half of the table */
+        index =  dtable_index(dtable, f2, f1);
+        dtable->table[index] = level;
+}
+
+int dtable_get(struct dtable *dtable, int f1, int f2)
+{
+        int index;
+
+        if ((index = dtable_index(dtable, f1, f2)) < 0) {
+                warn("dtable_get: defaulting to neutral\n");
+                return 0;
+        }
+
+        return dtable->table[index];
+}
+
+void dtable_del(struct dtable *dtable)
+{
+        assert(dtable);
+
+        if (dtable->table) {
+                free(dtable->table);
+        }
+        free(dtable);
+}
+
+
+void dtable_save(struct dtable *dtable, struct save *save)
+{
+        int rows;
+        int cols;
+        int index;
+
+        save->enter(save, "(kern-mk-dtable\n");
+
+        index = 0;
+        for (rows = 0; rows < dtable->n_factions; rows++) {
+                save->write(save, "(list ");
+                for (cols = 0; cols < dtable->n_factions; cols++) {
+                        save->write(save, "%2d ", dtable->table[index]);
+                        index++;
+                }
+                save->append(save, ")\n");
+        }
+        
+        save->exit(save, ")\n");
+}
+
+void dtable_inc(struct dtable *dtable, int f1, int f2)
+{
+        int level;
+
+        level = dtable_get(dtable, f1, f2);
+        dtable_set(dtable, f1, f2, level+1);
+}
+
+void dtable_dec(struct dtable *dtable, int f1, int f2)
+{
+        int level;
+
+        level = dtable_get(dtable, f1, f2);
+        dtable_set(dtable, f1, f2, level-1);
+
+}
+
+extern const char *dtable_describe(struct dtable *dtable, int f1, int f2)
+{
+        int level = dtable_get(dtable, f1, f2);
+        
+        if (level <= dtable->hostile)
+                return "hostile";
+        else if (level >= dtable->allies)
+                return "allied";
+        else
+                return "neutral";
+}
diff --git a/src/dtable.h b/src/dtable.h
new file mode 100644 (file)
index 0000000..084979d
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef dtable_h
+#define dtable_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#define FACTION_NONE               0
+#define DTABLE_DEFAULT_LOWER_BOUND -2
+#define DTABLE_DEFAULT_UPPER_BOUND 2
+#define DTABLE_DEFAULT_HOSTILE     -2
+#define DTABLE_DEFAULT_ALLIES      2
+
+#define dtable_are_hostile(dtable,f1, f2) \
+        (dtable_get((dtable),(f1),(f2)) <= dtable_hostile((dtable)))
+
+#define dtable_are_allies(dtable,f1, f2) \
+        (dtable_get((dtable),(f1),(f2)) >= dtable_allies((dtable)))
+
+#define dtable_set_hostile(tab,lvl)     ((tab)->hostile     = (lvl))
+#define dtable_set_allies(tab,lvl)      ((tab)->allies      = (lvl))
+#define dtable_set_lower_bound(tab,lvl) ((tab)->lower_bound = (lvl))
+#define dtable_set_upper_bound(tab,lvl) ((tab)->upper_bound = (lvl))
+
+#define dtable_hostile(tab)             ((tab)->hostile)
+#define dtable_allies(tab)              ((tab)->allies)
+
+struct dtable {
+        int n_factions;
+        int hostile;
+        int allies;
+        int lower_bound;
+        int upper_bound;
+        int *table;
+};
+
+extern struct dtable *dtable_new(int n_factions);
+extern void dtable_del(struct dtable *dtable);
+extern void dtable_set(struct dtable *dtable, int f1, int f2, int level);
+extern int dtable_get(struct dtable *dtable, int f1, int f2);
+extern void dtable_save(struct dtable *dtable, struct save *save);
+extern void dtable_inc(struct dtable *dtable, int f1, int f2);
+extern void dtable_dec(struct dtable *dtable, int f1, int f2);
+extern const char *dtable_describe(struct dtable *dtable, int f1, int f2);
+
+END_DECL
+
+#endif
diff --git a/src/dup_constants.h b/src/dup_constants.h
new file mode 100644 (file)
index 0000000..4b36c9e
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef dup_constants_h
+#define dup_constants_h
+
+// This section defines the mechanism events reserved by the game engine.
+#define MECH_ATTACK       1
+#define MECH_STEP         2
+#define MECH_HANDLE       3
+#define MECH_OPEN         4
+#define MECH_CLOSE        5
+#define MECH_LOCK         6
+#define MECH_UNLOCK       7
+#define MECH_MAGIC_LOCK   8
+#define MECH_MAGIC_UNLOCK 9
+#define MECH_TURN         10
+#define MECH_FULL_MOON    11
+
+// This value marks the beginning of the unreserved events. A game script can
+// define its own events and number them starting from here.
+#define MECH_FIRST_UNRESERVED_EVENT 100
+
+/* Effects */
+// gmcnutt: EFFECT_NATURAL was bit 30, and is intended to be used for natural
+// abilities (like snakes spitting venom) so that they will not be affected by
+// negate magic. But I ran into a problem: I needed to add EFFECT_RESTORE for
+// mana restoration potions, but I found that using a constant with bit 31 set
+// did not work out right. The parser uses atol(), which sees the high bit set
+// and I think assumes it's an overflow, so it converts the value to LONG_MAX,
+// which isn't what we intended. Since I'm basically out of bits something had
+// to give, and I sacrificed EFFECT_NATURAL for EFFECT_RESTORE.
+//
+// During the 0.3.x development line we'll address this issue. A simple thing
+// to do would be to start using multi-byte bitmaps and fix the parser. But the
+// new effect system may make this a non-issue anyway, so let's wait and see.
+//
+#define EFFECT_NATURAL      0
+#define EFFECT_NONE         0
+#define EFFECT_POISON       1  /* 0 */
+#define EFFECT_BURN         2  /* 1 */
+#define EFFECT_SLEEP        4  /* 2 */
+#define EFFECT_LIGHT        8  /* 3 */
+#define EFFECT_CURE         16 /* 4 */
+#define EFFECT_HEAL         32 /* 5 */
+#define EFFECT_AWAKEN       64 /* 6 */
+#define EFFECT_CHARM        128        /* 7 */
+#define EFFECT_DAMAGE       256        /* 8 */
+#define EFFECT_UNLOCK       512        /* 9 */
+#define EFFECT_REPEL        1024       /* 10 */
+#define EFFECT_LOCATE       2048       /* 11 */
+#define EFFECT_SUMMON       4096       /* 12 */
+#define EFFECT_WIND_CHANGE  8192       /* 13 */
+#define EFFECT_TELEPORT     16384      /* 14 */
+#define EFFECT_DESTROY      32768      /* 15 */
+#define EFFECT_ARMOUR       65536      /* 16 */
+#define EFFECT_REVEAL       131072     /* 17 */
+#define EFFECT_QUICK        262144     /* 18 */
+#define EFFECT_NEGATE       524288     /* 19 */
+#define EFFECT_TREMOR       1048576    /* 20 */
+#define EFFECT_CONFUSE      2097152    /* 21 */
+#define EFFECT_SHOW_TERRAIN 4194304    /* 22 */
+#define EFFECT_WIND         8388608    /* 23 */
+#define EFFECT_PEER         16777216   /* 24 */
+#define EFFECT_CLONE        33554432   /* 25 */
+#define EFFECT_INVISIBLE    67108864   /* 26 */
+#define EFFECT_TIME_STOP    134217728  /* 27 */
+#define EFFECT_RESURRECT    268435456  /* 28 */
+#define EFFECT_GATE_TRAVEL  536870912  /* 29 */
+#define EFFECT_RESTORE      1073741824  /* 30 */
+// WARNING: bit 31 will not work as intended! We are out of bits!
+
+#endif
diff --git a/src/effect.c b/src/effect.c
new file mode 100644 (file)
index 0000000..c0fb0a1
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2004 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "effect.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+const int EFFECT_ID = 0xeffec1;
+
+struct effect *effect_new(char *tag, scheme *sc, pointer exec_proc,
+                          pointer apply_proc, pointer rm_proc,
+                          pointer restart,
+                          char *name)
+{
+        struct effect *et;
+
+        et = (struct effect*)calloc(1, sizeof(*et));
+        assert(et);
+
+        et->ID = EFFECT_ID;
+
+        if (exec_proc) {
+                et->exec = closure_new_ref(sc, exec_proc);
+        }
+
+        if (apply_proc) {
+                et->apply = closure_new_ref(sc, apply_proc);
+        }
+
+        if (rm_proc) {
+                et->rm = closure_new_ref(sc, rm_proc);
+        }
+
+        if (restart) {
+                et->restart = closure_new_ref(sc, restart);
+        }
+
+        et->tag = strdup(tag);
+        assert(et->tag);
+
+        /* Effects with no name should be considered invisible to the UI */
+        if (name) {
+                et->name = strdup(name);
+                assert(et->name);
+        }
+
+        return et;
+}
+
+extern void effect_del(struct effect *et)
+{
+        free(et->tag);
+        free(et->name);
+        closure_unref_safe(et->exec);
+        closure_unref_safe(et->apply);
+        closure_unref_safe(et->rm);
+        closure_unref_safe(et->restart);
+        /* Need to free sprite? Nope -- sprites are global resources
+         * managed by the session. When the session is torn down it frees all
+         * of the sprites created when it loaded. */
+        free(et);
+}
diff --git a/src/effect.h b/src/effect.h
new file mode 100644 (file)
index 0000000..f396b22
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2004 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef effect_h
+#define effect_h
+
+#include "macros.h"
+#include "closure.h"
+
+BEGIN_DECL
+
+/* Negative expiration codes */
+#define EFFECT_PERMANENT          -1   /* never expires              */
+#define EFFECT_NONDETERMINISTIC   -2   /* can't tell when it expires */
+
+/* Runtime type-verification: */
+extern const int EFFECT_ID;
+#define is_effect(eff) ((eff) && ((eff)->ID == EFFECT_ID))
+#define effect_will_expire(eff) ((eff)->duration > 0)
+
+/* An effect type defines an effect like poison, protection, etc. Effects are
+ * attached to objects. */
+struct effect {
+        int ID;                 /* for runtime type-verification */
+        closure_t *exec;        /* scheme proc to execute on-hook */
+        closure_t *apply;       /* scheme proc to execute on-attach */
+        closure_t *rm;          /* scheme proc to execute on-removal */
+        closure_t *restart;     /* scheme proc to restart effect on reload */
+        char *tag;              /* identifier tag name */
+        char *name;             /* short name */
+        struct sprite *sprite;  /* might be used in ztats window */
+        int detect_dc;          /* detection difficulty class (default zero) */
+        int cumulative;         /* more then one instance can be attached */
+        int duration;           /* minutes before expire (-1 for never) */
+        int hook_id;            /* hook the effect attaches to */
+        struct sprite *status_icon; /* 8x16 sprite for status window */
+};
+
+/* Create the closure and dup the strings. Zero out other fields (caller must
+ * fill them in). */
+extern struct effect *effect_new(char *tag, scheme *sc, 
+                                 pointer exec, 
+                                 pointer apply, 
+                                 pointer rm, 
+                                 pointer restart,
+                                 char *name);
+
+/* Dealloc the closure, the strings and the struct. */
+extern void effect_del(struct effect *effect);
+
+END_DECL
+
+#endif
diff --git a/src/escape.c b/src/escape.c
new file mode 100644 (file)
index 0000000..9f34bb9
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "cmd.h"
+#include "event.h"
+#include "log.h"
+#include "session.h"
+
+#include <SDL.h>
+
+static struct KeyHandler esc_key_hndlr;
+
+static void esc_help(void)
+{
+    log_begin("F)ollow mode\n");
+    log_continue("Q)uit\n");
+    log_continue("[1-9] Solo mode\n");
+    log_continue("CTRL-R)eload\n");
+    log_continue("CTRL-S)ave\n");
+    log_end("ESC to continue game\n");
+}
+
+static int esc_menu_key_fx(struct KeyHandler *kh, int key, int keymod)
+{
+    switch (key) {
+    case 'f':
+        cmdToggleFollowMode();
+        return 1;
+    case 'q':
+        cmdQuit();
+        return 1;
+    case SDLK_1:
+    case SDLK_2:
+    case SDLK_3:
+    case SDLK_4:
+    case SDLK_5:
+    case SDLK_6:
+    case SDLK_7:
+    case SDLK_8:
+    case SDLK_9:                        
+        cmdSetSoloMode(key - SDLK_1);
+        return 1;
+    case KEY_CTRL_S:
+        cmdSave();
+        break;
+    case KEY_CTRL_R:
+        cmdReload();
+        return 1;
+    case SDLK_F10:
+        cmdSettings();
+        break;
+    case SDLK_ESCAPE:
+        log_msg("Continue");
+        return 1;
+    case '?':
+        esc_help();
+        break;
+    default:
+        //log_msg("Sorry, %d is not a valid command.");
+        break;
+    }
+    return 0;
+}
+
+static int esc_key_fx(struct KeyHandler *esckh, int key, int keymod)
+{
+    struct KeyHandler kh;
+
+    if (SDLK_ESCAPE != key) {
+        return 0;
+    }
+
+    log_banner("ESC mode - press '?' for help");
+
+    kh.fx = esc_menu_key_fx;
+    eventPushKeyHandler(&kh);
+    eventHandle();
+    eventPopKeyHandler();
+    return 0;
+}
+
+void escape_start_handler(void)
+{
+    esc_key_hndlr.fx = esc_key_fx;
+    eventPushKeyHandler(&esc_key_hndlr);
+}
+
+void escape_stop_handler(void)
+{
+    eventPopKeyHandler();
+}
diff --git a/src/escape.h b/src/escape.h
new file mode 100644 (file)
index 0000000..1786f3a
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef escape_h
+#define escape_h
+
+void escape_start_handler(void);
+void escape_stop_handler(void);
+
+#endif
diff --git a/src/event.c b/src/event.c
new file mode 100644 (file)
index 0000000..a90548b
--- /dev/null
@@ -0,0 +1,433 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "event.h"
+#include "cfg.h"
+
+#include <SDL.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <common.h>
+
+#ifndef DEBUG_KEYS
+# define DEBUG_KEYS 0
+#endif
+
+#define EVENT_NONBLOCK   (1 << 0)
+#define EVENT_NOPLAYBACK (1 << 1)
+
+#define getHandler(stack,type) \
+  (list_empty((stack)) ? NULL : (type*)(stack)->next)
+#define pushHandler(stack,handler) (list_add((stack), &(handler)->list))
+
+typedef struct {
+        struct list list;
+        SDL_Event event;
+} sdl_event_list_t;
+
+static struct list KeyHandlers;
+static struct list TickHandlers;
+static struct list QuitHandlers;
+static struct list MouseButtonHandlers;
+static struct list MouseMotionHandlers;
+static struct list backlog;
+
+static bool record_events;
+static int record_fd;
+static bool playback_events;
+static int playback_fd;
+static int event_playback_speed = 0;
+
+static void (*eventHook) (void);
+static int (*wait_event) (SDL_Event * event, int flags);
+static int qcount = 0;
+
+static struct list *popHandler(struct list *stack) 
+{
+        if (list_empty(stack)) {
+                return NULL;
+        }
+
+        struct list *lptr = stack->next;
+        list_remove(lptr);
+        return lptr;
+}
+
+static void backlog_enqueue(SDL_Event *event)
+{
+        sdl_event_list_t *elem = (sdl_event_list_t*)malloc(sizeof(*elem));
+        elem->event = *event;
+        list_add(&backlog, &elem->list);
+        qcount++;
+}
+
+static int backlog_dequeue(SDL_Event *event)
+{
+        sdl_event_list_t *elem;
+        struct list *ptr;
+        if (list_empty(&backlog))
+                return -1;
+        ptr = backlog.next;
+        elem = outcast(ptr, sdl_event_list_t, list);
+        list_remove(&elem->list);
+        *event = elem->event;
+        free(elem);
+        qcount--;
+        return 0;
+}
+
+static int mapKey(SDL_keysym * keysym)
+{
+       int key = keysym->sym;
+        
+        if (DEBUG_KEYS) {
+                printf("sym='%c'[%d] mod=%02x unicode=%04x\n", 
+                       keysym->sym,  
+                       keysym->sym,
+                       keysym->mod,
+                       keysym->unicode);
+        }
+
+        /* If the key has a UNICODE representation and its from the default
+         * Basic Latin code page then return it as an ASCII character. */
+        /* fixme: unicode is messing up ctrl+key sequences */
+        if (keysym->unicode) {
+
+                /* Map CR to LF (legacy code expects this) */
+                if (keysym->unicode == 0x000d)
+                        return '\n';
+
+                /* Map all other Basic Latin codes to ASCII */
+                if (keysym->unicode < 0x7f)
+                        return keysym->unicode & 0x7f;
+
+                /* Code page not supported... fall through */
+        }
+
+        /* Map arrow keys to equivalent numberpad entries */
+        if (key >= SDLK_UP && key <= SDLK_LEFT) {
+                static int map[] = { KEY_NORTH, KEY_SOUTH, KEY_EAST, 
+                                     KEY_WEST };
+                key = map[key - SDLK_UP];
+        }
+
+        /* Set the "shift" bit */
+        if (keysym->mod & KMOD_SHIFT) {
+                key |= KEY_SHIFT;
+        }
+
+        /* Unsupported? fallback to the SDL sym */
+       return key;
+}
+
+static int event_get_next_event(SDL_Event *event, int flags)
+{
+        /* if a key handler exists */
+        if (getHandler(&KeyHandlers, struct KeyHandler)) {
+
+                /* if the backlog queue is not empty */
+                if (! backlog_dequeue(event)) {
+
+                        /* get the event from the backlog queue */
+                        return 1;
+                }
+        }
+
+        if (flags & EVENT_NONBLOCK)
+                return SDL_PollEvent(event);
+        else
+                return SDL_WaitEvent(event);
+}
+
+static int playback_event(SDL_Event * event, int flags)
+{
+       // For now use the expedient but non-portable technique of reading the
+       // binary data straight to the file.
+       int n;
+       int len = sizeof(SDL_Event);
+       char *ptr = (char *) event;
+
+        if (flags & EVENT_NOPLAYBACK)
+                return 0;
+
+
+       while (len) {
+               n = read(playback_fd, ptr, len);
+               if (n == -1) {
+                       perror("read");
+                       return -1;
+               }
+               ptr += n;
+               len -= n;
+       }
+
+       SDL_Delay(event_playback_speed);
+
+       return 1;
+}
+
+static void record_event(SDL_Event * event)
+{
+       // For now use the expedient but non-portable technique of writing the
+       // binary data straight to the file.
+       int n;
+       int len = sizeof(SDL_Event);
+       char *ptr = (char *) event;
+       while (len) {
+               n = write(record_fd, ptr, len);
+               if (n == -1) {
+                       perror("write");
+                       return;
+               }
+               ptr += n;
+               len -= n;
+       }
+}
+
+static void event_handle_aux(int flags)
+{
+       bool done = false;
+        bool use_hook = false;
+
+       while (!done) {
+
+               SDL_Event event;
+                if (!wait_event(&event, flags)) {
+                        return;
+                }
+                if (record_events)
+                        record_event(&event);
+
+               switch (event.type) {
+
+               case SDL_USEREVENT:
+                       {
+                               struct TickHandler *tickh;
+                               tickh = getHandler(&TickHandlers,
+                                                   struct TickHandler);
+                               if (tickh) {
+                                        use_hook = true;
+                                        if (tickh->fx(tickh)) {
+                                                done = true;
+                                        }
+                                }
+                                
+                       }
+                       break;
+
+               case SDL_KEYDOWN:
+                       {
+                               struct KeyHandler *keyh;
+                               keyh = getHandler(&KeyHandlers, 
+                                                  struct KeyHandler);
+                               if (keyh) {
+                                        int mapped_key = 
+                                                mapKey(&event.key.keysym);
+                                        use_hook = true;
+                                        if (keyh->fx(keyh, mapped_key, 
+                                                     event.key.keysym.mod)) {
+                                                done = true;
+                                        }
+                                } else {
+                                        /* enqueue this event */
+                                        backlog_enqueue(&event);
+                                }
+                       }
+                       break;
+
+               case SDL_QUIT:
+                       {
+                               struct QuitHandler *quith;
+                               quith =
+                                   getHandler(&QuitHandlers,
+                                              struct QuitHandler);
+                               if (quith && quith->fx(quith))
+                                       done = true;
+                       }
+                       break;
+
+               case SDL_MOUSEBUTTONDOWN:
+                       {
+                               struct MouseButtonHandler *mouseh;
+                               mouseh = getHandler(&MouseButtonHandlers,
+                                                   struct MouseButtonHandler);
+                               if (mouseh &&
+                                   mouseh->fx(mouseh, &event.button)) {
+                                       done = true;
+                                }
+                       }
+                       break;
+
+               case SDL_MOUSEMOTION:
+                       {
+                               struct MouseMotionHandler *mouseh;
+                               mouseh = getHandler(&MouseMotionHandlers,
+                                                   struct MouseMotionHandler);
+                               if (mouseh &&
+                                   mouseh->fx(mouseh, &event.motion)) {
+                                       done = true;
+                                }
+                       }
+                       break;
+
+               default:
+                       break;
+               }
+
+               if (use_hook && eventHook)
+                       eventHook();
+
+       }
+
+}
+
+int eventInit(void)
+{
+        char *record_fname = cfg_get("record-filename");
+        char *playback_fname = cfg_get("playback-filename");
+
+       list_init(&KeyHandlers);
+       list_init(&TickHandlers);
+       list_init(&QuitHandlers);
+       list_init(&MouseButtonHandlers);
+       list_init(&MouseMotionHandlers);
+        list_init(&backlog);
+       eventHook = NULL;
+       wait_event = event_get_next_event;
+        qcount=0;
+
+       if (record_fname != NULL) {
+               record_events = true;
+               record_fd = open(record_fname, O_WRONLY | O_CREAT, 00666);
+               if (record_fd == -1) {
+                       perror(record_fname);
+                       return -1;
+               }
+       }
+
+       if (playback_fname != NULL) {
+                char *playback_spd_str = cfg_get("playback-speed");
+               playback_events = true;
+               playback_fd = open(playback_fname, O_RDONLY, 00666);
+               if (playback_fd == -1) {
+                       perror(playback_fname);
+                       return -1;
+               }
+               // Override the normal wait_event routine
+               wait_event = playback_event;
+
+                /* Set the play back speed. */
+                if (playback_spd_str) {
+                        event_playback_speed = atoi(playback_spd_str);
+                }
+       }
+
+        SDL_EnableUNICODE(1);
+
+       return 0;
+}
+
+void eventExit(void)
+{
+        /* cleanup the backlog queue */
+        SDL_Event event;
+        while (! backlog_dequeue(&event))
+                ;
+}
+
+void eventHandle(void)
+{
+        event_handle_aux(0);
+}
+
+void eventHandlePending(void)
+{
+        event_handle_aux(EVENT_NONBLOCK|EVENT_NOPLAYBACK);
+}
+
+void eventPushKeyHandler(struct KeyHandler *keyh)
+{
+       pushHandler(&KeyHandlers, keyh);
+}
+
+struct KeyHandler * eventPopKeyHandler(void)
+{
+        return (struct KeyHandler*)popHandler(&KeyHandlers);
+}
+
+void eventPushTickHandler(struct TickHandler *keyh)
+{
+       pushHandler(&TickHandlers, keyh);
+}
+
+void eventPopTickHandler(void)
+{
+       popHandler(&TickHandlers);
+}
+
+void eventPushQuitHandler(struct QuitHandler *keyh)
+{
+       pushHandler(&QuitHandlers, keyh);
+}
+
+void eventPopQuitHandler(void)
+{
+       popHandler(&QuitHandlers);
+}
+
+void eventPushMouseButtonHandler(struct MouseButtonHandler *keyh)
+{
+       pushHandler(&MouseButtonHandlers, keyh);
+}
+
+void eventPopMouseButtonHandler(void)
+{
+       popHandler(&MouseButtonHandlers);
+}
+
+void eventPushMouseMotionHandler(struct MouseMotionHandler *keyh)
+{
+       pushHandler(&MouseMotionHandlers, keyh);
+}
+
+void eventPopMouseMotionHandler(void)
+{
+       popHandler(&MouseMotionHandlers);
+}
+
+void eventAddHook(void (*fx) (void))
+{
+       eventHook = fx;
+}
+
+void eventRunKeyHandler(key_handler_fx_t fx, void *data)
+{
+       struct KeyHandler kh;
+       kh.fx = fx;
+       kh.data = data;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+}
diff --git a/src/event.h b/src/event.h
new file mode 100644 (file)
index 0000000..709ec04
--- /dev/null
@@ -0,0 +1,129 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef event_h
+#define event_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "list.h"
+#include <SDL.h>
+
+/* Map directions to the numeric keypad */
+#define KEY_NORTHWEST   SDLK_KP7
+#define KEY_NORTH       SDLK_KP8
+#define KEY_NORTHEAST   SDLK_KP9
+#define KEY_WEST        SDLK_KP4
+#define KEY_HERE        SDLK_KP5
+#define KEY_EAST        SDLK_KP6
+#define KEY_SOUTHWEST   SDLK_KP1
+#define KEY_SOUTH       SDLK_KP2
+#define KEY_SOUTHEAST   SDLK_KP3
+#define KEY_UP          KEY_NORTH
+#define KEY_DOWN        KEY_SOUTH
+#define KEY_RIGHT       KEY_EAST
+#define KEY_LEFT        KEY_WEST
+
+#define KEY_SHIFT (1 << 9) /* 512, SDLK_LAST is 323 */
+
+#define KEY_SHIFT_NORTH (KEY_NORTH|KEY_SHIFT)
+#define KEY_SHIFT_SOUTH (KEY_SOUTH|KEY_SHIFT)
+#define KEY_SHIFT_EAST  (KEY_EAST|KEY_SHIFT)
+#define KEY_SHIFT_WEST  (KEY_WEST|KEY_SHIFT)
+
+#define KEY_SHIFT_NORTHEAST (KEY_NORTHEAST|KEY_SHIFT)
+#define KEY_SHIFT_NORTHWEST (KEY_NORTHWEST|KEY_SHIFT)
+#define KEY_SHIFT_SOUTHEAST (KEY_SOUTHEAST|KEY_SHIFT)
+#define KEY_SHIFT_SOUTHWEST (KEY_SOUTHWEST|KEY_SHIFT)
+
+/* 
+ * Give canonical names to the UNICODE versions of the CTRL keypresses 
+ * that we care about.
+ * CTRL-A is 0x01 and CTRL-Z is 0x1A, others are in-between of course.
+ */
+#define KEY_CTRL_D      0x04
+#define KEY_CTRL_E      0x05
+#define KEY_CTRL_O      0x0F
+#define KEY_CTRL_Q      0x11
+#define KEY_CTRL_R      0x12
+#define KEY_CTRL_S      0x13
+#define KEY_CTRL_T      0x14
+#define KEY_CTRL_Z      0x1A
+
+typedef int (*key_handler_fx_t)(struct KeyHandler * handler, int key, int keymod);
+
+struct TickHandler {
+        struct list list;
+        bool(*fx) (struct TickHandler * handler);
+        void *data;
+};
+
+
+struct KeyHandler {
+        struct list list;
+        key_handler_fx_t fx;
+        void *data;  
+        // The data field should always be filled with a struct, 
+        // rather than a scalar such as bool or int,
+        // to facilitate expansions to two or more subfields
+        // For example, the 'struct cursor_movement_keyhandler' above.
+};
+
+struct QuitHandler {
+        struct list list;
+        bool(*fx) (struct QuitHandler * handler);
+        void *data;
+};
+
+struct MouseMotionHandler {
+        struct list list;
+        bool(*fx) (struct MouseMotionHandler * handler, SDL_MouseMotionEvent *event);
+        void *data;
+};
+
+struct MouseButtonHandler {
+        struct list list;
+        bool(*fx) (struct MouseButtonHandler * handler, SDL_MouseButtonEvent *event);
+        void *data;
+};
+
+extern int eventInit(void);
+extern void eventExit(void);
+extern void eventHandle(void);
+extern void eventHandlePending(void); /* non-blocking version of eventHandle */
+extern void eventPushKeyHandler(struct KeyHandler *keyh);
+extern struct KeyHandler * eventPopKeyHandler(void);
+extern void eventPushTickHandler(struct TickHandler *keyh);
+extern void eventPopTickHandler(void);
+extern void eventPushQuitHandler(struct QuitHandler *keyh);
+extern void eventPopQuitHandler(void);
+extern void eventPushMouseButtonHandler(struct MouseButtonHandler *keyh);
+extern void eventPopMouseButtonHandler(void);
+extern void eventPushMouseMotionHandler(struct MouseMotionHandler *keyh);
+extern void eventPopMouseMotionHandler(void);
+extern void eventAddHook(void (*fx) (void));
+extern void eventRunKeyHandler(key_handler_fx_t fx, void *data);
+
+END_DECL
+
+#endif
diff --git a/src/factions.h b/src/factions.h
new file mode 100644 (file)
index 0000000..67659f0
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef factions_h
+#define factions_h
+
+#include "session.h"
+#include "dtable.h"
+#include "Being.h"
+
+#define INVALID_HANDLE      -1
+#define INVALID_FACTION     -1
+#define NIL_FACTION          0
+#define PLAYER_PARTY_FACTION 1
+
+static inline int are_hostile(Being *a, Being *b)
+{
+        return dtable_are_hostile(session_dtable(),
+                                  a->getCurrentFaction(),
+                                  b->getCurrentFaction());
+}
+
+static inline int are_natively_hostile(Being *a, Being *b)
+{
+        return dtable_are_hostile(session_dtable(),
+                                  a->getBaseFaction(),
+                                  b->getBaseFaction());
+}
+
+static inline int are_allies(Being *a, Being *b)
+{
+        return dtable_are_allies(session_dtable(),
+                                  a->getCurrentFaction(),
+                                  b->getCurrentFaction());
+}
+
+static inline void make_hostile(Being *a, Being *b)
+{
+        dtable_set(session_dtable(),
+                   a->getCurrentFaction(),
+                   b->getCurrentFaction(),
+                   dtable_hostile(session_dtable()));
+}
+
+static inline void make_allies(Being *a, Being *b)
+{
+        dtable_set(session_dtable(),
+                   a->getCurrentFaction(),
+                   b->getCurrentFaction(),
+                   dtable_allies(session_dtable()));
+}
+
+static inline void improve_relations(Being *a, Being *b)
+{
+        dtable_inc(session_dtable(),
+                   a->getCurrentFaction(),
+                   b->getCurrentFaction());
+}
+
+static inline void harm_relations(Being *a, Being *b)
+{              
+       if (a->getCurrentFaction() != b->getCurrentFaction())
+       {
+        dtable_dec(session_dtable(),
+                   a->getCurrentFaction(),
+                   b->getCurrentFaction());
+       }
+}
+
+static inline const char * diplomacy_string(Being *a, Being *b)
+{
+        return dtable_describe(session_dtable(),
+                               a->getCurrentFaction(),
+                               b->getCurrentFaction());
+}
+
+#endif
diff --git a/src/file.c b/src/file.c
new file mode 100644 (file)
index 0000000..8aabef7
--- /dev/null
@@ -0,0 +1,202 @@
+/* $Id: file.c,v 1.4 2010/08/26 05:56:20 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "file.h"
+
+#include "cfg.h"
+#include "kern.h"
+#include "scheme.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+static const char *file_errstr = "Success";
+
+char *file_mkpath(const char *dir, const char *fname)
+{
+       char *ret;
+       size_t dl,fl;
+
+       if (! dir)
+               return strdup(fname);
+       dl = strlen(dir);
+       fl = strlen(fname);
+
+       ret = (char*)malloc(dl+fl+2);
+       if (! ret) {
+                file_errstr = "Allocation failed";
+               return ret;
+        }
+       memcpy(ret,dir,dl);
+       ret[dl] = '/';
+       memcpy(ret+dl+1,fname,fl);
+       ret[dl+1+fl] = '\0';
+
+       return ret;
+}
+
+int file_exists(const char *fname)
+{
+        FILE *file = fopen(fname, "r");
+        if (file) {
+                fclose(file);
+                return 1;
+        }
+        return 0;
+}
+
+int file_exists_in_dir(const char *dirname, const char *fname)
+{
+        int ret = -1;
+        char *path = file_mkpath(dirname, fname);
+        if (path) {
+                ret = file_exists(path);
+                free(path);
+        }
+        return ret;
+}
+
+int file_exists_in_include_dir(const char *fname)
+{
+        return file_exists_in_dir(cfg_get("include-dirname"), fname);
+}
+
+int file_exists_in_save_dir(const char *fname)
+{
+        return file_exists_in_dir(cfg_get("saved-games-dirname"), fname);
+
+}
+
+FILE *file_open(const char *fname, const char *mode)
+{
+        FILE *file = NULL;
+
+        /* Check args. */
+        if (!fname) {
+                file_errstr = "Null filename";
+                return 0;
+        }
+
+        /* Open the file. */
+        file = fopen(fname, mode);
+        if (!file) {
+                file_errstr = strerror(errno);
+                return 0;
+        }
+
+        return file;
+}
+
+FILE *file_open_in_dir(const char *dirname, const char *fname, const char *mode)
+{
+        FILE *file = 0;
+        char *path = file_mkpath(dirname, fname);
+        if (path) {
+                file = file_open(path, mode);
+                free(path);
+        }
+        return file;
+}
+
+FILE *file_open_in_include_dir(const char *fname)
+{
+        return file_open_in_dir(cfg_get("include-dirname"), fname, "r");
+}
+
+FILE *file_open_in_save_dir(const char *fname, const char *mode)
+{
+        char *dir = cfg_get("saved-games-dirname");
+
+#ifndef WIN32        
+        /* FIXME: cygwin build fails, saying that mkdir below has too
+         * many arguments. We don't use the save dir so not a
+         * problem */
+        if (dir
+            && strchr(mode, 'w')
+            && !file_exists(dir)) {
+                        if (mkdir(dir, 0777)) {
+                                file_errstr = strerror(errno);
+                                return 0;
+                        }
+        }
+#endif
+        return file_open_in_dir(dir, fname, mode);
+}
+
+int file_load(const char *fname)
+{
+        scheme *sc = NULL;
+        FILE *file = NULL;
+
+        /* Open the load file. */
+        file = file_open(fname, "r");
+       if (! file) {
+                return -1;
+        }
+
+        /* Create a new interpreter. */
+        if (! (sc = kern_init())) {
+                file_errstr = "Could not create interpreter";
+                fclose(file);
+                return -1;
+        }
+
+        /* Load the init file. */
+        scheme_load_named_file(sc, file, fname);
+
+        /* Cleanup interpreter. */
+        scheme_deinit(sc);
+        free(sc);
+
+        /* close the file */
+        fclose(file);
+
+        return 0;
+}
+
+int file_load_from_dir(const char *dirname, const char *fname)
+{
+        int ret = -1;
+        char *path = file_mkpath(dirname, fname);
+        if (path) {
+                ret = file_load(path);
+                free(path);
+        }
+        return ret;
+}
+
+int file_load_from_include_dir(const char *fname)
+{
+        return file_load_from_dir(cfg_get("include-dirname"), fname);
+}
+
+int file_load_from_save_dir(const char *fname)
+{
+        return file_load_from_dir(cfg_get("saved-games-dirname"), fname);
+}
+
+const char *file_get_error()
+{
+        return file_errstr;
+}
diff --git a/src/file.h b/src/file.h
new file mode 100644 (file)
index 0000000..eae2020
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Id: file.h,v 1.3 2010/08/26 05:56:20 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef file_h
+#define file_h
+
+#include <stdio.h>
+
+/* Declare some common file and directory utitilites. */
+
+/* This concatenates a bunch of directory names followed by a file name into a
+ * single string and returns it. Use the stdlib free() function to delete the
+ * string. */
+extern char *file_mkpath(const char *dir, const char *fname);
+
+/* The following all test for the existence of a file. The _include_dir and
+ * _save_dir versions check the configured read-only include dir and read-write
+ * save dir, resp. */
+extern int file_exists(const char *fname);
+extern int file_exists_in_dir(const char *dirname, const char *fname);
+extern int file_exists_in_include_dir(const char *fname);
+extern int file_exists_in_save_dir(const char *fname);
+
+/* The following all try to open a file in the respective directories. To close
+ * the file just use fclose(). The file_open_in_save_dir function will attempt
+ * to create the configured save dir if it doesn't exist yet, except on win32
+ * platforms. */
+extern FILE *file_open(const char *fname, const char *mode);
+extern FILE *file_open_in_dir(const char *dirname, const char *fname, const char *mode);
+extern FILE *file_open_in_include_dir(const char *fname);
+extern FILE *file_open_in_save_dir(const char *fname, const char *mode);
+
+/* The following all try to load a script file from the respective directories.
+ * These are meant for loading the various config scripts. They are not
+ * suitable for loading session save files, because they destroy the
+ * interpreter context after the scripts have executed (session.c knows this
+ * and loads save games "by hand" so it can keep the context). */
+extern int file_load(const char *fname);
+extern int file_load_from_dir(const char *dirname, const char *fname);
+extern int file_load_from_include_dir(const char *fname);
+extern int file_load_from_save_dir(const char *fname);
+
+/* If any of the file_open_ functions return NULL then use the following to get
+ * an error string description of what went wrong. Obviously this is not meant
+ * for multi-threaded usage. */
+extern const char *file_get_error();
+
+#endif
diff --git a/src/floodfill.c b/src/floodfill.c
new file mode 100644 (file)
index 0000000..f028ef2
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "los.h"
+
+#include <string.h>
+
+static void FLOODFILL_destroy(struct los *los)
+{
+}
+
+static int floodfillCheckDistance(struct los *los, int mx, int my)
+{
+       int d;
+       int x;
+       int y;
+
+       /* Limit LOS to the radius if given (creating a circle of visibility
+        * centered on the player). Otherwise limit it to the view dimensions
+        * (making the entire map window potentially visible). */
+       if (los->r <= 0)
+               return (!(mx < 0 || mx >= los->w || my < 0 || my >= los->h));
+
+       /* Convert coordinates to a system where the origin is in the center of 
+        * the los area */
+       x = mx - los->w / 2;
+       y = my - los->h / 2;
+
+       /* And force coordinates to absolute values so we can use the simple
+        * distance formula */
+       x = (x < 0 ? -x : x);
+       y = (y < 0 ? -y : y);
+
+       /* Use a quick-and-dirty distance formula (stolen from angband los
+        * algorithm) */
+       d = ((y > x) ? (y + x / 2) : (x + y / 2));
+
+       return (d <= los->r);
+}
+
+static void FLOODFILL_computeRecursive(struct los *los, int vx, int vy,
+                                      int mx, int my)
+{
+       int vindex;
+       int mindex;
+       int vnx;
+       int vny;
+       int mnx;
+       int mny;
+
+       /* If these are not valid viewing coordinates then return. This happens
+        * when we hit the edges of the los area. */
+       if (vx < 0 || vx >= los->w || vy < 0 || vy >= los->h)
+               return;
+
+       vindex = vy * los->w + vx;
+       mindex = my * los->w + mx;
+
+       /* If this tile has already been visited then return */
+       if (los->vmask[vindex] != 'u')
+               return;
+
+       /* If this tile is outside of the radius then return */
+       if (!floodfillCheckDistance(los, mx, my))
+               return;
+
+       /* Mark this tile as visible. */
+       los->vmask[vindex] = 1;
+
+       /* If this tile is opaque and not the tile the player is standing on
+        * then return. */
+       if (!los->alpha[mindex] && ((vx != los->w / 2) || (vy != los->h / 2)))
+               return;
+
+       /* revisit -- consider skipping diagonal neighbors */
+       /* revisit -- we could skip some neighbors if we knew which direction
+        * our parent was. We could also precheck neighbors before recurring,
+        * saving us some function call overhead */
+       /* For each of the eight neighboring tiles, call the recursive
+        * floodfill function */
+       for (vny = vy - 1, mny = my - 1; vny <= vy + 1; vny++, mny++) {
+               for (vnx = vx - 1, mnx = mx - 1; vnx <= vx + 1; vnx++, mnx++) {
+                       FLOODFILL_computeRecursive(los, vnx, vny, mnx, mny);
+               }
+       }
+
+}
+
+static void FLOODFILL_compute(struct los *los)
+{
+       int i;
+       int len;
+
+       len = los->w * los->h * sizeof(unsigned char);
+
+       /* Fill the mask with the 'unvisited' flag */
+       memset(los->vmask, 'u', len);
+
+       /* Start the recursion with the center tile */
+       FLOODFILL_computeRecursive(los, los->w / 2, los->h / 2,
+                                  los->w / 2, los->h / 2);
+
+       /* Replace all 'unvisited' and 'visited' flags with 'nonvisible' */
+       for (i = 0; i < len; i++) {
+               switch (los->vmask[i]) {
+               case 0:
+               case 1:
+                       break;
+               default:
+                       los->vmask[i] = 0;
+               }
+       }
+
+}
+
+struct los *FLOODFILL_Init(struct los *los)
+{
+       los->destroy = FLOODFILL_destroy;
+       los->compute = FLOODFILL_compute;
+       return 0;
+}
diff --git a/src/foogod.c b/src/foogod.c
new file mode 100644 (file)
index 0000000..05afb12
--- /dev/null
@@ -0,0 +1,383 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "foogod.h"
+#include "status.h"  // for status_get_h()
+#include "stdarg.h"
+#include "screen.h"
+#include "common.h"
+#include "player.h"
+#include "wq.h"
+#include "combat.h"
+#include "session.h"
+#include "vehicle.h"
+#include "sprite.h"
+#include "images.h"
+#include "effect.h"
+#include "cfg.h"
+
+#include <SDL_image.h>
+
+#define FOOGOD_CHARS_PER_LINE STAT_CHARS_PER_LINE
+#define FOOGOD_MAX_TITLE_LEN (FOOGOD_CHARS_PER_LINE-2)
+
+struct foogod {
+       SDL_Rect screenRect;
+       SDL_Rect turnRect;
+       SDL_Rect foodRect;
+       SDL_Rect combatRect;
+       SDL_Rect goldRect;
+       SDL_Rect hullRect;
+        SDL_Rect effectsRect;
+       SDL_Rect titleRect;
+        foogod_mode_t mode;
+        int hintLen;
+        char *hintText;
+        unsigned int progress_bar_max_steps;
+        unsigned int progress_bar_steps;
+        char *progress_bar_title;
+        struct images *image;
+        struct sprite *progress_bar_sprites[3];
+       char title[FOOGOD_MAX_TITLE_LEN+1];
+} Foogod;
+
+static void foogod_repaint_title(void)
+{
+    screenErase(&Foogod.titleRect);
+    screenPrint(&Foogod.titleRect, SP_CENTERED | SP_ONBORDER, "%s", Foogod.title);
+    screenUpdate(&Foogod.titleRect);
+}
+
+static int foogod_load_progress_bar_sprites(void)
+{
+        int i;
+        char *fname = cfg_get("progress-bar-image-filename");
+
+        if (!fname) {
+                return -1;
+        }
+
+       Foogod.image = (struct images *)calloc(1, sizeof(*Foogod.image));
+        assert(Foogod.image);
+
+       Foogod.image = images_new(0, 8, 16, 1, 3, 0, 0, fname);
+       if (!Foogod.image) {
+           err("images_new() failed for file '%s': '%s'\n", fname, SDL_GetError() );
+           goto fail;
+       }
+
+        for (i = 0; i < 3; i++) {
+                if (!(Foogod.progress_bar_sprites[i] = sprite_new(0, 1, i, 0, 0, Foogod.image))) {
+                        err("sprite_new() failed\n");
+                        goto fail;
+                }
+        }
+
+        return 0;
+
+ fail:
+        for (i = 0; i < 3; i++) {
+                if ((Foogod.progress_bar_sprites[i])) {
+                        sprite_del(Foogod.progress_bar_sprites[i]);
+                        Foogod.progress_bar_sprites[i] = 0;
+                }
+        }
+
+        if (Foogod.image) {
+                free(Foogod.image);
+                Foogod.image = 0;
+        }
+
+        return -1;
+}
+
+void foogodAdvanceTurns(void)
+{
+       foogodRepaint();
+}
+
+int foogodInit(void)
+{
+        memset(&Foogod, 0, sizeof(Foogod));
+
+        Foogod.mode = FOOGOD_DEFAULT;
+
+        // hint text buffer
+        Foogod.hintLen = FOOGOD_W / ASCII_W;
+        Foogod.hintText = (char*)malloc(Foogod.hintLen+1);
+        memset(Foogod.hintText, 0, Foogod.hintLen);
+
+       Foogod.screenRect.x = FOOGOD_X;
+       Foogod.screenRect.w = FOOGOD_W;
+        foogod_set_y(STAT_Y + status_get_h() + BORDER_H);
+        Foogod.screenRect.h = FOOGOD_H;
+    
+       // turns
+       Foogod.turnRect.x = FOOGOD_X;
+       Foogod.turnRect.y = foogod_get_y();
+       Foogod.turnRect.w = FOOGOD_W / 3;
+       Foogod.turnRect.h = ASCII_H;
+
+       // food
+       Foogod.foodRect.x = FOOGOD_X;
+       Foogod.foodRect.y = foogod_get_y() + ASCII_H;
+       Foogod.foodRect.w = FOOGOD_W / 3;
+       Foogod.foodRect.h = ASCII_H;
+
+       // hull
+       Foogod.hullRect.x = FOOGOD_X + FOOGOD_W / 3;
+       Foogod.hullRect.y = foogod_get_y();
+       Foogod.hullRect.w = FOOGOD_W / 3;
+       Foogod.hullRect.h = ASCII_H;
+
+        // effects
+       Foogod.effectsRect.x = FOOGOD_X + FOOGOD_W / 3;
+       Foogod.effectsRect.y = foogod_get_y() + ASCII_H;
+       Foogod.effectsRect.w = FOOGOD_W / 3;
+       Foogod.effectsRect.h = ASCII_H;
+
+       // gold
+       Foogod.goldRect.w = FOOGOD_W / 3;
+       Foogod.goldRect.x = FOOGOD_X + FOOGOD_W - FOOGOD_W / 3;
+       Foogod.goldRect.y = foogod_get_y();
+       Foogod.goldRect.h = ASCII_H;
+
+       // mode
+       Foogod.combatRect.w = FOOGOD_W / 3;
+       Foogod.combatRect.x = FOOGOD_X + FOOGOD_W - FOOGOD_W / 3;
+       Foogod.combatRect.y = foogod_get_y() + ASCII_H;
+       Foogod.combatRect.h = ASCII_H;
+
+        // title (on the border)
+        Foogod.titleRect.x = FOOGOD_X;
+        Foogod.titleRect.y = foogod_get_y() - BORDER_H;
+        Foogod.titleRect.w = FOOGOD_W;
+        Foogod.titleRect.h = BORDER_H;
+
+        return foogod_load_progress_bar_sprites();
+}
+
+static void foogodPaintEffect(SDL_Rect *rect, struct sprite *sprite)
+{
+        sprite_paint(sprite, 0, rect->x, rect->y);
+        rect->x += ASCII_W;
+}
+
+static int foogod_paint_effect_wrapper(struct hook_entry *entry, void *data)
+{
+       SDL_Rect *rect = (SDL_Rect*)data;
+       struct effect *effect = entry->effect;
+        if (effect->sprite) {
+                foogodPaintEffect(rect, effect->sprite);
+        }
+        return 0;
+}
+
+static void foogodPaintEffects()
+{
+        SDL_Rect rect = Foogod.effectsRect;
+
+        /* Effects well-known to the engine */
+        if (TimeStop) {
+                foogodPaintEffect(&rect, time_stop_effect_sprite());
+        }
+
+        if (Reveal) {
+                foogodPaintEffect(&rect, reveal_effect_sprite());
+        }
+
+        if (Quicken) {
+                foogodPaintEffect(&rect, quicken_effect_sprite());
+        }
+
+        if (MagicNegated) {
+                foogodPaintEffect(&rect, magic_negated_effect_sprite());
+        }
+
+        if (XrayVision) {
+                foogodPaintEffect(&rect, xray_vision_effect_sprite());
+        }
+
+        /* Custom effects added by the game */
+       for (int i = 0; i < OBJ_NUM_HOOKS; i++) {
+                player_party->hookForEach(i, foogod_paint_effect_wrapper, 0);
+       }
+
+
+}
+
+static void foogodPaintSessionInfo()
+{
+        screenPrint(&Foogod.turnRect, 0, "Turn: %d", session_get_turn_count());
+        foogodPaintEffects();
+
+        if (player_party) {
+                screenPrint(&Foogod.foodRect, 0, "Food: %d", 
+                            player_party->food);
+                screenPrint(&Foogod.goldRect, SP_RIGHTJUSTIFIED, "Gold: %d",  
+                            player_party->gold);
+                if (player_party->getVehicle()) {
+                        screenPrint(&Foogod.hullRect, 0, "Hull: %d", 
+                                    player_party->getVehicle()->getHp());
+                }
+        }
+}
+
+static void foogod_progress_bar_paint()
+{
+        int i;
+        int ticks;
+        int max_ticks;
+        SDL_Rect rect = Foogod.screenRect;
+
+        /* title */
+        rect.h = ASCII_H;
+        screenPrint(&rect, SP_CENTERED, Foogod.progress_bar_title);
+        
+        /* bar */
+        rect.y += ASCII_H;
+        rect.w = ASCII_W;
+
+        /* (ticks : maxTicks) = (steps : totalSteps) */
+        max_ticks = (Foogod.screenRect.w / ASCII_W);
+
+        /* Subtract two for the edges pieces of the progress bar. */
+        max_ticks -= 2;
+
+        ticks = (Foogod.progress_bar_steps * max_ticks) 
+                / Foogod.progress_bar_max_steps;
+
+        /* Paint the left edge. */
+        sprite_paint(Foogod.progress_bar_sprites[0], 0, rect.x, rect.y);
+        rect.x += ASCII_W;
+
+        /* Paint the center. */
+        for (i = 0; i < ticks; i++) {
+                sprite_paint(Foogod.progress_bar_sprites[1], 0, rect.x, rect.y);
+                //screenPrint(&rect, 0, ".");
+                rect.x += ASCII_W;
+        }
+
+        /* Paint the right edge. */
+        sprite_paint(Foogod.progress_bar_sprites[2], 0, rect.x, rect.y);
+}
+
+void foogodRepaint(void)
+{
+       screenErase(&Foogod.screenRect);
+
+        switch (Foogod.mode) {
+
+        default:
+        case FOOGOD_DEFAULT:
+                if (Session) {
+                        foogodPaintSessionInfo();
+                }
+                screenPrint(&Foogod.combatRect, SP_RIGHTJUSTIFIED, 
+                            "Combat: %c", combatGetState());
+                break;
+
+        case FOOGOD_HINT:
+                screenPrint(&Foogod.screenRect, 0, Foogod.hintText);
+                break;
+
+        case FOOGOD_PROGRESS_BAR:
+                foogod_progress_bar_paint();
+                break;
+        }
+
+        foogod_repaint_title();
+       screenUpdate(&Foogod.screenRect);
+}
+
+void foogod_set_y(int y)
+{
+       Foogod.screenRect.y  = y;
+       Foogod.turnRect.y    = y;
+       Foogod.foodRect.y    = y + ASCII_H;
+       Foogod.goldRect.y    = y;
+       Foogod.combatRect.y  = y + ASCII_H;
+        Foogod.hullRect.y    = y;
+        Foogod.effectsRect.y = y + ASCII_H;
+        Foogod.titleRect.y   = y - BORDER_H;
+}
+
+int foogod_get_y(void)
+{
+       return Foogod.screenRect.y;
+}
+
+int foogod_get_h(void)
+{
+        return (FOOGOD_H + BORDER_H);
+}
+
+void foogodSetMode(foogod_mode_t mode)
+{
+        Foogod.mode = mode;
+        foogodRepaint();
+}
+
+void foogodSetHintText(const char *text)
+{
+        strncpy(Foogod.hintText, text, Foogod.hintLen);
+}
+
+void foogod_progress_bar_set_title(const char *title)
+{
+        if (Foogod.progress_bar_title) {
+                free(Foogod.progress_bar_title);
+                Foogod.progress_bar_title = 0;
+        }
+
+        if (title) {
+                Foogod.progress_bar_title = strdup(title);
+        }
+}
+
+void foogod_progress_bar_set_max_steps(unsigned int val)
+{
+        Foogod.progress_bar_max_steps = val;
+        Foogod.progress_bar_steps = 0;
+}
+
+void foogod_progress_bar_advance(unsigned int steps)
+{
+        Foogod.progress_bar_steps += steps;
+        if (Foogod.progress_bar_steps > Foogod.progress_bar_max_steps) {
+                Foogod.progress_bar_steps = Foogod.progress_bar_max_steps;
+        }
+}
+
+void foogod_progress_bar_finish()
+{
+        dbg("Foogod.progress_bar_steps=%d\n", Foogod.progress_bar_steps);
+        Foogod.progress_bar_steps = Foogod.progress_bar_max_steps;
+}
+
+void foogod_set_title(const char *fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+    vsnprintf(Foogod.title, FOOGOD_MAX_TITLE_LEN, fmt, args);
+    va_end(args);
+}
+
diff --git a/src/foogod.h b/src/foogod.h
new file mode 100644 (file)
index 0000000..e62c9b0
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef foogod_h
+#define foogod_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+/* Food-Gold-Date window */
+typedef enum {
+        FOOGOD_DEFAULT = 0
+        , FOOGOD_HINT
+        , FOOGOD_PROGRESS_BAR
+} foogod_mode_t;
+
+typedef enum {
+        FOOGOD_QUICKEN = 0,
+        FOOGOD_REVEAL,
+        FOOGOD_MAGIC_NEGATED,
+        FOOGOD_TIME_STOP,
+        FOOGOD_XRAY_VISION,
+        FOOGOD_NUM_EFFECTS
+} foogod_effect_t;
+
+extern int foogodInit(void);
+extern void foogodRepaint(void);
+extern void foogodAdvanceTurns();
+extern void foogod_set_y(int y);
+extern int foogod_get_y(void);
+extern int foogod_get_h(void);
+
+extern void foogodSetMode(foogod_mode_t mode);
+extern void foogodSetHintText(const char *text);
+
+extern void foogod_progress_bar_set_title(const char *title);
+extern void foogod_progress_bar_set_max_steps(unsigned int val);
+extern void foogod_progress_bar_advance(unsigned int steps);
+extern void foogod_progress_bar_finish(void);
+extern void foogod_set_title(const char *fmt, ...);
+
+END_DECL
+
+#endif
diff --git a/src/formation.c b/src/formation.c
new file mode 100644 (file)
index 0000000..5ed0b69
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "formation.h"
+#include "common.h"
+
+static struct formation_entry default_formation_entries[] = {
+        {0, 0},
+        {1, 1},
+        {-1, 1},
+        {2, 2},
+        {0, 2},
+        {-2, 2},
+        {3, 3},
+        {1, 3},
+        {-1, 3},
+        {-3, 3},
+        {4, 4},
+        {2, 4},
+        {0, 4},
+        {-2, 4},
+        {-4, 4},
+        {5, 5},
+        {3, 5},
+        {1, 5},
+        {-1, 5},
+        {-3, 5},
+        {-5, 5},
+        {6, 6},
+        {4, 6},
+        {2, 6},
+        {0, 6},
+        {-2, 6},
+        {-4, 6},
+        {-6, 6},                /* 28 */
+};
+
+static struct formation default_formation;
+
+int formation_init(void)
+{
+        default_formation.n = array_sz(default_formation_entries);
+        default_formation.entry = default_formation_entries;
+        return 0;
+}
+
+struct formation *formation_get_default(void)
+{
+        return &default_formation;
+}
diff --git a/src/formation.h b/src/formation.h
new file mode 100644 (file)
index 0000000..44203e9
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef formation_h
+#define formation_h
+
+#include "list.h"
+
+struct formation_entry {
+       int x;
+       int y;
+};
+
+struct formation {
+       struct list list;
+       char *tag;
+       int n;
+       struct formation_entry *entry;
+};
+
+extern int formation_init(void);
+extern struct formation *formation_get_default(void);
+
+#endif
diff --git a/src/gob.c b/src/gob.c
new file mode 100644 (file)
index 0000000..5b04e63
--- /dev/null
+++ b/src/gob.c
@@ -0,0 +1,47 @@
+#include "gob.h"
+#include "session.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#define scm_car(sc, arg) ((sc)->vptr->pair_car(arg))
+#define scm_cdr(sc, arg) ((sc)->vptr->pair_cdr(arg))
+
+/* Fixme: gob_new should start with refcount 1 */
+struct gob *gob_new(scheme *sc, pointer p)
+{
+        struct gob *gob = (struct gob *)calloc(1, sizeof(*gob));
+        assert(gob);
+        gob->sc = sc;
+        gob->p = p;
+        sc->vptr->protect(sc, p);
+        return gob;
+}
+
+/* Fixme: this should not be public; clients should be required to use gob_unref */
+void gob_del(struct gob *gob)
+{
+        gob->sc->vptr->unprotect(gob->sc, gob->p);
+        free(gob);
+}
+
+void gob_save(struct gob *gob, struct save *save)
+{
+        pointer cell;
+
+        /* The car of the gob pointer is often non-data (kobj, etc). So only
+         * serialize the car of the cdr unless the creator specifically wants
+         * to. */
+        cell = (gob->flags & GOB_SAVECAR) ? gob->p : 
+                scm_car(gob->sc, scm_cdr(gob->sc, gob->p));
+
+        scheme_serialize(gob->sc, cell, save);
+}
+
+void gob_unref(struct gob *gob)
+{
+        assert(gob->refcount > 0);
+        gob->refcount--;
+        if (! gob->refcount)
+                gob_del(gob);
+}
diff --git a/src/gob.h b/src/gob.h
new file mode 100644 (file)
index 0000000..473123e
--- /dev/null
+++ b/src/gob.h
@@ -0,0 +1,22 @@
+#ifndef gob_h
+#define gob_h
+
+#include "scheme-private.h"
+
+#define GOB_SAVECAR (1 << 0)
+
+struct gob {
+        scheme *sc;
+        pointer p;
+        int flags;
+        int refcount;
+};
+
+#define gob_ref(gob) ((gob)->refcount++)
+
+extern struct gob *gob_new(scheme *sc, pointer p);
+extern void gob_del(struct gob *gob);
+extern void gob_save(struct gob *gob, struct save *save);
+extern void gob_unref(struct gob *gob);
+
+#endif
diff --git a/src/hash.c b/src/hash.c
new file mode 100644 (file)
index 0000000..0f0b523
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "hash.h"
+#include "olist.h"
+#include "common.h"
+
+struct hash *hash_create(int n)
+{
+       struct hash *hash;
+       int i;
+
+       CREATE(hash, struct hash, 0);
+       hash->n = n;
+       hash->buckets = (struct olist *) malloc(n * sizeof(struct olist));
+       if (!hash->buckets) {
+               hash_destroy(hash);
+               return 0;
+       }
+       for (i = 0; i < n; i++) {
+               list_init(&hash->buckets[i].list);
+       }
+       return hash;
+}
+
+void hash_destroy(struct hash *hash)
+{
+       if (hash->buckets)
+               free(hash->buckets);
+       free(hash);
+}
+
+void hash_add(struct hash *hash, struct olist *val)
+{
+       struct olist *b = &hash->buckets[val->key % hash->n];
+       olist_add(b, val);
+}
+
+struct olist *hash_lookup(struct hash *hash, int key)
+{
+       struct olist *b = &hash->buckets[key % hash->n];
+       return olist_lookup(b, key, 1);
+}
diff --git a/src/hash.h b/src/hash.h
new file mode 100644 (file)
index 0000000..ede2838
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef hash_h
+#define hash_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+       struct olist;
+
+       struct hash {
+               struct olist *buckets;
+               int n;
+       };
+
+       extern struct hash *hash_create(int n);
+       extern void hash_destroy(struct hash *hash);
+       extern void hash_add(struct hash *hash, struct olist *val);
+       extern struct olist *hash_lookup(struct hash *hash, int key);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/heap.c b/src/heap.c
new file mode 100644 (file)
index 0000000..53c7660
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "heap.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct heap *heap_create(unsigned int max_entries)
+{
+       struct heap *heap;
+
+       heap = (struct heap *) malloc(sizeof(struct heap));
+       if (!heap)
+               return 0;
+       memset(heap, 0, sizeof(struct heap));
+
+       heap->max_entries = max_entries;
+       heap->num_entries = 0;
+
+       heap->entries = (int **) malloc(sizeof(int *) * max_entries);
+       if (!heap->entries) {
+               free(heap);
+               return 0;
+       }
+       memset(heap->entries, 0, sizeof(void *) * max_entries);
+
+       return heap;
+}
+
+void heap_destroy(struct heap *heap)
+{
+       if (heap->entries)
+               free(heap->entries);
+       free(heap);
+}
+
+void heapify(struct heap *heap, int i)
+{
+       unsigned int left;
+       unsigned int right;
+       int largest;
+
+       left = 2 * i;
+       right = left + 1;
+
+       if (left < heap->num_entries &&
+           *heap->entries[left] > *heap->entries[i])
+               largest = left;
+       else
+               largest = i;
+
+       if (right < heap->num_entries &&
+           *heap->entries[right] > *heap->entries[largest])
+               largest = right;
+
+       if (largest != i) {
+               int *tmp = heap->entries[i];
+               heap->entries[i] = heap->entries[largest];
+               heap->entries[largest] = tmp;
+               heapify(heap, largest);
+       }
+}
+
+int heap_expand(struct heap *heap)
+{
+       int **tmp;
+       tmp =
+           (int **) realloc(heap->entries,
+                            heap->max_entries * 2 * sizeof(int *));
+       if (!tmp)
+               return -1;
+       heap->entries = tmp;
+       heap->max_entries *= 2;
+       return 0;
+}
+
+int heap_insert(struct heap *heap, int *entry)
+{
+       int i;
+
+       /* Expand the heap if necessary */
+       if (heap->num_entries == heap->max_entries) {
+               if (heap_expand(heap) < 0)
+                       return -1;
+       }
+
+       /* Put the new entry at the bottom of the heap */
+       i = heap->num_entries++;
+
+       /* Percolate the new entry up to where it belongs */
+       while (i > 0 && *heap->entries[i / 2] < *entry) {
+               heap->entries[i] = heap->entries[i / 2];
+               i /= 2;
+       }
+
+       heap->entries[i] = entry;
+
+       return 0;
+}
+
+int *heap_extract(struct heap *heap)
+{
+       int *max;
+
+       if (!heap->num_entries)
+               return 0;
+
+       max = heap->entries[0];
+       heap->entries[0] = heap->entries[heap->num_entries - 1];
+       heap->num_entries--;
+       heapify(heap, 0);
+
+       return max;
+}
+
+void heap_clean(struct heap *heap)
+{
+       memset(heap->entries, 0, heap->num_entries * sizeof(heap->entries[0]));
+       heap->num_entries = 0;
+}
diff --git a/src/heap.h b/src/heap.h
new file mode 100644 (file)
index 0000000..a68b99f
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef heap_h
+#define heap_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#define heap_entry(ptr,type,field) \
+        ((type*)((char*)(ptr)-(unsigned long)(&((type *)0)->field)))
+
+#define heap_empty(h) (!(h)->num_entries)
+
+struct heap {
+        unsigned int max_entries;
+        unsigned int num_entries;
+        int **entries;
+};
+
+extern struct heap *heap_create(unsigned int max_entries);
+extern void heap_destroy(struct heap *heap);
+extern void heapify(struct heap *heap, int i);
+extern int heap_expand(struct heap *heap);
+extern int heap_insert(struct heap *heap, int *entry);
+extern int *heap_extract(struct heap *heap);
+extern void heap_clean(struct heap *heap);
+
+END_DECL
+
+#endif
diff --git a/src/images.c b/src/images.c
new file mode 100644 (file)
index 0000000..580c5e5
--- /dev/null
@@ -0,0 +1,230 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "images.h"
+#include "screen.h"
+#include "file.h"
+#include "cfg.h"
+#include "debug.h"
+#include "screen.h" // for screenFormat()
+
+#include <assert.h>
+#include <SDL_image.h>
+#include <stdlib.h>
+#include <string.h>
+
+void images_dump_surface(char *name, SDL_Surface *surf)
+{
+        printf("DUMP SURFACE ============================\n");
+        printf("%s info:\n", name);
+        printf("     w, h: %d %d\n", surf->w, surf->h);
+        printf("    pitch: %d\n", surf->pitch);
+        printf("clip_rect: [%d %d %d %d]\n", surf->clip_rect.x, 
+               surf->clip_rect.y, surf->clip_rect.w, surf->clip_rect.h);
+        printf("   format:\n");
+        printf("      palette: %s\n", 
+               surf->format->palette ? "yes" : "no");
+        printf(" BitsPerPixel: %d\n",
+               surf->format->BitsPerPixel);
+        printf("BytesPerPixel: %d\n", 
+               surf->format->BytesPerPixel);
+        printf("  R/G/B/Amask: 0x%x 0x%x 0x%x 0x%x\n",
+               surf->format->Rmask, surf->format->Gmask, surf->format->Bmask,
+               surf->format->Amask);
+        printf(" R/G/B/Ashift: %d %d %d %d\n",
+               surf->format->Rshift, surf->format->Gshift, 
+               surf->format->Bshift, surf->format->Ashift);
+        printf("  R/G/B/Aloss: %d %d %d %d\n",
+               surf->format->Rloss, surf->format->Gloss, 
+               surf->format->Bloss, surf->format->Aloss);
+        printf("     colorkey: 0x%x\n", surf->format->colorkey);
+        printf("        alpha: 0x%x\n", surf->format->alpha);
+        printf("    flags:\n");
+        if (surf->flags & SDL_SWSURFACE)
+                printf("  SDL_SWSURFACE\n");
+        if (surf->flags & SDL_HWSURFACE)
+                printf("  SDL_HWSURFACE\n");
+        if (surf->flags & SDL_ASYNCBLIT)
+                printf("  SDL_ASYNCBLIT\n");
+        if (surf->flags & SDL_ANYFORMAT)
+                printf("  SDL_ANYFORMAT\n");
+        if (surf->flags & SDL_HWPALETTE)
+                printf("  SDL_HWPALETTE\n");
+        if (surf->flags & SDL_DOUBLEBUF)
+                printf("  SDL_DOUBLEBUF\n");
+        if (surf->flags & SDL_FULLSCREEN)
+                printf("  SDL_FULLSCREEN\n");
+        if (surf->flags & SDL_OPENGL)
+                printf("  SDL_OPENGL\n");
+        if (surf->flags & SDL_OPENGLBLIT)
+                printf("  SDL_OPENGLBLIT\n");
+        if (surf->flags & SDL_RESIZABLE)
+                printf("  SDL_RESIZABLE\n");
+        if (surf->flags & SDL_HWACCEL)
+                printf("  SDL_HWACCEL\n");
+        if (surf->flags & SDL_SRCCOLORKEY)
+                printf("  SDL_SRCCOLORKEY\n");
+        if (surf->flags & SDL_RLEACCEL)
+                printf("  SDL_RLEACCEL\n");
+        if (surf->flags & SDL_SRCALPHA)
+                printf("  SDL_SRCALPHA\n");
+        if (surf->flags & SDL_PREALLOC)
+                printf("  SDL_PREALLOC\n");
+
+}
+
+void images_del(struct images *images)
+{
+        if (images->tag)
+                free(images->tag);
+        if (images->fname)
+                free(images->fname);
+       if (images->images)
+               SDL_FreeSurface(images->images);
+       if (images->faded)
+               SDL_FreeSurface(images->faded);
+       delete images;
+}
+
+
+int images_fade(struct images *images)
+{
+
+       if (images->faded)
+               return 0;
+
+       images->faded = screenCreateSurface(images->images->w,
+                                           images->images->h);
+       if (images->faded == NULL)
+               return -1;
+
+       memcpy(images->faded->pixels, images->images->pixels,
+              images->faded->pitch * images->faded->h);
+
+       screen_fade_surface(images->faded, 1);
+       return 0;
+}
+
+int images_convert2display(struct images *images)
+{
+       SDL_Surface *tmp;
+       int imagesbits, screenbits;
+       imagesbits = images->images->format->BitsPerPixel;
+       screenbits = screenFormat()->BitsPerPixel;
+
+       /* Convert to video format for faster blitting
+        * (*much* faster on certain display bit depths).
+        * 8-bit surfaces are a special case in Nazghul though.
+        */
+       if (imagesbits != screenbits && imagesbits != 8) {
+
+               if ((tmp = SDL_DisplayFormat(images->images)) == NULL) {
+                       err("SDL_DisplayFormat: %s", SDL_GetError());
+                       return 0;
+               }
+               imagesbits = screenbits;
+               SDL_FreeSurface(images->images);
+               images->images = tmp;
+       }
+
+        /* Images which are saved with a transparency layer will have the
+         * SDL_SRCALPHA flag set. Their alpha layer will be managed
+         * automatically by SDL_BlitSurface(). For images without an alpha
+         * layer, assume that magenta (RGB 0xff00ff) is the special color for
+         * transparency. To correctly support transparent blitting we have to
+         * set their color key to magenta and we have to convert them to match
+         * the display format. */
+        if (! (images->images->flags & SDL_SRCALPHA)) {
+
+               if (imagesbits != screenbits) {
+                       /* Convert to video format for faster blitting */
+                       if ((tmp = SDL_DisplayFormat(images->images)) == NULL) {
+                               err("SDL_DisplayFormat: %s", SDL_GetError());
+                               return 0;
+                       }
+                       SDL_FreeSurface(images->images);
+                       images->images = tmp;
+               }
+
+                /* Make magenta the transparent color */
+                if (SDL_SetColorKey(images->images, SDL_SRCCOLORKEY,
+                                    SDL_MapRGB(images->images->format,
+                                               0xff, 0x00, 0xff)) < 0) {
+                        err("SDL_SetColorKey: %s", SDL_GetError());
+                        return 0;
+                }
+        }
+       return 1;
+}
+
+struct images *images_new(const char *tag, int w, int h, int rows, int cols, 
+                          int offx, int offy, const char *fname)
+{
+       struct images *images;
+       char *filename;
+
+       images = new struct images;
+        assert(images);
+       memset(images, 0, sizeof(*images));
+
+        if (tag) {
+                images->tag     = strdup(tag);
+                assert(images->tag);
+        }
+
+        images->fname   = strdup(fname);
+        assert(images->fname);
+
+        images->w       = w;
+        images->h       = h;
+        images->offx    = offx;
+        images->offy    = offy;
+        images->rows    = rows;
+        images->cols    = cols;
+
+       filename = file_mkpath(cfg_get("include-dirname"),fname);
+       if (filename) {
+               images->images = IMG_Load(filename);
+               free(filename);
+       }
+       if (!images->images) {
+                // BUG: Mac OS X fails to load PNG images here, but GIF works
+                // OK.  This could be a libPNG, libSDL, or libSDL_Image bug. In
+                // the meantime, better error logging is helpful.
+                err("IMG_Load() failed to load file '%s' because '%s'.\n", 
+                       fname, SDL_GetError() );
+                assert(false);
+                // err("IMG_Load: %s", SDL_GetError()); The err() macro acted
+                // strangely, emitting different error text than the above
+                // would indicate.  Perhaps that is a clue to the bug?
+                // 
+                // Perhaps the err() macro, or the call above, 
+                // differ from the nazghul-0.2.0 release and recent CVS?
+       }
+
+       if (images_convert2display(images)) {
+               //images_dump_surface(fname, images->images);
+               return images;
+       }
+       images_del(images);
+       return NULL;
+}
+
diff --git a/src/images.h b/src/images.h
new file mode 100644 (file)
index 0000000..0075eb3
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef images_h
+#define images_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "list.h"
+
+#include <SDL.h>
+
+struct images {
+        char *tag;
+        char *fname;
+        int w;         /* in pixels of the images */
+        int h;         /* in pixels of the images */
+        int rows;      /* in the image file */
+        int cols;      /* in the image file */
+        int offx;      /* pixels separating images */
+        int offy;      /* pixels separating images */
+        SDL_Surface *images;
+        SDL_Surface *faded;    /* faded copy of image set for
+                                 * sem-transparent sprites */
+};
+
+extern struct images *images_new(const char *tag, int w, int h, int rows, int cols, 
+                                 int offx, int offy, const char *fname);
+extern int images_convert2display(struct images *images);
+extern void images_del(struct images *images);
+extern int images_fade(struct images *images);
+
+END_DECL
+
+#endif
diff --git a/src/kern.c b/src/kern.c
new file mode 100644 (file)
index 0000000..15f841a
--- /dev/null
@@ -0,0 +1,10544 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "session.h"
+
+#include "applet.h"
+#include "blender.h"
+#include "character.h"
+#include "cmd.h"
+#include "conv.h"
+#include "config.h"
+#include "ctrl.h"
+#include "dice.h"
+#include "effect.h"
+#include "event.h"
+#include "gob.h"
+#include "object.h"
+#include "sched.h"
+#include "sprite.h"
+#include "terrain.h"
+#include "vmask.h"
+#include "wq.h"
+#include "place.h"
+#include "ptable.h"
+#include "images.h"
+#include "Party.h"
+#include "common.h"
+#include "player.h"
+#include "sky.h"
+#include "ascii.h"
+#include "map.h"
+#include "cursor.h"
+#include "Arms.h"
+#include "Field.h"
+#include "occ.h"
+#include "species.h"
+#include "Reagent.h"
+#include "screen.h"
+#include "vehicle.h"
+#include "formation.h"
+#include "combat.h"
+#include "Container.h"
+#include "clock.h"
+#include "wind.h"
+#include "foogod.h"
+#include "sound.h"
+#include "Missile.h"
+#include "conv.h"
+#include "mmode.h"
+#include "log.h"
+#include "dtable.h"
+#include "factions.h"
+#include "cmdwin.h"
+#include "cfg.h"
+#include "kern_intvar.h"  // SAM
+#include "menus.h"
+#include "file.h"
+#include "skill.h"
+#include "skill_set.h"
+#include "skill_set_entry.h"
+#include "templ.h"
+#include "macros.h"
+#include "ztats.h"
+#include "ztats_pane.h"
+#include "../config.h" /* for USE_QUESTS */
+// kern.c *doesnt* include kern.h?? wtf??
+
+#include <assert.h>
+#include <ctype.h>              // isspace()
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <SDL_image.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <SDL.h>            // for SDL_GetTicks()
+
+#include "scheme-private.h"
+
+#define API_DECL(sc, sym, val) \
+        scm_define(sc, sym, scm_mk_ptr(sc, val))
+
+#define KERN_API_CALL(name) static pointer name(scheme *sc, pointer args)
+#define KERN_OBSOLETE_CALL(name)                 \
+static pointer name(scheme *sc, pointer args) {  \
+        warn("warn: '" #name "' is obsolete\n"); \
+        return sc->NIL;                          \
+}
+
+#define KERN_ALLOC(type) (type *)calloc(1, sizeof(type))
+#define KERN_FREE(ptr) (free(ptr))
+
+#define TAG_UNK "<tag?>"
+
+
+struct kjob {
+        void *data;
+        closure_t *clx;
+};
+
+/* Struct used by callbacks which build scheme lists */
+struct kern_append_info {
+        scheme *sc;
+        pointer head;
+        pointer tail;
+        int (*filter)(Object *, struct kern_append_info *);
+        void *data;
+};
+
+struct kern_ui_target_info {
+        struct place *place;
+        int x, y, range;
+        struct list suggest;
+};
+
+/* Redefine the session query macro to turn its arg into a string, then #include
+ * the list of querys directly into an array of string pointers. */
+#undef SESSION_DECL_QUERY
+#define SESSION_DECL_QUERY(id) #id
+static const char * query_to_id[] = {
+#       include "session_queries.h"
+};
+
+/*****************************************************************************
+ *
+ * kjob - wrapper for work queue jobs
+ *
+ *****************************************************************************/
+static struct kjob * kjob_new(void *data, closure_t *clx)
+{
+        struct kjob *kjob;
+        kjob = (struct kjob *)malloc(sizeof(*kjob));
+        assert(kjob);
+        kjob->data = data;
+        kjob->clx = clx;
+        closure_ref(clx);
+        return kjob;
+}
+
+static void kjob_del(struct kjob *kjob)
+{
+        closure_unref(kjob->clx);
+        free(kjob);
+}
+
+static void kern_run_wq_job(struct wq_job *job, struct list *wq)
+{
+        struct kjob *kjob;
+        kjob = (struct kjob*)job->data;
+        //dbg("kjob_run: %08lx\n", kjob);
+        closure_exec(kjob->clx, "p", kjob->data);
+        kjob_del(kjob);
+        wq_job_del(job);
+}
+/*****************************************************************************/
+
+static void image_dtor(void *val)
+{
+        images_del((struct images*)val);
+}
+
+static void sprite_dtor(void *val)
+{
+        sprite_del((struct sprite*)val);
+}
+
+static void sound_dtor(void *val)
+{
+        sound_del((sound_t*)val);
+}
+
+static void terrain_palette_dtor(void *val)
+{
+        terrain_palette_del((struct terrain_palette*)val);
+}
+
+static void terrain_map_dtor(void *val)
+{
+        terrain_map_unref((struct terrain_map*)val);
+}
+
+static void incfile_dtor(void *val)
+{
+        free((char*)val);
+}
+
+static void incfile_save(save_t *save, void *val)
+{
+        save->write(save, "(kern-load \"%s\")\n\n", (char*)val);
+}
+
+static void place_dtor(void *val)
+{
+        place_del((struct place*)val);
+}
+
+static void species_dtor(void *val)
+{
+        species_del((struct species*)val);
+}
+
+static void occ_dtor(void *val)
+{
+        occ_unref((struct occ*)val);
+}
+
+static void arms_type_dtor(void *val)
+{
+        delete (class ArmsType *)val;
+}
+
+static void missile_type_dtor(void *val)
+{
+        delete (class MissileType *)val;
+}
+
+static void field_type_dtor(void *val)
+{
+        delete (class FieldType *)val;
+}
+
+static void obj_type_dtor(void *val)
+{
+        delete (class ObjectType *)val;
+}
+
+static void vehicle_type_dtor(void *val)
+{
+        delete (class VehicleType*)val;
+}
+
+static void blender_dtor(void *val)
+{
+        blender_t *blender=(blender_t*)val;
+        list_remove(&blender->list);
+        free(blender);
+}
+
+static int unpack(scheme *sc, pointer *cell, const char *fmt, ...)
+{
+        va_list args;
+        int expect, count = 0, errs = 0;
+        pointer car;
+        char **strval;
+        int *ival;
+        float *rval;
+        void **ptrval;
+        pointer *cval;
+
+        expect = strlen(fmt);
+
+        va_start(args, fmt);
+
+        while (*fmt && scm_is_pair(sc, *cell)) {
+
+                count++;
+                car = scm_car(sc, *cell);
+                *cell = scm_cdr(sc, *cell);
+
+                switch(*fmt++) {
+                case 'b': /* bool */
+                        ival = va_arg(args, int*);
+                        if (car == sc->T) {
+                                *ival = 1;
+                        } else if (car == sc->F) {
+                                *ival = 0;
+                        } else {
+                                errs++;
+                                load_err("arg %d not a bool", count);
+                        }
+                        break;
+                case 'c': /* closure (actually, a symbol, possibly for a
+                           * closure; this is misleading) */
+                        cval = va_arg(args, pointer*);
+                        if (car == sc->NIL) {
+                                *cval = sc->NIL;
+                        } else if (! scm_is_sym(sc, car)) {
+                                errs++;
+                                load_err("arg %d not a symbol", count);
+                        } else {
+                                *cval = car;
+                        }
+                        break;
+                case 'd': /* integer */
+                        ival = va_arg(args, int*);
+                        if (! scm_is_num(sc, car)) {
+                                errs++;
+                                load_err("arg %d not a number", count);
+                        } else if (! scm_is_int(sc, car)) {
+                                /*errs++;
+                                  load_err("arg %d not an int", count);*/
+                                /* coerce it */
+                                *ival = (int)scm_real_val(sc, car);
+                        } else {
+                                *ival = scm_int_val(sc, car);
+                        }
+                        break;
+                case 'f': /* float */
+                        rval = va_arg(args, float*);
+                        if (! scm_is_num(sc, car)) {
+                                errs++;
+                                load_err("arg %d not a number", count);
+                        } else if (! scm_is_real(sc, car)) {
+                                /* coerce it */
+                                *rval = scm_int_val(sc, car);
+                        } else {
+                                *rval = scm_real_val(sc, car);
+                        }
+                        break;
+                case 'o': /* procedure */
+                        cval = va_arg(args, pointer*);
+                        if (car == sc->NIL) {
+                                *cval = sc->NIL;
+                        } else if (! scm_is_closure(sc, car)) {
+                                errs++;
+                                load_err("arg %d not a closure", count);
+                        } else {
+                                *cval = car;
+                        }
+                        break;
+                case 'p': /* C pointer */
+                        ptrval = va_arg(args, void**);
+                        if (car == sc->NIL) {
+                                *ptrval = 0;
+                        } else if (scm_is_ptr(sc, car)) {
+                                *ptrval = scm_ptr_val(sc, car);
+                        } else {
+                                errs++;
+                                load_err("arg %d not a C ptr", count);
+                        }
+                        break;
+                case 'r': /* real number */
+                        rval = va_arg(args, float*);
+                        if (! scm_is_num(sc, car)) {
+                                errs++;
+                                load_err("arg %d not a number", count);
+                        } else if (! scm_is_real(sc, car)) {
+                                errs++;
+                                load_err("arg %d not an int", count);
+                        } else {
+                                *rval = scm_real_val(sc, car);
+                        }
+                        break;
+                case 's': /* string */
+                        strval = va_arg(args, char**);
+                        if (car == sc->NIL) {
+                                *strval = 0;
+                        } else if (scm_is_str(sc, car)) {
+                                *strval = scm_str_val(sc, car);
+                        } else {
+                                errs++;
+                                load_err("arg %d not a string", count);
+                        }
+                        break;
+                case 'y': /* symbol */
+                        strval = va_arg(args, char**);
+                        if (car == sc->NIL) {
+                                *strval = 0;
+                        } else if (scm_is_sym(sc, car)) {
+                                *strval = scm_sym_val(sc, car);
+                        } else {
+                                errs++;
+                                load_err("arg %d not a symbol", count);
+                        }
+                        break;
+                case 'l': /* plain old cell, (eg a gob) */
+                        cval = va_arg(args, pointer*);
+                        *cval = car;
+                        break;
+                default:
+                        dbg("unknown format char: %c\n", *(fmt - 1));
+                        assert(0);
+                        break;
+                }
+        }
+        
+        if (*fmt) {
+                load_err("received only %d of %d arguments",
+                         count, count + strlen(fmt));
+        }
+
+        va_end(args);
+
+        return (! *fmt && ! errs) ? 0 : -1;
+}
+
+static Object *unpack_obj(scheme *sc, pointer *args, const char *caller)
+{
+        class Object *obj;
+
+        if (unpack(sc, args, "p", &obj)) {
+                rt_err("%s: bad args", caller);
+                return NULL;
+        }
+
+        if (obj == NULL) {
+                rt_err("%s: null kernel object", caller);
+                return NULL;
+        }
+
+        return obj;
+}
+
+static int unpack_loc(scheme *sc, pointer *args, struct place **place, int *x,
+                      int *y, const char *func)
+{
+        pointer loc;
+
+        if (! scm_is_pair(sc, *args)) {
+                rt_err("%s: location not a list", func);
+                return -1;
+        }
+
+        loc = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+
+        if (unpack(sc, &loc, "pdd", place, x, y)) {
+                rt_err("%s: bad location list", func);
+                return -1;
+        }
+
+        if (!place) {
+                rt_err("%s: null place", func);
+                return -1;
+        }
+
+        return 0;
+}
+
+static int unpack_rect(scheme *sc, pointer *args, SDL_Rect *rect)
+{
+        pointer prect = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+        long x, y, w, h;
+
+        /* Can't use the rect fields directly because they're only Uint16 */
+        if (unpack(sc, &prect, "dddd",  &x, &y, &w, &h)) {
+                load_err("%s: error unpacking rect elements", __FUNCTION__);
+                return -1;
+        }
+
+        rect->x = x;
+        rect->y = y;
+        rect->w = w;
+        rect->h = h;
+        
+        return 0;
+}
+
+pointer vpack(scheme *sc, const char *fmt, va_list ap)
+{
+        pointer head=sc->NIL;
+        pointer tail=sc->NIL;
+        pointer cell=sc->NIL;
+        pointer arg=sc->NIL;
+        void *ptr;
+        int ival;
+        char *strval;
+
+        while (*fmt) {
+
+                switch(*fmt++) {
+                case 'p':
+                        ptr = va_arg(ap, void*);
+                        arg = scm_mk_ptr(sc, ptr);
+                        break;
+                case 'd':
+                        ival = va_arg(ap, int);
+                        arg = scm_mk_integer(sc, ival);
+                        break;
+                case 'y':
+                        strval = va_arg(ap, char*);
+                        arg = scm_mk_symbol(sc, strval);
+                        break;
+                case 'l':
+                    arg = va_arg(ap, pointer);
+                    if (!arg) {
+                        arg = sc->NIL;
+                    }
+                    break;
+                default:
+                        assert(false);
+                        break;
+                }
+
+                /* Note: arg already protected during _cons */
+                cell = _cons(sc, arg, sc->NIL, 0);
+
+                if (head == sc->NIL) {
+                        head = cell;
+                        tail = cell;
+
+                        /* By protecting the head we protect the rest of the
+                         * list */
+                        scm_protect(sc, head);
+                } else {
+                        tail->_object._cons._cdr = cell;
+                        tail = cell;
+                }
+        }
+
+        /* Allocations are over so unprotect the list */
+        if (head != sc->NIL)
+                scm_unprotect(sc, head);
+
+        return head;
+}
+
+struct mview * kern_unpack_mview(scheme *sc, pointer *args, const char *caller)
+{
+        struct mview *obj;
+
+        if (unpack(sc, args, "p", &obj)) {
+                rt_err("%s: bad args", caller);
+                return NULL;
+        }
+
+        if (obj == NULL) {
+                rt_err("%s: null view object");
+                return NULL;
+        }
+
+        return obj;
+}
+
+static int kern_unpack_loc(scheme *sc, pointer *args, struct place **place,
+                           int *x, int *y, const char *caller)
+{
+        pointer loc;
+
+        loc = scm_car(sc, *args);
+        if (! scm_is_pair(sc, loc)) {
+                rt_err("%s: location not a list", caller);
+                return 0;
+        }
+
+        *args = scm_cdr(sc, *args);
+
+        if (unpack(sc, &loc, "pdd", place, x, y)) {
+                rt_err("%s: bad location args", caller);
+                return 0;
+        }
+
+        if (!(*place)) {
+                rt_err("%s: null place", caller);
+                return 0;
+        }
+        
+        return 1;
+}
+
+static pointer pack(scheme *sc, const char *fmt, ...)
+{
+        pointer head;
+        va_list ap;
+
+        va_start(ap, fmt);
+        head = vpack(sc, fmt, ap);
+        va_end(ap);
+
+        return head;
+}
+
+static pointer kern_mk_sprite_set(scheme *sc, pointer args)
+{
+        int width, height, rows, cols, offx, offy;
+        char *fname;
+        struct images *image = NULL;
+        const char *tag = TAG_UNK;
+        pointer ret;
+
+        if (unpack(sc, &args, "ydddddds", &tag, &width, &height, &rows, &cols,
+                   &offx, &offy, &fname)) {
+                load_err("kern-mk-sprite-set %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        image = images_new(tag, width, height, rows, cols, offx, offy, fname);
+        session_add(Session, image, image_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, image);
+        scm_define(sc, tag, ret);
+
+        return ret;
+}
+
+static pointer kern_mk_sprite(scheme *sc, pointer args)
+{
+        struct images *images;
+        int n_frames, index, facings, wave;
+        struct sprite *sprite;
+        const char *tag = TAG_UNK;
+        pointer ret;
+
+        if (unpack(sc, &args, "ypddbd", &tag, &images, &n_frames, &index,
+                   &wave, &facings)) {
+                load_err("kern-mk-sprite %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        sprite = sprite_new(tag, n_frames, index, wave, facings, images); 
+        session_add(Session, sprite, sprite_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, sprite);
+        scm_define(sc, tag, ret);
+
+        return ret;
+}
+
+struct connection {
+        Object *from;
+        char *to;
+};
+
+static pointer kern_mk_terrain(scheme *sc, pointer args)
+{
+        int alpha, light;
+        void *sprite;
+        struct terrain *terrain;
+        const char *tag = TAG_UNK, *name;
+        pointer ret;
+        int pclass;
+        pointer proc = NULL;
+
+        /* Revisit: ignore effects for now */
+
+        if (unpack(sc, &args, "ysdpddc", &tag, &name, &pclass, &sprite, 
+                   &alpha, &light, &proc)) {
+                load_err("kern-mk-terrain %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        terrain = terrain_new(tag, name, (struct sprite*)sprite, pclass, 
+                              alpha, light);
+
+        if (proc != sc->NIL) {
+                terrain->effect = closure_new_ref(sc, proc);
+        }
+        terrain->renderCombat = NULL;
+
+        list_add(&Session->terrains, &terrain->session_list);
+        ret = scm_mk_ptr(sc, terrain);
+        scm_define(sc, tag, ret);
+
+        return ret;
+}
+
+static pointer kern_mk_sound(scheme *sc, pointer args)
+{
+        sound_t *sound;
+        const char *tag = TAG_UNK, *name;
+        pointer ret;
+
+        if (unpack(sc, &args, "ys", &tag, &name)) {
+                load_err("kern-mk-sound %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        sound = sound_new(tag, name);
+
+        /* Add it to the session */
+        session_add(Session, sound, sound_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, sound);
+        scm_define(sc, tag, ret);
+
+        return ret;
+}
+
+static pointer kern_mk_palette(scheme *sc, pointer args)
+{
+        int argno = 1;
+         const char *tag = TAG_UNK;
+        pointer ret;
+
+        if (Session->palette) {
+                load_err("kern-mk-palette: %s already set as the session "\
+                         "palette",
+                         Session->palette->tag);
+                return sc->NIL;
+        }
+
+        if (unpack(sc, &args, "y", &tag)) {
+                load_err("kern-mk-palette %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        Session->palette = terrain_palette_new(tag);
+
+        /* The next argument after the tag shoud be a list of (glyph, terrain)
+         * pairs. Since these are pairs - and not lists - */
+
+        if (! scm_is_pair(sc, args)) {
+                load_err("kern-mk-palette arg %d: arg list too short", argno);
+                terrain_palette_del(Session->palette);
+                return sc->NIL;
+        }
+
+        args = scm_car(sc, args);
+        argno = 1;
+
+        while (scm_is_pair(sc, args)) {
+
+                char *glyph;
+                void *terrain;
+                pointer pair;
+
+                pair = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+                unpack(sc, &pair, "sp", &glyph, &terrain);
+                terrain_palette_add(Session->palette, glyph, 
+                                    (struct terrain*)terrain);
+        }
+
+        session_add(Session, Session->palette, terrain_palette_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, Session->palette);
+        scm_define(sc, tag, ret);
+
+        return ret;
+}
+
+static pointer kern_mk_map(scheme *sc, pointer args)
+{
+        int width, height, x, y, i;
+        struct terrain_palette *pal;
+        const char *tag = TAG_UNK;
+        struct terrain_map *map;
+        pointer ret;
+        struct list *elem;
+
+        if (unpack(sc, &args, "yddp", &tag, &width, &height, &pal)) {
+                load_err("kern-mk-map %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        /* Final argument should be a list of strings. */
+
+        if (! scm_is_pair(sc, args)) {
+                load_err("kern-mk-map %s: arg list too short", tag);
+                return sc->NIL;
+        }
+
+        args = scm_car(sc, args);
+        map = terrain_map_new(tag, width, height, pal);
+        i = 0;
+
+        for (y = 0; y < height; y++) {
+
+                char *map_line;
+                char *glyph;
+
+               if (unpack(sc, &args, "s", &map_line))
+                        goto abort;
+
+                for (x = 0; x < width; x++) {
+
+                        struct terrain *tt;
+
+                        glyph = strtok(x ? NULL : map_line, " ");
+                        if (! glyph) {
+                                load_err("kern-mk-map %s: line %d only "\
+                                         "%d wide, should be %d wide", tag,
+                                         y, x, width);
+                                goto abort;
+                        }
+
+                        tt = palette_terrain_for_glyph(pal, glyph);
+                        if (! tt) {
+                                load_err("kern-mk-map %s: line %d "\
+                                         "column %d: glyph %s "\
+                                         "has no terrain in palette %s", tag,
+                                         y, x, glyph, pal->tag);
+                                goto abort;
+                        }
+
+                        map->terrain[i] = tt;
+                        i++;
+                        
+                }
+        }
+
+        /* run all registered terrain blenders on the new map */
+        list_for_each(&Session->blenders, elem) {
+                blender_t *blender=outcast(elem, blender_t, list);
+                terrain_map_blend(map, blender->inf, blender->n_nonsup,
+                                  blender->nonsup, blender->range);
+        }
+        
+
+        map->handle = session_add(Session, map, terrain_map_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, map);
+
+        /* Embedded maps (those defined within and used exclusively for) place
+         * constructors may not have and do not need tags. */
+        if (tag)
+                scm_define(sc, tag, ret);
+
+        return ret;
+
+ abort:
+        terrain_map_unref(map);
+        return sc->NIL;
+}
+
+
+
+static pointer kern_mk_composite_map(scheme *sc, pointer args)
+{
+        int width, height, x = 0, y = 0, i = 0;
+        const char *tag = TAG_UNK;
+        struct terrain_map *map=NULL, *submap=NULL;
+        pointer ret;        
+        struct list *elem;
+
+        /* parse supermap tag and dimensions */
+        if (unpack(sc, &args, "ydd", &tag, &width, &height)) {
+                load_err("kern-mk-composite-map %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        /* unpack the first submap */
+        if (unpack(sc, &args, "p", &submap)) {
+                load_err("kern-mk-composite-map %s: first submap invalid", tag);
+                goto abort;
+        }
+        
+        /* create the supermap, inferring the submap dimensions and palette
+         * from the first submap */
+        map = terrain_map_new(tag, width * submap->w, height * submap->h, 
+                              submap->palette);
+
+        /* set the supermap info */
+        map->submap_w = submap->w;
+        map->submap_h = submap->h;
+        map->composite = 1;
+        
+        /* blit the first submap onto the supermap in the upper left-hand
+         * corner */
+        terrain_map_blit(map, 0, 0, submap, 0, 0, submap->w, submap->h);
+
+        /* for each remaining submap in the list... */
+        for (y = 0; y < height; y++) {
+
+                for (x = 0; x < width; x++) {
+
+                        /* except the first one... */
+                        if (x == 0 && y == 0)
+                                continue;
+
+                        /* unpack it */
+                        if (unpack(sc, &args, "p", &submap)) {
+                                load_err("kern-mk-composite-map %s: submap "\
+                                         "%d invalid", tag, i);
+                                goto abort;
+                        }
+                        
+                        /* check its palette and dimensions */
+                        if (map->palette != submap->palette) {
+                                load_err("kern-mk-composite-map %s: submap %d "\
+                                         "palette doesn't match first submap "\
+                                         "palette", tag, i);
+                                goto abort;
+                        }
+                        if (map->submap_w != submap->w) {
+                                load_err("kern-mk-composite-map %s: submap %d "\
+                                         "width doesn't match first submap "\
+                                         "width", tag, i);
+                                goto abort;
+                        }
+                        if (map->submap_h != submap->h) {
+                                load_err("kern-mk-composite-map %s: submap %d "\
+                                         "height doesn't match first submap "\
+                                         "height", tag, i);
+                                goto abort;
+                        }
+                        
+                        /* blit the submap onto the supermap */
+                        terrain_map_blit(map, x * map->submap_w, y * map->submap_h, 
+                                         submap, 0, 0, 
+                                         map->submap_w, map->submap_h);
+                }
+        }
+
+        /* run all registered terrain blenders on the new map */
+        list_for_each(&Session->blenders, elem) {
+                blender_t *blender=outcast(elem, blender_t, list);
+                terrain_map_blend(map, blender->inf, blender->n_nonsup,
+                                  blender->nonsup, blender->range);
+        }
+
+        /* add it to the session */
+        map->handle = session_add(Session, map, terrain_map_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, map);
+
+        /* define its tag (if specified) */
+        if (tag)
+                scm_define(sc, tag, ret);
+
+        return ret;
+
+ abort:
+        terrain_map_unref(map);
+        return sc->NIL;
+}
+
+static int kern_place_load_subplaces(scheme *sc, pointer *args, struct place *place)
+{
+        pointer subplaces;
+
+        if (! scm_is_pair(sc, *args)) {
+                load_err("kern-mk-place %s: missing the subplaces list",
+                         place->tag);
+                return -1;
+        }
+
+        subplaces = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+
+        while (scm_is_pair(sc, subplaces)) {
+                struct place *subplace = 0;
+                int x, y;
+                pointer cell;
+
+                cell = scm_car(sc, subplaces);
+                subplaces = scm_cdr(sc, subplaces);
+
+                if (unpack(sc, &cell, "pdd", &subplace, &x, &y)) {
+                        load_err("kern-mk-place %s: bad arg in subplaces list",
+                                 place->tag);
+                        return -1;
+                }
+
+                if (!subplace) {
+                        load_err("kern-mk-place %s: null place in subplaces "\
+                                 "list", place->tag);
+                        return -1;
+                }
+
+                if (subplace->magic != PLACE_MAGIC) {
+                        load_err("kern-mk-place %s: subplace is not a place",
+                                 place->tag);
+                        return -1;
+                }
+
+                if (place_add_subplace(place, subplace, x, y)) {
+                        load_err("kern-mk-place %s: failed to put %s as a "\
+                                 "subplace at [%d, %d]; is another subplace "\
+                                 "already there? Are the coordinates off-map?",
+                                 place->tag, subplace->tag, x, y);
+                        return -1;
+                }
+        }
+
+        return 0;
+}
+
+
+
+static int kern_place_load_neighbors(scheme *sc, pointer *args, 
+                                     struct place *place)
+{
+        pointer neighbors;
+
+        if (! scm_is_pair(sc, *args)) {
+                load_err("kern-mk-place %s: missing the contents list",
+                         place->tag);
+                return -1;
+        }
+
+        neighbors = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+
+        while (scm_is_pair(sc, neighbors)) {
+                int dir, opdir;
+                struct place *neighbor, *tmp;
+                pointer cell;
+
+                cell = scm_car(sc, neighbors);
+                neighbors = scm_cdr(sc, neighbors);
+                
+                if (unpack(sc, &cell, "pd", &neighbor, &dir)) {
+                        load_err("kern-mk-place %s: error in neighbor list", 
+                                 place->tag);
+                        return -1;
+                }
+
+                if (! IS_LEGAL_DIRECTION(dir)) {
+                        load_err("kern-mk-place %s: invalid direction for "\
+                                 "neighbor: %d\n", place->tag, dir);
+                        return -1;
+                }
+                
+                opdir = directionToOpposite(dir);
+
+                /* check for existing neighbors */
+                if ((tmp = place_get_neighbor(place, dir))) {
+                        load_err("kern-mk-place %s: already has %s as a "\
+                                 "neighbor in direction %d\n",
+                                 place->tag, tmp->tag, dir);
+                        return -1;
+                }
+
+                if ((tmp = place_get_neighbor(neighbor, opdir))) {
+                        load_err("kern-mk-place %s: already has %s as a "\
+                                 "neighbor in direction %d\n",
+                                 neighbor->tag, 
+                                 tmp->tag, opdir);
+                        return -1;
+                }
+
+                /* finally, hook them up */
+                place_set_neighbor(place, dir, neighbor);
+        }
+
+        return 0;
+}
+
+KERN_API_CALL(kern_place_set_neighbor)
+{
+        int dir;
+        struct place *place, *neighbor;
+
+        if (unpack(sc, &args, "dpp", &dir, &place, &neighbor)) {
+                rt_err("kern-place-set-neighbor: bad args");
+                return sc->F;
+        }
+
+        // neighbor == null is allowed (it unlinks current neighbor)
+        if (! place) {
+                rt_err("kern-place-set-neighbor: null place");
+                return sc->F;                
+        }
+        
+        if (! IS_LEGAL_DIRECTION(dir)) {
+                rt_err("kern-place-set-neighbor: bad direction %d", dir);
+                return sc->F;                
+        }
+
+        /* link (works both ways) */
+            place_set_neighbor(place, dir, neighbor);
+        
+        return sc->T;
+}
+
+KERN_API_CALL(kern_place_apply_tile_effects)
+{
+        struct place *place;
+        class Object *obj;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-apply-tile-effects: bad place arg");
+                return sc->NIL;
+        }
+
+        obj = unpack_obj(sc, &args, "kern-obj-relocate");
+        if (!obj)
+                return sc->NIL;
+
+        place_apply_tile_effects(place, obj);
+        return sc->NIL;
+}
+
+static int kern_place_load_contents(scheme *sc, pointer *args, 
+                                    struct place *place)
+{
+        pointer contents;
+
+        if (! scm_is_pair(sc, *args)) {
+                load_err("kern-mk-place %s: missing the contents list",
+                         place->tag);
+                return -1;
+        }
+
+        contents = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+
+        while (scm_is_pair(sc, contents)) {
+
+                class Object *obj = 0;
+                int x, y;
+                pointer cell;
+
+                cell = scm_car(sc, contents);
+                contents = scm_cdr(sc, contents);
+
+                if (unpack(sc, &cell, "pdd", &obj, &x, &y)) {
+                        load_err("kern-mk-place %s: bad arg in content list",
+                                 place->tag);
+                        return -1;
+                }
+
+                if (!obj) {
+                        load_err("kern-mk-place %s: null obj in content list",
+                                 place->tag);
+                        return -1;
+                }
+
+                obj->relocate(place, x, y, REL_NOTRIG);
+        }
+
+        return 0;
+}
+
+static int kern_place_load_entrances(scheme *sc, pointer *args, 
+                                     struct place *place)
+{
+        pointer entrances;
+
+        if (! scm_is_pair(sc, *args)) {
+                load_err("kern-mk-place %s: missing the entrances list",
+                         place->tag);
+                return -1;
+        }
+
+        entrances = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+
+        while (scm_is_pair(sc, entrances)) {
+
+                int dir, x, y;
+                pointer cell;
+
+                cell = scm_car(sc, entrances);
+                entrances = scm_cdr(sc, entrances);
+
+                if (unpack(sc, &cell, "ddd", &dir, &x, &y)) {
+                        load_err("kern-mk-place %s: bad arg in entrances list",
+                                 place->tag);
+                        return -1;
+                }
+
+                if (place_set_edge_entrance(place, dir, x, y)) {
+                        load_err("kern-mk-place %s: failed to set entrance for "\
+                                 "direction %d to [%d %d]", place->tag, dir, x, y);
+                        return -1;
+                }
+        }
+
+        return 0;
+}
+
+static int kern_place_load_hooks(scheme *sc, pointer *args, 
+                                    struct place *place)
+{
+        pointer contents;
+        pointer pre_entry_proc;
+
+        if (! scm_is_pair(sc, *args)) {
+                load_err("kern-mk-place %s: missing the hooks list",
+                         place->tag);
+                return -1;
+        }
+
+        contents = scm_car(sc, *args);
+        *args = scm_cdr(sc, *args);
+
+        while (scm_is_pair(sc, contents)) {
+
+                if (unpack(sc, &contents, "c", &pre_entry_proc)) {
+                        load_err("kern-mk-place %s: bad arg in hook list",
+                                 place->tag);
+                        return -1;
+                }
+
+                place_add_on_entry_hook(place,
+                                        closure_new_ref(sc, pre_entry_proc));
+        }
+
+        return 0;
+}
+
+KERN_API_CALL(kern_place_add_on_entry_hook)
+{
+        struct place *place; 
+        pointer proc;
+
+       if (unpack(sc, &args, "pc", &place, &proc)) {
+                rt_err("kern-place-add-on-entry-hook: bad args");
+                return sc->NIL;
+        }
+
+        if (! place) {
+                rt_err("kern-place-add-on-entry-hook: null place");
+                return sc->NIL;
+        }
+
+        place_add_on_entry_hook(place,
+                                closure_new_ref(sc, proc));
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_place)
+{
+        int wild, wraps, underground, combat;
+        struct terrain_map *map;
+        struct place *place;
+        struct sprite *sprite;
+        const char *tag = TAG_UNK, *name;
+        pointer ret;
+
+        if (unpack(sc, &args, "ysppbbbb", &tag, &name, &sprite, &map,
+                   &wraps, &underground, &wild, &combat)) {
+                load_err("kern-mk-place %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        if ( ! map->handle) {
+                load_err("kern-mk-place %s: map %s has no session handle; "\
+                         "is it already being used in another place?", tag, 
+                         map->tag);
+                return sc->NIL;
+        }
+
+        session_rm(Session, map->handle);
+        map->handle = 0;
+        place = place_new(tag, name, sprite, map, wraps, underground, wild, 
+                          combat);
+
+
+        if (kern_place_load_subplaces(sc, &args, place) ||
+            kern_place_load_neighbors(sc, &args, place) ||
+            kern_place_load_contents(sc, &args, place)  ||
+            kern_place_load_hooks(sc, &args, place)     ||
+            kern_place_load_entrances(sc, &args, place))
+                goto abort;
+
+        place->handle = session_add(Session, place, place_dtor, place_save, place_start);
+        ret = scm_mk_ptr(sc, place);
+        scm_define(sc, tag, ret);
+        return ret;
+
+ abort:
+        place_del(place);
+        return sc->NIL;
+}
+
+static pointer kern_mk_species(scheme *sc, pointer args)
+{
+        struct species *species;
+        int str, intl, dex, spd, vr, hpmod, hpmult, argno = 1;
+        int mpmod, mpmult, visible, n_slots, n_spells, i, xpval;
+        int stationary=0;
+        struct sprite *sleep_sprite;
+        class ArmsType *weapon;
+        const char *tag = TAG_UNK, *name, *armor_dice;
+        sound_t *damage_sound, *walking_sound;
+        pointer slots;
+        pointer spells;
+        pointer ret;
+        struct mmode *mmode;
+        
+
+        if (unpack(sc, &args, "ysdddddpddddppbppdbs", &tag, &name, &str, 
+                   &intl, &dex, &spd, &vr, &mmode, &hpmod, &hpmult, &mpmod, 
+                   &mpmult, &sleep_sprite, &weapon, 
+                   &visible, &damage_sound, &walking_sound,
+                   &xpval, &stationary, &armor_dice)) {
+                load_err("kern-mk-species %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        if (scm_len(sc, args) < 2) {
+                load_err("kern-mk-species %s: arg list too short", tag,
+                         argno++);
+                return sc->NIL;
+        }
+
+        if (! mmode) {
+                load_err("kern-mk-species %s: null mmode", tag);
+                return sc->NIL;
+        }
+        
+
+        /* get the list of slots */
+        slots = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        /* get the list of spells */
+        spells = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        /* get the sizes of the various lists */
+        n_slots = scm_len(sc, slots);
+        n_spells = scm_len(sc, spells);
+
+        species = species_new(tag, name, damage_sound, walking_sound, str,
+                              intl, dex, spd, vr, hpmod, hpmult,
+                              mpmod, mpmult, visible,
+                              n_slots, n_spells);
+        species->weapon = weapon;
+        species->sleep_sprite = sleep_sprite;
+        species->mmode = mmode;
+        species->xpval = xpval;
+        species->stationary = stationary;
+
+        /* Optional armor dice */
+        if (armor_dice) {
+                species->armor_dice = strdup(armor_dice);
+        }
+
+        /* Load the list of slots. */
+        i = 0;
+        while (scm_is_pair(sc, slots)) {
+                if (unpack(sc, &slots, "d", &species->slots[i++]))
+                        goto abort;
+        }
+
+        /* Load the list of spells */
+        i = 0;
+        while (scm_is_pair(sc, spells)) {
+                char *code;
+                if (unpack(sc, &spells, "s", &code))
+                        goto abort;
+                species->spells[i] = strdup(code);
+                assert(species->spells[i]);
+                i++;
+        }
+
+        session_add(Session, species, species_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, species);
+        scm_define(sc, tag, ret);
+        return ret;
+
+ abort:
+        species_del(species);
+        return sc->NIL;
+}
+
+static pointer kern_mk_arms_type(scheme *sc, pointer args)
+{
+        class ArmsType *arms;
+        const char *tag = TAG_UNK, *name;
+        sound_t *fire_sound;
+        int slots, hands, range, weight;
+        char *hit, *defend, *damage, *armor;
+        int rap, AP_mod, thrown, ubiq;
+        struct sprite *sprite;
+        class MissileType *missile;
+        class ObjectType *ammo;
+        pointer gifc;
+        pointer ret;
+        int gifc_cap;
+               int str_attack_mod;
+               int dex_attack_mod;
+               int char_damage_mod;
+               float char_avoid_mod;
+                 struct mmode *mmode;
+               
+
+        if (unpack(sc, &args, "yspssssdddddppbbdpdodddrp",
+                                               &tag, 
+                                               &name, 
+                                               &sprite, 
+                       &hit, &damage, &armor, &defend,
+                  &slots, &hands, &range, &rap, &AP_mod, 
+                       &missile, &ammo,
+                       &thrown, &ubiq,
+                       &weight, 
+                       &fire_sound,
+                       &gifc_cap,
+                       &gifc,
+                                               &str_attack_mod, &dex_attack_mod, &char_damage_mod,
+                                               &char_avoid_mod,
+                                               &mmode)) {
+                load_err("kern-mk-arms-type %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        if (! dice_valid(hit)) {
+                load_err("kern-mk-arms-type %s: bad dice format '%s'",
+                         tag, hit);
+                return sc->NIL;
+        }
+
+        if (! dice_valid(defend)) {
+                load_err("kern-mk-arms-type %s: bad dice format '%s'", 
+                         tag, defend);
+                return sc->NIL;
+        }
+
+        if (! dice_valid(damage)) {
+                load_err("kern-mk-arms-type %s: bad dice format '%s'", 
+                         tag, damage);
+                return sc->NIL;
+        }
+
+        if (! dice_valid(armor)) {
+                load_err("kern-mk-arms-type %s: bad dice format '%s'", 
+                         tag, armor);
+                return sc->NIL;
+        }
+
+        arms = new ArmsType(tag, name, sprite, slots, hit, defend, hands, 
+                            range,
+                            weight, damage, armor, rap, AP_mod, thrown, ubiq,
+                            fire_sound, missile, ammo, str_attack_mod, dex_attack_mod,
+                                                       char_damage_mod, char_avoid_mod, false);
+                                                                                                       
+                       arms->setMovementMode(mmode);
+                       
+        if (gifc != sc->NIL) {
+                /* arms->get_handler = closure_new(sc, get_handler); */
+                arms->setGifc(closure_new(sc, gifc), gifc_cap);
+        }
+
+        session_add(Session, arms, arms_type_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, arms);
+        scm_define(sc, tag, ret);
+        return ret;
+}
+
+static pointer kern_mk_missile_type(scheme *sc, pointer args)
+{
+       class MissileType *arms;
+       const char *tag = TAG_UNK, *name;
+       struct sprite *sprite;
+       pointer gifc;
+       pointer ret;
+       int gifc_cap;
+       struct mmode *mmode;
+       int beam;
+       int fixedrange;
+       
+       
+       if (unpack(sc, &args, "yspdopbb",
+                       &tag, 
+                       &name,
+                       &sprite,
+                       &gifc_cap,
+                       &gifc,
+                       &mmode,
+                       &beam,
+                       &fixedrange))
+       {
+               load_err("kern-mk-projectile-type %s: bad args", tag);
+               return sc->NIL;
+       }
+       
+       arms = new MissileType(tag, name, sprite, beam, fixedrange, mmode);
+       
+       if (gifc != sc->NIL)
+       {
+               /* arms->get_handler = closure_new(sc, get_handler); */
+               arms->setGifc(closure_new(sc, gifc), gifc_cap);
+       }
+       
+       session_add(Session, arms, missile_type_dtor, NULL, NULL);
+       ret = scm_mk_ptr(sc, arms);
+       scm_define(sc, tag, ret);
+       
+       return ret;
+}
+
+static pointer kern_mk_field_type(scheme *sc, pointer args)
+{
+        class FieldType *field;
+        const char *tag = TAG_UNK, *name;
+        struct sprite *sprite;
+        int light, duration, pclass;
+        closure_t *clx = NULL;
+        pointer func = sc->NIL;
+        pointer ret;
+        struct mmode *mmode = NULL;      
+
+        if (unpack(sc, &args, "yspdddcp", &tag, &name, &sprite, &light, 
+                   &duration, &pclass, &func, &mmode)) {
+                load_err("kern-mk-field-type %s: bad args", tag);
+                return sc->NIL;
+        }
+        
+        if (func != sc->NIL) {
+                clx = closure_new(sc, func);
+        }
+
+        field = new FieldType(tag, name, sprite, light, duration, pclass, clx);
+        field->setMovementMode(mmode);
+        session_add(Session, field, field_type_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, field);
+        scm_define(sc, tag, ret);
+        return ret;
+}
+
+static void mmode_dtor(void *ptr)
+{
+        mmode_del((struct mmode*)ptr);
+}
+
+KERN_API_CALL(kern_mk_mmode)
+{
+        char *tag, *name;
+        int index;
+        struct mmode *mmode;
+        pointer ret;
+
+        if (unpack(sc, &args, "ysd", &tag, &name, &index)) {
+                load_err("kern-mk-mmode: bad args");
+                return sc->NIL;
+        }
+
+        mmode = mmode_new(tag, name, index);
+        session_add(Session, mmode, mmode_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, mmode);
+        scm_define(sc, tag, ret);
+        return ret;
+}
+
+static pointer kern_mk_obj_type(scheme *sc, pointer args)
+{
+        class ObjectType *type;
+        const char *tag = TAG_UNK, *name;
+        char *pluralName=NULL;
+        enum layer layer;
+        struct sprite *sprite;
+        pointer ret;
+        pointer gifc;
+        int gifc_cap;
+        struct mmode *mmode;
+
+        /* unpack the tag */
+        if (unpack(sc, &args, "y", &tag)) {
+                load_err("kern-mk-obj-type %s: bad args (did you mean to use "\
+                         "kern-mk-obj instead?)", tag);
+                return sc->NIL;
+        }
+
+        /* probe the name to see if it is a list, if so then use the car as the
+         * name and the cadr as the pluralName */
+        if (scm_is_pair(sc, scm_car(sc, args))) {
+                pointer list = scm_car(sc, args);
+                args=scm_cdr(sc, args);
+                if (unpack(sc, &list, "ss", &name, &pluralName)) {
+                        load_err("kern-mk-obj-type %s: bad name arg", tag);
+                        return sc->NIL;
+                }
+        } else if (unpack(sc, &args, "s", &name)) {
+                load_err("kern-mk-obj-type %s: bad name arg", tag);
+                return sc->NIL;
+        }
+
+        /* continue unpacking the rest of the args */
+        if (unpack(sc, &args, "pddop", &sprite, &layer, &gifc_cap, &gifc, &mmode)) {
+                load_err("kern-mk-obj-type %s: bad args (did you mean to use "\
+                         "kern-mk-obj instead?)", tag);
+                return sc->NIL;
+        }
+
+        type = new ObjectType(tag, name, sprite, layer);
+        assert(type);
+
+        if (gifc != sc->NIL) {
+                type->setGifc(closure_new(sc, gifc), gifc_cap);
+        }
+
+        if (pluralName) {
+                type->setPluralName(pluralName);
+        }
+        
+        type->setMovementMode(mmode);
+        session_add(Session, type, obj_type_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, type);
+        scm_define(sc, tag, ret);
+        return ret;
+}
+
+static pointer kern_mk_occ(scheme *sc, pointer args)
+{
+        struct occ *occ;
+        int hpmod, hpmult;
+        int mpmod, mpmult, hit, def, dam, arm, xpval;
+        const char *tag = TAG_UNK, *name;
+        struct skill_set *skset;
+        float magic;
+        pointer ret;
+
+        /* Basic args */
+        if (unpack(sc, &args, "ysrdddddddddp",
+                   &tag, &name, &magic, &hpmod, &hpmult, &mpmod, &mpmult, &hit,
+                   &def, &dam, &arm, &xpval, &skset)) {
+                load_err("kern-mk-occ %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        occ = occ_new(tag, name, magic, hpmod, hpmult, mpmod, mpmult, hit, def,
+                      dam, arm);
+        occ_ref(occ);
+        occ->xpval = xpval;
+        occ_set_skills(occ, skset);
+
+        session_add(Session, occ, occ_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, occ);
+        scm_define(sc, tag, ret);
+        return ret;
+}
+
+static int kern_load_hooks(scheme *sc, pointer hook_tbl, Object *obj)
+{
+        while (scm_is_pair(sc, hook_tbl)) {
+
+                struct effect *effect;
+                int flags;
+                pointer gobcell;
+                pointer hook_entry;
+                struct gob *gob = NULL;
+                clock_alarm_t clk;
+
+                hook_entry = scm_car(sc, hook_tbl);
+                hook_tbl = scm_cdr(sc, hook_tbl);
+
+                if (unpack(sc, &hook_entry, "pldd", &effect, &gobcell, &flags, 
+                           &clk)) {
+                        return -1;
+                }
+
+                /* Note: even if gobcell is sc->NIL we want to wrap it. I once
+                 * tried to use a NULL gob instead but if we pass that back
+                 * into scheme as an arg and the gc tries to mark it we'll
+                 * crash. */
+                gob = gob_new(sc, gobcell);
+                gob->flags |= GOB_SAVECAR;
+                
+                obj->restoreEffect(effect, gob, flags, clk);
+        }
+
+        return 0;
+}
+
+static void kern_load_conv(scheme *sc, pointer sym, Object *obj)
+{
+        struct conv *conv;
+        struct closure *proc;
+
+        if (sym == sc->NIL) {
+            return;
+        }
+
+        if (! (proc = closure_new_ref(sc, sym))) {
+                load_err("%s: closure_new failed", __FUNCTION__);
+                return;
+        }
+
+        if (!(conv = conv_new(proc))) {
+                load_err("%s: conv_new failed", __FUNCTION__);
+                goto done2;
+        }
+
+        obj->setConversation(conv);
+        conv_unref(conv);
+ done2:
+        closure_unref(proc);
+}
+
+static pointer kern_mk_char(scheme *sc, pointer args)
+{
+        class Character *character;
+        int str, intl, dex, hpmod, hpmult;
+        int mpmod, mpmult, hp, xp, mp, AP_per_round, lvl, dead;
+        const char *tag = TAG_UNK, *name;
+        struct species *species;
+        struct occ *occ;
+        struct sprite *sprite;
+        pointer conv;
+        pointer readied;
+        pointer ret;
+        pointer ai;
+        pointer hook_tbl;
+        int base_faction;
+        struct sched *sched;
+        class Container *inventory;
+
+        if (unpack(sc, &args, "yspppdddddddddddddbcpcp",
+                   &tag, &name, &species, &occ, 
+                   &sprite, &base_faction, &str,
+                   &intl, &dex, &hpmod, &hpmult, &mpmod, &mpmult, 
+                   &hp, &xp, &mp, &AP_per_round, &lvl, &dead,
+                   &conv, &sched, &ai, &inventory)) {
+                load_err("kern-mk-char %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        if (! scm_is_pair(sc, args)) {
+                load_err("kern-mk-char %s: no readied arms list", tag);
+                return sc->NIL;
+        }
+
+        readied = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        character = new class Character(tag, name, sprite,species, occ,
+                                        str, intl, dex, hpmod, hpmult, mpmod, 
+                                        mpmult,
+                                        hp, xp, mp, AP_per_round, lvl);
+        assert(character);
+        character->setBaseFaction(base_faction);
+        character->setSchedule(sched);
+        character->setInventoryContainer(inventory);
+        character->setDead(dead);
+
+        kern_load_conv(sc, conv, character);
+
+        if (ai != sc->NIL) {
+                character->setAI(closure_new(sc, ai));
+        }
+
+        /* Load the list of arms. */
+        while (scm_is_pair(sc, readied)) {
+                class ArmsType *arms;
+                if (unpack(sc, &readied, "p", &arms)) {
+                        load_err("kern-mk-char %s: error in arms list", tag);
+                        goto abort;
+                }
+                /*character->add(arms, 1);*/
+                character->ready(arms);
+        }
+
+        /* Load the hooks. */
+        hook_tbl = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+        if (kern_load_hooks(sc, hook_tbl, character)) {
+                load_err("kern-mk-char %s: bad hook entry", tag);
+                goto abort;
+        }
+
+
+        ret = scm_mk_ptr(sc, character);
+        
+        /* If the character is tagged then it's not "anonymous", and we'll
+         * assign it to a scheme variable named after the tag. */
+        if (tag) {
+                scm_define(sc, tag, ret);
+
+                /* Tagged objects may be referred to in the script by their
+                 * tag. If the object is destroyed, the scheme variable that
+                 * refers to the object is still valid (in Scheme, it isn't
+                 * really possible to undefine variables). To prevent crashes
+                 * on dereferencing this variable we'll bump the refcount. To
+                 * ensure the object is destroyed on session teardown, we'll
+                 * mark it for custom finalization, which will decrement the
+                 * extra refcount. */
+                obj_inc_ref(character);
+                scm_set_cust_fin(sc, ret);
+        }
+
+        return ret;
+
+ abort:
+        delete character;
+        return sc->NIL;
+}
+
+static pointer kern_mk_obj(scheme *sc, pointer args)
+{
+        class Object *obj;
+        class ObjectType *type = 0;
+        int count;
+
+        if (unpack(sc, &args, "pd", &type, &count)) {
+                load_err("kern-mk-obj: bad args");
+                return sc->NIL;
+        }
+
+        if (!type) {
+                load_err("kern-mk-obj: null type");
+                return sc->NIL;
+        }
+
+        // Fixme: we need a MAGIC number field, but it won't work because
+        // 'type' is a c++ object. If the script hands us something that is not
+        // really an ObjectType we'll crash sooner or later.
+
+        obj = type->createInstance();        
+        assert(obj);
+        obj->setCount(count);
+
+        if (kern_load_hooks(sc, scm_car(sc, args), obj)) {
+                load_err("kern-mk-obj: error in hook list");
+                goto abort;
+        }
+        args = scm_cdr(sc, args);
+
+        // Objects aren't added to the session the way types are. Every object
+        // will end up in some type of container; objects should always be
+        // loaded as part of a container's contents; and the container should
+        // always save the objects it contains.
+        //
+        // There's nothing to prevent a script from creating a "dangling"
+        // object which is never put anywhere. Although weird (and probably a
+        // bug in the script), it should be benign. Memory leaks are prevented
+        // by deinitializing the interpreter every time we load a new session.
+        // Furthermore, such orphan objects will never be saved, so they won't
+        // propogate.
+
+        return scm_mk_ptr(sc, obj);
+        
+ abort:
+        delete obj;
+        return sc->NIL;
+}
+
+static pointer kern_mk_field(scheme *sc, pointer args)
+{
+        class Field *obj;
+        class FieldType *type = 0;
+        int duration;
+
+        if (unpack(sc, &args, "pd", &type, &duration)) {
+                load_err("kern-mk-obj: bad args");
+                return sc->NIL;
+        }
+
+        if (!type) {
+                load_err("kern-mk-obj: null type");
+                return sc->NIL;
+        }
+
+        obj = new Field(type, duration);
+        assert(obj);
+
+        // Objects aren't added to the session the way types are. Every object
+        // will end up in some type of container; objects should always be
+        // loaded as part of a container's contents; and the container should
+        // always save the objects it contains.
+
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_mk_party(scheme *sc, pointer args)
+{
+        class Party *obj;
+
+        obj = new Party();
+        assert(obj);
+
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_obj_put_at(scheme *sc, pointer args)
+{
+        class Object *obj;
+        struct place *place;
+        pointer loc;
+        int x, y;
+
+        if (unpack(sc, &args, "p", &obj)) {
+                rt_err("kern-obj-put-at: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-put-at: null obj");
+                return sc->NIL;
+        }
+
+        loc = scm_car(sc, args);
+        if (! scm_is_pair(sc, loc)) {
+                rt_err("kern-obj-put-at: invalid location");
+                return sc->NIL;
+        }
+
+        if (unpack(sc, &loc, "pdd", &place, &x, &y)) {
+                rt_err("kern-obj-put-at: bad location args");
+                return sc->NIL;
+        }
+
+        if (!place) {
+                rt_err("kern-obj-put-at: null place");
+                return sc->NIL;
+        }
+
+        obj->relocate(place, x, y, REL_NOSTEP);
+        return sc->NIL;
+}
+
+static pointer kern_obj_relocate(scheme *sc, pointer args)
+{
+        class Object *obj;
+        struct place *place;
+        pointer cutscene;
+        int x, y;
+        struct closure *clx = NULL;
+
+        obj = unpack_obj(sc, &args, "kern-obj-relocate");
+        if (!obj)
+                return sc->NIL;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-obj-relocate"))
+                return sc->NIL;
+
+        if (unpack(sc, &args, "o", &cutscene)) {
+                rt_err("kern-obj-relocate: bad args");
+                return sc->NIL;
+        }
+
+        if (cutscene != sc->NIL) {
+                clx = closure_new_ref(sc, cutscene);
+        }
+
+        obj->relocate(place, x, y, REL_NOSTEP, clx);
+
+        closure_unref_safe(clx);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_get_location(scheme *sc, pointer args)
+{
+        class Object *obj;
+        struct place *place;
+        int x, y;
+
+        if (!(obj = unpack_obj(sc, &args, "kern-obj-get-location"))) {
+                assert(false);
+                return sc->NIL;
+        }
+
+        if ((place = obj->getPlace())) {
+                x = obj->getX();
+                y = obj->getY();
+                return pack(sc, "pdd", place, x, y);
+        }
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_get_dir(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int dx, dy;
+
+        if (!(obj = unpack_obj(sc, &args, "kern-obj-get-dir"))) {
+                assert(false);
+                return sc->NIL;
+        }
+
+        dx = obj->getDx();
+        dy = obj->getDy();
+
+        return pack(sc, "dd", dx, dy);
+}
+
+static pointer kern_place_get_location(scheme *sc, pointer args)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-location: bad args");
+                return sc->NIL;
+        }
+
+        if (! place) {
+                rt_err("kern-place-get-location: null place");
+                return sc->NIL;
+        }
+
+        if (! place->location.place)
+                return sc->NIL;
+
+        return pack(sc, "pdd", 
+                    place->location.place, 
+                    place->location.x, 
+                    place->location.y);
+}
+
+static int kern_append_effect(struct hook_entry *entry, void *data)
+{
+        pointer cell;
+        struct kern_append_info *info;
+
+        info = (struct kern_append_info *)data;
+
+        cell = scm_mk_ptr(info->sc, entry->effect);
+        cell = _cons(info->sc, cell, info->sc->NIL, 0);
+
+        if (info->head == info->sc->NIL) {
+                info->head = cell;
+                info->tail = cell;
+        } else {
+                info->tail->_object._cons._cdr = cell;
+                info->tail = cell;
+        }
+
+        return 0;
+}
+
+KERN_API_CALL(kern_obj_get_effects)
+{
+        class Object *obj;
+        int i;
+        struct kern_append_info info;
+
+        if (!(obj = unpack_obj(sc, &args, "kern-obj-get-effects"))) {
+                return sc->NIL;
+        }
+
+        /* initialize the context used by the callback to append objects */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = NULL;
+
+        /* for each effect hook on the object */
+        for (i = 0; i < OBJ_NUM_HOOKS; i++) {
+
+                /* build a scheme list of the attached effects */
+                obj->hookForEach(i, kern_append_effect, &info);
+        }
+
+        return info.head;
+}
+
+static pointer kern_obj_get_vision_radius(scheme *sc, pointer args)
+{
+        class Object *obj;
+
+        if (!(obj = unpack_obj(sc, &args, "kern-obj-get-location"))) {
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, obj->getVisionRadius());
+}
+
+static pointer kern_obj_put_into(scheme *sc, pointer args)
+{
+        class Object *obj;
+        class Object *container;
+
+        if (unpack(sc, &args, "pp", &obj,  &container)) {
+                load_err("kern-obj-put: bad args");
+                return sc->F;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-put: null obj");
+                return sc->F;
+        }
+
+        if (!container) {
+                rt_err("kern-obj-put: null container");
+                return sc->F;
+        }
+
+        return container->add(obj->getObjectType(), 
+                              obj->getCount()) ? sc->T : sc->F;
+
+}
+
+/*
+ * kern_obj_remove - remove an object from the map. Note that this implicitly
+ * destroys most objects automatically, unless the object has another reference
+ * count. Use kern_obj_inc_ref to prevent destruction during this call.
+ */
+static pointer kern_obj_remove(scheme *sc, pointer args)
+{
+        class Object *obj;
+
+        if (!(obj=unpack_obj(sc, &args, "kern-obj-remove"))) {
+                return sc->NIL;
+        }
+
+        /* Bugfix: don't use place_remove_object() because it doesn't call
+           setOnMap(false). */
+        //place_remove_object(obj->getPlace(), obj);
+        obj->remove();
+
+        return sc->NIL;
+}
+
+#if 0
+/*
+ * kern_obj_destroy - obsolete explicit destructor. Try to use kern_obj_dec_ref
+ * instead, wait and see if we really need this.
+ */
+static pointer kern_obj_destroy(scheme *sc, pointer args)
+{
+        class Object *obj;
+
+        if (!(obj=unpack_obj(sc, &args, "kern-obj-destroy"))) {
+                return sc->NIL;
+        }
+
+        delete obj;
+
+        return sc->NIL;
+}
+#endif
+
+static pointer kern_obj_inc_ref(scheme *sc, pointer args)
+{
+        class Object *obj;
+
+        if (!(obj=unpack_obj(sc, &args, "kern-obj-inc-ref"))) {
+                return sc->NIL;
+        }
+
+        obj_inc_ref(obj);
+
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_obj_dec_ref(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int refcount;
+
+        if (!(obj=unpack_obj(sc, &args, "kern-obj-dec-ref"))) {
+                return sc->NIL;
+        }
+
+        refcount = obj->refcount;
+        obj_dec_ref(obj);
+        
+        if (refcount > 1)
+                /* object was not destroyed - return it */
+                return scm_mk_ptr(sc, obj);
+
+        /* object was destroyed - return NIL */
+        return sc->NIL;
+}
+
+static pointer kern_obj_add_food(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int quantity;
+
+        if (unpack(sc, &args, "pd", &obj, &quantity)) {
+                load_err("kern-obj-add-food: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-add-food: null obj");
+                return sc->NIL;
+        }
+
+        if (! obj->addFood(quantity)) {
+                rt_err("kern-obj-add-food: '%s' does not use food",
+                       obj->getName());
+        }
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_add_gold(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int quantity;
+
+        if (unpack(sc, &args, "pd", &obj, &quantity)) {
+                load_err("kern-obj-add-gold: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-add-gold: null obj");
+                return sc->NIL;
+        }
+
+        if (! obj->addGold(quantity)) {
+                /* NPC's can't add gold (not even if they have containers)
+                 * because gold is not an object! Gold coins are, but that's
+                 * not what gets passed in here, is it? */
+                rt_err("kern-obj-add-gold: '%s' does not use gold",
+                       obj->getName());
+        }
+
+        return sc->NIL;
+}
+
+static pointer kern_mk_inventory(scheme *sc, pointer args)
+{
+        class Container *container;
+        pointer contents;
+
+        container = new Container();
+
+        /* contents */
+        contents = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+        while (contents != sc->NIL) {
+
+                int num;
+                class ObjectType *type;
+                pointer entry;
+
+                entry = scm_car(sc, contents);
+                contents = scm_cdr(sc, contents);
+
+                if (! scm_is_pair(sc, entry)) {
+                        load_err("kern-mk-inventory: error in inv list "\
+                                 "(not a pair)");
+                        goto abort;
+                }
+
+                if (unpack(sc, &entry, "dp", &num, &type)) {
+                        load_err("kern-mk-inventory: error in inv list");
+                        goto abort;
+                }
+
+                container->add(type, num);
+        }
+
+        /* hooks */
+        if (kern_load_hooks(sc, scm_car(sc, args), container)) {
+                load_err("kern-mk-inventory: error in hook list");
+                goto abort;
+        }
+        args = scm_cdr(sc, args);
+
+        return scm_mk_ptr(sc, container);
+        
+ abort:
+        delete container;
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_player)
+{
+        int food, gold, ttnm;
+        char *mv_desc, *tag;
+        sound_t *mv_sound;
+        struct sprite *sprite;
+        struct terrain_map *campsite;
+        struct formation *form, *camp_form;
+        class Container *inventory;
+        Vehicle *vehicle;
+        pointer members;
+        pointer ret;
+
+        if (unpack(sc, &args, "ypspdddppppp", 
+                   &tag,
+                   &sprite,
+                   &mv_desc, &mv_sound,
+                   &food, &gold, &ttnm,
+                   &form, &campsite, &camp_form, 
+                   &vehicle, 
+                   &inventory)) {
+                load_err("kern-mk-player: bad args");
+                return sc->NIL;
+        }
+
+        if (! inventory) {
+                load_err("kern-mk-player: nil inventory container");
+                return sc->NIL;
+        }
+
+        //members = scm_car(sc, scm_cdr(sc, args));
+        members = scm_car(sc, args);
+
+        player_party = new class PlayerParty(tag, sprite, 
+                                              mv_desc, 
+                                              mv_sound,
+                                              food, gold, form, 
+                                              campsite, 
+                                              camp_form);
+        player_party->setInventoryContainer(inventory);
+        player_party->setTurnsToNextMeal(ttnm);
+
+        /* Load the members. */
+        while (scm_is_pair(sc, members)) {
+
+                class Character *ch;
+
+                if (unpack(sc, &members, "p", &ch)) {
+                        load_err("kern-mk-player: error in member list");
+                        goto abort;
+                }
+
+                if (!ch) {
+                        load_err("kern-mk-player: null member object");
+                        goto abort;
+                }
+
+                if (! player_party->addMember(ch)) {
+                        load_err("kern-mk-player: failed to add %s to player "
+                                 "party", ch->getName());
+                        goto abort;
+                }
+        }
+
+        /* Board the vehicle */
+        if (vehicle) {
+
+                /* This sets the vehicle's occupant, too. */
+                player_party->setVehicle(vehicle);
+
+                /* bugfix: party unrefs vehicle when it disembarks; needs to
+                 * keep a refcount while boarded */
+                obj_inc_ref(vehicle);
+        }
+
+        session_add_obj(Session, player_party, player_dtor, player_save, NULL);
+        ret = scm_mk_ptr(sc, player_party);
+        scm_define(sc, tag, ret);
+        return ret;
+
+ abort:
+        delete player_party;
+        player_party = 0;
+        return sc->NIL;
+}
+
+static void sched_dtor(void *data)
+{
+        sched_del((struct sched *)data);
+}
+
+static void effect_dtor(void *data)
+{
+        effect_del((struct effect *)data);
+}
+
+static pointer kern_mk_sched(scheme *sc, pointer args)
+{
+        struct sched *sched;
+        char *tag;
+        char *activity;
+        int n_appts;
+        int i;
+        pointer ret;
+
+        /* unpack the tag */
+        if (unpack(sc, &args, "y", &tag)) {
+                load_err("kern-mk-sched: bad args");
+                return sc->NIL;
+        }
+
+        /* count the number of appointments */
+        n_appts = scm_len(sc, args);
+
+        /* alloc the schedule */
+        sched = sched_new(tag, n_appts);
+        sched->sc = sc;
+        
+        /* loop, adding the appointments to the schedule */
+        for (i = 0; i < n_appts; i++) {
+                struct appt *appt = &sched->appts[i];
+                pointer p = scm_car(sc, args);
+                pointer rect;
+                args = scm_cdr(sc, args);
+
+                if (unpack(sc, &p, "dd", &appt->hr, &appt->min, &activity)) {
+                        load_err("kern-mk-sched %s: bad args in appt %d time",
+                                 tag, i);
+                        goto abort;
+                }
+
+                rect = scm_car(sc, p);
+                p = scm_cdr(sc, p);
+
+                if (unpack(sc, &rect, "cdddd", &appt->place_sym, 
+                           &appt->x, &appt->y, 
+                           &appt->w, &appt->h)) {
+                        load_err("kern-mk-sched %s: bad args in appt %d rect",
+                                 tag, i);
+                        goto abort;
+                }
+
+                if (unpack(sc, &p, "s", &activity)) {
+                        load_err("kern-mk-sched %s: bad args in appt %d activity",
+                                 tag, i);
+                        goto abort;
+                }
+
+                appt->act = sched_name_to_activity(activity);
+                if (appt->act < 0) {
+                        load_err("kern-mk-sched %d: unknown activity name %s",
+                                 tag, activity);
+                        goto abort;
+                }
+        }
+
+        session_add(Session, sched, sched_dtor, 0, NULL);
+        ret = scm_mk_ptr(sc, sched);
+        scm_define(sc, tag, ret);
+        return ret;
+
+ abort:
+        sched_del(sched);
+        return sc->NIL;
+}
+
+static pointer kern_interp_error(scheme *sc, pointer args)
+{
+        load_err("interpreter error");
+        return sc->NIL;
+}
+
+static pointer kern_include(scheme *sc, pointer args)
+{
+        char *fname;
+
+        if (unpack(sc, &args, "s", &fname)) {
+                load_err("kern-include: bad args");
+                return sc->NIL;
+        }
+
+        session_add(Session, strdup(fname), incfile_dtor, incfile_save, NULL);
+        Session->num_kern_includes++;
+        return sc->NIL;
+}
+
+
+static pointer kern_set_crosshair(scheme *sc, pointer args)
+{
+        if (unpack(sc, &args, "p", &Session->crosshair_type)) {
+                load_err("kern-set-crosshair: bad args");
+        }
+        return sc->NIL;
+}
+
+
+static pointer kern_set_damage_sprite(scheme *sc, pointer args)
+{
+        if (unpack(sc, &args, "p", &Session->damage_sprite)) {
+                load_err("kern-set-damage-sprite: bad args");
+        }
+        return sc->NIL;
+}
+
+static pointer kern_set_clock(scheme *sc, pointer args)
+{
+        if (unpack(sc, &args, "dddddd",
+                   &Session->clock.year,
+                   &Session->clock.month,
+                   &Session->clock.week,
+                   &Session->clock.day,
+                   &Session->clock.hour,
+                   &Session->clock.min)) {
+                load_err("kern-set-clock: bad args");
+                return sc->NIL;
+        }
+
+        if (Session->clock.month  >= MONTHS_PER_YEAR ||
+            Session->clock.week   >= WEEKS_PER_MONTH ||
+            Session->clock.day    >= DAYS_PER_WEEK   ||
+            Session->clock.hour   >= HOURS_PER_DAY   ||
+            Session->clock.min    >= MINUTES_PER_HOUR) {
+                load_err("kern-set-clock: invalid time");
+                return sc->NIL;
+        }
+
+        Session->clock.total_minutes = 
+                Session->clock.min +
+                Session->clock.hour * MINUTES_PER_HOUR +
+                Session->clock.day * MINUTES_PER_DAY +
+                Session->clock.week * MINUTES_PER_WEEK +
+                Session->clock.month * MINUTES_PER_MONTH;
+        Session->clock.tick_to_change_time = CLOCK_TICKS_PER_MINUTE;
+        Session->clock.set = 1;
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_apply_damage(scheme *sc, pointer args)
+{
+        class Object *obj;
+        char *desc;
+        int amount;
+
+        if (unpack(sc, &args, "psd", &obj, &desc, &amount)) {
+                rt_err("kern-obj-inflict-damage: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-inflict-damage: null object");
+                return sc->NIL;
+        }
+
+        obj->damage(amount);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_inflict_damage(scheme *sc, pointer args)
+{
+        class Object *obj;
+        char *desc;
+        int amount;
+               class Character *attacker;
+
+        if (unpack(sc, &args, "psdp", &obj, &desc, &amount, &attacker)) {
+                rt_err("kern-obj-apply-damage: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-apply-damage: null object");
+                return sc->NIL;
+        }
+
+        obj->inflictDamage(amount,attacker);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_add_effect(scheme *sc, pointer args)
+{
+        class Object *obj;
+        struct effect *effect = NULL;
+        pointer gobcell;
+        struct gob *gob = NULL;
+
+        if (unpack(sc, &args, "ppl", &obj, &effect, &gobcell)) {
+                rt_err("kern-obj-add-effect: bad args");
+                return sc->F;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-add-effect: null object");
+                return sc->F;
+        }
+
+        if (! is_effect(effect)) {
+                rt_err("kern-obj-remove-effect: wrong type for effect!");
+                return sc->F;
+        }
+
+        /* Note: even if gobcell is sc->NIL we want to wrap it. I once tried to
+         * use a NULL gob instead but if we pass that back into scheme as an
+         * arg and the gc tries to mark it we'll crash. */
+        gob = gob_new(sc, gobcell);
+        gob->flags |= GOB_SAVECAR;
+
+        return obj->addEffect(effect, gob) ? sc->T : sc->F;
+}
+
+static pointer kern_obj_remove_effect(scheme *sc, pointer args)
+{
+        class Object *obj;
+        struct effect *effect;
+
+        if (unpack(sc, &args, "pp", &obj, &effect)) {
+                load_err("kern-obj-remove-effect: bad args");
+                return sc->F;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-remove-effect: null object");
+                return sc->F;
+        }
+
+        if (! is_effect(effect)) {
+                rt_err("kern-obj-remove-effect: wrong type for effect!");
+                return sc->F;
+        }
+
+        /* Just remove one per call */
+        return obj->removeEffect(effect) ? sc->T : sc->F;
+}
+
+static pointer kern_print(scheme *sc,  pointer args)
+{
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+
+                if (scm_is_str(sc, val)) {
+                        consolePrint(scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        consolePrint("%d", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        consolePrint("%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-print: bad args");
+                }
+        }
+
+        return sc->NIL;
+}
+
+static pointer kern_log_msg(scheme *sc,  pointer args)
+{
+        log_begin(NULL);
+
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+
+                if (scm_is_str(sc, val)) {
+                        log_continue(scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        log_continue("%d", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        log_continue("%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-log-msg: bad args");
+                }
+        }
+
+        log_end(NULL);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_log_begin)
+{
+        log_begin(NULL);
+
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+
+                if (scm_is_str(sc, val)) {
+                        log_continue(scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        log_continue("%d", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        log_continue("%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-log-begin: bad args");
+                }
+        }
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_log_end)
+{
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+
+                if (scm_is_str(sc, val)) {
+                        log_continue(scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        log_continue("%d", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        log_continue("%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-log-end: bad args");
+                }
+        }
+
+        log_end(NULL);
+
+        return sc->NIL;
+}
+
+static pointer kern_log_continue(scheme *sc,  pointer args)
+{
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+
+                if (scm_is_str(sc, val)) {
+                        log_continue(scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        log_continue("%d", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        log_continue("%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-log-continue: bad args");
+                }
+        }
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_log_flush)
+{
+        log_flush();
+        return sc->T;
+}
+
+static pointer kern_stdout_msg(scheme *sc,  pointer args)
+{
+
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+
+                if (scm_is_str(sc, val)) {
+                        fprintf(stdout,"%s",scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        fprintf(stdout,"%ld",scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        fprintf(stdout,"%f",scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-print: bad args");
+                }
+        }
+               fprintf(stdout,"\n");
+               
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_log_enable)
+{
+        int val;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern_log_enable: bad args");
+                return sc->F;
+        }
+
+        if (val)
+                log_enable();
+        else
+                log_disable();
+
+        return sc->T;
+}
+
+static pointer kern_conv_say(scheme *sc,  pointer args)
+{
+        class Character *speaker;
+        struct conv *conv;
+
+        if (unpack(sc, &args, "p", &speaker)) {
+                rt_err("kern-conv-say: bad args");
+                return sc->NIL;
+        }
+
+        if (speaker == NULL) {
+                rt_err("kern-conv-say: null speaker");
+                return sc->NIL;
+        }
+
+        if (!(conv = speaker->getConversation())) {
+                rt_err("%s() no conv for %s", __FUNCTION__, speaker->getName());
+                return sc->NIL;
+        }
+        
+        if (speaker->isKnown()) {
+                log_begin("^c+%c%s:^c- ", CONV_NPC_COLOR, speaker->getName());
+        } else {
+                log_begin("^c+%c", CONV_NPC_COLOR);
+                speaker->describe();
+                log_continue(":^c- ");
+        }
+
+        args = scm_car(sc, args);
+
+        while (scm_is_pair(sc, args)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+                if (scm_is_str(sc, val)) {
+                        char *beg, *end, *text = scm_str_val(sc, val);
+                        while (text) {
+                                if (! conv_get_word(text, &beg, &end)) {
+                                        log_continue(text);
+                                        text = NULL;
+                                } else {
+                                        int keyword = conv_is_keyword(conv, beg);
+                                        if (text<beg) {
+                                                do {
+                                                        log_continue("%c", *text);
+                                                        text++;
+                                                } while (text<beg);
+                                        }
+                                        if (keyword) {
+                                                char color = (keyword & CONV_IS_MARKED) ? 'G' : 'm';
+                                                log_continue("^c+%c", color);
+                                        }
+                                        while (beg<end) {
+                                                log_continue("%c", *beg);
+                                                beg++;
+                                        }
+                                        if (keyword) {
+                                                log_continue("^c-");
+                                        }
+                                        text = end;
+                                }
+                        }
+                } else if (scm_is_int(sc, val)) {
+                        log_continue("%d", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        log_continue("%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("kern-print: bad args");
+                }
+        }
+
+        log_end(NULL);
+
+        return sc->NIL;
+}
+
+static pointer kern_conv_get_yes_no(scheme *sc,  pointer args)
+{
+        Object *pc = unpack_obj(sc, &args, "kern-conv-get-yes-no?");
+        if (NULL == pc)
+                return sc->F;
+        return ui_get_yes_no(pc->getName()) ? sc->T : sc->F;
+}
+
+static pointer kern_conv_get_amount(scheme *sc,  pointer args)
+{
+        cmdwin_clear();
+        cmdwin_spush("How much");
+        return scm_mk_integer(sc, ui_get_quantity(-1));
+}
+
+static pointer kern_conv_get_reply(scheme *sc,  pointer args)
+{
+        char buf[32];
+
+        Object *pc = unpack_obj(sc, &args, "kern-conv-get-reply");
+        if (NULL == pc)
+                return sc->F;
+
+        ui_getline(buf, sizeof(buf));
+        log_msg("^c+%c%s:^c- %s", CONV_PC_COLOR, pc->getName(), buf);
+
+        /* Return only the first four characters, to be consistent with the
+         * usual keyword/reply scheme. */
+        buf[4] = 0;
+
+        return scm_mk_symbol(sc, buf);
+}
+
+static pointer kern_conv_get_string(scheme *sc,  pointer args)
+{
+        char buf[32];
+
+        Object *pc = unpack_obj(sc, &args, "kern-conv-get-string");
+        if (NULL == pc)
+                return sc->F;
+
+        ui_getline(buf, sizeof(buf));
+        log_msg("%s: %s", pc->getName(), buf);
+
+        return scm_mk_string(sc, buf);
+}
+
+static pointer kern_conv_trade(scheme *sc, pointer args)
+{
+        Object *npc;
+        Object *pc;
+        struct merchant merch;
+        int i, traded = 0;
+        char *menu = 0;
+        pointer catalog = sc->NIL;
+
+        if (unpack(sc, &args, "pps", &npc, &pc, &menu)) {
+                rt_err("kern-conv-trade: bad args");
+                return sc->NIL;
+        }
+
+        if (! npc || ! pc) {
+                rt_err("kern-conv-trade: null kernel object(s)");
+                return sc->NIL;
+        }
+
+        /* Get the catalog */
+        if (! scm_is_pair(sc, args)) {
+                rt_err("kern-conv-trade: no catalog!");
+                return sc->NIL;
+        }
+        catalog = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+        if (! scm_is_pair(sc, catalog)) {
+                rt_err("kern-conv-trade: catalog is not a list");
+                return sc->NIL;
+        }
+        
+        /* setup the merchant struct */
+        merch.name = npc->getName();
+        merch.n_trades = scm_len(sc, catalog);
+        if (! merch.n_trades) {
+                rt_err("kern-conv-trade: nothing in trade list");
+                return sc->NIL;
+        }
+        merch.trades = (struct trade_info*)calloc(merch.n_trades, 
+                                                 sizeof(struct trade_info));
+        assert(merch.trades);
+
+        /* fill out the merchant's item list */
+        for (i = 0; i < merch.n_trades; i++) {
+
+                ObjectType *type;
+                pointer p = scm_car(sc, catalog);
+                struct trade_info *trade = &merch.trades[i];
+                catalog = scm_cdr(sc, catalog);
+
+                if (unpack(sc, &p, "pds", &type, &trade->cost, &trade->sales_pitch)) {
+                        rt_err("kern-conv-trade: bad args in trade list %d", i);
+                        goto abort;
+                }
+
+                if (! type) {
+                        rt_err("kern-conv-trade: null object type in trade list %d", i);
+                        goto abort;
+                }
+
+                /* This is kind of dumb. We should just point to the ObjectType
+                 * and be done with it. */
+                trade->sprite = type->getSprite();
+                trade->name = type->getName();
+                trade->data = type;
+                trade->quantity = player_party->inventory->numAvail(type);
+                trade->show_sprite = 1;
+                trade->show_quantity = 1;
+        }
+
+        if (! strcmp(menu, "buy")) {
+                traded = ui_buy(&merch);
+        } else if (! strcmp(menu, "sell")) {
+                traded = ui_sell(&merch);
+        } else {
+                traded = ui_trade(&merch);
+        }
+
+ abort:
+        free(merch.trades);
+        return traded ? sc->T : sc->F;
+}
+
+static pointer kern_obj_get_activity(scheme *sc, pointer args)
+{
+        class Object *obj = unpack_obj(sc, &args, "kern-obj-get-activity");
+        if (obj == NULL)
+                return sc->NIL;
+
+        return scm_mk_string(sc, 
+                             sched_activity_to_name(obj->getActivity()));
+}
+
+static pointer kern_obj_set_sprite(scheme *sc, pointer args)
+{
+        class Object *obj;
+        struct sprite *sprite;
+
+        if (unpack(sc, &args, "pp", &obj, &sprite)) {
+                rt_err("kern-obj-set-sprite: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-sprite: null object");
+                return sc->NIL;
+        }
+
+        obj->setSprite(sprite);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_set_opacity(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int opacity;
+
+        if (unpack(sc, &args, "pb", &obj, &opacity)) {
+                rt_err("kern-obj-set-opacity: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-opacity: null object");
+                return sc->NIL;
+        }
+
+        obj->setOpacity(opacity != 0);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_set_ap(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int ap;
+
+        if (unpack(sc, &args, "pd", &obj, &ap)) {
+                rt_err("kern-obj-set-ap: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-ap: null object");
+                return sc->NIL;
+        }
+
+        obj->setActionPoints(ap);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_set_facing(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int facing;
+
+        if (unpack(sc, &args, "pd", &obj, &facing)) {
+                rt_err("kern-obj-set-facing: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-facing: null object");
+                return sc->NIL;
+        }
+
+        obj->setFacing(facing);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_get_facing(scheme *sc, pointer args)
+{
+        class Object *obj;
+
+        if (unpack(sc, &args, "p", &obj)) {
+                rt_err("kern-obj-get-facing: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-get-facing: null object");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, obj->getFacing());
+}
+
+static pointer kern_obj_set_conv(scheme *sc, pointer args)
+{
+        class Object *obj;
+        pointer conv;
+
+        if (unpack(sc, &args, "pc", &obj, &conv)) {
+                rt_err("kern-obj-set-conv: bad args");
+                return sc->NIL;
+        }
+
+        if (conv == sc->NIL) {
+                obj->setConversation(NULL);
+        } else {
+                kern_load_conv(sc, conv, obj);
+        }
+
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_char_set_known(scheme *sc, pointer args)
+{
+        class Character *ch;
+        int val;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-known");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-char-set-known: bad args");
+                return sc->NIL;
+        }
+
+        ch->setKnown(val);
+        return scm_mk_ptr(sc, ch);
+}
+
+static pointer kern_obj_set_visible(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int val;
+
+        if (unpack(sc, &args, "pb", &obj, &val)) {
+                rt_err("kern-obj-set-visible: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-visible: null object");
+                return sc->NIL;
+        }
+
+        obj->setVisible(val);
+
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_obj_set_submerged(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int val;
+
+        if (unpack(sc, &args, "pb", &obj, &val)) {
+                rt_err("kern-obj-set-submerged: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-submerged: null object");
+                return sc->NIL;
+        }
+
+        obj->setSubmerged(val);
+
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_obj_set_pclass(scheme *sc, pointer args)
+{
+        class Object *obj;
+        int val;
+
+        if (unpack(sc, &args, "pd", &obj, &val)) {
+                rt_err("kern-obj-set-pclass: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-pclass: null object");
+                return sc->NIL;
+        }
+
+        obj->setPclass(val);
+
+        return sc->NIL;
+}
+
+static pointer kern_obj_get_type(scheme *sc, pointer  args)
+{
+        Object *obj;
+
+        if (!(obj = unpack_obj(sc, &args, "kern-obj-get-type")))
+                return sc->NIL;
+
+        return scm_mk_ptr(sc, obj->getObjectType());
+}
+
+static pointer kern_place_map(scheme *sc, pointer args)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-map: bad args");
+                return sc->NIL;
+        }
+
+        if (! place || ! place->terrain_map) {
+                rt_err("kern-place-map: null place or map");
+                return sc->NIL;
+        }
+
+        return scm_mk_ptr(sc, place->terrain_map);
+}
+
+KERN_API_CALL(kern_place_synch)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-synch: bad args");
+                return sc->NIL;
+        }
+
+        if (! place) {
+                rt_err("kern-place-synch: null place");
+                return sc->NIL;
+        }
+        place_synchronize(place);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_place_is_visible)
+{
+       struct place *place;
+       int x, y;
+       
+       if (unpack_loc(sc, &args, &place, &x, &y, "kern_place_is_visible"))
+               return sc->NIL;
+       
+       if (! place) {
+               rt_err("kern_place_is_visible: null place");
+               return sc->NIL;
+       }
+       
+       // the player party doesnt wind up being in a temporary combat map,
+       // but by its existance we can infer the player is there
+       if (!place_is_wilderness_combat(place) && place != player_party->getPlace())
+       {
+               return sc->F;   
+       }
+       
+       if (mapTileIsVisible(x,y) && (mapTileLightLevel(x,y) >= MIN_XAMINE_LIGHT_LEVEL))
+       {
+               return sc->T;   
+       }
+       else
+       {
+               return sc->F;   
+       }
+}
+
+KERN_API_CALL(kern_place_is_combat_map)
+{
+       struct place *place;
+       
+  if (unpack(sc, &args, "p", &place)) {
+       rt_err("kern_place_is_combat_map: bad args");
+       return sc->NIL;
+   }
+   
+       if (! place) {
+               rt_err("kern_place_is_combat_map: null place");
+               return sc->NIL;
+       }
+       
+       if (place_is_wilderness_combat(place))
+       {
+               return sc->T;   
+       }
+       else
+       {
+               return sc->F;   
+       }
+}
+
+static pointer kern_blit_map(scheme *sc, pointer args)
+{
+        struct terrain_map *src;
+        struct terrain_map *dst;
+        int dst_x;
+        int dst_y;
+        int src_x;
+        int src_y;
+        int w;
+        int h;
+
+        if (unpack(sc, &args, "pddpdddd", &dst, &dst_x, &dst_y, 
+                   &src, &src_x, &src_y, &w, &h)) {
+                rt_err("kern-blit-map: bad args");
+                return sc->NIL;
+        }
+
+        if (! dst || ! src) {
+                rt_err("kern-blit-map: null src or dst map");
+                return sc->NIL;
+        }
+
+        terrain_map_blit(dst, dst_x, dst_y, src, src_x, src_y, w, h);
+
+        vmask_flush_all();
+
+
+        /* Return the modified destination map */
+        return scm_mk_ptr(sc, dst);
+}
+
+static pointer kern_map_rotate(scheme *sc, pointer args)
+{
+        struct terrain_map *map;
+        int degree;
+
+        if (unpack(sc, &args, "pd", &map, &degree)) {
+                rt_err("kern-map-rotate: bad args");
+                return sc->NIL;
+        }
+
+        if (! map) {
+                rt_err("kern-map-rotate: null map");
+                return sc->NIL;
+        }
+
+        terrain_map_rotate(map, degree);
+
+        /* Return the modified map */
+        return scm_mk_ptr(sc, map);
+}
+
+
+static pointer kern_map_flash_sprite(scheme *sc, pointer args)
+{
+       int x, y;
+       struct sprite *sprite;
+       
+       if (unpack(sc, &args, "pdd", &sprite, &x, &y)) {
+               rt_err("kern_map_flash_sprite: bad args");
+               return sc->NIL;
+       }
+       
+       if (!sprite) {
+               rt_err("kern_map_flash_sprite: null sprite");
+               return sc->NIL;
+       }
+       
+       if (mapTileLightLevel(x,y) < MIN_XAMINE_LIGHT_LEVEL || (!mapTileIsVisible(x,y)))
+       {
+               return sc->NIL;   
+       }
+       
+       mapFlashSprite(x, y, sprite);
+       
+       return sc->NIL;
+}
+
+static pointer kern_tag(scheme *sc, pointer  args)
+{
+        char *tag;
+        Object *obj;
+        pointer p;
+
+        if (unpack(sc, &args, "y", &tag)) {
+                rt_err("kern-tag: bad args");
+                return sc->NIL;
+        }
+
+        if (! scm_is_pair(sc, args)) {
+                rt_err("kern-tag %s: no second arg", tag);
+                return sc->NIL;
+        }
+
+        p = scm_car(sc, args);
+        scm_define(sc, tag, p);
+
+        if (unpack(sc, &args, "p", &obj)) {
+                rt_err("kern-tag: bad object");
+                return sc->NIL;
+        }
+
+        /* Tagged objects may be referred to in the script by their
+         * tag. If the object is destroyed, the scheme variable that
+         * refers to the object is still valid (in Scheme, it isn't
+         * really possible to undefine variables). To prevent crashes
+         * on dereferencing this variable we'll bump the refcount. To
+         * ensure the object is destroyed on session teardown, we'll
+         * mark it for custom finalization, which will decrement the
+         * extra refcount. */
+        obj_inc_ref(obj);
+        scm_set_cust_fin(sc, p);
+
+        obj->tag = strdup(tag);
+        assert(obj->tag);
+
+        return p;
+}
+
+static pointer kern_obj_get_gob(scheme *sc, pointer  args)
+{
+        Object *obj;
+
+        if (unpack(sc, &args, "p", &obj)) {
+                rt_err("kern-obj-get-gob: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-get-gob: null obj");
+                return sc->NIL;
+        }
+
+        if (obj->getGob() == NULL) {
+                return sc->NIL;
+        }
+
+        // It's already a scheme pointer so just return it directly
+        return obj->getGob()->p;
+}
+
+static pointer kern_obj_set_gob(scheme *sc, pointer  args)
+{
+        Object *obj;
+
+        if (! (obj = unpack_obj(sc, &args, "kern-obj-set-gob"))) {
+                return sc->NIL;
+        }
+
+        if (! scm_is_pair(sc, args)) {
+               rt_err("kern-obj-set-gob: no gob specified");
+               return sc->NIL;
+        }
+
+       obj->setGob(gob_new(sc, scm_car(sc, args)));
+
+       return sc->NIL;
+}
+
+static pointer kern_obj_set_ttl(scheme *sc, pointer  args)
+{
+        Object *obj;
+        int ttl;
+
+        if (! (obj = unpack_obj(sc, &args, "kern-obj-set-ttl"))) {
+                goto done;
+        }
+
+        if (unpack(sc, &args, "d", &ttl)) {
+               rt_err("kern-obj-set-ttl: bad ttl");
+               goto done;
+        }
+
+        Object::setTTL(obj, ttl);
+ done:
+        return scm_mk_ptr(sc, obj);
+}
+
+static pointer kern_astral_body_get_gob(scheme *sc, pointer  args)
+{
+        struct astral_body *astral_body;
+
+        if (unpack(sc, &args, "p", &astral_body)) {
+                rt_err("kern-astral-body-get-gob: bad args");
+                return sc->NIL;
+        }
+
+        if (! astral_body) {
+                rt_err("kern-astral-body-get-gob: null object");
+                return sc->NIL;
+        }
+
+        if (astral_body->gob == NULL) {
+                rt_err("kern-astral-body-get-gob: no gob for %s", 
+                       astral_body->name);
+                return sc->NIL;
+        }
+
+        // It's already a scheme pointer so just return it directly
+        return astral_body->gob->p;
+}
+
+static pointer kern_astral_body_get_phase(scheme *sc, pointer  args)
+{
+        struct astral_body *astral_body;
+
+        if (unpack(sc, &args, "p", &astral_body)) {
+                rt_err("kern-astral-body-get-phase: bad args");
+                return sc->NIL;
+        }
+
+        if (! astral_body) {
+                rt_err("kern-astral-body-get-phase: null object");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, astral_body->phase);
+}
+
+static pointer kern_astral_body_set_gob(scheme *sc, pointer  args)
+{
+        struct astral_body *astral_body;
+
+        if (unpack(sc, &args, "p", &astral_body)) {
+                rt_err("kern-astral-body-set-gob: bad args");
+                return sc->NIL;
+        }
+
+        if (! astral_body) {
+                rt_err("kern-astral-body-set-gob: null object");
+                return sc->NIL;
+        }
+
+        if (! scm_is_pair(sc, args)) {
+               rt_err("kern-astral-body-set-gob: no gob specified");
+               return sc->NIL;
+        }
+
+       astral_body->gob = (gob_new(sc, scm_car(sc, args)));
+
+       return sc->NIL;
+}
+
+static pointer kern_type_get_gifc(scheme *sc, pointer  args)
+{
+        ObjectType *cptr;
+        closure_t *gifc;
+
+        if (unpack(sc, &args, "p", &cptr)) {
+                rt_err("kern-type-get-gifc: bad args");
+                return sc->NIL;
+        }
+
+        if (cptr == NULL) {
+                /* This is not necessarily an error. Some objects (like
+                 * characters) have no type, which can result in us getting
+                 * here. */
+                return sc->NIL;
+        }
+
+        gifc = cptr->getGifc();
+
+        return gifc ? gifc->code : sc->NIL;
+}
+
+static pointer kern_type_get_name(scheme *sc, pointer  args)
+{
+        ObjectType *cptr;
+
+        if (unpack(sc, &args, "p", &cptr)) {
+                rt_err("kern-type-get-name: bad args");
+                return sc->NIL;
+        }
+
+        if (cptr == NULL) {
+                /* This is not necessarily an error. Some objects (like
+                 * characters) have no type, which can result in us getting
+                 * here. */
+                return sc->NIL;
+        }
+
+        return scm_mk_string(sc, cptr->getName());
+}
+
+static pointer kern_type_describe(scheme *sc, pointer  args)
+{
+        ObjectType *cptr;
+
+        if (unpack(sc, &args, "p", &cptr)) {
+                rt_err("kern-type-get-name: bad args");
+                return sc->NIL;
+        }
+
+        if (cptr == NULL) {
+                /* This is not necessarily an error. Some objects (like
+                 * characters) have no type, which can result in us getting
+                 * here. */
+                return sc->NIL;
+        }
+
+        cptr->describeType(1);
+        return sc->NIL;
+}
+
+static pointer kern_add_tick_job(scheme *sc, pointer args)
+{
+        int tick;
+        pointer proc;
+        void *data;
+
+        if (unpack(sc, &args, "dop", &tick, &proc, &data)) {
+                rt_err("kern-add-tick-job: bad args");
+                return sc->NIL;
+        }
+
+        wqCreateJob(&TickWorkQueue, Tick + tick, 0, 
+                    kjob_new(data, closure_new(sc, proc)), 
+                    kern_run_wq_job);
+
+        return sc->NIL;
+}
+
+static pointer kern_ui_select_party_member(scheme *sc, pointer args)
+{
+        class Character *member;
+
+        member = select_party_member();
+        cmdwin_pop();
+        if (! member) {
+                return sc->NIL;
+        }
+        return scm_mk_ptr(sc, member);
+}
+
+static pointer kern_conv_end(scheme *sc, pointer args)
+{
+        conv_end();
+        return sc->T;
+}
+
+
+static pointer kern_conv_begin(scheme *sc, pointer args)
+{
+        class Character *npc, *member;
+        struct conv *conv;
+
+        if (unpack(sc, &args, "p", &npc)) {
+                rt_err("kern-conv-begin: bad args");
+                return sc->F;
+        }
+
+        conv = npc->getConversation();
+        if (! conv) {
+                rt_err("kern-conv-begin: npc has no conv!");
+                return sc->F;                
+        }
+
+        member = player_party->get_leader();
+        if (! member) {
+                rt_err("kern-conv-begin: no player party leader!");
+                return sc->F;                
+        }
+
+       log_begin("You are accosted by ");
+        Session->subject = player_party;
+       npc->describe();
+        Session->subject = NULL;
+       log_end(".");
+
+        conv_enter(npc, member, conv);
+
+        return sc->T;
+}
+
+static pointer kern_map_set_dirty(scheme *sc, pointer args)
+{
+        mapSetDirty();
+        return sc->T;
+}
+
+static pointer kern_mk_astral_body(scheme *sc, pointer args)
+{
+        struct astral_body *body;
+        char *tag;
+        char *name;
+        int minutes_per_phase;
+        int minutes_per_degree;
+        int initial_arc;
+        int initial_phase;
+        int distance;
+        pointer proc;
+        pointer phases;
+        pointer ret;
+        int i;
+
+        if (unpack(sc, &args, "ysdddddc", 
+                   &tag,
+                   &name,
+                   &distance,
+                   &minutes_per_phase,
+                   &minutes_per_degree,
+                   &initial_arc,
+                   &initial_phase,
+                   &proc)) {
+                load_err("kern-mk-astral-body: bad args");
+                return sc->NIL;
+        }
+
+        if (! scm_is_pair(sc, args)) {
+                load_err("kern-mk-astral-body: null phase list");
+                return sc->NIL;
+        }
+
+        phases = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        body = astral_body_new(tag, name, scm_len(sc, phases));
+        body->distance = distance;
+        body->minutes_per_phase = minutes_per_phase;
+        body->minutes_per_degree = minutes_per_degree;
+        body->initial_arc = initial_arc;
+        body->initial_phase = initial_phase;
+        body->arc = initial_arc;
+        body->phase = initial_phase;
+
+        if (proc != sc->NIL)
+                body->gifc = closure_new_ref(sc, proc);
+
+        i = 0;
+        while (scm_is_pair(sc, phases)) {
+                pointer phase = scm_car(sc, phases);
+                phases = scm_cdr(sc, phases);
+                char *phase_name = NULL;
+
+                if (unpack(sc, &phase, "pds", 
+                           &body->phases[i].sprite,
+                           &body->phases[i].maxlight,
+                           &phase_name)) {
+                        load_err("kern-mk-astral-body: bad args in phase "\
+                                 "list at entry %d", i);
+                        goto abort;
+                }
+                if (! phase_name) {
+                        load_err("kern-mk-astral-body %s: null phase name",
+                                 body->tag);
+                        goto abort;
+                }
+                body->phases[i].name = strdup(phase_name);
+                assert(body->phases[i].name);
+                i++;
+        }
+
+        /* Like types, I define astral bodies in the script so they can be
+         * referred to by their tags as script variables. I do this because a)
+         * kern-obj-tag won't work on them, so I need some other way to tag
+         * them, and b) they are unique enough that it won't hurt to just
+         * automatically make them variables. */
+        sky_add_astral_body(&Session->sky, body);        
+        ret = scm_mk_ptr(sc, body);
+        scm_define(sc, tag, ret);
+
+        return ret;
+
+ abort:
+        astral_body_del(body);
+        return sc->NIL;
+        
+}
+
+KERN_API_CALL(kern_mk_vehicle_type)
+{
+        VehicleType *type;
+        const char *tag = TAG_UNK;
+        char *name;
+        struct sprite *sprite;
+        struct terrain_map *map;
+        ArmsType *ordnance;
+        int vulnerable;
+        int killsOccupants;
+        int mustTurn;
+        char *mv_desc;
+        sound_t *mv_sound;
+        int tailwind_penalty;
+        int headwind_penalty;
+        int crosswind_penalty;
+        int max_hp;
+        int speed;
+        pointer ret;
+        struct mmode *mmode;
+                 pointer proc;        
+
+        if (unpack(sc, &args, "yspppbbbspdddddpo",
+                   &tag,
+                   &name,
+                   &sprite,
+                   &map,
+                   &ordnance,
+                   &vulnerable,
+                   &killsOccupants,
+                   &mustTurn,
+                   &mv_desc,
+                   &mv_sound,
+                   &tailwind_penalty,
+                   &headwind_penalty,
+                   &crosswind_penalty,
+                   &max_hp,
+                   &speed,
+                   &mmode,
+                   &proc
+                    )) {
+                load_err("kern-mk-vehicle-type %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        type = new VehicleType(tag,
+                               name,
+                               sprite,
+                               map,
+                               ordnance,
+                               vulnerable,
+                               killsOccupants,
+                               mustTurn,
+                               mv_desc,
+                               mv_sound,
+                               tailwind_penalty,
+                               headwind_penalty,
+                               crosswind_penalty,
+                               max_hp,
+                               speed
+                               );
+        assert(type);
+
+        type->mmode = mmode;
+        session_add(Session, type, vehicle_type_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, type);
+        scm_define(sc, tag, ret);
+        
+               if (proc != sc->NIL) {
+                       type->renderCombat = closure_new(sc, proc);
+                       closure_ref(type->renderCombat); //TODO clean up this nasty leaky hack
+               }
+               else
+               {
+                       type->renderCombat=NULL;        
+               }
+        
+        return ret;
+}
+
+KERN_API_CALL(kern_mk_vehicle)
+{
+        Vehicle *vehicle;
+        VehicleType *type;
+        int facing;
+        int hp;
+
+        if (unpack(sc, &args, "pdd", &type, &facing, &hp)) {
+                load_err("kern-mk-vehicle: bad args");
+                return sc->NIL;
+        }
+
+        if (!type) {
+                load_err("kern-mk-vehicle-type: null type");
+                return sc->NIL;
+        }
+
+        vehicle = new Vehicle(type, facing, hp);
+        assert(vehicle);
+
+        return scm_mk_ptr(sc, vehicle);
+}
+
+KERN_API_CALL(kern_obj_get_sprite)
+{
+        Object *obj = unpack_obj(sc, &args, "kern-obj-get-sprite");
+        if (!obj)
+                return sc->NIL;
+
+        return scm_mk_ptr(sc, obj->getSprite());
+}
+
+KERN_API_CALL(kern_obj_get_light)
+{
+        Object *obj = unpack_obj(sc, &args, "kern-obj-get-light");
+        if (!obj)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, obj->getLight());
+}
+
+KERN_API_CALL(kern_obj_get_mmode)
+{
+        struct mmode *mmode;
+
+        Object *obj = unpack_obj(sc, &args, "kern-obj-get-mmode");
+        if (!obj)
+                return sc->NIL;
+
+        mmode = obj->getMovementMode();
+        if (mmode)
+                return scm_mk_ptr(sc, mmode);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_get_movecost)
+{
+            class Object *obj;
+        int val;
+
+        if (unpack(sc, &args, "pd", &obj, &val)) {
+                rt_err("kern_obj_get_movecost: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern_obj_get_movecost: null object");
+                return sc->NIL;
+        }
+       
+        val = obj->getMovementCost(val);
+        return scm_mk_integer(sc,val);
+}
+
+KERN_API_CALL(kern_obj_get_name)
+{
+        Object *obj = unpack_obj(sc, &args, "kern-obj-get-name");
+        if (!obj) {
+                return sc->NIL;
+        }
+
+        if (!obj->getName()) {
+                return sc->NIL;
+        }
+
+        return scm_mk_string(sc, obj->getName());
+}
+
+KERN_API_CALL(kern_obj_set_light)
+{
+        Object *obj;
+        int light;
+
+        if (unpack(sc, &args, "pd", &obj, &light)) {
+                rt_err("kern-obj-set-light: bad args");
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("kern-obj-set-light: null obj");
+                return sc->NIL;
+        }
+
+        obj->setLight(light);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_sleep)
+{
+        int msecs;
+
+        if (unpack(sc, &args, "d", &msecs)) {
+                rt_err("kern-sleep: bad args");
+                return sc->F;
+        }
+        //usleep(MS_PER_TICK * msecs);
+        SDL_Delay(msecs);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_map_view_create)
+{
+        return scm_mk_ptr(sc, mapCreateView());
+}
+
+
+KERN_API_CALL(kern_map_view_destroy)
+{
+        struct mview *v = kern_unpack_mview(sc, &args, 
+                                            "kern-map-view-destroy");
+        if (v)
+                mapDestroyView(v);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_view_add)
+{
+        struct mview *v = kern_unpack_mview(sc, &args, "kern-map-view-add");
+        if (v)
+                mapAddView(v);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_view_rm)
+{
+        struct mview *v = kern_unpack_mview(sc, &args, "kern-map-view-rm");
+        if (v)
+                mapRmView(v);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_view_center)
+{
+        struct place *place;
+        int x, y;
+
+        struct mview *v = kern_unpack_mview(sc, &args, 
+                                            "kern-map-view-center");
+        if (!v)
+                return sc->NIL;
+
+        if (! kern_unpack_loc(sc, &args, &place, &x, &y,
+                              "kern-map-view-center"))
+                return sc->NIL;
+
+        mapSetPlace(place);
+        mapCenterView(v, x, y);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_center_camera)
+{
+        struct place *place;
+        int x, y;
+
+        if (! kern_unpack_loc(sc, &args, &place, &x, &y,
+                              "kern-map-view-center"))
+                return sc->NIL;
+
+        mapCenterCamera(x, y);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_repaint)
+{
+        mapUpdate(0);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_flash)
+{
+        int msecs;
+        if (unpack(sc, &args, "d", &msecs)) {
+                rt_err("kern-map-flash: bad args");
+                return sc->NIL;
+        }
+        mapFlash(msecs);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_sound_play)
+{
+        sound_t *sound;
+        if (unpack(sc, &args, "p", &sound)) {
+                rt_err("kern-sound-play: bad args");
+                return sc->NIL;
+        }
+        sound_play(sound, SOUND_MAX_VOLUME);
+        return sc->NIL;
+}
+
+//refactor refactor refactor!
+KERN_API_CALL(kern_sound_play_at)
+{
+       sound_t *sound;
+       struct place *place, *foc_place;
+       int x, foc_x;
+       int y, foc_y;
+       if (unpack(sc, &args, "p", &sound))\
+       {
+               rt_err("kern-sound-play-at: bad args");
+               return sc->NIL;
+       }
+       if (unpack_loc(sc, &args, &place, &x, &y, "kern-sound-play-at: bad loc"))
+       {
+               return sc->NIL;
+       }
+       int volume = SOUND_MAX_VOLUME;
+       int distance;
+       mapGetCameraFocus(&foc_place, &foc_x, &foc_y);
+       if (foc_place == place)
+       {
+               distance = place_flying_distance(foc_place, foc_x, foc_y, x, y);
+               if (distance > 1)
+                       volume = (volume * (20 - distance))/20;
+               if (volume > 0)
+               {
+                       sound_play(sound, volume, false);
+               }
+       }
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_sound_play_ambient)
+{
+       sound_t *sound;
+       struct place *place, *foc_place;
+       int x, foc_x;
+       int y, foc_y;
+       if (unpack(sc, &args, "p", &sound))
+       {
+              rt_err("kern-sound-play-ambient: bad args");
+              return sc->NIL;
+       }
+       if (unpack_loc(sc, &args, &place, &x, &y, "kern-sound-play-ambient: bad loc"))
+       {
+              return sc->NIL;
+       }
+       int volume = SOUND_MAX_VOLUME;
+       int distance;
+       mapGetCameraFocus(&foc_place, &foc_x, &foc_y);
+       if (foc_place == place)
+       {
+               distance = place_flying_distance(foc_place, foc_x, foc_y, x, y);
+               if (distance > 1)
+                       volume = (volume * (20 - distance))/20;
+               if (volume > 0)
+               {
+                       sound_play(sound, volume, true);
+               }
+       }
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_music_play)
+{
+       char *file;
+       if (unpack(sc, &args, "s", &file))
+       {
+              rt_err("kern-music-play: bad args");
+              return sc->NIL;
+       }
+       music_load_track(file);
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_set_spell_words)
+{
+        int i = 0;
+        pointer words;
+        pointer word;
+
+        words = args;
+
+        for (i = 0; i < MAX_SPELL_WORDS; i++) {
+
+                /* check for end-of-list */
+                if (! scm_is_pair(sc, words))
+                        break;
+
+                word = scm_car(sc, words);
+        
+                /* type-check */
+                if (! scm_is_str(sc, word)) {
+                        load_err("kern-set-spell-words: entry %i not a string",
+                                 i);
+                        break;
+                }
+
+                /* copy the word into the global list of words */
+                if (magic_add_word(&Session->magic, scm_str_val(sc, word))) {
+                        load_err("kern-set-spell-words: error adding '%s'",
+                                 scm_str_val(sc, word));
+                }
+                                
+                words = scm_cdr(sc, words);
+        }
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_skill)
+{
+        char *name, *desc;
+        pointer yuse, can_yuse, list;
+        struct skill *skill;
+        int wilderness_ok, passive;
+
+        /* Unpack name and desc */
+        if (unpack(sc, &args, "ss", &name, &desc)) {
+                load_err("kern-mk-skill: bad args");
+                return sc->NIL;
+        }
+
+        skill = skill_new();
+        skill_set_name(skill, name);
+        skill_set_desc(skill, desc);
+
+        /* Unpack ap, mp and yusage procs */
+        if (unpack(sc, &args, "ddbbcc", 
+                   &skill->ap, 
+                   &skill->mp, 
+                   &wilderness_ok,
+                   &passive,
+                   &yuse, &can_yuse)) {
+                load_err("kern-mk-skill %s: bad args", name);
+                goto abort;
+        }
+
+        /* I used an int for the unpack since I don't trust the cast to work
+         * portably on structure bit fields */
+        skill->wilderness_ok = wilderness_ok;
+        skill->passive = passive;
+
+        /* yuse is mandatory for non-passive skills */
+        if (! skill->passive 
+            && yuse == sc->NIL) {
+                load_err("kern-mk-skill %s: active but nil yuse proc", name);
+                goto abort;
+        }
+
+        if (yuse != sc->NIL) {
+                skill->yuse = closure_new_ref(sc, yuse);
+        }
+
+        /* can_yuse is optional */
+        if (can_yuse != sc->NIL) {
+                skill->can_yuse = closure_new_ref(sc, can_yuse);
+        }
+
+        /* list of tools */
+        list = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+        while (scm_is_pair(sc, list)) {
+                void *objtype;
+                if (unpack(sc, &list, "p", &objtype)) {
+                        load_err("kern-mk-skill %s: bad tool arg", name);
+                        goto abort;
+                }
+                skill_add_tool(skill, objtype);
+        }
+
+        /* list of materials: (objtype, int) pairs */
+        list = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+        while (scm_is_pair(sc, list)) {
+                void *objtype;
+                int quan;
+                pointer pair = scm_car(sc, list);
+                list = scm_cdr(sc, list);
+                if (unpack(sc, &pair, "pd", &objtype, &quan)) {
+                        load_err("kern-mk-skill %s: bad material arg", name);
+                        goto abort;
+                }
+                skill_add_material(skill, objtype, quan);
+        }
+
+        list_add(&Session->skills, &skill->list);
+        return scm_mk_ptr(sc, skill);
+
+ abort:
+        skill_unref(skill);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_skill_set)
+{
+        char *name;
+        struct skill_set *skset;
+        pointer list;
+
+        if (unpack(sc, &args, "s", &name)) {
+                load_err("kern-mk-skill-set: bad name");
+                return sc->NIL;
+        }
+
+        skset = skill_set_new();
+        skill_set_set_name(skset, name);
+
+        list = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+        while (scm_is_pair(sc, list)) {
+                pointer pair;
+                int lvl;
+                struct skill *skill;
+
+                pair = scm_car(sc, list);
+                list = scm_cdr(sc, list);
+                if (unpack(sc, &pair, "dp", &lvl, &skill)) {
+                        load_err("kern-mk-skill-set %s: bad skill list args", 
+                                 name);
+                        goto abort;
+                }
+
+                if (!skill) {
+                        load_err("kern-mk-skill-set %s: nil skill", name);
+                        goto abort;
+                }
+
+                skill_set_add_skill(skset, skill, lvl);
+        }
+
+        list_add(&Session->skill_sets, &skset->list);
+        return scm_mk_ptr(sc, skset);
+
+ abort:
+        skill_set_unref(skset);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_add_spell)
+{
+        char *code;
+        ObjectType *type;
+        struct spell *spell;
+        pointer reagents;
+
+        /* Unpack just as far as the word until we can verify that we can add
+         * this spell. */
+        if (unpack(sc, &args, "ps", &type, &code)) {
+                load_err("kern-add-spell: bad args");
+                return sc->NIL;
+        }
+        
+        if (!(spell = magic_add_spell(&Session->magic, code))) {
+                load_err("kern-add-spell: failed to add %s",
+                         type->getName());
+                return sc->NIL;
+        }
+
+        spell->type = type;
+
+        /* NOTE: unlike other kernel data structures/objects, if we fail we
+         * don't have to deallocate the spell structure. Nor do we need to
+         * explicitly add it to the session for teardown later. After
+         * magic_add_spell() returns the spell structure has already been added
+         * to the spell tree associated with the session, and will be
+         * automatically deallocated at end-of-session. */
+
+        /* unpack remaining fields (other than the reagent list) directly into
+         * the spell structure. */
+        if (unpack(sc, &args, "ddddp", &spell->level, &spell->cost,
+                   &spell->context, &spell->action_points, &spell->sprite)) {
+                load_err("kern-add-spell: bad args");
+                return sc->NIL;
+        }
+
+        reagents = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        while (scm_is_pair(sc, reagents)) {
+                ObjectType *reagent_type;
+                if (unpack(sc, &reagents, "p", &reagent_type)) {
+                        load_err("kern-add-spell %s: bad arg in reagent list",
+                                 spell->type->getName());
+                        return sc->NIL;
+                }
+                if (spell_add_reagent(spell, reagent_type)) {
+                        load_err("kern-add-spell: failed to add reagent %s "\
+                                 "to mixture for spell %s", 
+                                 reagent_type->getName(), 
+                                 spell->type->getName());
+                        return sc->NIL;
+                }
+                
+        }
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_init_random)
+{
+       /* This should have some timing randomness,
+               since human interaction is required before scripts run */
+       
+       srand(clock());
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_dice_roll)
+{
+        static char *dice;
+
+        if (unpack(sc, &args, "s", &dice)) {
+                rt_err("kern-dice-roll: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (!dice_valid(dice)) {
+                rt_err("kern-dice-roll: bad dice '%s'", dice);
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, dice_roll(dice));
+}
+
+KERN_API_CALL(kern_char_set_sleep)
+{
+        class Character *ch;
+        int val;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-sleep");
+        if (!ch)
+                return sc->F;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-char-set-sleep: bad args");
+                return sc->F;
+        }
+
+        if (val)
+                ch->sleep();
+        else
+                ch->awaken();
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_char_force_drop)
+{
+        class Character *ch;
+        int val;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-force-drop");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-char-force-drop: bad args");
+                goto done;
+        }
+
+        ch->setForceContainerDrop(val);
+ done:
+        return scm_mk_ptr(sc, ch);
+}
+
+KERN_API_CALL(kern_char_unready)
+{
+        class Character *ch;
+        class ArmsType *type;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-unready");
+        if (!ch)
+                return sc->F;
+
+        if (unpack(sc, &args, "p", &type)) {
+                rt_err("kern-char-unready: bad args");
+                return sc->F;
+        }
+
+        return ch->unready(type) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_char_get_readied_weapons)
+{
+        class Character *ch;
+        class ArmsType *weapon;
+        pointer head = sc->NIL;
+        pointer tail = sc->NIL;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-unready");
+        if (!ch)
+                return sc->F;
+
+               int armsIndex = 0;
+        for (weapon = ch->enumerateWeapons(&armsIndex); weapon != NULL; 
+             weapon = ch->getNextWeapon(&armsIndex)) {
+                    
+                /* skip "natural" weapons that are not really readied */
+                if (ch->species &&
+                    weapon == ch->species->weapon)
+                        continue;
+
+                pointer cell = scm_mk_ptr(sc, weapon);
+                cell = _cons(sc, cell, sc->NIL, 0);
+
+                if (head == sc->NIL) {
+                        head = cell;
+                        tail = cell;
+                } else {
+                        tail->_object._cons._cdr = cell;
+                        tail = cell;
+                }
+        }
+
+        return head;
+}
+
+KERN_API_CALL(kern_char_set_hp)
+{
+        class Character *ch;
+        int val;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-hp");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-hp: bad args");
+        } else {
+                ch->setHp(val);
+        }
+
+        return scm_mk_ptr(sc, ch);;
+}
+
+KERN_API_CALL(kern_char_set_mana)
+{
+        class Character *ch;
+        int val;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-mana");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-mana: bad args");
+        } else {
+                ch->setMana(val);
+        }
+
+        return scm_mk_ptr(sc, ch);;
+}
+
+KERN_API_CALL(kern_char_set_schedule)
+{
+        class Character *ch;
+        struct sched *val;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-schedule");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "p", &val)) {
+                rt_err("kern-char-set-schedule: bad args");
+        } else {
+                ch->setSchedule(val);
+        }
+
+        return scm_mk_ptr(sc, ch);
+}
+
+/* 
+ * kern_char_join_player -- wrapper for Character::joinPlayer
+ */
+KERN_API_CALL(kern_char_join_player)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-join-player");
+        if (!ch)
+                return sc->F;
+
+        if (ch->joinPlayer())
+                return sc->T;
+        return sc->F;
+}
+
+KERN_API_CALL(kern_char_is_known)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-is-known");
+        if (!ch) {
+                return sc->F;
+        }
+
+        return ch->isKnown() ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_char_leave_player)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-leave-player");
+        if (!ch)
+                return sc->F;
+
+        if (NULL==ch->getPlace()
+            || place_is_wilderness(ch->getPlace()))
+                return sc->F;
+
+        ch->leavePlayer();
+
+        return sc->T;
+}
+
+/* 
+ * kern_char_set_ai -- change the AI for a Character object
+ */
+KERN_API_CALL(kern_char_set_ai)
+{
+        class Character *ch;
+        pointer ai;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-ai");
+        if (!ch)
+                return sc->F;
+
+        if (unpack(sc, &args, "c", &ai)) {
+                rt_err("kern-char-set-ai: bad args");
+                return sc->F;
+        }
+
+        if (ai == sc->NIL) {
+                ch->setAI(NULL);
+        } else {
+                ch->setAI(closure_new(sc, ai));
+        }
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_char_task_abort)
+{
+    class Character *ch;
+
+    ch = (class Character*)unpack_obj(sc, &args, "kern-char-task-abort");
+    if (ch) {
+        ch->taskAbort();
+    }
+    return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_task_begin)
+{
+    char *taskname = NULL;
+    class Character *ch;
+    pointer taskproc, taskgob;
+    struct closure *closure = NULL;
+    struct gob *gob = NULL;
+
+    ch = (class Character*)unpack_obj(sc, &args, "kern-char-task-begin");
+    if (!ch) {
+        return sc->F;
+    }
+
+    if (unpack(sc, &args, "scl", &taskname, &taskproc, &taskgob)) {
+        rt_err("%s: bad args", __FUNCTION__);
+        return sc->F;
+    }
+
+    if (taskproc == sc->NIL) {
+        rt_err("%s: nil task procedure not allowed", __FUNCTION__);
+        return sc->F;
+    }
+
+    /* For now, disallow starting tasks in the wilderness. Maybe later. */
+    if (place_is_wilderness(ch->getPlace())) {
+        return sc->F;
+    }
+
+    if (!(closure = closure_new_ref(sc, taskproc))) {
+        return sc->F;
+    }
+
+    /* gob is optional */
+    if (taskgob != sc->NIL) {
+        if (!(gob = gob_new(sc, taskgob))) {
+            closure_unref(closure);
+            return sc->F;
+        }
+    }
+
+    ch->taskBegin(taskname, closure, gob);
+    closure_unref(closure);
+
+    return sc->T;
+}
+
+KERN_API_CALL(kern_char_task_continue)
+{
+    char *taskname = NULL;
+    class Character *ch;
+    pointer taskproc, taskgob;
+    struct closure *closure = NULL;
+    struct gob *gob = NULL;
+
+    ch = (class Character*)unpack_obj(sc, &args, "kern-char-task-continue");
+    if (!ch) {
+        return sc->F;
+    }
+
+    if (unpack(sc, &args, "scl", &taskname, &taskproc, &taskgob)) {
+        rt_err("%s: bad args", __FUNCTION__);
+        return sc->F;
+    }
+
+    if (taskproc == sc->NIL) {
+        return sc->F;
+    }
+    
+    if (!(closure = closure_new_ref(sc, taskproc))) {
+        return sc->F;
+    }
+
+    /* gob is optional */
+    if (taskgob != sc->NIL) {
+        if (!(gob = gob_new(sc, taskgob))) {
+            closure_unref(closure);
+            return sc->F;
+        }
+    }
+
+    ch->taskContinue(taskname, closure, gob);
+    closure_unref(closure);
+
+    return sc->T;
+}
+
+KERN_API_CALL(kern_char_task_end)
+{
+    class Character *ch;
+
+    ch = (class Character*)unpack_obj(sc, &args, "kern-char-task-end");
+    if (ch) {
+        ch->taskEnd();
+    }
+    return sc->NIL;
+}
+
+
+KERN_API_CALL(kern_char_set_sched)
+{
+        class Character *ch;
+        struct sched *sched = 0;
+
+        if (unpack(sc, &args, "pp", &ch, &sched)) {
+                rt_err("kern-char-set-sched: bad args");
+                return sc->NIL;
+        }
+
+        if (!ch) {
+                rt_err("kern-char-set-sched: null object");
+                return sc->NIL;
+        }
+
+        ch->setSchedule(sched);
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_char_set_control_mode)
+{
+        static struct { const char *str; enum control_mode mode; } tbl[] = {
+                { "auto", CONTROL_MODE_AUTO },
+                { "player", CONTROL_MODE_PLAYER },
+                { "idle", CONTROL_MODE_IDLE },
+                { "follow", CONTROL_MODE_FOLLOW }
+        };
+        class Character *ch;
+        char *modestr = 0;
+        int i;
+
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-control-mode");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "s", &modestr)) {
+                rt_err("kern-char-set-control-mode: bad args");
+                return sc->NIL;
+        }
+
+        for (i = 0; i < array_sz(tbl); i++) {
+                if (! strcmp(tbl[i].str, modestr)) {
+                        ch->setControlMode(tbl[i].mode);
+                        return sc->NIL;
+                }
+        }
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_attack)
+{
+        class Character *attacker, *defender;
+        class ArmsType *weapon;
+
+        if (unpack(sc, &args, "ppp", &attacker, &weapon, &defender)) {
+                rt_err("kern-char-attack: bad args");
+                return sc->F;
+        }
+
+        if (! attacker) {
+                rt_err("kern-char-attack: null attacker");
+                return sc->F;
+        }
+
+        if (! weapon) {
+                rt_err("kern-char-attack: null weapon");
+                return sc->F;
+        }
+
+        if (! defender) {
+                rt_err("kern-char-attack: null defender");
+                return sc->F;
+        }
+
+        ctrl_do_attack(attacker, weapon, defender, 
+                       attacker->getToHitPenalty());
+        
+        attacker->decActionPoints(weapon->getRequiredActionPoints());
+                       
+        return sc->T;
+}
+
+KERN_API_CALL(kern_char_is_asleep)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-is-asleep");
+        if (!ch)
+                return sc->F;
+
+        return ch->isAsleep() ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_char_is_dead)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-is-dead");
+        if (!ch)
+                return sc->T;
+
+        return ch->isDead() ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_mk_effect)
+{
+        struct effect *effect;
+        pointer exec_proc = sc->NIL;
+        pointer apply_proc = sc->NIL;
+        pointer rm_proc = sc->NIL;
+        pointer restart_proc = sc->NIL;
+        void *sprite;
+        pointer ret;
+        char *name, *tag = 0;
+        int hook_id;
+
+        if (unpack(sc, &args, "yspccccd", &tag, &name, &sprite, &exec_proc,
+                   &apply_proc, &rm_proc, &restart_proc, &hook_id)) {
+                load_err("kern-mk-effect %s: bad args", tag);
+                return sc->NIL;
+        }
+
+        if (exec_proc == sc->NIL)
+                exec_proc = NULL;
+
+        if (apply_proc == sc->NIL)
+                apply_proc = NULL;
+
+        if (rm_proc == sc->NIL)
+                rm_proc = NULL;
+
+        if (restart_proc == sc->NIL)
+                restart_proc = NULL;
+                               
+        effect = effect_new(tag, sc, exec_proc, apply_proc, rm_proc, 
+                            restart_proc, name);
+
+        effect->hook_id = hook_id;
+        effect->sprite = (struct sprite*)sprite;
+
+        if (unpack(sc, &args, "dbd", &effect->detect_dc,
+                   &effect->cumulative, &effect->duration)) {
+                load_err("kern-mk-effect %s: bad args", tag);
+                goto abort;
+        }
+
+        session_add(Session, effect, effect_dtor, NULL, NULL);
+        ret = scm_mk_ptr(sc, effect);
+        scm_define(sc, tag, ret);
+
+        return ret;
+
+ abort:
+        effect_del(effect);
+        return sc->NIL;
+}
+
+/*  kern_ui_target_visitor - build a suggested list of targets from all beings
+ *  in range. */
+static void kern_ui_target_visitor(class Object *obj, void *data)
+{
+        struct kern_ui_target_info *info = (struct kern_ui_target_info*)data;
+        class Character *npc = 0;
+        int dist = 0;
+        struct location_list *entry = 0;
+
+        if (being_layer!=obj->getLayer())
+                return;
+
+        npc = (class Character*)obj;
+
+        if (! npc->isVisible() && ! Reveal)
+                return;
+        
+        dist = place_flying_distance(info->place,
+                                     info->x,
+                                     info->y,
+                                     obj->getX(),
+                                     obj->getY());
+        if (dist > info->range)
+                return;
+
+        /* Add it to the list */
+        entry = (struct location_list*)malloc(sizeof(*entry));
+        assert(entry);
+        entry->x = obj->getX();
+        entry->y = obj->getY();
+        list_add_tail(&info->suggest, &entry->list);
+}
+
+/* kern_ui_target_cleanup_info - free the suggest list. */
+static void kern_ui_target_cleanup_info(struct kern_ui_target_info *info)
+{
+        struct list *head = &info->suggest;
+        struct list *entry = head->next;
+        while (entry != head) {
+                struct location_list *tmp = 
+                        (struct location_list*)entry;
+                entry = entry->next;
+                list_remove(&tmp->list);
+                free(tmp);
+        }
+}
+
+KERN_API_CALL(kern_ui_target)
+{
+        struct place *place;
+        int ox, oy, tx, ty, range;
+        struct kern_ui_target_info info;
+        pointer ret;
+
+        /* Unpack the origin */
+        if (unpack_loc(sc, &args, &place, &ox, &oy, "kern-ui-target")) {
+                return sc->NIL;
+        }
+        
+        /* Unpack the range */
+        if (unpack(sc, &args, "d", &range)) {
+                rt_err("kern-ui-target: bad range arg");
+                return sc->NIL;
+        }
+
+        /* Build a list of suggested targets. */
+        memset(&info, 0, sizeof(info));
+        info.place = Place;
+        info.x = ox;
+        info.y = oy;
+        info.range = range;
+        list_init(&info.suggest);
+        place_for_each_object(Place,
+                              kern_ui_target_visitor,
+                              &info);
+        
+
+        /* Get the target coords from the user */
+        tx = ox;
+        ty = oy;
+        if (select_target(ox, oy, &tx, &ty, range, &info.suggest)) {
+                ret = sc->NIL;
+        }
+        
+        /* Pack the target coords for return */
+        else { 
+                ret = pack(sc, "pdd", place, tx, ty);
+        }
+
+        kern_ui_target_cleanup_info(&info);
+        return ret;
+}
+
+static int kern_mk_templ_visitor(struct templ *templ, int x, int y, void *data)
+{
+        closure_t *check = (closure_t*)data;
+        
+        /* if the check proc returns #f then turn off this location in the
+         * template */
+        if (! closure_exec(check, "dd", x, y)) {
+                templ_set(templ, x, y, 0);
+        }
+
+        return 0;
+}
+
+KERN_API_CALL(kern_mk_templ)
+{
+        int rad, x, y;
+        struct place *place;
+        pointer checkptr;
+        struct templ *templ;
+        closure_t *checkproc;
+
+        /* origin */
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-mk-templ")) {
+                return sc->NIL;
+        }
+
+        /* radius, check-proc and gob */
+        if (unpack(sc, &args, "dc", &rad, &checkptr)) {
+                rt_err("kern-mk-templ: bad args");
+                return sc->NIL;
+        }
+
+        /* create the templ and set its origin */
+        templ = templ_new_from_range(rad);
+        templ_set_origin(templ, x, y);
+
+        /* run the check procedure on each location covered by the templ */
+        checkproc = closure_new_ref(sc, checkptr);
+        templ_for_each(templ, kern_mk_templ_visitor, checkproc);
+        closure_unref(checkproc);
+
+        return scm_mk_ptr(sc, templ);
+}
+
+KERN_API_CALL(kern_ui_target_generic)
+{
+        ui_select_target_req_t req;
+        pointer move_cb, select_cb, gob, dummy;
+
+        ui_select_target_req_init(&req);
+
+        /* Unpack the origin */
+        if (unpack_loc(sc, &args, &req.place, &req.x1, &req.y1, 
+                       "kern-ui-target-generic")) {
+                return sc->NIL;
+        }
+
+        /* Unpack the initial cursor loc */
+        if (unpack_loc(sc, &args, &req.place, &req.x2, &req.y2, 
+                       "kern-ui-target-generic")) {
+                return sc->NIL;
+        }
+        
+        /* Unpack the template */
+        if (unpack(sc, &args, "p", &req.tiles)) {
+                rt_err("kern-ui-target-generic: bad template arg");
+                return sc->NIL;
+        }
+
+        /* fixme: unpack the suggested list */
+        if (unpack(sc, &args, "p", &dummy)) {
+                rt_err("kern-ui-target-generic: bad template arg");
+                return sc->NIL;
+        }
+
+        /* unpack the move-cb, select-cb and gob */
+        if (unpack(sc, &args, "ccc", &move_cb, &select_cb, &gob)) {
+                rt_err("kern-ui-target-generic: bad callback or gob arg");
+                return sc->NIL;
+        }
+        
+        /* fixme: convert the cb procs into closures (will have to clean them
+         * up at the bottom, too) */
+
+        /* Prompt the player; returns when player has made selection */
+        if (ui_select_target_generic(&req)) {
+                return sc->NIL;
+        }
+
+        /* Kind of a hack: manually unref the templ here, assuming the caller
+         * is done with it, which is going to be the usual case. If I encounter
+         * an unusual case then I'll need to add kern-templ-ref/unref so the
+         * script can protect it. */
+        if (req.tiles) {
+                templ_unref(req.tiles);
+        }
+        
+        /* Pack the target coords for return */
+        return pack(sc, "pdd", req.place, req.x2, req.y2);
+}
+
+KERN_API_CALL(kern_fire_missile)
+{
+        MissileType *missile_type;
+        Missile *missile;
+        struct place *oplace, *dplace;
+        int ox, oy, dx, dy, hitTarget = 0;
+
+        /* Unpack the missile type */
+        if (unpack(sc, &args, "p", &missile_type)) {
+                rt_err("kern-fire-missile: bad missile type arg");
+                return sc->NIL;
+        }
+        if (! missile_type) {
+                rt_err("kern-fire-missile: null missile type");
+                return sc->NIL;
+        }
+
+        /* Unpack the origin */
+        if (unpack_loc(sc, &args, &oplace, &ox, &oy, "kern-fire-missile"))
+                return sc->NIL;
+
+        /* Unpack the destination */
+        if (unpack_loc(sc, &args, &dplace, &dx, &dy, "kern-fire-missile"))
+                return sc->NIL;
+
+        /* Create the missile */
+        missile = new Missile(missile_type);
+        assert(missile);
+
+        /* Fire the missile */
+        missile->setPlace(dplace);
+        missile->animate(ox, oy, &dx, &dy, 0, 0);
+        hitTarget = missile->hitTarget();
+        missile->fireHitLoc(NULL, NULL, oplace,dx,dy,-1);
+        delete missile;
+        return hitTarget ? sc->T : sc->F;
+}
+
+
+KERN_API_CALL(kern_fire_missile_to_max)
+{
+        MissileType *missile_type;
+        Missile *missile;
+        struct place *oplace, *dplace;
+        int ox, oy, dx, dy, hitTarget = 0;
+        int range;
+
+        /* Unpack the missile type */
+        if (unpack(sc, &args, "pd", &missile_type, &range)) {
+                rt_err("kern-fire-missile-to-max: bad missile type arg");
+                return sc->NIL;
+        }
+        if (! missile_type) {
+                rt_err("kern-fire-missile-to-max: null missile type");
+                return sc->NIL;
+        }
+
+        /* Unpack the origin */
+        if (unpack_loc(sc, &args, &oplace, &ox, &oy, "kern-fire-missile-to-max"))
+                return sc->NIL;
+
+        /* Unpack the destination */
+        if (unpack_loc(sc, &args, &dplace, &dx, &dy, "kern-fire-missile-to-max"))
+                return sc->NIL;
+
+        /* Create the missile */
+        missile = new Missile(missile_type);
+        assert(missile);
+
+        /* Fire the missile */
+        missile->setPlace(dplace);
+        missile->animate(ox, oy, &dx, &dy, 0, range);
+        hitTarget = missile->hitTarget();
+        missile->fireHitLoc(NULL, NULL, oplace,dx,dy,-1);
+        delete missile;
+        return hitTarget ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_inc_light)
+{
+        int light;
+
+        Object *obj = unpack_obj(sc, &args, "kern-obj-inc-light");
+        if (!obj)
+                return sc->F;
+
+        if (unpack(sc, &args, "d", &light)) {
+                rt_err("kern-obj-inc-light: bad args");
+                return sc->F;
+        }
+
+        obj->setLight(obj->getLight() + light);
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_obj_dec_light)
+{
+        int light;
+
+        Object *obj = unpack_obj(sc, &args, "kern-obj-dec-light");
+        if (!obj)
+                return sc->F;
+
+        if (unpack(sc, &args, "d", &light)) {
+                rt_err("kern-obj-dec-light: bad args");
+                return sc->F;
+        }
+
+        obj->setLight(obj->getLight() - light);
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_obj_dec_ap)
+{
+        int val;
+
+        Object *obj = unpack_obj(sc, &args, "kern-obj-add-ap");
+        if (!obj)
+                return sc->F;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-obj-add-ap: bad args");
+                return sc->F;
+        }
+
+        obj->decActionPoints(val);
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_place_is_wilderness)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-is-wilderness: bad args");
+                return sc->F;
+        }
+
+        if (!place) {
+                rt_err("kern-place-is-wilderness: null place");
+                return sc->F;
+        }
+
+        return place_is_wilderness(place) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_place_is_wrapping)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-is-wrapping: bad args");
+                return sc->F;
+        }
+
+        if (!place) {
+                rt_err("kern-place-is-wrapping: null place");
+                return sc->F;
+        }
+
+        return place_is_wrapping(place) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_heal)
+{
+        Object *obj;
+        int val;
+
+        obj = unpack_obj(sc, &args, "kern-obj-heal");
+        if (!obj)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-obj-heal: bad args");
+                return sc->NIL;
+        }
+        
+        obj->heal(val);
+
+        return sc->T;
+}
+
+static int kern_filter_being(Object *obj, struct kern_append_info *info)
+{
+        return (obj->getLayer() == being_layer);
+}
+
+static int kern_filter_visible_hostile(Object *obj, 
+                                       struct kern_append_info *info)
+{
+        class Being *subj;
+
+        /* Extract a pointer to the subject looking for hostiles */
+        subj = (class Being *)info->data;
+
+        /* Filter out non-beings */
+        if (obj->getLayer() != being_layer)
+                return 0;
+
+        /* Filter out non-hostiles */
+        if (! are_hostile(subj, (class Being*)obj))
+                return 0;
+
+        /* Filter out objects not in los of the subject */
+        if (! place_in_los(subj->getPlace(),subj->getX(),subj->getY(),
+                                   obj->getPlace(),obj->getX(),obj->getY()))
+                return 0;
+
+        /* Filter out object not in the vision radius of the subject */
+        if (place_flying_distance(subj->getPlace(),subj->getX(),subj->getY(),
+                                  obj->getX(),obj->getY())
+            > subj->getVisionRadius())
+                return 0;
+
+        /* Filter out invisible objects */
+        if (! obj->isVisible())
+                return 0;
+
+        return 1;
+}
+
+static int kern_filter_visible_allies(Object *obj, 
+                                      struct kern_append_info *info)
+{
+        class Being *subj;
+
+        /* Extract a pointer to the subject looking for hostiles */
+        subj = (class Being *)info->data;
+
+        /* Filter out non-beings */
+        if (obj->getLayer() != being_layer)
+                return 0;
+
+        /* Filter out non-allies */
+        if (! are_allies(subj, (class Being*)obj))
+                return 0;
+
+        /* Filter out objects not in los of the subject */
+        if (! place_in_los(subj->getPlace(),subj->getX(),subj->getY(),
+                                   obj->getPlace(),obj->getX(),obj->getY()))
+                return 0;
+
+        /* Filter out object not in the vision radius of the subject */
+        if (place_flying_distance(subj->getPlace(),subj->getX(),subj->getY(),
+                                  obj->getX(),obj->getY())
+            > subj->getVisionRadius())
+                return 0;
+
+        /* Filter out invisible objects */
+        if (! obj->isVisible())
+                return 0;
+
+        return 1;
+}
+
+static void kern_append_object(Object *obj, void *data)
+{
+        pointer cell;
+        struct kern_append_info *info;
+
+        info = (struct kern_append_info *)data;
+
+        /* If there is a filter then use it */
+        if (info->filter != NULL)
+
+                /* If the filter rejects the object then don't append it */
+                if (! info->filter(obj, info))
+                        return;
+
+        cell = scm_mk_ptr(info->sc, obj);
+        cell = _cons(info->sc, cell, info->sc->NIL, 0);
+
+        if (info->head == info->sc->NIL) {
+                info->head = cell;
+                info->tail = cell;
+
+                /* Protect the list from gc until we can return to scheme */
+                scm_protect(info->sc, cell);
+        } else {
+                info->tail->_object._cons._cdr = cell;
+                info->tail = cell;
+        }
+}
+
+static pointer scm_mk_loc(scheme *sc, struct place *place, int x, int y)
+{
+        return pack(sc, "pdd", place, x, y);
+}
+
+static pointer 
+kern_place_for_each_object_at(scheme *sc, struct place *place, int x, int y,
+                              int (*filter)(Object *, 
+                                            struct kern_append_info *),
+                              void *data)
+{
+        struct kern_append_info info;
+
+        /* initialize the context used by the callback to append objects */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = filter;
+        info.data = data;
+
+        /* build a scheme list of the objects at that location */
+        place_for_each_object_at(place, x, y, kern_append_object, &info);
+
+        /* unprotect the list prior to return */
+        if (info.head != sc->NIL)
+                scm_unprotect(sc, info.head);
+
+        /* return the scheme list */
+        return info.head;
+
+}
+
+static pointer 
+kern_place_for_each_object(scheme *sc, struct place *place, 
+                           int (*filter)(Object *, struct kern_append_info *),
+                           void *data)
+{
+        struct kern_append_info info;
+
+        /* initialize the context used by the callback to append objects */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = filter;
+        info.data = data;
+
+        /* build a scheme list of the objects at that location */
+        place_for_each_object(place, kern_append_object, &info);
+
+        /* unprotect the list prior to return */
+        if (info.head != sc->NIL)
+                scm_unprotect(sc, info.head);
+
+        /* return the scheme list */
+        return info.head;
+
+}
+
+
+KERN_API_CALL(kern_get_objects_at)
+{
+        struct place *place;
+        int x, y;
+
+        /* unpack the location */
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-get-objects-at"))
+                return sc->NIL;
+
+        /* get all objects with no filtering */
+        return kern_place_for_each_object_at(sc, place, x, y, NULL, NULL);
+}
+
+KERN_API_CALL(kern_obj_is_char)
+{
+        /* OBSOLETE! Use kern-obj-is-being */
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-char?");
+        if (!obj)
+                return sc->F;
+
+        return (obj->getLayer() == being_layer) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_is_container)
+{
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-container?");
+        if (!obj)
+                return sc->F;
+
+        return (obj->getLayer() == container_layer) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_is_field)
+{
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-field?");
+        if (!obj)
+                return sc->F;
+
+        return (obj->getLayer() == field_layer) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_is_being)
+{
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-being?");
+        if (!obj)
+                return sc->F;
+
+        return (obj->getLayer() == being_layer) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_is_mech)
+{
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-mech?");
+        if (!obj)
+                return sc->F;
+
+        return (obj->getLayer() == mech_layer) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_is_visible)
+{
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-visible?");
+        if (!obj)
+                return sc->F;
+
+        return obj->isVisible() ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_obj_is_submerged)
+{
+        Object *obj;
+
+        obj = unpack_obj(sc, &args, "kern-obj-is-submerged?");
+        if (!obj)
+                return sc->F;
+
+        return obj->isSubmerged() ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_char_set_fleeing)
+{
+        int val;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-fleeing");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-char-set-fleeing: bad args");
+                return sc->NIL;
+        }
+        
+        ch->setFleeing(val);
+
+        return sc->NIL;
+
+}
+
+KERN_API_CALL(kern_char_set_player_controlled)
+{
+        int val;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-set-player-controlled");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-char-set-player-controlled: bad args");
+                return sc->NIL;
+        }
+        
+        ch->setPlayerControlled(val);
+
+        return sc->NIL;
+
+}
+
+KERN_API_CALL(kern_char_get_species)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-get-species");
+        if (!ch)
+                return sc->NIL;
+
+        return scm_mk_ptr(sc, ch->species);
+}
+
+KERN_API_CALL(kern_char_get_occ)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-get-occ");
+        if (!ch || ! ch->occ)
+                return sc->NIL;
+
+        return scm_mk_ptr(sc, ch->occ);
+}
+
+KERN_API_CALL(kern_char_get_mana)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-get-mana");
+        if (!ch)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, ch->getMana());
+}
+
+KERN_API_CALL(kern_place_get_beings)
+{
+        struct place *place;
+
+        /* unpack the place */
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-beings: bad args");
+                return sc->NIL;
+        }
+        if (! place) {
+                rt_err("kern-place-get-beings: null place");
+                return sc->NIL;
+        }
+
+        return kern_place_for_each_object(sc, place, kern_filter_being, NULL);
+}
+
+KERN_API_CALL(kern_being_get_visible_hostiles)
+{
+        Object *subj;
+
+        /* Unpack the subject */
+        subj = unpack_obj(sc, &args, "kern-place-get-visible-hostiles");
+        if (!subj)
+                return sc->NIL;
+
+        if (! subj->getPlace()) {
+                rt_err("kern-place-get-visible-hostiles: null place");
+                return sc->NIL;
+        }
+
+        return kern_place_for_each_object(sc, subj->getPlace(), 
+                                          kern_filter_visible_hostile,
+                                          subj);
+}
+
+KERN_API_CALL(kern_being_get_visible_allies)
+{
+        Object *subj;
+
+        /* Unpack the subject */
+        subj = unpack_obj(sc, &args, "kern-place-get-visible-allies");
+        if (!subj)
+                return sc->NIL;
+
+        if (! subj->getPlace()) {
+                rt_err("kern-place-get-visible-allies: null place");
+                return sc->NIL;
+        }
+
+        return kern_place_for_each_object(sc, subj->getPlace(), 
+                                          kern_filter_visible_allies,
+                                          subj);
+}
+
+KERN_API_CALL(kern_being_get_visible_tiles)
+{
+        Object *subj;
+        struct place *place;
+        int ox, oy, vr;
+        pointer head = sc->NIL;
+        pointer tail = sc->NIL;
+        pointer cell;
+
+        /* Unpack the subject */
+        subj = unpack_obj(sc, &args, "kern-being-get-visible-tiles");
+        if (!subj)
+                return sc->NIL;
+
+        place = subj->getPlace();
+        if (! place) {
+                rt_err("kern-being-get-visible-tiles: null place");
+                return sc->NIL;
+        }
+
+        ox = subj->getX();
+        oy = subj->getY();
+        vr = subj->getVisionRadius();
+        
+        for (int y = 0; y < place_h(place); y++) {
+                for (int x = 0; x < place_w(place); x++) {
+
+                        /* Filter out tiles not in los of the subject */
+                        if (! place_in_los(place, ox, oy, place, x, y))
+                                continue;
+                        
+                        /* Filter out tiles not in the vision radius of the
+                         * subject */
+                        if (place_flying_distance(place, ox, oy, x, y) > vr)
+                                continue;
+                        
+                        /* else append this location to the list */
+                        cell = scm_mk_loc(sc, place, x, y);
+                        cell = _cons(sc, cell, sc->NIL, 0);
+
+                        if (head == sc->NIL) {
+                                head = cell;
+                                tail = cell;
+                                scm_protect(sc, cell);
+                        } else {
+                                tail->_object._cons._cdr = cell;
+                                tail = cell;
+                        }
+                }
+        }
+
+        /* unprotect the list prior to returning */
+        if (head != sc->NIL)
+                scm_unprotect(sc, head);
+
+        return head;
+}
+
+KERN_API_CALL(kern_place_get_objects)
+{
+        struct place *place;
+
+        /* unpack the place */
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-objects: bad args");
+                return sc->NIL;
+        }
+        if (! place) {
+                rt_err("kern-place-get-objects: null place");
+                return sc->NIL;
+        }
+
+        return kern_place_for_each_object(sc, place, NULL, NULL);
+}
+
+
+/* struct kern_place_get_objects_in_los_info { */
+/*         struct kern_append_info ap_info; */
+/*         struct place *place; */
+/*         int ox;  /\* looker's x *\/ */
+/*         int oy;  /\* looker's y *\/ */
+/*         int rad; /\* looke r's rad *\/ */
+/*         int vx;  /\* vmask ulc x *\/ */
+/*         int vy;  /\* vmask ulc y *\/ */
+/*         char *vmask; */
+/* }; */
+
+/* static void kern_place_get_objects_in_los_cb(Object *obj, void *data) */
+/* { */
+/*         struct kern_place_get_objects_in_los_info *info; */
+/*         int x, y; */
+
+/*         info = (struct kern_place_get_objects_in_los_info *)data; */
+
+/*         /\* check if the object is within vision radius *\/ */
+/*         if (place_flying_distance(info->place, */
+/*                                   info->ox, */
+/*                                   info->oy, */
+/*                                   obj->getX(), */
+/*                                   obj->getY()) */
+/*             > info->rad) { */
+/*                 return; */
+/*         } */
+
+/*         /\* translate the object's coordinates into coordinates offset from the */
+/*          * upper left corner of the vmask region *\/ */
+/*         x = obj->getX() - info->vx; */
+/*         y = obj->getY() - info->vy; */
+
+/*         /\* check if the object is outside the vmask *\/ */
+/*         if (x < 0 || */
+/*             y < 0 || */
+/*             x >= VMASK_W || */
+/*             y >= VMASK_H) */
+/*                 return; */
+
+/*         /\* if the object's tile is marked as visible then add it to the list *\/ */
+/*         if (info->vmask[y * VMASK_W + x]) */
+/*                 kern_append_object(obj, &info->ap_info); */
+/* } */
+
+/* KERN_API_CALL(kern_place_get_objects_in_los) */
+/* { */
+/*         class Object *obj; */
+/*         struct kern_place_get_objects_in_los_info info; */
+
+/*         obj = unpack_obj(sc, &args, "kern-place-get-objects-in-los"); */
+/*         if (! obj) */
+/*                 return sc->NIL; */
+
+/*         if (! obj->getPlace()) { */
+/*                 rt_err("kern-place-get-object-in-los: obj has null place"); */
+/*                 return sc->NIL; */
+/*         } */
+
+/*         /\* initialize the context used by the callback to append objects *\/ */
+/*         info.ap_info.sc   = sc; */
+/*         info.ap_info.head = sc->NIL; */
+/*         info.ap_info.tail = sc->NIL; */
+/*         info.place        = obj->getPlace(); */
+/*         info.ox           = obj->getX(); */
+/*         info.oy           = obj->getY(); */
+/*         info.rad          = obj->getVisionRadius(); */
+/*         info.vx           = obj->getX() - VMASK_W / 2; */
+/*         info.vy           = obj->getY() - VMASK_H / 2; */
+/*         info.vmask        = vmask_get(obj->getPlace(), */
+/*                                       obj->getX(),  */
+/*                                       obj->getY()); */
+
+/*         /\* build a scheme list of the objects *\/ */
+/*         place_for_each_object(obj->getPlace(),  */
+/*                               kern_place_get_objects_in_los_cb, &info); */
+
+/*         /\* return the scheme list *\/ */
+/*         return info.ap_info.head; */
+/* } */
+
+KERN_API_CALL(kern_place_get_name)
+{
+        struct place *place;
+
+        /* unpack the place */
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-name: bad args");
+                return sc->NIL;
+        }
+        if (! place) {
+                rt_err("kern-place-get-name: null place");
+                return sc->NIL;
+        }
+
+        return scm_mk_string(sc, place->name);
+}
+
+KERN_API_CALL(kern_place_is_passable)
+{
+        struct place *place;
+        int x, y;
+        class Object *obj;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-is-passable"))
+                return sc->F;
+
+        obj = unpack_obj(sc, &args, "kern-place-is-passable");
+        if (!obj)
+                return sc->F;
+
+        return place_is_passable(place, x, y, obj, 0) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_place_move_is_passable)
+{
+        struct place *fplace, *tplace;
+        int fx, fy, tx, ty;
+        class Object *obj;
+
+        if (unpack_loc(sc, &args, &fplace, &fx, &fy, 
+                       "kern-place-move-is-passable"))
+                return sc->F;
+
+        if (unpack_loc(sc, &args, &tplace, &tx, &ty,
+                       "kern-place-move-is-passable"))
+                return sc->F;
+
+        obj = unpack_obj(sc, &args, "kern-place-move-is-passable");
+        if (!obj)
+                return sc->F;
+
+        return place_move_is_passable(fplace, fx, fy, tx, ty, obj, 0) ? sc->T 
+                : sc->F;
+}
+
+KERN_API_CALL(kern_place_is_hazardous)
+{
+        struct place *place;
+        int x, y;
+        class Object *obj;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-is-hazardous"))
+                return sc->F;
+
+        obj = unpack_obj(sc, &args, "kern-place-is-hazardous");
+        if (!obj)
+                return sc->F;
+
+        return place_is_hazardous(place, x, y) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_place_set_terrain)
+{
+        struct place *place;
+        int x, y;
+        struct terrain *terrain;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-set-terrain"))
+                return sc->F;
+
+        if (unpack(sc, &args, "p", &terrain)) {
+                rt_err("kern-place-set-terrain: bad args");
+                return sc->F;
+        }
+
+        if (! terrain) {
+                rt_err("kern-place-set-terrain: nil terrain");
+                return sc->F;
+        }
+
+        place_set_terrain(place, x, y, terrain);
+
+        /* Often changing the terrain requires us to recalculate LOS in the
+         * surrounding area. */
+        vmask_invalidate(place, x, y, 1, 1);
+
+        /* And that means the map usually needs repainting, too */
+        mapSetDirty();
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_place_set_subplace)
+{
+        struct place *place, *subplace;
+        int x, y;
+
+        if (unpack(sc, &args, "p", &subplace)) {
+                rt_err("kern-place-set-subplace: bad args");
+                return sc->NIL;
+        }
+
+        if (! subplace) {
+                rt_err("kern-place-set-subplace: nil subplace");
+                return sc->NIL;
+        }
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-set-subplace"))
+                return sc->NIL;
+
+
+        place_add_subplace(place, subplace, x, y);
+
+        return scm_mk_ptr(sc, subplace);
+}
+
+KERN_API_CALL(kern_place_get_terrain)
+{
+        struct place *place;
+        int x, y;
+        struct terrain *terrain;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-get-terrain"))
+                return sc->F;
+
+        terrain = place_get_terrain(place, x, y);
+
+        return terrain ? scm_mk_ptr(sc, terrain) : sc->NIL;
+}
+
+KERN_API_CALL(kern_place_get_movement_cost)
+{
+        struct place *place;
+        int x, y, cost=0;
+        class Object *obj;
+        
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-get-movement-cost"))
+                goto done;
+
+        obj = unpack_obj(sc, &args, "kern-place-get-movement-cost");
+        if (!obj)
+                goto done;
+
+        cost = place_get_movement_cost(place, x, y, obj,0);
+
+ done:
+        return scm_mk_integer(sc, cost);
+}
+
+KERN_API_CALL(kern_place_get_light)
+{
+        struct place *place;
+        int x, y;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-get-light"))
+                return sc->F;
+
+        return scm_mk_integer(sc, place_get_light(place, x, y));
+}
+
+KERN_API_CALL(kern_place_get_terrain_map)
+{
+        struct place *place;
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-terrain-map: bad args");
+                return sc->NIL;
+        }
+
+        map = place_get_terrain_map(place);
+        if (!map)
+                return sc->NIL;
+        return scm_mk_ptr(sc, map);
+}
+
+KERN_API_CALL(kern_place_set_terrain_map)
+{
+        struct place *place;
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "pp", &place, &map)) {
+                rt_err("kern-place-set-terrain-map: bad args");
+                return sc->NIL;
+        }
+
+        place_set_terrain_map(place, map);
+        return scm_mk_ptr(sc, place);
+}
+
+KERN_API_CALL(kern_place_blocks_los)
+{
+        struct place *place;
+        int x, y;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-blocks-los?"))
+                return sc->F;
+
+        return place_visibility(place, x, y) ? sc->F : sc->T;
+}
+
+KERN_API_CALL(kern_obj_set_temporary)
+{
+        class Object *obj;
+        int val;
+
+        obj = unpack_obj(sc, &args, "kern-obj-set-temporary");
+        if (!obj)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-obj-set-temporary: bad value arg");
+                return scm_mk_ptr(sc, obj);
+        }
+
+        obj->setTemporary(val);
+
+        return scm_mk_ptr(sc, obj);
+}
+
+KERN_API_CALL(kern_obj_set_ignore_time_stop)
+{
+        class Object *obj;
+        int val;
+
+        obj = unpack_obj(sc, &args, "kern-obj-set-ignore-time-stop");
+        if (!obj)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-obj-set-ignore-time-stop: bad value arg");
+                return scm_mk_ptr(sc, obj);
+        }
+
+        obj->setIgnoreTimeStop(val);
+
+        return scm_mk_ptr(sc, obj);
+}
+
+KERN_API_CALL(kern_obj_wander)
+{
+       class Object *obj;
+       
+       obj = unpack_obj(sc, &args, "kern-obj-wander");
+       if (!obj)
+       return sc->NIL;
+       
+       //moves can have nasty consequences,
+       //so keep our own ref to the object for a bit
+       obj_inc_ref(obj);
+       ctrl_wander(obj);
+       obj_dec_ref(obj);
+       
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_clone)
+{
+        class Object *obj, *clone;
+
+        obj = unpack_obj(sc, &args, "kern-char-clone");
+        if (!obj)
+                return sc->NIL;
+
+        clone = obj->clone();
+        assert(clone);
+        clone->setTemporary(1);
+
+        return scm_mk_ptr(sc, clone);
+}
+
+KERN_API_CALL(kern_obj_freeze)
+{
+        class Object *obj;
+               char* key;
+               int x,y;
+
+        obj = unpack_obj(sc, &args, "kern-obj-freeze");
+        if (!obj)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "sdd", &key, &x, &y)) {
+                rt_err("kern-obj-freeze: bad args");
+                return sc->NIL;
+        }
+
+        obj_inc_ref(obj);
+        freezer_freezeObject(key, x, y, obj);
+
+        return sc->NIL;
+}
+               
+KERN_API_CALL(kern_obj_thaw)
+{
+        class Object *obj;
+               struct place *place;
+               char* key;
+               int x,y;
+
+        if (unpack(sc, &args, "sp", &key, &place)) {
+                rt_err("kern-obj-thaw-at: bad args");
+                return sc->NIL;
+        }
+
+        obj = freezer_thawObject(key, &x, &y);
+
+               if (obj)
+               {
+                       obj->relocate(place, x, y, REL_NOTRIG);
+                       scm_mk_ptr(sc, obj);
+                       obj_dec_ref(obj);
+                       return scm_mk_ptr(sc, obj);
+               }
+               
+        return sc->NIL;
+}
+       
+KERN_API_CALL(kern_set_wind)
+{
+        int dur, dir;
+
+        if (unpack(sc, &args, "dd", &dir, &dur)) {
+                rt_err("kern-set-wind: bad args");
+                return sc->F;
+        }
+
+        windSetDirection(dir, dur);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_get_wind)
+{
+        return scm_mk_integer(sc, windGetDirection());
+}
+
+KERN_API_CALL(kern_ui_direction)
+{
+        int dir = ui_get_direction();
+
+        if (dir == CANCEL)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, dir);
+}
+
+KERN_API_CALL(kern_place_get_neighbor)
+{
+        struct place *place;
+        struct place *neighbor;
+        int dir;
+
+        if (unpack(sc, &args, "pd", &place, &dir)) {
+                rt_err("kern-place-get-neighbor: bad args");
+                return sc->NIL;
+        }
+
+        /* lookup neighbor */
+        neighbor = place_get_neighbor(place, dir);
+        if (neighbor)
+                return scm_mk_ptr(sc, neighbor);
+        else
+                return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_get_party)
+{
+        class Character *ch;
+        class Party *party;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-get-party");
+        if (!ch)
+                return sc->NIL;
+
+        party = ch->getParty();
+        if (party)
+                return scm_mk_ptr(sc, party);
+        else
+                return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_add_defense)
+{
+        int val;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-add-defense");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-add-defense: bad args");
+                return sc->NIL;
+        }
+        
+        ch->addDefense(val);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_add_experience)
+{
+        int val;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, 
+                                          "kern-char-add-experience");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-add-experience: bad args");
+                goto done;
+        }
+        
+        ch->addExperience(val);
+ done:
+        return scm_mk_ptr(sc, ch);
+}
+
+KERN_API_CALL(kern_add_magic_negated)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-add-magic-negated: bad args");
+                return sc->F;
+        }
+
+        add_magic_negated(val);
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_get_magic_negated)
+{
+        return scm_mk_integer(sc, MagicNegated);
+}
+
+KERN_API_CALL(kern_add_quicken)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-add-quicken: bad args");
+                return sc->F;
+        }
+
+        add_quicken(val);
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_set_time_accel)
+{
+        float val;
+
+        if (unpack(sc, &args, "f", &val)) {
+                rt_err("kern-set-time-accel: bad args");
+                return sc->F;
+        }
+
+        session_set_time_accel(val);
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_set_turn_count)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-set-turn-count: bad args");
+                return sc->F;
+        }
+
+        session_set_turn_count(val);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_add_reveal)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-add-reveal: bad args");
+                return sc->F;
+        }
+
+        add_reveal(val);
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_add_time_stop)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-add-time-stop: bad args");
+                return sc->F;
+        }
+
+        add_time_stop(val);
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_being_is_hostile)
+{
+        class Being *one, *another;
+
+        if (unpack(sc, &args, "pp", &one, &another)) {
+                rt_err("kern-being-is-hostile: bad args");
+                return sc->F;
+        }
+
+        if (! one || ! another) {
+                rt_err("kern-being-is-hostile: null character");
+                return sc->F;                
+        }
+
+        return are_hostile(one, another) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_being_is_ally)
+{
+        class Being *one, *another;
+
+        if (unpack(sc, &args, "pp", &one, &another)) {
+                rt_err("kern-being-is-ally: bad args");
+                return sc->F;
+        }
+
+        if (! one || ! another) {
+                rt_err("kern-being-is-ally: null character");
+                return sc->F;                
+        }
+
+        return are_allies(one, another) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_add_xray_vision)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-add-xray-vision: bad args");
+                return sc->F;
+        }
+
+        add_xray(val);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_char_charm)
+{
+        int val;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-charm");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-charm: bad args");
+                return sc->NIL;
+        }
+        
+        ch->charm(val);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_uncharm)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-charm");
+        if (!ch)
+                return sc->NIL;
+
+        ch->unCharm();
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_set_jitter)
+{
+        int val;
+
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-map-set-jitter: bad args");
+                return sc->F;
+        }
+
+        mapJitter(val);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_image_load)
+{
+        char *fname, *path;
+        SDL_Surface *image = 0;
+
+        if (unpack(sc, &args, "s", &fname)) {
+                rt_err("kern-image-load: bad args");
+                return sc->NIL;
+        }
+
+        path = file_mkpath(cfg_get("include-dirname"), fname);
+        if (! path) {
+                rt_err("kern-image-load: %s", file_get_error());
+                return sc->NIL;
+        }
+
+        image = IMG_Load(path);
+        if (! image) {
+                rt_err("kern-image-load: %s", SDL_GetError());
+        }
+        free(path);
+
+        return scm_mk_ptr(sc, image);
+}
+
+KERN_API_CALL(kern_image_free)
+{
+        SDL_Surface *image;
+
+        if (unpack(sc, &args, "p", &image)) {
+                rt_err("kern-image-free: bad args");
+                return sc->NIL;
+        }
+
+        SDL_FreeSurface(image);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_set_image)
+{
+        SDL_Surface *image;
+
+        if (unpack(sc, &args, "p", &image)) {
+                rt_err("kern-map-set-image: bad args");
+                return sc->NIL;
+        }
+
+        if (!image) {
+                mapClearImage();
+                mapUpdate(0);
+                return sc->NIL;
+        }
+
+        mapSetImage(image);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_blit_image)
+{
+        SDL_Surface *image;
+        Uint32 x, y;
+
+        if (unpack(sc, &args, "pdd", &image, &x, &y)) {
+                rt_err("kern-map-blit-image: bad args");
+                return sc->NIL;
+        }
+
+        if (!image) {
+                return sc->NIL;
+        }
+
+        mapBlitImage(image, x, y);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_map_get_width)
+{
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "p", &map)) {
+                rt_err("kern-map-get-width: bad args");
+                return sc->NIL;
+        }
+
+        if (!map) {
+                rt_err("kern-map-get-width: null map");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, map->w);
+}
+
+
+KERN_API_CALL(kern_map_get_height)
+{
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "p", &map)) {
+                rt_err("kern-map-get-width: bad args");
+                return sc->NIL;
+        }
+
+        if (!map) {
+                rt_err("kern-map-get-width: null map");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, map->h);
+}
+
+KERN_API_CALL(kern_char_kill)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-kill");
+        if (!ch)
+                return sc->NIL;
+
+        ch->kill();
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_char_resurrect)
+{
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-resurrect");
+        if (!ch)
+                return sc->NIL;
+
+        ch->resurrect();
+
+        return scm_mk_ptr(sc, ch);
+}
+
+KERN_API_CALL(kern_is_valid_location)
+{
+        struct place *place;
+        int x, y;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-is-valid-location?"))
+                return sc->F;
+
+        if (place->wraps)
+                return sc->T;
+
+        if (x < 0 || x >= place_w(place) ||
+            y < 0 || y >= place_h(place))
+                return sc->F;
+
+        return sc->T;
+}
+
+KERN_API_CALL(kern_terrain_blocks_los)
+{
+        struct terrain *terrain;
+
+        if (unpack(sc, &args, "p", &terrain)) {
+                rt_err("kern-terrain-blocks-los?: bad args");
+                return sc->NIL;
+        }
+
+        if(! terrain) {
+                rt_err("kern-terrain-blocks-los?: null terrain");
+                return sc->NIL;
+        }
+
+        return terrain->alpha ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_terrain_get_pclass)
+{
+        struct terrain *terrain;
+
+        if (unpack(sc, &args, "p", &terrain)) {
+                rt_err("kern-terrain-get-pclass: bad args");
+                return sc->NIL;
+        }
+
+        if(! terrain) {
+                rt_err("kern-terrain-get-pclass: null terrain");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, terrain_pclass(terrain));
+}
+
+KERN_API_CALL(kern_terrain_set_combat_map)
+{
+        struct terrain *terrain;
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "pp", &terrain, &map)) {
+                rt_err("kern-terrain-set-combat-map: bad args");
+                return sc->NIL;
+        }
+
+        if(! terrain) {
+                rt_err("kern-terrain-set-combat-map: null terrain");
+                return sc->NIL;
+        }
+
+        terrain->combat_map = map;
+
+        return scm_mk_ptr(sc, terrain);
+}
+
+KERN_API_CALL(kern_terrain_set_combat_handler)
+{
+       struct terrain *terrain;
+       pointer proc;
+       
+       if (unpack(sc, &args, "po", &terrain, &proc)) {
+               rt_err("kern-terrain-set-combat-handler: bad args");
+               return sc->NIL;
+       }
+       
+       if(!terrain) {
+               rt_err("kern-terrain-set-combat-handler: null terrain");
+               return sc->NIL;
+       }
+       
+       if (proc != sc->NIL) {
+               terrain->renderCombat = closure_new(sc, proc);
+               closure_ref(terrain->renderCombat); //TODO clean up this nasty leaky hack
+       }
+       
+       return scm_mk_ptr(sc, terrain);
+}
+
+KERN_API_CALL(kern_terrain_map_inc_ref)
+{
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "p", &map)) {
+                rt_err("kern-terrain-map-inc-ref: bad args");
+                return sc->NIL;
+        }
+
+        terrain_map_ref(map);
+        return scm_mk_ptr(sc, map);
+}
+
+KERN_API_CALL(kern_terrain_map_dec_ref)
+{
+        struct terrain_map *map;
+
+        if (unpack(sc, &args, "p", &map)) {
+                rt_err("kern-terrain-map-dec-ref: bad args");
+                return sc->NIL;
+        }
+
+        terrain_map_ref(map);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_blender)
+{
+        blender_t *blender;
+        pointer rlist;
+        int i = 0;
+
+        blender = (blender_t*)calloc(1, sizeof(*blender));
+        list_init(&blender->list);
+
+        if (unpack(sc, &args, "p", &blender->inf)) {
+                rt_err("kern-terrain-map-blend: bad args");
+                goto abort;
+        }
+
+        /* list of not-superior terrains */
+        rlist = scm_car(sc, args);
+        args = scm_cdr(sc,  args);
+
+        if (! scm_is_pair(sc, rlist)) {
+                rt_err("kern-terrain-map-blend: missing non-superior list");
+                goto abort;
+        }
+
+        while (scm_is_pair(sc, rlist) 
+               && blender->n_nonsup < BLENDER_MAX_NONSUP) {
+                if (unpack(sc, &rlist, "p", &blender->nonsup[blender->n_nonsup])) {
+                        rt_err("kern-terrain-map-blend: non-superior terrain %d bad", i);
+                        goto abort;
+                }
+                blender->n_nonsup++;
+        }
+        
+        if (scm_is_pair(sc, rlist)) {
+                warn("kern-terrain-map-blend: at most %d non-superior "\
+                     "terrains may be used, the rest will be ignored",
+                     BLENDER_MAX_NONSUP);
+        }
+
+        /* list of target (range) terrains */
+        i = 0;
+        rlist = scm_car(sc, args);
+        args = scm_cdr(sc,  args);
+
+        if (! scm_is_pair(sc, rlist)) {
+                rt_err("kern-terrain-map-blend: missing range list");
+                goto abort;
+        }
+
+        while (scm_is_pair(sc, rlist) 
+               && i < BLENDER_N_RANGE) {
+
+                if (unpack(sc, &rlist, "p", &blender->range[i])) {
+                        rt_err("kern-terrain-map-blend: range %d bad", i);
+                        return sc->NIL;
+                }
+
+                i++;
+        }
+
+        if (i < BLENDER_N_RANGE) {
+                rt_err("kern-terrain-map-blend: expected %d ranges, got %d", 
+                       BLENDER_N_RANGE, i);
+                goto abort;
+        }
+
+        session_add(Session, blender, blender_dtor, NULL, NULL);
+        list_add(&Session->blenders, &blender->list);
+
+        return sc->T;
+
+ abort:
+        free(blender);
+        return sc->F;
+}
+
+KERN_API_CALL(kern_terrain_map_blend)
+{
+        struct terrain_map *map;
+        struct terrain *inf, *nonsup[32], *range[16];
+        pointer rlist;
+        int i = 0;
+        int n_nonsup = 0;
+
+        if (unpack(sc, &args, "pp", &map,  &inf)) {
+                rt_err("kern-terrain-map-blend: bad args");
+                return sc->NIL;
+        }
+
+        /* list of not-superior terrains */
+        rlist = scm_car(sc, args);
+        args = scm_cdr(sc,  args);
+
+        if (! scm_is_pair(sc, rlist)) {
+                rt_err("kern-terrain-map-blend: missing non-superior list");
+                return sc->NIL;
+        }
+
+        while (scm_is_pair(sc, rlist) && n_nonsup < array_sz(nonsup)) {
+
+                if (unpack(sc, &rlist, "p", &nonsup[n_nonsup])) {
+                        rt_err("kern-terrain-map-blend: non-superior terrain %d bad", i);
+                        return sc->NIL;
+                }
+
+                n_nonsup++;
+        }
+        
+        if (scm_is_pair(sc, rlist)) {
+                warn("kern-terrain-map-blend: at most %d non-superior "\
+                     "terrains may be used, the rest will be ignored",
+                     array_sz(nonsup));
+        }
+
+        /* list of target (range) terrains */
+        i = 0;
+        rlist = scm_car(sc, args);
+        args = scm_cdr(sc,  args);
+
+        if (! scm_is_pair(sc, rlist)) {
+                rt_err("kern-terrain-map-blend: missing range list");
+                return sc->NIL;
+        }
+
+        while (scm_is_pair(sc, rlist) && i < 16) {
+
+                if (unpack(sc, &rlist, "p", &range[i])) {
+                        rt_err("kern-terrain-map-blend: range %d bad", i);
+                        return sc->NIL;
+                }
+
+                i++;
+        }
+
+        if (i < 16) {
+                rt_err("kern-terrain-map-blend: expected 16 ranges, got %d", i);
+                return sc->NIL;
+        }
+
+        terrain_map_blend(map, inf, n_nonsup, nonsup, range);
+
+        return scm_mk_ptr(sc, map);
+}
+
+KERN_API_CALL(kern_place_get_width)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-width: bad args");
+                return sc->NIL;
+        }
+
+        if (!place) {
+                rt_err("kern-place-get-width: null place");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, place_w(place));
+}
+
+KERN_API_CALL(kern_place_get_vehicle)
+{
+        struct place *place;
+        int x, y;
+        class Vehicle *veh;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-place-get-vehicle"))
+                return sc->NIL;
+
+        if (!place) {
+                rt_err("kern-place-get-vehicle: null place");
+                return sc->NIL;
+        }
+
+        veh = place_get_vehicle(place, x, y);
+        
+        return veh ? scm_mk_ptr(sc, veh) : sc->NIL;
+}
+
+KERN_API_CALL(kern_place_get_height)
+{
+        struct place *place;
+
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-place-get-height: bad args");
+                return sc->NIL;
+        }
+
+        if (!place) {
+                rt_err("kern-place-get-height: null place");
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, place_h(place));
+}
+
+KERN_API_CALL(kern_get_distance)
+{
+        struct place *p1, *p2;
+        int x1, x2, y1, y2;
+
+        if (unpack_loc(sc, &args, &p1, &x1, &y1, "kern-get-distance") ||
+            unpack_loc(sc, &args, &p2, &x2, &y2, "kern-get-distance"))
+                return sc->NIL;
+
+        /* warn("p1=%s x1=%d y1=%d x2=%d y2=%d\n", p1->name, x1, y1, x2, y2); */
+
+        if (p1 != p2) {
+                rt_err("kern-get-distance: place %s different from %s",
+                       p1->tag, p2->tag);
+                return sc->NIL;
+        }
+
+        return scm_mk_integer(sc, place_flying_distance(p1, x1, y1, x2, y2));
+}
+
+KERN_API_CALL(kern_in_los)
+{
+        struct place *p1, *p2;
+        int x1, x2, y1, y2;
+
+        if (unpack_loc(sc, &args, &p1, &x1, &y1, "kern-in-los?") ||
+            unpack_loc(sc, &args, &p2, &x2, &y2, "kern-in-los?"))
+                return sc->F;
+
+        if (p1 != p2) {
+                /* happens sometimes when player exits a place and NPC's
+                 * looking for him in the same round */
+                warn("kern-in-los?: place %s different from %s\n",
+                     p1->tag, p2->tag);
+                return sc->F;
+        }
+
+        return place_in_los(p1, x1, y1, p2, x2, y2) ? sc->T : sc->F;
+}
+
+KERN_API_CALL(kern_map_set_peering)
+{
+        int val;
+        if (unpack(sc, &args, "b", &val)) {
+                rt_err("kern-map-set-peering: bad args");
+                return sc->NIL;
+        }
+        mapPeer(val);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_ui_waitkey)
+{
+        int key;
+        getkey(&key, anykey);
+        return scm_mk_integer(sc, key);
+}
+
+KERN_API_CALL(kern_char_dec_mana)
+{
+        int val;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-char-dec-mana");
+        if (!ch)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-dec-mana: bad args");
+                return sc->NIL;
+        }
+        
+        ch->addMana(0 - val);
+
+        return sc->NIL;        
+}
+
+KERN_API_CALL(kern_test_recursion)
+{
+        pointer func;
+
+        if (unpack(sc, &args, "o", &func)) {
+                rt_err("kern-test-recursion: bad args");
+                return sc->NIL;
+        }
+
+        scheme_call(sc, func, sc->NIL);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_ui_select_from_list)
+{
+        struct KeyHandler kh;
+       struct ScrollerContext data;
+        const char **strings;
+        int list_sz;
+        int i = 0;
+        enum StatusMode omode;
+        char *selection = NULL;
+
+        list_sz = scm_len(sc, args);
+        if (! list_sz)
+                return sc->NIL;
+
+        strings = (const char**)calloc(list_sz, sizeof(strings[0]));
+        assert(strings);
+
+        while (scm_is_pair(sc, args)) {
+                if (unpack(sc, &args, "s", &strings[i])) {
+                        rt_err("kern-ui-select-from-list: bad args");
+                        goto done;
+                }
+                i++;
+        }
+
+        foogodSetHintText(SCROLLER_HINT);
+        foogodSetMode(FOOGOD_HINT);
+        omode = statusGetMode();
+        statusSetStringList("Select", list_sz, strings);
+        statusSetMode(StringList);
+
+        data.selection = NULL;
+        data.selector  = String;
+        kh.fx   = scroller;
+        kh.data = &data;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+        statusSetMode(omode);
+        foogodSetMode(FOOGOD_DEFAULT);
+        
+        selection = (char*)data.selection;
+
+ done:
+        if (strings)
+                free(strings);
+
+        if (selection)
+                return scm_mk_string(sc, selection);
+
+        return sc->NIL;
+
+}
+
+KERN_API_CALL(kern_ui_select_item)
+{
+        enum StatusMode omode;
+        struct inv_entry *ie;
+        class Character *ch;
+
+        ch = (class Character*)unpack_obj(sc, &args, "kern-ui-select-item");
+        if (!ch || !ch->getInventoryContainer())
+                return sc->NIL;
+
+        omode = statusGetMode();
+        statusBrowseContainer(ch->getInventoryContainer(), "Select");
+        ie = ui_select_item();
+        statusSetMode(omode);
+
+        if (!ie) {
+                return sc->NIL;
+        }
+
+        return scm_mk_ptr(sc, ie->type);
+}
+
+KERN_API_CALL(kern_ui_page_text)
+{
+        struct KeyHandler kh;
+        char *title;
+        char *text = NULL;   
+        int len = 0;
+        int lines = 0;
+
+        if (unpack(sc, &args, "s", &title)) {
+                rt_err("kern-ui-status-page-text: bad title");
+                return sc->NIL;
+        }
+
+        while (scm_is_pair(sc, args)) {
+
+                char *line;
+
+                if (unpack(sc, &args, "s", &line)) {
+                        rt_err("kern-ui-status-page-text: bad text line");                        
+                        goto done;
+                }
+                
+                len += strlen(line);
+                len++; /* for \n */
+                text = (char*)realloc(text, len + 1 /* for \0 */);
+                if (lines == 0) {
+                        text[0] = 0;
+                }
+                strcat(text, line);
+                strcat(text, "\n");
+                lines++;
+        }
+
+        foogodSetHintText(PAGER_HINT);
+        foogodSetMode(FOOGOD_HINT);
+        statusSetPageText(title, text);
+        statusSetMode(Page);
+        consolePrint("[Hit ESC to continue]\n");
+
+        kh.fx = scroller;
+        kh.data = NULL;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+        statusSetMode(ShowParty);
+        foogodSetMode(FOOGOD_DEFAULT);
+
+ done:
+        if (text)
+                free(text);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_remove_from_inventory)
+{
+        class Object *obj;
+        class ObjectType *type;
+        int amount;
+
+        if (unpack(sc, &args, "ppd", &obj, &type, &amount)) {
+                rt_err("kern-obj-remove-from-inventory: bad args");
+                return sc->NIL;
+        }
+
+        if (! obj->takeOut(type, amount)) {
+                rt_err("kern-obj-remove-from-inventory: failed! "\
+                       "(is quantity > amount available to take out?)");
+        }
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_add_to_inventory)
+{
+        class Object *obj;
+        class ObjectType *type;
+        int amount;
+
+        if (unpack(sc, &args, "ppd", &obj, &type, &amount)) {
+                rt_err("kern-obj-add-to-inventory: bad args");
+                return sc->NIL;
+        }
+
+        obj->add(type, amount);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_ptable)
+{
+        int n_mmode;
+        int n_pclass;
+        int pclass;
+        struct ptable *ptable;
+        pointer row;
+        pointer col;
+
+        /* The ptable table is a list of lists. Each row corresponds to a
+         * passability class (a property of terrain, and objects which affect
+         * passability onto a tile). Each column corresponds to a movement
+         * mode. */
+
+        if (! scm_is_pair(sc, args)) {
+                load_err("kern-mk-ptable: arg 0 not a list");
+                return sc->NIL;
+        }
+
+        /* count the number of passability classes and movement modes given in
+         * the table */
+        row = args;
+        col = scm_car(sc, args);
+
+        n_pclass = scm_len(sc, row);
+        n_mmode = scm_len(sc, col);
+
+        if (n_pclass <= 0) {
+                load_err("kern-mk-ptable: 0 rows given");
+                return sc->NIL;
+        }
+
+        if (n_mmode <= 0) {
+                load_err("kern-mk-ptable: row 0 has no columns");
+                return sc->NIL;
+        }
+
+        /* allocate the kernel passability table */
+        ptable = ptable_new(n_mmode, n_pclass);
+        
+        /* for each row (passability class) */
+        for (pclass = 0; pclass < n_pclass; pclass++) {
+
+                int mmode;
+
+                col = scm_car(sc, row);
+                row = scm_cdr(sc, row);
+
+                if (scm_len(sc, col) < n_mmode) {
+                        load_err("kern-mk-ptable: row %d has only %d columns",
+                                 pclass, scm_len(sc, col));
+                        goto abort;
+                }
+
+                /* for each column (movement mode) */
+                for (mmode = 0; mmode < n_mmode; mmode++) {
+
+                        int mcost;
+
+                        /* get the movement cost */
+                        if (unpack(sc, &col, "d", &mcost)) {
+                                load_err("kern-mk-ptable: row %d col %d bad arg",
+                                         pclass, mmode);
+                                goto abort;
+                        }
+
+                        /* insert it into the passability table */
+                        ptable_set(ptable, mmode, pclass, mcost);
+                }
+        }
+
+
+        /* associate the session with the new table */
+        if (Session->ptable) {
+                ptable_del(Session->ptable);
+        }
+        Session->ptable = ptable;
+
+        return sc->NIL;
+
+ abort:
+        ptable_del(ptable);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_mk_dtable)
+{
+        int n_factions;
+        int r_faction;
+        struct dtable *dtable;
+        pointer rows;
+        pointer row;
+
+        /* The dtable table is a list of lists. Each row corresponds to a
+         * passability class (a property of terrain, and objects which affect
+         * passability onto a tile). Each column corresponds to a movement
+         * mode. */
+
+        if (! scm_is_pair(sc, args)) {
+                load_err("kern-mk-dtable: arg 0 not a list");
+                return sc->NIL;
+        }
+
+        /* count the number of factions given in the table */
+        rows = args;
+        row  = scm_car(sc, rows);
+        n_factions = scm_len(sc, rows);
+        if (n_factions != scm_len(sc, row)) {
+                load_err("kern-mk-dtable: # of rows and columns must be same");
+                return sc->NIL;
+        }
+        if (n_factions <= 0) {
+                load_err("kern-mk-dtable: 0 factions given");
+                return sc->NIL;
+        }
+
+        /* allocate the kernel table */
+        dtable = dtable_new(n_factions);
+
+        /* for each row */
+        for (r_faction = 0; r_faction < n_factions; r_faction++) {
+
+                int c_faction;
+
+                row  = scm_car(sc, rows);
+                rows = scm_cdr(sc, rows);
+
+                if (scm_len(sc, row) < n_factions) {
+                        load_err("kern-mk-dtable: row %d has only %d columns "
+                                 "(expected %d)",
+                                 r_faction, scm_len(sc, row),
+                                 n_factions);
+                        goto abort;
+                }
+
+                /* for each column up to the limit */
+                for (c_faction = 0; c_faction < n_factions; c_faction++) {
+
+                        int val;
+
+                        /* unpack the value */
+                        if (unpack(sc, &row, "d", &val)) {
+                                load_err("kern-mk-dtable: row %d column %d "
+                                         "is a bad entry", r_faction, 
+                                         c_faction);
+                                goto abort;
+                        }
+                        
+                        /* poke it into the table */
+                        dtable_set(dtable, r_faction, c_faction, val);
+                }
+        }
+
+        /* associate the session with the new table */
+        if (Session->dtable) {
+                dtable_del(Session->dtable);
+        }
+        Session->dtable = dtable;
+
+        return scm_mk_ptr(sc, dtable);
+
+ abort:
+        dtable_del(dtable);
+        return sc->NIL;
+}
+
+#define DTABLE_SET    0x81
+#define DTABLE_GET    0x05
+#define DTABLE_INC    0x06
+#define DTABLE_DEC    0x07
+
+#define DTABLE_FX_USES_LEVEL(fx) ((fx) & 0x80)
+
+static pointer kern_dtable_aux(scheme *sc, pointer args, const char *name, int fx)
+{
+        int f1, f2, level;
+        const char *errstr = NULL;
+
+        if (! session_dtable()) {
+                errstr = "no dtable";
+                goto abort;
+        }
+
+        if (unpack(sc, &args, "dd", &f1, &f2)) {
+                errstr = "bad faction args";
+                goto abort;
+        }
+
+        if (DTABLE_FX_USES_LEVEL(fx)) {
+                if (unpack(sc, &args, "d", &level)) {
+                        errstr = "bad level arg";
+                        goto abort;
+                }
+        }
+
+        switch (fx) {
+        case DTABLE_SET:
+                dtable_set(session_dtable(), f1, f2, level);
+                break;
+        case DTABLE_GET:
+                level = dtable_get(session_dtable(), f1, f2);
+                return scm_mk_integer(sc, level);
+                break;
+        case DTABLE_INC:
+                dtable_inc(session_dtable(), f1, f2);
+                break;
+        case DTABLE_DEC:
+                dtable_dec(session_dtable(), f1, f2);
+                break;
+        default:
+                assert(0);
+                break;
+        }
+
+        return sc->T;
+abort:
+        rt_err("%s: %s", name, errstr);
+        return sc->F;
+
+}
+
+KERN_API_CALL(kern_dtable_set)
+{
+        return kern_dtable_aux(sc, args, "kern_dtable_set", DTABLE_SET);
+}
+
+KERN_API_CALL(kern_dtable_get)
+{
+        return kern_dtable_aux(sc, args, "kern_dtable_get", DTABLE_GET);
+}
+
+KERN_API_CALL(kern_dtable_inc)
+{
+        return kern_dtable_aux(sc, args, "kern_dtable_inc", DTABLE_INC);
+}
+
+KERN_API_CALL(kern_dtable_dec)
+{
+        return kern_dtable_aux(sc, args, "kern_dtable_dec", DTABLE_DEC);
+}
+
+KERN_API_CALL(kern_party_add_member)
+{
+        class Party *party;
+        class Character *new_member;
+
+        party = (Party*)unpack_obj(sc, &args, "kern_party_add_member:<party>");
+        if (!party)
+                return sc->NIL;
+
+        new_member = (class Character*)unpack_obj(sc, &args, 
+                                                  "kern_party_add_member:<member>");
+        if (!new_member)
+                return sc->NIL;
+
+        if (party->addMember(new_member))
+                return sc->T;
+
+        return sc->F;
+}
+
+KERN_API_CALL(kern_party_set_vehicle)
+{
+        class Party *party;
+        class Vehicle *vehicle;
+
+        party = (Party*)unpack_obj(sc, &args, "kern-party-set-vehicle");
+        if (!party)
+                return sc->NIL;
+
+        vehicle = (Vehicle*)unpack_obj(sc, &args, "kern-party-set-vehicle");
+        party->setVehicle(vehicle);
+
+        return scm_mk_ptr(sc, party);
+}
+
+KERN_API_CALL(kern_party_get_vehicle)
+{
+        class Party *party;
+        class Vehicle *vehicle;
+
+        party = (Party*)unpack_obj(sc, &args, "kern-party-get-vehicle");
+        if (!party)
+                return sc->NIL;
+
+        vehicle = party->getVehicle();
+        if (vehicle)
+                return scm_mk_ptr(sc, vehicle);
+        return sc->NIL;
+}
+
+static bool wrap_kern_append_obj(class Character *c, void *v)
+{
+        kern_append_object(c, v);
+        return false;
+}
+
+KERN_API_CALL(kern_get_time)
+{
+        pointer head, tail, cell;
+
+        /* have to do everything in forward order so that our cells remain
+         * protected from gc until the list is built */
+        head = _cons(sc, scm_mk_integer(sc, clock_year()), sc->NIL, 0);
+        tail = head;
+        scm_protect(sc, head);
+
+        cell = _cons(sc, scm_mk_integer(sc, clock_month()), sc->NIL, 0);
+        tail->_object._cons._cdr = cell;
+        tail = cell;
+
+        cell = _cons(sc, scm_mk_integer(sc, clock_week()), sc->NIL, 0);
+        tail->_object._cons._cdr = cell;
+        tail = cell;
+
+        cell = _cons(sc, scm_mk_integer(sc, clock_day()), sc->NIL, 0);
+        tail->_object._cons._cdr = cell;
+        tail = cell;
+
+        cell = _cons(sc, scm_mk_integer(sc, clock_hour()), sc->NIL, 0);
+        tail->_object._cons._cdr = cell;
+        tail = cell;
+
+        cell = _cons(sc, scm_mk_integer(sc, clock_minute()), sc->NIL, 0);
+        tail->_object._cons._cdr = cell;
+        tail = cell;
+
+        scm_unprotect(sc, head);
+        return head;
+}
+
+KERN_API_CALL(kern_get_time_remainder)
+{
+        return scm_mk_integer(sc, clock_tick());
+}
+
+
+KERN_API_CALL(kern_get_total_minutes)
+{
+               return scm_mk_integer(sc, clock_time());
+}
+
+
+KERN_API_CALL(kern_party_get_members)
+{
+        class Party *party;
+        struct kern_append_info info;
+
+        if (unpack(sc, &args, "p", &party)) {
+                rt_err("kern-party-get-members: bad args");
+                return sc->NIL;
+        }
+
+        /* initialize the context used by the callback to append objects */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = NULL;
+        info.data = NULL;
+
+        /* build a scheme list of the objects at that location */
+        party->forEachMember(wrap_kern_append_obj, &info);
+
+        /* unprotect the list prior to return */
+        if (info.head != sc->NIL)
+                scm_unprotect(sc, info.head);
+
+        /* return the scheme list */
+        return info.head;
+}
+
+KERN_API_CALL(kern_being_set_base_faction)
+{
+        class Being *being;
+        int faction;
+
+        being = (class Being*)unpack_obj(sc, &args, "kern-being-set-base-faction");
+        if (!being)
+                goto done;
+
+        if (unpack(sc, &args, "d", &faction)) {
+                rt_err("kern-being-set-base-faction: bad arg");
+                goto done;
+        }
+
+        being->setBaseFaction(faction);
+ done:
+        return scm_mk_ptr(sc, being);
+
+}
+
+KERN_API_CALL(kern_being_set_current_faction)
+{
+        class Being *being;
+        int faction;
+
+        being = (class Being*)unpack_obj(sc, &args, "kern-being-set-current-faction");
+        if (!being)
+                goto done;
+
+        if (unpack(sc, &args, "d", &faction)) {
+                rt_err("kern-being-set-current-faction: bad arg");
+                goto done;
+        }
+
+        being->setCurrentFaction(faction);
+ done:
+        return scm_mk_ptr(sc, being);
+
+}
+
+KERN_API_CALL(kern_being_set_name)
+{
+        class Being *being;
+        char *val;
+
+        being = (class Being*)unpack_obj(sc, &args, "kern-being-set-name");
+        if (!being)
+                goto done;
+
+        if (unpack(sc, &args, "s", &val)) {
+                rt_err("kern-being-set-name: bad arg");
+                goto done;
+        }
+
+        being->setName(val);
+ done:
+        return scm_mk_ptr(sc, being);
+
+}
+
+KERN_API_CALL(kern_vehicle_set_name)
+{
+        class Vehicle *vehicle;
+        char *val;
+
+        vehicle = (class Vehicle*)unpack_obj(sc, &args, "kern-vehicle-set-name");
+        if (!vehicle)
+                goto done;
+
+        if (unpack(sc, &args, "s", &val)) {
+                rt_err("kern-vehicle-set-name: bad arg");
+                goto done;
+        }
+
+        vehicle->setName(val);
+ done:
+        return scm_mk_ptr(sc, vehicle);
+
+}
+
+KERN_API_CALL(kern_harm_relations)
+{
+        class Character *cha;
+        class Character *chb;
+
+        if (unpack(sc, &args, "pp", &cha, &chb)) {
+                rt_err("kern-harm-relations: bad args");
+                return sc->NIL;
+        }
+
+               harm_relations(cha,chb);
+
+               return sc->NIL;
+}
+
+KERN_API_CALL(kern_being_get_current_faction)
+{
+        class Being *being;
+        int faction = INVALID_FACTION;
+
+        being = (Being*)unpack_obj(sc, &args, "kern-being-get-current-faction");
+        if (!being)
+                goto done;
+
+        faction = being->getCurrentFaction();
+ done:
+        return scm_mk_integer(sc, faction);
+}
+
+KERN_API_CALL(kern_being_get_base_faction)
+{
+        class Being *being;
+        int faction = INVALID_FACTION;
+
+        being = (Being*)unpack_obj(sc, &args, "kern-being-get-base-faction");
+        if (!being)
+                goto done;
+
+        faction = being->getBaseFaction();
+ done:
+        return scm_mk_integer(sc, faction);
+}
+
+KERN_API_CALL(kern_add_hook)
+{
+        pointer pproc;
+        char *hookstr;
+
+        if(unpack(sc, &args, "yc", &hookstr, &pproc)) {
+                load_err("%s: bad args", __FUNCTION__);
+                return sc->NIL;
+        }
+
+////         printf("%s() %s: ", __FUNCTION__, hookstr);
+////         if (scm_is_sym(sc, pproc)) {
+////             printf("%s\n", scm_sym_val(sc, pproc));
+////         } else {
+////             printf("<raw code>\n");
+////         }
+
+        session_hook_id_t id = session_str_to_hook_id(hookstr);
+        if (id >= NUM_HOOKS) {
+            load_err("%s: bad hook id=%d (%s)", __FUNCTION__, id, hookstr);
+            return sc->NIL;
+        }
+
+        pointer pargs = sc->NIL;
+        if (scm_is_pair(sc, args)) {
+            pargs = scm_car(sc, args);
+        }
+        void *ret = session_add_hook(Session, (session_hook_id_t)id, closure_new(sc, pproc), pargs);
+        return ret ? scm_mk_ptr(sc, ret) : sc->NIL;
+}
+
+KERN_API_CALL(kern_rm_hook)
+{
+    pointer pproc;
+    char *hookstr;
+    
+    if(unpack(sc, &args, "yc", &hookstr, &pproc)) {
+        load_err("%s: bad args", __FUNCTION__);
+        return sc->NIL;
+    }
+    
+    session_hook_id_t id = session_str_to_hook_id(hookstr);
+    if (id < NUM_HOOKS) {
+        session_rm_hook(Session, (session_hook_id_t)id, pproc);
+    }
+    
+    return sc->NIL;
+}
+
+KERN_API_CALL(kern_add_query)
+{
+        pointer pproc;
+        char *str;
+        int id = 0;
+
+        if(unpack(sc, &args, "yo", &str, &pproc)) {
+                load_err("%s: bad args", __FUNCTION__);
+                return sc->F;
+        }
+        
+        for (id = 0; id < NUM_HOOKS; id++) {
+                if (! strcmp(query_to_id[id], str)) {
+                        session_add_query(Session, (session_query_id_t)id, closure_new(sc, pproc));
+                        return pproc;
+                }
+        }
+
+        return sc->F;
+}
+
+KERN_API_CALL(kern_player_set_follow_mode)
+{
+        player_party->enableFollowMode();
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_has)
+{
+        class Object *object;
+        class ObjectType *type;
+        int has = 0;
+
+        object = (Object*)unpack_obj(sc, &args, "kern-obj-has");
+        if (!object)
+                goto done;
+
+        if (unpack(sc, &args, "p", &type)) {
+                rt_err("kern-obj-has?");
+                goto done;
+        }
+
+        has = object->hasInInventory(type);
+ done:
+        return has ? sc->T : sc->F;
+}
+
+static pointer kern_astar_path_to_scheme_list(scheme *sc, struct astar_node *path)
+{
+        pointer head;
+        pointer cell;
+
+        /* base case - end of path */
+        if (!path)
+                return sc->NIL;
+
+        /* create a scheme pair (x, y) */
+        cell = _cons(sc, 
+                     scm_mk_integer(sc, path->x), 
+                     scm_mk_integer(sc, path->y),
+                     0);
+
+        /* recursively build a scheme list of pairs */
+        head = _cons(sc, 
+                     cell, 
+                     kern_astar_path_to_scheme_list(sc, path->next), 
+                     0);
+
+        /* cleanup the node */
+        astar_node_destroy(path);
+
+        return head;
+}
+
+KERN_API_CALL(kern_obj_find_path)
+{
+        class Object *object;
+        struct place *place;
+        struct astar_node *path = NULL;
+        struct astar_search_info as_info;
+        pointer sc_path;
+
+        memset(&as_info, 0, sizeof (as_info));
+
+        object = (Object*)unpack_obj(sc, &args, "kern-obj-find-path");
+        if (!object)
+                return sc->NIL;
+
+        if (unpack_loc(sc, &args, &place, &as_info.x1, &as_info.y1, 
+                       "kern-obj-find-path")) {
+                return sc->NIL;
+        }
+
+        /* can't pathfind between places */
+        if (object->getPlace() != place)
+                return sc->NIL;
+
+        /* find the path */
+        as_info.x0 = object->getX();
+        as_info.y0 = object->getY();
+        path = place_find_path(place, &as_info, object);
+        if (! path)
+                return sc->NIL;
+
+        /* convert the path to a scheme list */
+        sc_path = kern_astar_path_to_scheme_list(sc, path);
+        return sc_path;
+}
+
+static pointer kern_build_weapon_list(scheme *sc, 
+                                      class Character *character, 
+                                      class ArmsType *weapon,
+                                                                         int *armsIndex)
+{
+        /* base case */
+        if (! weapon)
+                return sc->NIL;
+        
+        /* recursive case */
+        return _cons(sc, 
+                     scm_mk_ptr(sc, weapon), 
+                     kern_build_weapon_list(sc, 
+                                            character, 
+                                            character->getNextWeapon(armsIndex),
+                                                                                       armsIndex), 
+                     0);
+}
+
+KERN_API_CALL(kern_char_get_weapons)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-weapons");
+        if (!character)
+                return sc->NIL;
+
+        /* recursively enumerate the character's available weapons into a
+         * scheme list */
+               int armsIndex = 0;
+        return kern_build_weapon_list(sc, 
+                                      character, 
+                                      character->enumerateWeapons(&armsIndex),
+                                                                         &armsIndex);
+}
+
+/**
+ * A generic append-to-scheme-list function.
+ */
+static void kern_list_append(struct kern_append_info *info, void *data)
+{
+        /* alloc a cell */
+        pointer cell = scm_mk_ptr(info->sc, data);
+
+        /* make it a list element */
+        cell = _cons(info->sc, cell, info->sc->NIL, 0);
+        
+        /* add it to the list */
+        if (info->head == info->sc->NIL) {
+                info->head = cell;
+                info->tail = cell;
+
+                /* Protect the head from garbage collection. As long as the
+                 * head is protected the entire list is protected. The caller
+                 * must unprotect the head just before returning the list back
+                 * to scheme, so the collector will clean it up when the script
+                 * no longer needs it. */
+                scm_protect(info->sc, cell);
+
+        } else {
+                info->tail->_object._cons._cdr = cell;
+                info->tail = cell;
+        }  
+}
+
+/**
+ * Used by kern-char-get-skills to add all the skills in a skill set to the
+ * list.
+ */
+static void kern_add_skill_set(struct kern_append_info *info, int pclvl, 
+                               struct skill_set *skset)
+{
+        struct list *elem;
+
+        /* for each skill in the skill set */
+        list_for_each(&skset->skills, elem) {
+
+                struct skill_set_entry *ssent;
+                ssent = list_entry(elem, struct skill_set_entry, list);
+
+                /* is the character of sufficient level? */
+                if (pclvl < ssent->level) {
+                        continue;
+                }
+
+                kern_list_append(info, ssent->skill);
+        }
+}
+
+/**
+ * A generic append-to-scheme-list function.
+ */
+static void kern_list_append_pointer(struct kern_append_info *info, pointer cell)
+{
+        /* make it a list element */
+        cell = _cons(info->sc, cell, info->sc->NIL, 0);
+        
+        /* add it to the list */
+        if (info->head == info->sc->NIL) {
+                info->head = cell;
+                info->tail = cell;
+
+                /* Protect the head from garbage collection. As long as the
+                 * head is protected the entire list is protected. The caller
+                 * must unprotect the head just before returning the list back
+                 * to scheme, so the collector will clean it up when the script
+                 * no longer needs it. */
+                scm_protect(info->sc, cell);
+
+        } else {
+                info->tail->_object._cons._cdr = cell;
+                info->tail = cell;
+        }  
+}
+
+/**
+ * A generic pagination function.
+ * Copies one line of text to output.
+ * output should be pre-allocated, and large enough to glom all of input if necessary
+ * returns a pointer offset to the location the search finished at
+ */
+static char* kern_paginate_text(char *input, char *output)
+{
+       int curlength = 0;
+       char* endinput = NULL;
+       char* endoutput = output;
+       while (*input != 0)
+       {
+               if (isspace(*input))
+               {
+                       endinput = input;
+                       endoutput = output;
+                       //printf("[ ]");
+               }
+               else if (*input == '^') // handle colour codes
+               {
+                       //printf("[col:");
+                       *output=*input;
+                       input++;
+                       output++;
+                       if (*input == 0) break;
+                       if (*input != 'c')
+                       {
+                               //printf("?%c]",*input);
+                               *output=*input;
+                               input++;
+                               output++;
+                               continue;
+                       }
+                       *output=*input;
+                       input++;
+                       output++;
+                       if (*input == 0) break;
+                       if (*input == '+')
+                       {
+                               //printf("+");
+                               *output=*input;
+                               input++;
+                               output++;                               
+                               if (*input == 0) break;
+                       }
+                       //printf("%c]",*input);
+                       *output=*input;
+                       input++;
+                       output++;
+                       continue;
+               }
+               else
+               {
+                       //printf("%c",*input);  
+               }
+               if (curlength >= STAT_CHARS_PER_LINE)
+               {               
+                       //printf("[LEN]\n");
+                       if (endinput != NULL)
+                       {
+                               *endoutput = '\0';
+                               return (endinput + 1);
+                       }
+                       else
+                       {
+                               *output = '\0';
+                               return input;
+                       }
+               }
+               *output=*input;
+               curlength++;
+               input++;
+               output++;
+       }
+       //printf("[EOS]\n");
+       *output='\0';
+       return input;
+}
+
+KERN_API_CALL(kern_ui_paginate_text)
+{
+       struct kern_append_info info;
+       
+       /* initialize the context used by the callback to append objects */
+       info.sc = sc;
+       info.head = sc->NIL;
+       info.tail = sc->NIL;
+       info.filter = NULL;
+       info.data = NULL;
+       
+       while (scm_is_pair(sc, args))
+       {
+               char *line;     
+               if (unpack(sc, &args, "s", &line))
+               {
+                       rt_err("kern-ui-paginate-text: bad text line");
+                       break;
+               }
+               // shortcut empty strings
+               if (*line == '\0')
+               {
+                       pointer paginated_string_element=scm_mk_string(sc,line);
+                       kern_list_append_pointer(&info, paginated_string_element);
+                       continue;
+               }
+               
+               char *buffer;
+               int totallen = strlen(line);
+               buffer = (char *)malloc((1+totallen)*sizeof(char));
+               assert(buffer);
+               assert(line[totallen]==0);      
+               
+               char* seek=line;
+               while (*seek != 0)
+               {
+                       *buffer='\0';
+                       seek = kern_paginate_text(seek,buffer);
+                       pointer paginated_string_element=scm_mk_string(sc,buffer);
+                       kern_list_append_pointer(&info, paginated_string_element);
+               }
+               
+               free(buffer);
+       }
+       
+       /* unprotect the list prior to return */
+       if (info.head != sc->NIL)
+           scm_unprotect(sc, info.head);
+
+       return info.head;
+}
+
+
+KERN_API_CALL(kern_char_get_skills)
+{
+        class Character *subj;
+        struct kern_append_info info;
+
+        /* unpack the character */
+        subj = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-skills");
+        if (!subj) {
+                return sc->NIL;
+        }
+        
+        /* initialize the relevant list-building info */
+        memset(&info, 0, sizeof(info));
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+
+        /* add species skills */
+        if (subj->species
+            && subj->species->skills) {
+                kern_add_skill_set(&info, subj->getLevel(), 
+                                   subj->species->skills);
+        }
+
+        /* add occupation skills */
+        if (subj->occ
+            && subj->occ->skills) {
+                kern_add_skill_set(&info, subj->getLevel(), 
+                                   subj->occ->skills);
+        }
+        
+        /* allow the list to be gc'd when the script is done with it */
+        if (info.head != sc->NIL) {
+                scm_unprotect(sc, info.head);
+        }
+
+        return info.head;
+}
+
+static pointer kern_build_arm_list(scheme *sc, 
+                                   class Character *character, 
+                                   class ArmsType *arm,
+                                   int *armsIndex)
+{
+        /* base case */
+        if (! arm)
+                return sc->NIL;
+        
+        /* recursive case */
+        return _cons(sc, 
+                     scm_mk_ptr(sc, arm), 
+                     kern_build_arm_list(sc, 
+                                         character, 
+                                         character->getNextArms(armsIndex),
+                                         armsIndex), 
+                     0);
+}
+
+KERN_API_CALL(kern_char_get_arms)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-arms");
+        if (!character)
+                return sc->NIL;
+
+        /* recursively enumerate the character's available arms into a
+         * scheme list */
+               int armsIndex=0;
+        return kern_build_arm_list(sc, 
+                                      character, 
+                                      character->enumerateArms(&armsIndex),
+                                                                         &armsIndex);
+}
+
+KERN_API_CALL(kern_char_arm_self)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-weapons");
+        if (!character)
+                return sc->NIL;
+
+        /* recursively enumerate the character's available weapons into a
+         * scheme list */
+        character->armThyself();
+
+        return scm_mk_ptr(sc, character);
+}
+
+static pointer kern_build_container_list(scheme *sc,
+                                         class Container *container,
+                                         struct inv_entry *ie)
+{
+        pointer cell;
+
+        /* base case */
+        if (! ie)
+                return sc->NIL;
+        
+        /* make a type/count pair */
+        cell = _cons(sc, 
+                     scm_mk_ptr(sc, ie->type),
+                     scm_mk_integer(sc, ie->count),
+                     0);
+
+        /* recursively build a list of such pairs */
+        return _cons(sc, 
+                     cell,
+                     kern_build_container_list(sc, 
+                                               container, 
+                                               container->next(ie, NULL)), 
+                     0);
+}
+
+KERN_API_CALL(kern_char_get_inventory)
+{
+        class Container *container;
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-inventory");
+        if (!character)
+                return sc->NIL;
+
+        /* grab it's inventory container */
+        container = character->getInventoryContainer();
+        if (!container)
+                return sc->NIL;
+
+        /* enumerate its contents into a scheme list */
+        return kern_build_container_list(sc, container, container->first(NULL));
+}
+
+KERN_API_CALL(kern_char_get_hp)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-hp");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getHp());
+}
+
+KERN_API_CALL(kern_obj_get_hp)
+{
+        class Object *kobj;
+
+        /* unpack the character */
+        kobj = (class Object*)unpack_obj(sc, &args, 
+                                                 "kern-obj-get-hp");
+        if (!kobj)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, kobj->getHp());
+}
+
+KERN_API_CALL(kern_char_get_max_hp)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-max-hp");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getMaxHp());
+}
+
+KERN_API_CALL(kern_char_get_max_mana)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, 
+                                                 "kern-char-get-max-mana");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getMaxMana());
+}
+
+KERN_API_CALL(kern_char_get_level)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-level");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getLevel());
+}
+
+
+KERN_API_CALL(kern_char_get_experience_value)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-level");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getExperienceValue());
+}
+
+KERN_API_CALL(kern_char_set_level)
+{
+        class Character *character;
+        int val = 0;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-set-level");
+        if (!character)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-level: bad args");
+                return sc->NIL;
+        }
+
+        character->setLevel(val);
+        return scm_mk_ptr(sc, character);
+}
+
+KERN_API_CALL(kern_char_get_strength)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-strength");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getStrength());
+}
+
+KERN_API_CALL(kern_char_get_dexterity)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-dexterity");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getDexterity());
+}
+
+KERN_API_CALL(kern_char_get_intelligence)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-intelligence");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getIntelligence());
+
+}
+
+KERN_API_CALL(kern_char_get_base_strength)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-strength");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getBaseStrength());
+}
+
+KERN_API_CALL(kern_char_get_base_dexterity)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-dexterity");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getBaseDexterity());
+}
+
+KERN_API_CALL(kern_char_get_base_intelligence)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-intelligence");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getBaseIntelligence());
+
+}
+
+KERN_API_CALL(kern_char_set_strength)
+{
+        class Character *character;
+        int val = 0;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-set-strength");
+        if (!character)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-strength: bad args");
+                return sc->NIL;
+        }
+
+       character->setStrength(val);
+        return scm_mk_ptr(sc, character);
+}
+
+KERN_API_CALL(kern_char_set_dexterity)
+{
+        class Character *character;
+        int val = 0;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-set-dexterity");
+        if (!character)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-dexterity: bad args");
+                return sc->NIL;
+        }
+
+       character->setDexterity(val);
+        return scm_mk_ptr(sc, character);
+}
+
+KERN_API_CALL(kern_char_set_intelligence)
+{
+        class Character *character;
+        int val = 0;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-set-intelligence");
+        if (!character)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-intelligence: bad args");
+                return sc->NIL;
+        }
+
+       character->setIntelligence(val);
+        return scm_mk_ptr(sc, character);
+}
+
+KERN_API_CALL(kern_char_get_speed)
+{
+        class Character *character;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-get-speed");
+        if (!character)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, character->getSpeed());
+}
+
+KERN_API_CALL(kern_char_set_speed)
+{
+        class Character *character;
+        int val = 0;
+
+        /* unpack the character */
+        character = (class Character*)unpack_obj(sc, &args, "kern-char-set-speed");
+        if (!character)
+                return sc->NIL;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-char-set-speed: bad args");
+                return sc->NIL;
+        }
+
+       character->setSpeed(val);
+        return scm_mk_ptr(sc, character);
+}
+
+KERN_API_CALL(kern_obj_get_ap)
+{
+        class Object *object;
+
+        /* unpack the object */
+        object = (class Object*)unpack_obj(sc, &args, "kern-obj-get-ap");
+        if (!object)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, object->getActionPoints());
+}
+
+KERN_API_CALL(kern_obj_get_count)
+{
+        class Object *object;
+
+        /* unpack the object */
+        object = (class Object*)unpack_obj(sc, &args, "kern-obj-get-count");
+        if (!object)
+                return sc->NIL;
+
+        return scm_mk_integer(sc, object->getCount());
+}
+
+KERN_API_CALL(kern_arms_type_get_range)
+{
+        class ArmsType *type;
+
+        /* unpack the type (should be an arms type, but no way to safely
+         * tell) */
+        if (unpack(sc, &args, "p", &type)) {
+                rt_err("kern-arms-type-get-range");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! type) {
+                rt_err("kern-arms-type-get-range: null type");
+                return scm_mk_integer(sc, 0);
+        }
+
+        /* get the range */
+        return scm_mk_integer(sc, type->getRange());
+}
+
+KERN_API_CALL(kern_arms_type_get_ammo_type)
+{
+        class ArmsType *type;
+        class ObjectType *ammo;
+
+        /* unpack the type (should be an arms type, but no way to safely
+         * tell) */
+        if (unpack(sc, &args, "p", &type)) {
+                rt_err("kern-char-arms-type");
+                return sc->NIL;
+        }
+
+        /* get the ammo type */
+        ammo = type->getAmmoType();
+
+        /* return it, if any */
+        return ammo ? scm_mk_ptr(sc, ammo) : sc->NIL;
+}
+
+KERN_API_CALL(kern_arms_type_set_mmode)
+{
+        class ArmsType *type;
+        struct mmode *mmode;
+        
+        /* unpack the type (should be an arms type, but no way to safely
+         * tell) */
+        if (unpack(sc, &args, "pp", &type, &mmode)) {
+                rt_err("kern-arms-type-set-mmode");
+                return sc->NIL;
+        }
+
+        if (! type) {
+                rt_err("kern-arms-type-set-mmode: null type");
+                return sc->NIL;
+        }
+
+        type->setMovementMode(mmode);
+
+        return sc->NIL;
+}
+
+
+KERN_API_CALL(kern_arms_type_fire_in_direction)
+{
+       class ArmsType *type;
+       struct place *place;
+       int startx, starty;
+       int dx,dy;
+       
+       /* unpack the type (should be an arms type, but no way to safely
+       * tell) */
+       if (unpack(sc, &args, "p", &type)) {
+               rt_err("kern_arms_type_fire_in_direction");
+               return sc->NIL;
+       }
+       
+       if (unpack_loc(sc, &args, &place, &startx,&starty, "kern_arms_type_fire_in_direction"))
+               return sc->NIL;
+       
+       if (unpack(sc, &args, "dd", &dx,&dy)) {
+               rt_err("kern_arms_type_fire_in_direction");
+               return sc->NIL;
+       }
+               
+       if (! type) {
+               rt_err("kern_arms_type_fire_in_direction: null type");
+               return sc->NIL;
+       }
+       
+       if (! place) {
+               rt_err("kern_arms_type_fire_in_direction: null place");
+               return sc->NIL;
+       }
+       
+       type->fireInDirection(place, startx, starty, dx, dy, NULL);
+       
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_move)
+{
+       class Object *object;
+       int dx, dy;
+       enum MoveResult result;
+       
+       object = (Object*)unpack_obj(sc, &args, "kern-obj-move");
+       if (!object)
+               return sc->F;
+       
+       if (unpack(sc, &args, "dd", &dx, &dy))
+       {
+               rt_err("kern-obj-move: bad args");
+               return sc->F;
+       }
+       
+       //moves can have nasty consequences,
+       //so keep our own ref to the object for a bit
+       obj_inc_ref(object);
+       result = object->move(dx, dy);
+       obj_dec_ref(object);
+       
+       switch (result)
+       {
+               case MovedOk:
+               case ExitedMap:
+               case SwitchedOccupants:
+                       return sc->T;
+                       break;
+               default:
+                       return sc->F;
+       }
+}
+
+KERN_API_CALL(kern_get_ticks)
+{
+        return scm_mk_integer(sc, SDL_GetTicks());
+}
+
+KERN_API_CALL(kern_ticks_per_turn)
+{
+        return scm_mk_integer(sc, session_ticks_per_turn());
+}
+
+static int kern_obj_is_type(class Object *obj, struct kern_append_info *info)
+{
+        return (obj->getObjectType() == (class ObjectType*)info->data);
+}
+
+static void kern_append_loc(Object *obj, void *data)
+{
+        pointer cell;
+        struct kern_append_info *info;
+
+        info = (struct kern_append_info *)data;
+
+        /* If there is a filter then use it */
+        if (info->filter != NULL)
+
+                /* If the filter rejects the object then don't append it */
+                if (! info->filter(obj, info))
+                        return;
+
+        cell = scm_mk_loc(info->sc, obj->getPlace(), obj->getX(), obj->getY());
+        cell = _cons(info->sc, cell, info->sc->NIL, 0);
+
+        if (info->head == info->sc->NIL) {
+                info->head = cell;
+                info->tail = cell;
+                scm_protect(info->sc, cell);
+        } else {
+                info->tail->_object._cons._cdr = cell;
+                info->tail = cell;
+        }
+}
+
+KERN_API_CALL(kern_search_rect)
+{
+        struct place *place;
+        int ulc_x, ulc_y, w, h, lrc_x, lrc_y, x, y;
+        struct terrain *ter;
+        class ObjectType *objtype;
+        struct kern_append_info info;
+
+        /* unpack the args */
+        if (unpack(sc, &args, "pddddpp", &place, &ulc_x, &ulc_y, &w, &h, 
+                   &ter, &objtype)) {
+                rt_err("kern-search-rect: bad args");
+                return sc->NIL;
+        }
+
+        /* check the place */
+        if (! place) {
+                rt_err("kern-search-rect: null place");
+                return sc->NIL;
+        }
+
+        /* clip the rectangle */
+        lrc_x = ulc_x + w;
+        lrc_y = ulc_y + h;
+        place_clip_to_map(place, &ulc_x, &ulc_y);
+        place_clip_to_map(place, &lrc_x, &lrc_y);
+
+        /* prepare to search */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = kern_obj_is_type;
+        info.data = objtype;
+
+        /* iterate over the tiles */
+        for (y = ulc_y; y < lrc_y; y++) {
+                for (x = ulc_x; x < lrc_x; x++) {
+
+                        /* check if terrain matches */
+                        if (place_get_terrain(place, x, y) == ter) {
+                                
+                                pointer cell = scm_mk_loc(info.sc, 
+                                                          place, x, y);
+                                cell = _cons(info.sc, cell, info.sc->NIL, 0);
+                                
+                                if (info.head == info.sc->NIL) {
+                                        info.head = cell;
+                                        info.tail = cell;
+                                        scm_protect(sc, cell);
+                                } else {
+                                        info.tail->_object._cons._cdr = cell;
+                                        info.tail = cell;
+                                }
+                                
+
+                        } else {
+
+                                /* check for an object match */
+                                place_for_each_object_at(place, x, y, 
+                                                         kern_append_loc, 
+                                                         &info);
+                        }
+                }
+        }
+
+        /* unprotect the list prior to returning */
+        if (info.head != sc->NIL)
+                scm_unprotect(sc, info.head);
+
+        return info.head;
+}
+
+KERN_API_CALL(kern_search_rect_for_obj_type)
+{
+        struct place *place;
+        int ulc_x, ulc_y, w, h, lrc_x, lrc_y, x, y;
+        class ObjectType *objtype;
+        struct kern_append_info info;
+
+        /* unpack the args */
+        if (unpack(sc, &args, "pddddp", &place, &ulc_x, &ulc_y, &w, &h, 
+                   &objtype)) {
+                rt_err("kern-search-rect-for-obj-type: bad args");
+                return sc->NIL;
+        }
+
+        /* check the place */
+        if (! place) {
+                rt_err("kern-search-rect-for-obj-type: null place");
+                return sc->NIL;
+        }
+
+        /* clip the rectangle */
+        lrc_x = ulc_x + w;
+        lrc_y = ulc_y + h;
+        place_clip_to_map(place, &ulc_x, &ulc_y);
+        place_clip_to_map(place, &lrc_x, &lrc_y);
+
+        /* prepare to search */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = kern_obj_is_type;
+        info.data = objtype;
+
+        /* iterate over the tiles */
+        for (y = ulc_y; y < lrc_y; y++) {
+                for (x = ulc_x; x < lrc_x; x++) {
+
+                        /* check for an object match */
+                        place_for_each_object_at(place, x, y, 
+                                                 kern_append_loc, 
+                                                 &info);
+                }
+        }
+
+        /* unprotect the list prior to returning */
+        if (info.head != sc->NIL)
+                scm_unprotect(sc, info.head);
+
+        return info.head;
+}
+
+KERN_API_CALL(kern_search_rect_for_terrain)
+{
+        struct place *place;
+        int ulc_x, ulc_y, w, h, lrc_x, lrc_y, x, y;
+        struct terrain *ter;
+        pointer cell;
+        struct kern_append_info info;
+
+        /* unpack the args */
+        if (unpack(sc, &args, "pddddp", &place, &ulc_x, &ulc_y, &w, &h, 
+                   &ter)) {
+                rt_err("kern-search-rect-for-terrain: bad args");
+                return sc->NIL;
+        }
+
+        /* check the place */
+        if (! place) {
+                rt_err("kern-search-rect-for-terrain: null place");
+                return sc->NIL;
+        }
+
+        /* clip the rectangle */
+        lrc_x = ulc_x + w;
+        lrc_y = ulc_y + h;
+        place_clip_to_map(place, &ulc_x, &ulc_y);
+        place_clip_to_map(place, &lrc_x, &lrc_y);
+
+        /* prepare to search */
+        info.sc = sc;
+        info.head = sc->NIL;
+        info.tail = sc->NIL;
+        info.filter = NULL;
+
+        /* iterate over the tiles */
+        for (y = ulc_y; y < lrc_y; y++) {
+                for (x = ulc_x; x < lrc_x; x++) {
+
+                        /* check if terrain matches */
+                        if (place_get_terrain(place, x, y) != ter)
+                                continue;
+                                
+                        /* make a scheme-style loc */
+                        cell = scm_mk_loc(info.sc, place, x, y);
+
+                        /* make it a list element */
+                        cell = _cons(info.sc, cell, info.sc->NIL, 0);
+                        
+                        /* append it to the list */
+                        if (info.head == info.sc->NIL) {
+                                info.head = cell;
+                                info.tail = cell;
+                        } else {
+                                info.tail->_object._cons._cdr = cell;
+                                info.tail = cell;
+                        }
+                }
+        }
+
+        /* unprotect the list prior to returning */
+        if (info.head != sc->NIL)
+                scm_unprotect(sc, info.head);
+
+        /* return the list of locations */
+        return info.head;
+}
+
+
+KERN_API_CALL(kern_fold_rect)
+{
+        struct place *place;
+        int ulc_x, ulc_y, w, h, lrc_x, lrc_y, x, y;
+        pointer proc;
+        pointer val;
+
+        /* unpack the args */
+        if (unpack(sc, &args, "pdddd", &place, &ulc_x, &ulc_y, &w, &h)) { 
+                rt_err("kern-fold-rect: bad args");
+                return sc->NIL;
+        }
+
+        /* check the place */
+        if (! place) {
+                rt_err("kern-fold-rect: null place");
+                return sc->NIL;
+        }
+
+        /* get a ptr to the procedure */
+        if (! scm_is_pair(sc, args)) {
+                rt_err("kern-fold-rect: no proc arg");
+                return sc->NIL;
+        }
+        proc = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        /* get a ptr to the initial value */
+        if (! scm_is_pair(sc, args)) {
+                rt_err("kern-fold-rect: no proc arg");
+                return sc->NIL;
+        }
+        val = scm_car(sc, args);
+        args = scm_cdr(sc, args);
+
+        /* clip the rectangle */
+        lrc_x = ulc_x + w;
+        lrc_y = ulc_y + h;
+        place_clip_to_map(place, &ulc_x, &ulc_y);
+        place_clip_to_map(place, &lrc_x, &lrc_y);
+
+        /* iterate over the tiles */
+        for (y = ulc_y; y < lrc_y; y++) {
+                for (x = ulc_x; x < lrc_x; x++) {
+
+                        /* val may be unreferenced by the script, so protect it
+                         * while we allocate cells (I don't think it matters if
+                         * val is immutable, but we could always test that) */
+                        scm_protect(sc, val);
+
+                        /* make the location for the closure callback */
+                        pointer loc = scm_mk_loc(sc, place, x, y);
+
+                        /* NOTE: don't need to protect the loc, the args to
+                         * _cons are always protected within it */
+
+                        /* make the arg list (val, loc) */
+                        pointer pargs = _cons(sc, val, 
+                                              _cons(sc, loc, sc->NIL, 0), 0);
+
+                        /* done with allocations, so val does not need
+                         * protection any more */
+                        scm_unprotect(sc, val);
+
+                        /* call the procedure, storing the return val for
+                         * later */
+                        val = scheme_call(sc, proc, pargs);
+                }
+        }
+
+        return val;
+}
+
+KERN_API_CALL(kern_player_get_gold)
+{
+        return scm_mk_integer(sc, player_party->gold);
+}
+
+KERN_API_CALL(kern_player_set_gold)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-player-set-gold: bad args");
+                return sc->F;
+        }
+
+        player_party->gold = val;
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_player_get_food)
+{
+        return scm_mk_integer(sc, player_party->food);
+}
+
+KERN_API_CALL(kern_player_set_food)
+{
+        int val;
+
+        if (unpack(sc, &args, "d", &val)) {
+                rt_err("kern-player-set-food: bad args");
+                return sc->F;
+        }
+
+        player_party->food = val;
+        foogodRepaint();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_begin_combat)
+{
+        struct move_info info;
+        struct combat_info cinfo;
+        class Party *party;
+        struct place *place;
+        int x, y;
+
+        if (unpack_loc(sc, &args, &place, &x, &y, "kern-begin-combat")) {
+                return sc->NIL;
+        }
+
+        party = (class Party*)unpack_obj(sc, &args, "kern-begin-combat");
+        if (!party)
+                return sc->NIL;
+
+        /* Combat expects the npc party to have valid coords, whereas I don't
+         * expect the script to always put the npc party on the map before
+         * calling this function, so force the location of the npc party to the
+         * location specified. */
+        party->setPlace(place);
+        party->setX(x);
+        party->setY(y);
+
+        memset(&info, 0, sizeof(info));
+        info.place = place;
+        info.x = x;
+        info.y = y;
+        info.dx = party->getDx();
+        info.dy = party->getDy();
+        info.px = player_party->getX();
+        info.py = player_party->getY();
+        info.npc_party = party;
+                
+        /* If the npc party has a null or invalid direction vector (this is the
+         * case with an ambush) then use the opposite of the player's direction
+         * vector. */
+        if ((!info.dx && !info.dy) ||
+            (info.dx && info.dy)) {
+                info.dx = - player_party->getDx();
+                info.dy = - player_party->getDy();
+        }
+
+        memset(&cinfo, 0, sizeof(cinfo));
+        cinfo.defend = true;
+        cinfo.move = &info;
+                
+        combat_enter(&cinfo);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_ambush_while_camping)
+{
+        class Party *party;
+        int dx, dy;
+        struct place *place;
+
+        /* we need to be in town or wilderness combat for this to work; this
+         * will leak memory if it fails and the caller does not destroy the
+         * party */
+        if (place_is_wilderness(Place)) {
+                rt_err("kern-ambush-while-camping: not in combat");
+                return sc->F;
+        }
+
+        /* unpack the npc party */
+        party = (class Party*)unpack_obj(sc, &args, "kern-ambush-while-camping");
+        if (!party)
+                return sc->F;
+        
+        if (unpack(sc, &args, "p", &place)) {
+                rt_err("kern-ambush-while-camping: bad args");
+                return sc->F;
+        }
+
+        if (! place) {
+                rt_err("kern-ambush-while-camping: null place");
+                return sc->F;
+        }
+
+        /* Workaround for 1808708: if both the player and npc party are in
+         * vehicles then don't do the normal ambush routine (the combat map
+         * will be wrong). Instead, let's just wake the player up. */
+        if (party->getVehicle()
+            && player_party->getVehicle()) {
+
+                log_begin(0);
+                Session->subject = player_party;
+                party->describe();
+                log_continue(" approaches!");
+                log_end(0);
+
+                player_party->endCamping();
+                player_party->removeMembers();
+                return sc->T;
+        }
+
+        /* If the npc party has a null or invalid direction vector then
+         * generate a random one. */
+        dx = party->getDx();
+        dy = party->getDy();
+        while (! dx && ! dy) {
+                /* gmcnutt: the following is not random. Was there a reason for
+                 * it? */
+                //dx = - player_party->getDx();
+                //dy = - player_party->getDy();
+                dx = (rand() % 3) - 1;
+                dy = (rand() % 3) - 1;
+        }
+
+        /* Partial bugfix for 1612006: If the player is on impassable terrain,
+         * and the npc is in a vehicle, disembark first, and move them directly
+         * over the player's location. This prevents ships from coming ashore
+         * onto your camping map (and bringing part of the ocean with them). */
+        if (! place_is_passable(player_party->getPlace(), 
+                                player_party->getX(), 
+                                player_party->getY(), 
+                                party, 0)
+            && party->getVehicle()) {
+                int newx = player_party->getX();
+                int newy = player_party->getY();
+                party->disembark();
+                place_move_object(party->getPlace(), party, newx, newy);
+                party->setX(newx);
+                party->setY(newy);
+        }
+
+        if (combat_add_party(party, dx, dy, 0, place, 0, 0)) {
+                player_party->ambushWhileCamping();
+                return sc->T;
+        }
+        return sc->F;
+}
+
+/*
+ * kern_being_pathfind_to -- wrapper for Being::pathfindTo
+ */
+KERN_API_CALL(kern_being_pathfind_to)
+{
+       class Being *being;
+       struct place *place;
+       int x, y;
+       
+       /* unpack being */
+       being = (class Being*)unpack_obj(sc, &args, "kern-being-pathfind-to");
+       if (! being)
+               return sc->F;
+       
+       /* unpack destination */
+       if (unpack_loc(sc, &args, &place, &x, &y, "kern-being-pathfind-to"))
+               return sc->F;
+       
+       //moves can have nasty consequences,
+       //so keep our own ref to the object for a bit
+       obj_inc_ref(being);
+               
+               
+       /* pathfind */
+       if (being->pathfindTo(place, x, y))
+       {
+               obj_dec_ref(being);
+               return sc->T;
+       }
+       obj_dec_ref(being);
+       return sc->F;
+}
+
+KERN_API_CALL(kern_get_player)
+{
+        return scm_mk_ptr(sc, player_party);
+}
+
+KERN_API_CALL(kern_species_get_hp_mod)
+{
+        struct species *species;
+
+        if (unpack(sc, &args, "p", &species)) {
+                rt_err("kern-species-get-hp-mod: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! species) {
+                rt_err("kern-species-get-hp-mod: null species");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, species->hp_mod);
+}
+
+KERN_API_CALL(kern_species_get_hp_mult)
+{
+        struct species *species;
+
+        if (unpack(sc, &args, "p", &species)) {
+                rt_err("kern-species-get-hp-mult: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! species) {
+                rt_err("kern-species-get-hp-mult: null species");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, species->hp_mult);
+}
+
+KERN_API_CALL(kern_species_get_mp_mod)
+{
+        struct species *species;
+
+        if (unpack(sc, &args, "p", &species)) {
+                rt_err("kern-species-get-mp-mod: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! species) {
+                rt_err("kern-species-get-mp-mod: null species");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, species->mp_mod);
+}
+
+KERN_API_CALL(kern_species_get_mp_mult)
+{
+        struct species *species;
+
+        if (unpack(sc, &args, "p", &species)) {
+                rt_err("kern-species-get-mp-mult: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! species) {
+                rt_err("kern-species-get-mp-mult: null species");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, species->mp_mult);
+}
+
+KERN_API_CALL(kern_occ_get_hp_mod)
+{
+        struct occ *occ;
+
+        if (unpack(sc, &args, "p", &occ)) {
+                rt_err("kern-occ-get-hp-mod: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! occ) {
+                rt_err("kern-occ-get-hp-mod: null occ");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, occ->hp_mod);
+}
+
+KERN_API_CALL(kern_occ_get_hp_mult)
+{
+        struct occ *occ;
+
+        if (unpack(sc, &args, "p", &occ)) {
+                rt_err("kern-occ-get-hp-mult: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! occ) {
+                rt_err("kern-occ-get-hp-mult: null occ");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, occ->hp_mult);
+}
+
+KERN_API_CALL(kern_occ_get_mp_mod)
+{
+        struct occ *occ;
+
+        if (unpack(sc, &args, "p", &occ)) {
+                rt_err("kern-occ-get-mp-mod: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! occ) {
+                rt_err("kern-occ-get-mp-mod: null occ");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, occ->mp_mod);
+}
+
+KERN_API_CALL(kern_occ_get_mp_mult)
+{
+        struct occ *occ;
+
+        if (unpack(sc, &args, "p", &occ)) {
+                rt_err("kern-occ-get-mp-mult: bad args");
+                return scm_mk_integer(sc, 0);
+        }
+
+        if (! occ) {
+                rt_err("kern-occ-get-mp-mult: null occ");
+                return scm_mk_integer(sc, 0);
+        }
+
+        return scm_mk_integer(sc, occ->mp_mult);
+}
+
+KERN_API_CALL(kern_occ_get_gob)
+{
+        struct occ *occ;
+
+        if (unpack(sc, &args, "p", &occ)) {
+                rt_err("kern-occ-get-gob: bad args");
+                return sc->NIL;
+        }
+
+        if (! occ) {
+                rt_err("kern-occ-get-gob: null occ");
+                return sc->NIL;
+        }
+
+               if (occ->gob == NULL)
+               {
+                       return sc->NIL;
+               }
+
+        // It's already a scheme pointer so just return it directly
+        return occ->gob->p;
+}
+
+KERN_API_CALL(kern_occ_set_gob)
+{
+
+        struct occ *occ;
+               
+        if (unpack(sc, &args, "p", &occ)) {
+                rt_err("kern-occ-set-gob: bad args");
+                return sc->NIL;
+        }
+               
+        if (! scm_is_pair(sc, args)) {
+               rt_err("kern-occ-set-gob: no gob specified");
+               return sc->NIL;
+        }
+
+       occ->gob = gob_new(sc, scm_car(sc, args));
+
+       return sc->NIL;
+}
+
+KERN_API_CALL(kern_end_game)
+{
+        Quit = true;
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_sprite_clone)
+{
+        struct sprite *orig, *clone;
+        char *tag;
+
+        if (unpack(sc, &args, "py", &orig, &tag)) {
+                rt_err("kern-sprite-clone: bad args");
+                return sc->NIL;
+        }
+        clone = sprite_clone(orig, tag);
+        if (clone) {
+                pointer ret = scm_mk_ptr(sc, clone);
+                session_add(Session, clone, sprite_dtor, NULL, NULL);
+
+                /* Tags are optional on clones, but only clones with tags will
+                 * be assigned to scheme variables. */
+                if (tag) {
+                        scm_define(sc, tag, ret);
+                }
+                return ret;
+        }
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_sprite_append_decoration)
+{
+        struct sprite *orig, *decor;
+
+        if (unpack(sc, &args, "pp", &orig, &decor)) {
+                rt_err("kern-sprite-append-decoration: bad args");
+                return sc->NIL;
+        }
+        if (!orig || ! decor) {
+                rt_err("kern-sprite-append-decoration: null arg");
+                return sc->NIL;
+        }
+        sprite_append_decoration(orig, decor);
+        return scm_mk_ptr(sc, orig);
+}
+
+KERN_API_CALL(kern_sprite_blit_over)
+{
+        struct sprite *orig, *decor;
+
+        if (unpack(sc, &args, "pp", &orig, &decor)) {
+                rt_err("kern-sprite-append-decoration: bad args");
+                return sc->NIL;
+        }
+        if (!orig || ! decor) {
+                rt_err("kern-sprite-append-decoration: null arg");
+                return sc->NIL;
+        }
+        sprite_blit_over(orig, decor);
+        return scm_mk_ptr(sc, orig);
+}
+
+KERN_API_CALL(kern_sprite_strip_decorations)
+{
+        struct sprite *orig;
+
+        if (unpack(sc, &args, "p", &orig)) {
+                rt_err("kern-sprite-strip-decoration: bad args");
+                return sc->NIL;
+        }
+        sprite_strip_decorations(orig);
+        return scm_mk_ptr(sc, orig);
+}
+
+KERN_API_CALL(kern_sprite_apply_matrix)
+{
+        struct sprite *sprite;
+        float matrix[4][3];
+        int row;
+        pointer pcol;
+
+        /* unpack the sprite */
+        if (unpack(sc, &args, "p", &sprite)) {
+                load_err("kern-sprite-apply-matrix: bad args");
+                return sc->NIL;
+        }
+
+        if (!scm_is_pair(sc, args)) {
+                load_err("kern-sprite-apply-matrix: no matrix!");
+                goto abort;
+        }
+        args = scm_car(sc, args);
+
+        /* unpack the matrix */
+        for (row = 0; row < 4; row++) {
+                if (! scm_is_pair(sc, args)) {
+                        load_err("kern-sprite-apply-matrix: only %d of 4 rows!", row);
+                        goto abort;
+                }
+                pcol = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+                if (unpack(sc, &pcol, "fff", &matrix[row][0],
+                           &matrix[row][1],
+                           &matrix[row][2])) {
+                        load_err("kern-sprite-apply-matrix: bad args in row %d!", row);
+                        goto abort;
+                }
+        }
+
+        sprite_apply_matrix(sprite, matrix);
+ abort:
+        return scm_mk_ptr(sc, sprite);
+}
+
+
+KERN_API_CALL(kern_los_invalidate)
+{
+        vmask_flush_all();
+        return sc->T;
+}
+
+KERN_API_CALL(kern_cfg_set)
+{
+        char *key, *val;
+
+        while (scm_is_pair(sc, args)) {
+                if (unpack(sc, &args, "ss", &key, &val)) {
+                        rt_err("kern-cfg-set: bad args");
+                        return sc->NIL;
+                }
+                cfg_set(key, val);
+        }
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_cfg_get)
+{
+        char *key, *val;
+
+        if (unpack(sc, &args, "s", &key)) {
+                rt_err("kern-cfg-get: bad args");
+                return sc->NIL;
+        }
+        val = cfg_get(key);
+        if (!val)
+                return sc->NIL;
+        return scm_mk_string(sc, cfg_get(key));
+}
+
+KERN_API_CALL(kern_set_kern_intvar)
+{
+        char *key;
+       int   value;
+
+        while (scm_is_pair(sc, args)) {
+                if (unpack(sc, &args, "sd", &key, &value)) {
+                        rt_err("kern-set-kern-intvar: bad args");
+                        return sc->NIL;
+                }
+               kern_intvar_set(key, value);
+        }
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_get_kern_intvar)
+{
+    char *key;
+    int   value;
+
+        if (unpack(sc, &args, "s", &key)) {
+                rt_err("kern_get_kern_intvar: bad args");
+                return sc->NIL;
+        }
+        value = kern_intvar_get(key);
+
+        return scm_mk_integer(sc, value);
+}
+
+KERN_API_CALL(kern_add_save_game)
+{
+        char *fname;
+
+        while (scm_is_pair(sc, args)) {
+                if (unpack(sc, &args, "s", &fname)) {
+                        rt_err("kern-add-save-game: bad args");
+                }
+                menu_add_saved_game(fname);
+        }
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_type_set_gob)
+{
+        ObjectType *type = 0;
+
+        if (unpack(sc, &args, "p", &type)) {
+                rt_err("kern-type-set-gob: bad args");
+                return sc->NIL;
+        }
+
+        if (! scm_is_pair(sc, args)) {
+               rt_err("kern-type-set-gob: no gob specified");
+        } else {
+                type->setGob(gob_new(sc, scm_car(sc, args)));
+        }
+
+       return scm_mk_ptr(sc, type);
+}
+
+KERN_API_CALL(kern_type_set_quest_item_flag)
+{
+        ObjectType *type = 0;
+        int val = 0;
+
+        if (unpack(sc, &args, "pb", &type, &val)) {
+                rt_err("kern-type-set-quest-item-flag: bad args");
+                return sc->NIL;
+        }
+
+        type->setQuestItemFlag(val);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_type_get_gob)
+{
+        ObjectType *type = 0;
+
+        if (unpack(sc, &args, "p", &type)) {
+                rt_err("kern-type-get-gob: bad args");
+                return sc->NIL;
+        }
+
+        if (!type) {
+                rt_err("kern-type-get-gob: null obj");
+                return sc->NIL;
+        }
+
+        if (! type->getGob()) {
+                return sc->NIL;
+        }
+
+        return type->getGob()->p;
+}
+
+KERN_API_CALL(kern_set_quicken_sprite)
+{
+        struct sprite *sprite;
+        if (unpack(sc, &args, "p", &sprite)) {
+                load_err("kern-set-quicken-sprite: bad args");
+                return sc->F;
+        }
+        quicken_effect_sprite() = sprite;
+        return sc->T;
+}
+
+KERN_API_CALL(kern_set_magic_negated_sprite)
+{
+        struct sprite *sprite;
+        if (unpack(sc, &args, "p", &sprite)) {
+                load_err("kern-set-magic-negated-sprite: bad args");
+                return sc->F;
+        }
+        magic_negated_effect_sprite() = sprite;
+        return sc->T;
+}
+
+KERN_API_CALL(kern_set_reveal_sprite)
+{
+        struct sprite *sprite;
+        if (unpack(sc, &args, "p", &sprite)) {
+                load_err("kern-set-reveal-sprite: bad args");
+                return sc->F;
+        }
+        reveal_effect_sprite() = sprite;
+        return sc->T;
+}
+
+KERN_API_CALL(kern_set_xray_vision_sprite)
+{
+        struct sprite *sprite;
+        if (unpack(sc, &args, "p", &sprite)) {
+                load_err("kern-set-xray-vision-sprite: bad args");
+                return sc->F;
+        }
+        xray_vision_effect_sprite() = sprite;
+        return sc->T;
+}
+
+KERN_API_CALL(kern_set_time_stop_sprite)
+{
+        struct sprite *sprite;
+        if (unpack(sc, &args, "p", &sprite)) {
+                load_err("kern-set-time_stop-sprite: bad args");
+                return sc->F;
+        }
+        time_stop_effect_sprite() = sprite;
+        return sc->T;
+}
+
+KERN_API_CALL(kern_obj_set_mmode)
+{
+        Object *obj;
+        struct mmode *mmode;
+
+        if (!(obj = unpack_obj(sc, &args, "kern-obj-set-mmode")))
+                return sc->NIL;
+
+        if (unpack(sc, &args, "p", &mmode)) {
+                rt_err("kern-obj-set-mmode: bad args");
+                return sc->NIL;
+        }
+
+        obj->setMovementMode(mmode);
+
+        return scm_mk_ptr(sc, obj);
+        
+}
+
+KERN_API_CALL(kern_progress_bar_start)
+{
+        char *title = 0;
+        unsigned int max_steps = 0;
+
+        if (unpack(sc, &args, "sd", &title, &max_steps)) {
+                load_err("kern-progress-bar-start: bad args");
+                return sc->NIL;
+        }
+
+        foogod_progress_bar_set_title(title);
+        foogod_progress_bar_set_max_steps(max_steps);
+        foogodSetMode(FOOGOD_PROGRESS_BAR);
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_progress_bar_advance)
+{
+        unsigned int steps = 0;
+
+        if (unpack(sc, &args, "d", &steps)) {
+                load_err("kern-progress-bar-advance: bad args");
+                return sc->NIL;
+        }
+
+        foogod_progress_bar_advance(steps);
+        foogodRepaint();
+
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_progress_bar_finish)
+{
+        foogod_progress_bar_finish();
+        foogodRepaint();
+
+        return sc->NIL;
+}
+
+/**
+ * (kern-ztats-add-pane <enter> <scroll> <paint> <gob>)
+ *
+ * <enter> is (enter <gob> <kparty> <dir> <x> <y> <w> <h>)
+ * <scroll> is (scroll <gob> <dir>), returning #t iff the scroll was handled
+ * <paint> is (paint <gob>)
+ * <gob> is script info
+ */
+struct kern_ztats_pane {
+        struct ztats_pane base;
+        struct closure *enter, *scroll, *paint, *select;
+        struct gob *gob;
+        scheme *sc;
+        unsigned char added:1;
+};
+
+static pointer pack_rect(scheme *sc, SDL_Rect *rect)
+{
+        return pack(sc, "dddd", rect->x, rect->y, rect->w, rect->h);
+}
+
+static void kern_ztats_pane_enter(struct ztats_pane *pane, class Party *party, enum StatusScrollDir via, 
+                           SDL_Rect *dims)
+{
+        struct kern_ztats_pane *kzp = (struct kern_ztats_pane*)pane;
+        pointer prect = pack_rect(kzp->sc, dims);
+        scm_protect(kzp->sc, prect);
+        closure_exec(kzp->enter, "lpdl", kzp->gob->p, party, via, prect);
+        scm_unprotect(kzp->sc, prect);
+}
+
+static int kern_ztats_pane_scroll(struct ztats_pane *pane, enum StatusScrollDir dir)
+{
+        struct kern_ztats_pane *kzp = (struct kern_ztats_pane*)pane;
+        return closure_exec(kzp->scroll, "ld", kzp->gob->p, dir);
+}
+
+static void kern_ztats_pane_paint(struct ztats_pane *pane)
+{
+        struct kern_ztats_pane *kzp = (struct kern_ztats_pane*)pane;
+        closure_exec(kzp->paint, "l", kzp->gob->p);
+}
+
+static void kern_ztats_pane_select(struct ztats_pane *pane)
+{
+        struct kern_ztats_pane *kzp = (struct kern_ztats_pane*)pane;
+        closure_exec(kzp->select, "l", kzp->gob->p);
+}
+
+static void kern_ztats_pane_dtor(void *val)
+{
+        struct kern_ztats_pane *kzp = (struct kern_ztats_pane*)val;
+
+        if (kzp->added) {
+                ztats_rm_pane(&kzp->base);
+        }
+
+        if (kzp->gob) {
+                gob_unref(kzp->gob);
+        }
+        if (kzp->paint) {
+                closure_unref(kzp->paint);
+        }
+        if (kzp->scroll) {
+                closure_unref(kzp->scroll);
+        }
+        if (kzp->enter) {
+                closure_unref(kzp->enter);
+        }
+        if (kzp->select) {
+                closure_unref(kzp->select);
+        }
+        free(kzp);
+}
+
+static struct ztats_pane_ops kern_ztats_pane_ops = {
+        kern_ztats_pane_enter,
+        kern_ztats_pane_scroll,
+        kern_ztats_pane_paint,
+        kern_ztats_pane_select
+};
+
+KERN_API_CALL(kern_ztats_add_pane)
+{
+        pointer penter, pscroll, ppaint, pselect, pgob;
+        struct kern_ztats_pane *kzp;
+
+#ifndef USE_QUESTS
+        return sc->F;
+#endif
+
+        if (unpack(sc, &args, "ooool", &penter, &pscroll, &ppaint, &pselect, &pgob)) {
+                load_err("kern-ztats-add-pane: bad args");
+                return sc->NIL;
+        }
+
+        if (!(kzp = (struct kern_ztats_pane*)calloc(1, sizeof(*kzp)))) {
+                load_err("alloc failed");
+                return sc->NIL;
+        }
+
+        kzp->base.ops = &kern_ztats_pane_ops;
+        kzp->sc = sc;
+        if (! (kzp->enter = closure_new_ref(sc, penter))) {
+                goto fail;
+        }
+        if (! (kzp->scroll = closure_new_ref(sc, pscroll))) {
+                goto fail;
+        }
+        if (! (kzp->paint = closure_new_ref(sc, ppaint))) {
+                goto fail;
+        }
+        if (! (kzp->select = closure_new_ref(sc, pselect))) {
+                goto fail;
+        }
+        if (! (kzp->gob = gob_new(sc, pgob))) {
+                goto fail;
+        }
+        gob_ref(kzp->gob);
+
+        ztats_add_pane(&kzp->base);
+
+        /* Mark that we've added it so that we remember to remove it in the
+         * dtor. */
+        kzp->added = 1;
+
+        session_add(Session, kzp, kern_ztats_pane_dtor, NULL, NULL);
+        return sc->T;
+
+ fail:
+        kern_ztats_pane_dtor(kzp);
+        return sc->F;
+}
+
+KERN_API_CALL(kern_status_set_title)
+{
+        char *title;
+        if (unpack(sc, &args, "s", &title)) {
+                load_err("%s: bad args", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        status_set_title(title);
+        return sc->T;
+}
+
+/**
+ * (kern-screen-print (<x> <y> <w> <h>) <flags> <...>)
+ *
+ * <x> <y> <w> <h> are the rect (absolute screen coords) to print to
+ * <flags> are the SP_* #defines in screen.h
+ * <fmt> is std printf format plus the color tag extensions of ascii.h
+ * <...> are the varargs
+ */
+KERN_API_CALL(kern_screen_print)
+{
+        static char buf[256];
+        int room = sizeof(buf);
+        char *ptr = buf;
+        SDL_Rect rect;
+        int flags = 0;
+
+        if (unpack_rect(sc, &args, &rect)) {
+                load_err("%s: error unpacking rect", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        if (unpack(sc, &args, "d", &flags)) {
+                load_err("%s: error unpacking flags", __FUNCTION__);
+                return sc->NIL;
+        }
+        
+        while (scm_is_pair(sc, args) && (room > 1)) {
+
+                pointer val = scm_car(sc, args);
+                args = scm_cdr(sc, args);
+                int n = 0;
+
+                if (scm_is_str(sc, val)) {
+                        n = snprintf(ptr, room, scm_str_val(sc, val));
+                } else if (scm_is_int(sc, val)) {
+                        n = snprintf(ptr, room, "%ld", scm_int_val(sc, val));
+                } else if (scm_is_real(sc, val)) {
+                        n = snprintf(ptr, room, "%f", scm_real_val(sc, val));
+                } else {
+                        rt_err("%s: unknown type", __FUNCTION__);
+                }
+
+                ptr += n;
+                room -= n;
+        }
+
+        screenPrint(&rect, flags, buf);
+
+        return sc->NIL;
+}
+
+/**
+ * (kern-screen-draw-sprite (<x> <y> <w> <h>) <flags> <sprite>)
+ *
+ * <x> <y> <w> <h> are the rect (absolute screen coords) to print to
+ * <flags> are the SP_* #defines in screen.h
+ * <fmt> is std printf format plus the color tag extensions of ascii.h
+ * <sprite> is the sprite to draw
+ */
+KERN_API_CALL(kern_screen_draw_sprite)
+{
+        SDL_Rect rect;
+        int flags = 0;
+               struct sprite *toblit;
+
+        if (unpack_rect(sc, &args, &rect)) {
+                load_err("%s: error unpacking rect", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        if (unpack(sc, &args, "d", &flags)) {
+                load_err("%s: error unpacking flags", __FUNCTION__);
+                return sc->NIL;
+        }
+        
+        if (unpack(sc, &args, "p", &toblit)) {
+                rt_err("kern-sprite-clone: bad args");
+                return sc->NIL;
+        }
+        
+        sprite_paint_direct(toblit, 0, &rect);
+        
+        //screenBlit(toblit->rsurf->surf, &toblit->frames[0], &rect);
+
+        return sc->NIL;
+}
+
+/**
+ * (kern-screen-shade <rect> <amount>)
+ *
+ * <rect> specifies the area of the screen to shade
+ * <amount> is a value from 0 (transparent) to 255 (opaque black)
+ */
+KERN_API_CALL(kern_screen_shade)
+{
+        SDL_Rect rect;
+        int amount;
+
+        if (unpack_rect(sc, &args, &rect)) {
+                load_err("%s: error unpacking 'screenrect' arg", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        if (unpack(sc, &args, "d", &amount)) {
+                load_err("%s: error unpacking 'amount' arg", __FUNCTION__);
+                return sc->NIL;
+        }
+        
+        screenShade(&rect, amount);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_screen_erase)
+{
+        SDL_Rect rect;
+
+        if (unpack_rect(sc, &args, &rect)) {
+                load_err("%s: error unpacking 'screenrect' arg", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        screenErase(&rect);
+        return sc->T;
+}
+
+KERN_API_CALL(kern_screen_update)
+{
+        SDL_Rect rect;
+
+        if (unpack_rect(sc, &args, &rect)) {
+                load_err("%s: error unpacking 'screenrect' arg", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        screenUpdate(&rect);
+        return sc->T;
+}
+
+
+
+/**
+ * (kern-event-push-keyhandler <keyh>)
+ *
+ * <keyh> is a proc of the form (keyh key keymod)
+ */
+static int kern_keyh_fx(struct KeyHandler *keyh, int key, int keymod)
+{
+        DECL_CAST(struct closure, proc, keyh->data);
+        return closure_exec(proc, "dd", key, keymod) ? 1 : 0;
+}
+
+KERN_API_CALL(kern_event_run_keyhandler)
+{
+        pointer pclos;
+        struct closure *proc;
+
+        if (unpack(sc, &args, "o", &pclos)) {
+                load_err("%s: error in arg", __FUNCTION__);
+                return sc->F;
+        }
+
+        if (sc->NIL == pclos) {
+                load_err("%s: NIL closure arg", __FUNCTION__);
+                return sc->F;
+        }
+
+        if (! (proc =closure_new_ref(sc, pclos))) {
+                load_err("%s: closure_new failed", __FUNCTION__);
+                return sc->F;
+        }
+
+        eventRunKeyHandler(kern_keyh_fx, proc);
+        closure_unref(proc);
+        return sc->T;
+}
+
+/**
+ * (kern-applet-run <run> <paint>)
+ *
+ * <run> is a proc of form (run <dims>), dims being the screen rect.
+ * <paint> is a proc of form (paint)
+ */
+struct kern_applet {
+        struct applet base;
+        struct closure *run, *paint;
+        struct gob *gob;
+        scheme *sc;
+};
+
+static void kern_applet_run(struct applet *applet, SDL_Rect *dims, struct session *session)
+{
+        DECL_CAST(struct kern_applet, ka, applet);
+        pointer prect = pack_rect(ka->sc, dims);
+        closure_exec(ka->run, "ll", ka->gob->p, prect);
+}
+
+static void kern_applet_paint(struct applet *applet)
+{
+        DECL_CAST(struct kern_applet, ka, applet);
+        closure_exec(ka->paint, "l", ka->gob->p);
+}
+
+static void kern_applet_dtor(void *val)
+{
+        struct kern_applet *ka = (struct kern_applet*)val;
+        if (ka->gob) {
+                gob_unref(ka->gob);
+        }
+        if (ka->paint) {
+                closure_unref(ka->paint);
+        }
+        if (ka->run) {
+                closure_unref(ka->run);
+        }
+        KERN_FREE(ka);
+}
+
+static struct applet_ops kern_applet_ops = {
+        kern_applet_run,
+        kern_applet_paint
+};
+
+KERN_API_CALL(kern_applet_run)
+{
+        pointer prun, ppaint, pgob;
+        struct kern_applet *ka;
+
+        if (unpack(sc, &args, "ool", &prun, &ppaint, &pgob)) {
+                load_err("%s: bad args", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        if (!(ka = KERN_ALLOC(struct kern_applet))) {
+                load_err("%s: alloc failed", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        ka->base.ops = &kern_applet_ops;
+        ka->sc = sc;
+        if (! (ka->run = closure_new_ref(sc, prun))) {
+                goto fail;
+        }
+        if (! (ka->paint = closure_new_ref(sc, ppaint))) {
+                goto fail;
+        }
+        if (! (ka->gob = gob_new(sc, pgob))) {
+                goto fail;
+        }
+        gob_ref(ka->gob);
+
+        statusRunApplet(&ka->base);
+        kern_applet_dtor(ka);
+
+        return sc->T;
+
+ fail:
+        kern_applet_dtor(ka);
+        return sc->F;
+
+        
+}
+
+/**
+ * (kern-define <symbol> <value>)
+ *
+ * This is a way to define mutable scheme variables that persist across
+ * sessions. In other words, you can declare a variable in scheme, change
+ * something about it during the game, and rest assured that when the game
+ * reloads the value will be the same. By way of contrast, normal statements
+ * like (define foo (list 'a 6)) define variables for the current session only.
+ */
+
+struct kern_define_data {
+        scheme *sc;
+        char *sym;
+        pointer cell;
+};
+
+static void kern_define_dtor(void *val)
+{
+        DECL_CAST(struct kern_define_data, data, val);
+        free(data->sym);
+        KERN_FREE(val);
+}
+
+static void kern_define_save(save_t *save, void *val)
+{
+        DECL_CAST(struct kern_define_data, data, val);
+        save->write(save, "(kern-define '%s ", data->sym);
+        scheme_serialize(data->sc, data->cell, save);
+        save->write(save, ")\n");
+}
+
+KERN_API_CALL(kern_define)
+{
+        char *str;
+        pointer pcell;
+        struct kern_define_data *data;
+        
+        if (unpack(sc, &args, "yl", &str, &pcell)) {
+                load_err("%s: bad args", __FUNCTION__);
+                return sc->NIL;
+        }
+        
+        if (!(data = KERN_ALLOC(struct kern_define_data))) {
+                load_err("%s: alloc failed", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        if (!(data->sym = strdup(str))) {
+                KERN_FREE(data);
+                load_err("%s: strdup failed", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        data->sc = sc;
+        data->cell = pcell;
+        session_add(Session, data, kern_define_dtor, kern_define_save, NULL);
+        scm_define(sc, str, pcell);
+        return sc->NIL;
+}
+
+KERN_API_CALL(kern_obj_set_portrait)
+{
+        class Object *obj;
+        struct sprite *sprite;
+
+        if (unpack(sc, &args, "pp", &obj, &sprite)) {
+                rt_err("%s: bad args", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        if (!obj) {
+                rt_err("%s: null object", __FUNCTION__);
+                return sc->NIL;
+        }
+
+        obj->setPortrait(sprite);
+
+        return scm_mk_ptr(sc, obj);
+
+}
+
+KERN_API_CALL(kern_script_version)
+{
+        char *verstr = NULL;
+
+        if (unpack(sc, &args, "s", &verstr)) {
+               char buffer[40]; // max length of unsigned int = 10 digits
+               sprintf(buffer,"%u.%u.%u",Session->major, Session->minor,Session->release);
+               return scm_mk_string(sc, buffer);
+        }
+
+        if (sscanf(verstr, "%u.%u.%u", &Session->major, &Session->minor, 
+                   &Session->release) != 3) {
+                load_err("%s: bad version string '%s'", __FUNCTION__, verstr);
+                return sc->NIL;
+        }
+
+        return sc->NIL;
+}
+
+KERN_OBSOLETE_CALL(kern_set_ascii);
+KERN_OBSOLETE_CALL(kern_set_frame);
+KERN_OBSOLETE_CALL(kern_set_cursor);
+
+static int fincount=0; /* for debug */
+static void kern_finalize(scheme *sc, pointer pp)
+{
+        class Object *obj = (class Object*)pp;
+        obj_dec_ref(obj);
+        fincount++;
+}
+
+scheme *kern_init(void)
+{        
+        scheme *sc;
+
+        sc = (scheme*)malloc(sizeof(*sc));
+        if (!sc) {
+                warn("error: could not allocate interpreter");
+                return 0;
+        }
+
+        if(!scheme_init(sc)) {
+                warn("load error: could not initialize script interpreter\n");
+                free(sc);
+                return 0;
+        }
+
+        fincount=0;
+        scheme_set_custom_finalize(sc, kern_finalize);
+
+        /* Setup the script-to-kernel API */
+
+        /* kern-arms-type api */
+        API_DECL(sc, "kern-arms-type-get-ammo-type", kern_arms_type_get_ammo_type);
+        API_DECL(sc, "kern-arms-type-get-range",     kern_arms_type_get_range);
+        API_DECL(sc, "kern-arms-type-set-mmode",     kern_arms_type_set_mmode);
+        API_DECL(sc, "kern-arms-type-fire-in-direction", kern_arms_type_fire_in_direction);
+
+        /* kern-astral-body api */
+        API_DECL(sc, "kern-astral-body-get-gob", kern_astral_body_get_gob);
+        API_DECL(sc, "kern-astral-body-get-phase", kern_astral_body_get_phase);
+        API_DECL(sc, "kern-astral-body-set-gob", kern_astral_body_set_gob);
+
+        /* kern-being-api */
+        API_DECL(sc, "kern-being-get-base-faction", kern_being_get_base_faction);
+        API_DECL(sc, "kern-being-get-current-faction", kern_being_get_current_faction);
+        API_DECL(sc, "kern-being-get-visible-hostiles", kern_being_get_visible_hostiles);
+        API_DECL(sc, "kern-being-get-visible-allies", kern_being_get_visible_allies);
+        API_DECL(sc, "kern-being-get-visible-tiles", kern_being_get_visible_tiles);
+        API_DECL(sc, "kern-being-is-hostile?", kern_being_is_hostile);
+        API_DECL(sc, "kern-being-is-ally?", kern_being_is_ally);
+        API_DECL(sc, "kern-being-set-name", kern_being_set_name);
+        API_DECL(sc, "kern-being-pathfind-to", kern_being_pathfind_to);
+        API_DECL(sc, "kern-being-set-base-faction", kern_being_set_base_faction);
+        API_DECL(sc, "kern-being-set-current-faction", kern_being_set_current_faction);
+
+        /* kern-char api */
+        API_DECL(sc, "kern-char-add-defense", kern_char_add_defense);
+        API_DECL(sc, "kern-char-add-experience", kern_char_add_experience);
+        API_DECL(sc, "kern-char-arm-self", kern_char_arm_self);
+        API_DECL(sc, "kern-char-attack", kern_char_attack);
+        API_DECL(sc, "kern-char-dec-mana", kern_char_dec_mana);
+        API_DECL(sc, "kern-char-charm", kern_char_charm);
+        API_DECL(sc, "kern-char-force-drop", kern_char_force_drop);
+        API_DECL(sc, "kern-char-get-arms", kern_char_get_arms);
+        API_DECL(sc, "kern-char-get-experience-value", kern_char_get_experience_value);                
+        API_DECL(sc, "kern-char-get-hp", kern_char_get_hp);
+        API_DECL(sc, "kern-char-get-inventory", kern_char_get_inventory);
+        API_DECL(sc, "kern-char-get-level", kern_char_get_level);
+        API_DECL(sc, "kern-char-get-mana", kern_char_get_mana);
+        API_DECL(sc, "kern-char-get-occ", kern_char_get_occ);
+        API_DECL(sc, "kern-char-get-max-hp", kern_char_get_max_hp);
+        API_DECL(sc, "kern-char-get-max-mana", kern_char_get_max_mana);
+        API_DECL(sc, "kern-char-get-party", kern_char_get_party);
+        API_DECL(sc, "kern-char-get-readied-weapons", kern_char_get_readied_weapons);
+        API_DECL(sc, "kern-char-get-species", kern_char_get_species);
+        API_DECL(sc, "kern-char-get-strength", kern_char_get_strength);
+        API_DECL(sc, "kern-char-get-dexterity", kern_char_get_dexterity);
+        API_DECL(sc, "kern-char-get-intelligence", kern_char_get_intelligence);
+        API_DECL(sc, "kern-char-get-base-strength", kern_char_get_base_strength);
+        API_DECL(sc, "kern-char-get-base-dexterity", kern_char_get_base_dexterity);
+        API_DECL(sc, "kern-char-get-base-intelligence", kern_char_get_base_intelligence);
+        API_DECL(sc, "kern-char-set-sched", kern_char_set_sched);
+        API_DECL(sc, "kern-char-set-speed", kern_char_set_speed);
+        API_DECL(sc, "kern-char-get-speed", kern_char_get_speed);
+        API_DECL(sc, "kern-char-set-strength", kern_char_set_strength);
+        API_DECL(sc, "kern-char-set-dexterity", kern_char_set_dexterity);
+        API_DECL(sc, "kern-char-set-intelligence", kern_char_set_intelligence);
+        API_DECL(sc, "kern-char-task-abort", kern_char_task_abort);
+        API_DECL(sc, "kern-char-task-begin", kern_char_task_begin);
+        API_DECL(sc, "kern-char-task-continue", kern_char_task_continue);
+        API_DECL(sc, "kern-char-task-end", kern_char_task_end);
+        API_DECL(sc, "kern-char-get-skills", kern_char_get_skills);
+        API_DECL(sc, "kern-char-get-weapons", kern_char_get_weapons);
+        API_DECL(sc, "kern-char-is-asleep?", kern_char_is_asleep);
+        API_DECL(sc, "kern-char-is-dead?", kern_char_is_dead);
+        API_DECL(sc, "kern-char-is-known?", kern_char_is_known);
+        API_DECL(sc, "kern-char-join-player", kern_char_join_player);
+        API_DECL(sc, "kern-char-kill", kern_char_kill);
+        API_DECL(sc, "kern-char-leave-player", kern_char_leave_player);
+        API_DECL(sc, "kern-char-resurrect", kern_char_resurrect);
+        API_DECL(sc, "kern-char-set-ai", kern_char_set_ai);
+        API_DECL(sc, "kern-char-set-control-mode", kern_char_set_control_mode);
+        API_DECL(sc, "kern-char-set-fleeing", kern_char_set_fleeing);
+        API_DECL(sc, "kern-char-set-hp", kern_char_set_hp);
+        API_DECL(sc, "kern-char-set-known", kern_char_set_known);
+        API_DECL(sc, "kern-char-set-level", kern_char_set_level);
+        API_DECL(sc, "kern-char-set-mana", kern_char_set_mana);
+        API_DECL(sc, "kern-char-set-player-controlled", kern_char_set_player_controlled);
+        API_DECL(sc, "kern-char-set-schedule", kern_char_set_schedule);
+        API_DECL(sc, "kern-char-set-sleep", kern_char_set_sleep);
+        API_DECL(sc, "kern-char-uncharm", kern_char_uncharm);
+        API_DECL(sc, "kern-char-unready", kern_char_unready);
+
+        /* kern-event api */
+        API_DECL(sc, "kern-event-run-keyhandler", kern_event_run_keyhandler);
+
+        /* kern-map api */
+        API_DECL(sc, "kern-map-rotate", kern_map_rotate);
+
+        /* kern-mk api */
+        API_DECL(sc, "kern-mk-arms-type", kern_mk_arms_type);
+        API_DECL(sc, "kern-mk-astral-body", kern_mk_astral_body);
+        API_DECL(sc, "kern-mk-blender", kern_mk_blender);
+        API_DECL(sc, "kern-mk-char", kern_mk_char);
+        API_DECL(sc, "kern-mk-inventory", kern_mk_inventory);
+        API_DECL(sc, "kern-mk-effect", kern_mk_effect);
+        API_DECL(sc, "kern-mk-field", kern_mk_field);
+        API_DECL(sc, "kern-mk-field-type", kern_mk_field_type);
+        API_DECL(sc, "kern-mk-map", kern_mk_map);
+        API_DECL(sc, "kern-mk-missile-type", kern_mk_missile_type);
+        API_DECL(sc, "kern-mk-composite-map", kern_mk_composite_map);
+        API_DECL(sc, "kern-mk-mmode", kern_mk_mmode);
+        API_DECL(sc, "kern-mk-obj", kern_mk_obj);
+        API_DECL(sc, "kern-mk-obj-type", kern_mk_obj_type);
+        API_DECL(sc, "kern-mk-occ", kern_mk_occ);
+        API_DECL(sc, "kern-mk-palette", kern_mk_palette);
+        API_DECL(sc, "kern-mk-party", kern_mk_party);
+        API_DECL(sc, "kern-mk-place", kern_mk_place);
+        API_DECL(sc, "kern-mk-player", kern_mk_player);
+        API_DECL(sc, "kern-mk-ptable", kern_mk_ptable);
+        API_DECL(sc, "kern-mk-sched", kern_mk_sched);
+        API_DECL(sc, "kern-mk-skill", kern_mk_skill);
+        API_DECL(sc, "kern-mk-skill-set", kern_mk_skill_set);
+        API_DECL(sc, "kern-mk-sound", kern_mk_sound);
+        API_DECL(sc, "kern-mk-species", kern_mk_species);
+        API_DECL(sc, "kern-mk-sprite", kern_mk_sprite);
+        API_DECL(sc, "kern-mk-sprite-set", kern_mk_sprite_set);
+        API_DECL(sc, "kern-mk-templ", kern_mk_templ);
+        API_DECL(sc, "kern-mk-terrain", kern_mk_terrain);
+        API_DECL(sc, "kern-mk-vehicle", kern_mk_vehicle);
+        API_DECL(sc, "kern-mk-vehicle-type", kern_mk_vehicle_type);
+
+        /* kern-obj api */
+        API_DECL(sc, "kern-obj-add-food", kern_obj_add_food);
+        API_DECL(sc, "kern-obj-add-gold", kern_obj_add_gold);
+        API_DECL(sc, "kern-obj-add-effect", kern_obj_add_effect);
+        API_DECL(sc, "kern-obj-add-to-inventory", kern_obj_add_to_inventory);
+        API_DECL(sc, "kern-obj-apply-damage", kern_obj_apply_damage);
+        API_DECL(sc, "kern-obj-inflict-damage", kern_obj_inflict_damage);
+        API_DECL(sc, "kern-obj-clone", kern_obj_clone);
+        API_DECL(sc, "kern-obj-dec-ap", kern_obj_dec_ap);
+        API_DECL(sc, "kern-obj-dec-light", kern_obj_dec_light);
+        API_DECL(sc, "kern-obj-dec-ref", kern_obj_dec_ref);
+        /*API_DECL(sc, "kern-obj-destroy", kern_obj_destroy);*/
+        API_DECL(sc, "kern-obj-find-path", kern_obj_find_path);
+        API_DECL(sc, "kern-obj-get-activity", kern_obj_get_activity);
+        API_DECL(sc, "kern-obj-get-ap", kern_obj_get_ap);
+        API_DECL(sc, "kern-obj-get-count", kern_obj_get_count);
+        API_DECL(sc, "kern-obj-get-dir", kern_obj_get_dir);
+        API_DECL(sc, "kern-obj-get-hp", kern_obj_get_hp);
+        API_DECL(sc, "kern-obj-get-effects", kern_obj_get_effects);
+        API_DECL(sc, "kern-obj-get-facing", kern_obj_get_facing);
+        API_DECL(sc, "kern-obj-get-gob", kern_obj_get_gob);
+        API_DECL(sc, "kern-obj-get-light", kern_obj_get_light);
+        API_DECL(sc, "kern-obj-get-location", kern_obj_get_location);
+        API_DECL(sc, "kern-obj-get-mmode", kern_obj_get_mmode);
+        API_DECL(sc, "kern-obj-get-movecost", kern_obj_get_movecost);
+        API_DECL(sc, "kern-obj-get-name", kern_obj_get_name);
+        API_DECL(sc, "kern-obj-get-sprite", kern_obj_get_sprite);
+        API_DECL(sc, "kern-obj-get-type", kern_obj_get_type);
+        API_DECL(sc, "kern-obj-get-vision-radius", kern_obj_get_vision_radius);
+        API_DECL(sc, "kern-obj-has?", kern_obj_has);
+        API_DECL(sc, "kern-obj-heal", kern_obj_heal);
+        API_DECL(sc, "kern-obj-inc-light", kern_obj_inc_light);
+        API_DECL(sc, "kern-obj-inc-ref", kern_obj_inc_ref);
+        API_DECL(sc, "kern-obj-is-being?", kern_obj_is_being);
+        API_DECL(sc, "kern-obj-is-char?", kern_obj_is_char);
+        API_DECL(sc, "kern-obj-is-container?", kern_obj_is_container);
+        API_DECL(sc, "kern-obj-is-field?", kern_obj_is_field);
+        API_DECL(sc, "kern-obj-is-mech?", kern_obj_is_mech);
+        API_DECL(sc, "kern-obj-is-submerged?", kern_obj_is_submerged);
+        API_DECL(sc, "kern-obj-is-visible?", kern_obj_is_visible);
+        API_DECL(sc, "kern-obj-move", kern_obj_move);
+        API_DECL(sc, "kern-obj-put-at", kern_obj_put_at);
+        API_DECL(sc, "kern-obj-put-into", kern_obj_put_into);
+        API_DECL(sc, "kern-obj-relocate", kern_obj_relocate);
+        API_DECL(sc, "kern-obj-remove", kern_obj_remove);
+        API_DECL(sc, "kern-obj-remove-effect", kern_obj_remove_effect);
+        API_DECL(sc, "kern-obj-remove-from-inventory", kern_obj_remove_from_inventory);
+        API_DECL(sc, "kern-obj-set-ap", kern_obj_set_ap);
+        API_DECL(sc, "kern-obj-set-conv", kern_obj_set_conv);
+        API_DECL(sc, "kern-obj-set-facing", kern_obj_set_facing);
+        API_DECL(sc, "kern-obj-set-gob", kern_obj_set_gob);
+        API_DECL(sc, "kern-obj-set-ignore-time-stop", kern_obj_set_ignore_time_stop);
+        API_DECL(sc, "kern-obj-set-light", kern_obj_set_light);
+        API_DECL(sc, "kern-obj-set-opacity", kern_obj_set_opacity);
+        API_DECL(sc, "kern-obj-set-pclass", kern_obj_set_pclass);
+        API_DECL(sc, "kern-obj-set-mmode", kern_obj_set_mmode);
+        API_DECL(sc, "kern-obj-set-portrait", kern_obj_set_portrait);
+        API_DECL(sc, "kern-obj-set-sprite", kern_obj_set_sprite);
+        API_DECL(sc, "kern-obj-set-submerged", kern_obj_set_submerged);
+        API_DECL(sc, "kern-obj-set-temporary", kern_obj_set_temporary);
+        API_DECL(sc, "kern-obj-set-ttl", kern_obj_set_ttl);
+        API_DECL(sc, "kern-obj-set-visible", kern_obj_set_visible);
+        API_DECL(sc, "kern-obj-wander", kern_obj_wander);
+               API_DECL(sc, "kern-obj-freeze", kern_obj_freeze);
+               API_DECL(sc, "kern-obj-thaw", kern_obj_thaw);
+
+        /* kern-occ api */
+        API_DECL(sc, "kern-occ-get-hp-mod",  kern_occ_get_hp_mod);
+        API_DECL(sc, "kern-occ-get-hp-mult", kern_occ_get_hp_mult);
+        API_DECL(sc, "kern-occ-get-mp-mod",  kern_occ_get_mp_mod);
+        API_DECL(sc, "kern-occ-get-mp-mult", kern_occ_get_mp_mult);
+        API_DECL(sc, "kern-occ-get-gob", kern_occ_get_gob);
+        API_DECL(sc, "kern-occ-set-gob", kern_occ_set_gob);
+
+        /* kern-place api */
+        API_DECL(sc, "kern-place-add-on-entry-hook", kern_place_add_on_entry_hook);
+        API_DECL(sc, "kern-place-apply-tile-effects", kern_place_apply_tile_effects);
+        API_DECL(sc, "kern-place-set-subplace", kern_place_set_subplace);
+        API_DECL(sc, "kern-place-get-beings", kern_place_get_beings);
+        API_DECL(sc, "kern-place-get-height", kern_place_get_height);
+        API_DECL(sc, "kern-place-get-light", kern_place_get_light);
+        API_DECL(sc, "kern-place-get-location", kern_place_get_location);
+        API_DECL(sc, "kern-place-get-movement-cost", kern_place_get_movement_cost);
+        API_DECL(sc, "kern-place-get-name", kern_place_get_name);
+        API_DECL(sc, "kern-place-get-neighbor", kern_place_get_neighbor);
+        API_DECL(sc, "kern-place-get-objects", kern_place_get_objects);
+        API_DECL(sc, "kern-place-get-terrain", kern_place_get_terrain);
+        API_DECL(sc, "kern-place-get-terrain-map", kern_place_get_terrain_map);
+        API_DECL(sc, "kern-place-get-vehicle", kern_place_get_vehicle);       
+        API_DECL(sc, "kern-place-get-width", kern_place_get_width);
+        API_DECL(sc, "kern-place-is-passable", kern_place_is_passable);
+        API_DECL(sc, "kern-place-is-hazardous", kern_place_is_hazardous);
+        API_DECL(sc, "kern-place-is-wrapping?", kern_place_is_wrapping);
+        API_DECL(sc, "kern-place-is-wilderness?", kern_place_is_wilderness);
+        API_DECL(sc, "kern-place-blocks-los?", kern_place_blocks_los);
+        API_DECL(sc, "kern-place-map", kern_place_map);
+        API_DECL(sc, "kern-place-move-is-passable?", kern_place_move_is_passable);
+        API_DECL(sc, "kern-place-set-neighbor", kern_place_set_neighbor);
+        API_DECL(sc, "kern-place-set-terrain", kern_place_set_terrain);
+        API_DECL(sc, "kern-place-set-terrain-map", kern_place_set_terrain_map);
+        API_DECL(sc, "kern-place-synch", kern_place_synch);
+        API_DECL(sc, "kern-place-is-visible?", kern_place_is_visible);        
+        API_DECL(sc, "kern-place-is-combat-map?", kern_place_is_combat_map);        
+
+        /* player api */
+        API_DECL(sc, "kern-player-get-food", kern_player_get_food);
+        API_DECL(sc, "kern-player-get-gold", kern_player_get_gold);
+        API_DECL(sc, "kern-player-set-follow-mode", kern_player_set_follow_mode);
+        API_DECL(sc, "kern-player-set-food", kern_player_set_food);
+        API_DECL(sc, "kern-player-set-gold", kern_player_set_gold);
+
+        /* screen api */
+        API_DECL(sc, "kern-screen-erase", kern_screen_erase);
+        API_DECL(sc, "kern-screen-print", kern_screen_print);
+        API_DECL(sc, "kern-screen-shade", kern_screen_shade);
+        API_DECL(sc, "kern-screen-update", kern_screen_update);
+        API_DECL(sc, "kern-screen-draw-sprite", kern_screen_draw_sprite);
+
+        /* kern-set api */
+        API_DECL(sc, "kern-set-crosshair", kern_set_crosshair);
+        API_DECL(sc, "kern-set-damage-sprite", kern_set_damage_sprite);
+        API_DECL(sc, "kern-set-clock", kern_set_clock);
+
+        /* kern-species api */
+        API_DECL(sc, "kern-species-get-hp-mod",  kern_species_get_hp_mod);
+        API_DECL(sc, "kern-species-get-hp-mult", kern_species_get_hp_mult);
+        API_DECL(sc, "kern-species-get-mp-mod",  kern_species_get_mp_mod);
+        API_DECL(sc, "kern-species-get-mp-mult", kern_species_get_mp_mult);
+
+        /* kern-terrain api */
+        API_DECL(sc, "kern-terrain-blocks-los?", kern_terrain_blocks_los);
+        API_DECL(sc, "kern-terrain-get-pclass", kern_terrain_get_pclass);
+        API_DECL(sc, "kern-terrain-set-combat-map", kern_terrain_set_combat_map);
+        API_DECL(sc, "kern-terrain-set-combat-handler", kern_terrain_set_combat_handler);
+        API_DECL(sc, "kern-terrain-map-inc-ref", kern_terrain_map_inc_ref);
+        API_DECL(sc, "kern-terrain-map-dec-ref", kern_terrain_map_dec_ref);
+        API_DECL(sc, "kern-terrain-map-blend", kern_terrain_map_blend);
+        API_DECL(sc, "kern-terrainmap-get-width", kern_map_get_width);
+        API_DECL(sc, "kern-terrainmap-get-height", kern_map_get_height);
+
+        /* kern-type api */
+        API_DECL(sc, "kern-type-describe", kern_type_describe);
+        API_DECL(sc, "kern-type-get-gifc", kern_type_get_gifc);
+        API_DECL(sc, "kern-type-get-gob", kern_type_get_gob);
+        API_DECL(sc, "kern-type-get-name", kern_type_get_name);
+        API_DECL(sc, "kern-type-set-gob", kern_type_set_gob);
+        API_DECL(sc, "kern-type-set-quest-item-flag", kern_type_set_quest_item_flag);
+
+        /* misc api */
+        API_DECL(sc, "kern-add-magic-negated", kern_add_magic_negated);
+        API_DECL(sc, "kern-add-quicken", kern_add_quicken);
+        API_DECL(sc, "kern-add-reveal", kern_add_reveal);
+        API_DECL(sc, "kern-add-save-game", kern_add_save_game);
+        API_DECL(sc, "kern-add-spell", kern_add_spell);
+        API_DECL(sc, "kern-add-tick-job", kern_add_tick_job);
+        API_DECL(sc, "kern-add-time-stop", kern_add_time_stop);
+        API_DECL(sc, "kern-ambush-while-camping", kern_ambush_while_camping);
+        API_DECL(sc, "kern-add-xray-vision", kern_add_xray_vision);
+        API_DECL(sc, "kern-begin-combat", kern_begin_combat);
+        API_DECL(sc, "kern-blit-map", kern_blit_map);
+        API_DECL(sc, "kern-init-random", kern_init_random);
+        API_DECL(sc, "kern-define", kern_define);
+        API_DECL(sc, "kern-dice-roll", kern_dice_roll);
+        API_DECL(sc, "kern-end-game" , kern_end_game);
+        API_DECL(sc, "kern-fire-missile", kern_fire_missile);
+        API_DECL(sc, "kern-fire-missile-to-max", kern_fire_missile_to_max);
+        API_DECL(sc, "kern-fold-rect", kern_fold_rect);
+        API_DECL(sc, "kern-get-distance", kern_get_distance);
+        API_DECL(sc, "kern-get-objects-at", kern_get_objects_at);
+        API_DECL(sc, "kern-get-magic-negated", kern_get_magic_negated);
+        API_DECL(sc, "kern-get-player", kern_get_player);
+        API_DECL(sc, "kern-get-ticks", kern_get_ticks);
+        API_DECL(sc, "kern-get-time", kern_get_time);
+        API_DECL(sc, "kern-time-get-remainder", kern_get_time_remainder);
+        API_DECL(sc, "kern-get-total-minutes", kern_get_total_minutes);
+        API_DECL(sc, "kern-harm-relations", kern_harm_relations);              
+        API_DECL(sc, "kern-in-los?", kern_in_los);
+        API_DECL(sc, "kern-los-invalidate", kern_los_invalidate);
+        API_DECL(sc, "kern-include", kern_include);
+        API_DECL(sc, "kern-interp-error", kern_interp_error);
+        API_DECL(sc, "kern-is-valid-location?", kern_is_valid_location);
+        API_DECL(sc, "kern-print", kern_print);
+        API_DECL(sc, "kern-search-rect", kern_search_rect);
+        API_DECL(sc, "kern-search-rect-for-terrain", 
+                 kern_search_rect_for_terrain);
+        API_DECL(sc, "kern-search-rect-for-obj-type", 
+                 kern_search_rect_for_obj_type);
+        API_DECL(sc, "kern-add-hook", kern_add_hook);
+        API_DECL(sc, "kern-add-query", kern_add_query);
+        API_DECL(sc, "kern-rm-hook", kern_rm_hook);
+        API_DECL(sc, "kern-set-quicken-sprite", kern_set_quicken_sprite);
+        API_DECL(sc, "kern-set-time-stop-sprite", kern_set_time_stop_sprite);
+        API_DECL(sc, "kern-set-magic-negated-sprite", kern_set_magic_negated_sprite);
+        API_DECL(sc, "kern-set-reveal-sprite", kern_set_reveal_sprite);
+        API_DECL(sc, "kern-set-xray-vision-sprite", kern_set_xray_vision_sprite);
+        API_DECL(sc, "kern-set-spell-words", kern_set_spell_words);
+        API_DECL(sc, "kern-set-wind", kern_set_wind);
+        API_DECL(sc, "kern-get-wind", kern_get_wind);
+        API_DECL(sc, "kern-set-time-accel", kern_set_time_accel);
+        API_DECL(sc, "kern-sleep", kern_sleep);
+        API_DECL(sc, "kern-music-play", kern_music_play);
+        API_DECL(sc, "kern-sound-play", kern_sound_play);
+        API_DECL(sc, "kern-sound-play-at", kern_sound_play_at);
+        API_DECL(sc, "kern-sound-play-ambient", kern_sound_play_ambient);
+        API_DECL(sc, "kern-tag", kern_tag);
+        API_DECL(sc, "kern-test-recursion", kern_test_recursion);
+        API_DECL(sc, "kern-ticks-per-turn", kern_ticks_per_turn);
+        API_DECL(sc, "kern-set-turn-count", kern_set_turn_count);
+        API_DECL(sc, "kern-map-flash-sprite", kern_map_flash_sprite); 
+        API_DECL(sc, "kern-script-version", kern_script_version);
+        
+        /* ui api */
+        API_DECL(sc, "kern-ui-direction", kern_ui_direction);
+        API_DECL(sc, "kern-ui-paginate-text", kern_ui_paginate_text);
+        API_DECL(sc, "kern-ui-page-text", kern_ui_page_text);
+        API_DECL(sc, "kern-ui-select-from-list", kern_ui_select_from_list);
+        API_DECL(sc, "kern-ui-select-item", kern_ui_select_item);
+        API_DECL(sc, "kern-ui-select-party-member", kern_ui_select_party_member);
+        API_DECL(sc, "kern-ui-target", kern_ui_target);
+        API_DECL(sc, "kern-ui-target-generic", kern_ui_target_generic);
+        API_DECL(sc, "kern-ui-waitkey", kern_ui_waitkey);
+        API_DECL(sc, "kern-applet-run", kern_applet_run);
+
+        /* conv api */
+        API_DECL(sc, "kern-conv-begin", kern_conv_begin);
+        API_DECL(sc, "kern-conv-end", kern_conv_end);
+        API_DECL(sc, "kern-conv-say", kern_conv_say);
+        API_DECL(sc, "kern-conv-get-amount", kern_conv_get_amount);
+        API_DECL(sc, "kern-conv-get-yes-no?", kern_conv_get_yes_no);
+        API_DECL(sc, "kern-conv-trade", kern_conv_trade);
+        API_DECL(sc, "kern-conv-get-reply", kern_conv_get_reply);
+        API_DECL(sc, "kern-conv-get-string", kern_conv_get_string);
+
+        /* kern-map api */
+        API_DECL(sc, "kern-map-blit-image", kern_map_blit_image);
+        API_DECL(sc, "kern-map-center-camera", kern_map_center_camera);
+        API_DECL(sc, "kern-map-flash", kern_map_flash);
+        API_DECL(sc, "kern-map-repaint", kern_map_repaint);
+        API_DECL(sc, "kern-map-set-dirty", kern_map_set_dirty);
+        API_DECL(sc, "kern-map-set-image", kern_map_set_image);
+        API_DECL(sc, "kern-map-set-jitter", kern_map_set_jitter);
+        API_DECL(sc, "kern-map-set-peering", kern_map_set_peering);
+        API_DECL(sc, "kern-map-view-create", kern_map_view_create);
+        API_DECL(sc, "kern-map-view-destroy", kern_map_view_destroy);
+        API_DECL(sc, "kern-map-view-center", kern_map_view_center);
+        API_DECL(sc, "kern-map-view-add", kern_map_view_add);
+        API_DECL(sc, "kern-map-view-rm", kern_map_view_rm);
+        API_DECL(sc, "kern-map-view-add", kern_map_view_add);
+        API_DECL(sc, "kern-map-view-rm", kern_map_view_rm);
+                
+        /* kern-log api */
+        API_DECL(sc, "kern-log-begin", kern_log_begin);
+        API_DECL(sc, "kern-log-continue", kern_log_continue);
+        API_DECL(sc, "kern-log-end", kern_log_end);
+        API_DECL(sc, "kern-log-enable", kern_log_enable);
+        API_DECL(sc, "kern-log-flush", kern_log_flush);
+        API_DECL(sc, "kern-log-msg", kern_log_msg);
+        API_DECL(sc, "kern-stdout-msg", kern_stdout_msg);
+               
+        /* kern-dtable api */
+        API_DECL(sc, "kern-mk-dtable", kern_mk_dtable);
+        API_DECL(sc, "kern-dtable-get", kern_dtable_get);
+        API_DECL(sc, "kern-dtable-set", kern_dtable_set);
+        API_DECL(sc, "kern-dtable-inc", kern_dtable_inc);
+        API_DECL(sc, "kern-dtable-dec", kern_dtable_dec);
+
+        /* kern-party-api */
+        API_DECL(sc, "kern-party-add-member", kern_party_add_member);
+        API_DECL(sc, "kern-party-get-members", kern_party_get_members);
+        API_DECL(sc, "kern-party-get-vehicle", kern_party_get_vehicle);
+        API_DECL(sc, "kern-party-set-vehicle", kern_party_set_vehicle);
+
+        /* kern-sprite api */
+        API_DECL(sc, "kern-sprite-clone", kern_sprite_clone);
+        API_DECL(sc, "kern-sprite-append-decoration", kern_sprite_append_decoration);
+        API_DECL(sc, "kern-sprite-apply-matrix", kern_sprite_apply_matrix);
+        API_DECL(sc, "kern-sprite-blit-over", kern_sprite_blit_over);
+        API_DECL(sc, "kern-sprite-strip-decorations", kern_sprite_strip_decorations);
+
+
+        /* kern-vehicle-api */
+        API_DECL(sc, "kern-vehicle-set-name", kern_vehicle_set_name);
+
+        /* kern-cfg api */
+        API_DECL(sc, "kern-cfg-set", kern_cfg_set);
+        API_DECL(sc, "kern-cfg-get", kern_cfg_get);
+
+        API_DECL(sc, "kern-set-kern-intvar", kern_set_kern_intvar);
+        API_DECL(sc, "kern-get-kern-intvar", kern_get_kern_intvar);
+
+
+        /* kern-image api */
+        API_DECL(sc, "kern-image-load", kern_image_load);
+        API_DECL(sc, "kern-image-free", kern_image_free);
+
+        /* kern-progress-bar api */
+        API_DECL(sc, "kern-progress-bar-start", kern_progress_bar_start);
+        API_DECL(sc, "kern-progress-bar-advance", kern_progress_bar_advance);
+        API_DECL(sc, "kern-progress-bar-finish", kern_progress_bar_finish);
+
+        /* kern-ztats api */
+        API_DECL(sc, "kern-ztats-add-pane", kern_ztats_add_pane);
+        API_DECL(sc, "kern-status-set-title", kern_status_set_title);
+
+        /* obsolete (keep these until old save games are unlikely to use
+         * them) */
+        API_DECL(sc, "kern-set-frame", kern_set_frame);
+        API_DECL(sc, "kern-set-cursor", kern_set_cursor);
+        API_DECL(sc, "kern-set-ascii", kern_set_ascii);
+
+        
+        /* Revisit: probably want to provide some kind of custom port here. */
+        scheme_set_output_port_file(sc, stderr);
+
+        /* Shared constants */
+        scm_define_int(sc, "kern-key-esc", SDLK_ESCAPE);
+        scm_define_int(sc, "kern-key-space", SDLK_SPACE);
+        scm_define_int(sc, "kern-key-return", '\n'); // remapped in event.c::mapKey
+        scm_define_int(sc, "kern-key-enter", SDLK_KP_ENTER);
+        scm_define_int(sc, "kern-key-up", SDLK_KP8); // also handles arrowkeys
+        scm_define_int(sc, "kern-key-down", SDLK_KP2); // also handles arrowkeys
+        scm_define_int(sc, "kern-key-kp-pgup", SDLK_KP9);
+        scm_define_int(sc, "kern-key-kp-pgdn", SDLK_KP3);
+        scm_define_int(sc, "kern-key-pgup", SDLK_PAGEUP);
+        scm_define_int(sc, "kern-key-pgdn", SDLK_PAGEDOWN);
+        scm_define_int(sc, "kern-sp-centered", SP_CENTERED);
+        scm_define_int(sc, "kern-ascii-h", ASCII_H);
+        return sc;
+}
diff --git a/src/kern.h b/src/kern.h
new file mode 100644 (file)
index 0000000..0b17f59
--- /dev/null
@@ -0,0 +1,30 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef kern_h
+#define kern_h
+
+#include "scheme.h"
+
+scheme * kern_init(void);
+
+#endif
diff --git a/src/kern_intvar.c b/src/kern_intvar.c
new file mode 100644 (file)
index 0000000..343b15f
--- /dev/null
@@ -0,0 +1,117 @@
+/* $Id: kern_intvar.c,v 1.3 2010/08/26 05:56:20 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "kern_intvar.h"
+// #include "repstr.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <stdio.h>
+
+#define KERN_INTVAR_HASH_SIZE 31
+
+struct kern_intvar_entry {
+    struct kern_intvar_entry *next;
+    char *key;
+    int value;
+} *kern_intvar_hash[KERN_INTVAR_HASH_SIZE];
+
+static struct kern_intvar_entry *kern_intvar_entry_new(const char *key, const int value)
+{
+    struct kern_intvar_entry *entry = (struct kern_intvar_entry*) malloc(sizeof(*entry));
+    assert(entry);
+
+    entry->next = 0;
+
+    entry->key = strdup(key);
+    assert(entry->key);
+
+    entry->value = value;
+
+    return entry;
+}
+
+static int hashfn(const char *key)
+{
+    unsigned int hashed = 0; 
+    const char *c; 
+    static const int bits_per_int = sizeof(unsigned int)*8; 
+
+     for (c = key; *c; c++) { 
+        /* letters have about 5 bits in them */ 
+        hashed = (hashed<<5) | (hashed>>(bits_per_int-5)); 
+        hashed ^= *c; 
+     } 
+    return hashed % KERN_INTVAR_HASH_SIZE;
+}
+
+int kern_intvar_init()
+{
+    memset(kern_intvar_hash, 0, sizeof(kern_intvar_hash));
+    return 0;
+}
+
+void kern_intvar_set(const char *key, int value)
+{
+    int hashkey = hashfn(key);
+    struct kern_intvar_entry *entry = kern_intvar_hash[hashkey];
+    if (! entry) {
+        kern_intvar_hash[hashkey] = kern_intvar_entry_new(key, value);
+    } 
+    else {
+        int match = !strcmp(entry->key, key);
+        while (! match
+               && entry->next) {
+            entry = entry->next;
+            match = !strcmp(entry->key, key);
+        }
+        if (match) {
+           entry->value = value;
+        } else {
+            entry->next = kern_intvar_entry_new(key, value);
+        }
+    }
+}
+
+int kern_intvar_get(const char *key)
+{
+    int hashkey = hashfn(key);
+    struct kern_intvar_entry *entry = kern_intvar_hash[hashkey];
+    if (! entry) {
+        return 0;
+    } 
+    else {
+        int match = !strcmp(entry->key, key);
+        while (! match
+               && entry->next) {
+            entry = entry->next;
+            match = !strcmp(entry->key, key);
+        }
+        if (match) {
+            return entry->value;
+        } else {
+            return 0;  // SAM: Perhaps -1 or MAXINT would be a useful return for this case?
+        }
+    }
+}
+
+
+// eof
diff --git a/src/kern_intvar.h b/src/kern_intvar.h
new file mode 100644 (file)
index 0000000..a7ebad7
--- /dev/null
@@ -0,0 +1,27 @@
+/* $Id: kern_intvar.h,v 1.2 2010/08/26 05:56:20 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef kern_intvar_h
+#define kern_intvar_h
+
+int  kern_intvar_init();
+void kern_intvar_set(const char *key, int value);
+int  kern_intvar_get(const char *key);
+
+#endif
diff --git a/src/knapsack.c b/src/knapsack.c
new file mode 100644 (file)
index 0000000..7869216
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "knapsack.h"
+
+//#define DEBUG
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+static unsigned char cur_in[MAX_N_ITEMS];
+static int max;
+static int cur_max;
+
+#ifdef DEBUG
+static void dump_problem(struct knapsack *prob)
+{
+       int i;
+       printf("-------------------------\n");
+       printf("max=%d\n", max);
+       for (i = 0; i < prob->n_items; i++) {
+               printf("%d %d %d\n", i, prob->value[i], prob->solution[i]);
+       }
+}
+#endif
+
+static int ks_solve(struct knapsack *prob)
+{
+       int i;
+
+#ifdef DEBUG
+       dump_problem(prob);
+#endif
+
+       /* For each item... */
+       for (i = 0; i < prob->n_items; i++) {
+
+               if (cur_in[i])
+                       /* The item is already in the knapsack */
+                       continue;
+
+               if (prob->put(prob->item[i], prob->context)) {
+
+                       /* The item fits. To decide if the item belongs in the
+                        * * final solution consider two subproblems: one where
+                        * * the item is included in the solution, and one where
+                        * * the item is not. */
+
+                       cur_in[i] = 1;
+                       cur_max += prob->value[i];
+
+                       if (max < cur_max) {
+                               /* This solution is better than the old * one.
+                                * Make a copy. */
+                               int j;
+                               max = cur_max;
+                               for (j = 0; j < prob->n_items; j++)
+                                       prob->solution[j] = cur_in[j];
+                       }
+
+                       /* Consider the subproblem where the item is included */
+                       ks_solve(prob);
+
+                       /* Consider the subproblem where the item is NOT *
+                        * included (by continuing at this level without it) */
+                       cur_in[i] = 0;
+                       cur_max -= prob->value[i];
+                       prob->remove(prob->item[i], prob->context);
+               }
+       }
+
+#if  0
+       /* remove any remaining items */
+       for (i = 0; i < prob->n_items; i++) {
+               if (cur_in[i])
+                       prob->remove(prob->item[i], prob->context);
+       }
+#endif
+
+       return 0;
+}
+
+int knapsack_solve(struct knapsack *prob)
+{
+       int i;
+
+       /* Sanity checks */
+       if (!prob || prob->n_items < 0 || prob->n_items > MAX_N_ITEMS)
+               return -1;
+
+       /* Initialize */
+       for (i = 0; i < prob->n_items; i++) {
+               prob->solution[i] = 0;
+               cur_in[i] = 0;
+       }
+       max = 0;
+       cur_max = 0;
+
+       return ks_solve(prob);
+}
diff --git a/src/knapsack.h b/src/knapsack.h
new file mode 100644 (file)
index 0000000..bbba6f0
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef knapsack_h
+#define knapsack_h
+
+#define MAX_N_ITEMS 100
+
+struct knapsack {
+
+       int n_items;            /* The number of items to consider */
+
+       void **item;            /* Array of pointers to the items under
+                                * consideration. Memory managed by caller. */
+
+       int *value;             /* Array of values of the items (in the same
+                                * order as the items). Memory managed by *
+                                * caller. */
+
+       unsigned char *solution;        /* Array representing the set of items
+                                        * chosen. If and only if the value of
+                                        * * solution[i] is * nonzero, then *
+                                        * item[i] was chosen. Memory managed *
+                                        * by * caller. */
+
+       int (*put) (void *context, void *item); /* Attempt to put the item in
+                                                * the 'knapsack' and return
+                                                * nonzero if successful or
+                                                * zero if it failed. */
+
+       void (*remove) (void *context, void *item);     /* Remove an item from
+                                                        * the knapsack. */
+
+       void *context;          /* Used as the 'context' parameter to the 'put'
+                                * callback */
+};
+
+extern int knapsack_solve(struct knapsack *problem);
+
+#endif
diff --git a/src/list.h b/src/list.h
new file mode 100644 (file)
index 0000000..806ded7
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+/* 
+ * From-scratch impl inspired by the Linux kernel source's list.h 
+ */
+
+#ifndef list_h
+#define list_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#define list_for_each(head,ptr) \
+        for ((ptr) = (head)->next; (ptr) != (head); (ptr) = (ptr)->next)
+#define list_init(list) { (list)->next = (list); (list)->prev = (list); }
+#define list_empty(list) ((list)->next == (list) && (list)->prev == (list))
+#define list_entry(ptr,type,field) \
+        ((type*)((char*)(ptr)-(unsigned long)(&((type *)0)->field)))
+
+struct list {
+        struct list *next;
+        struct list *prev;
+};
+
+static inline void list_add_aux(struct list *before, struct list *after,
+                                struct list *between) 
+{
+        between->next = after;
+        between->prev = before;
+        before->next = between;
+        after->prev = between;
+}
+
+static inline void list_add(struct list *head, struct list *ptr) 
+{
+        list_add_aux(head, head->next, ptr);
+}
+
+static inline void list_add_tail(struct list *head, struct list *ptr) 
+{
+        list_add_aux(head->prev, head, ptr);
+}
+
+static inline void list_remove(struct list *list) 
+{
+        list->prev->next = list->next;
+        list->next->prev = list->prev;
+        list_init(list);
+}
+
+static inline void list_switch_adjacent(struct list *first, 
+                                        struct list *second)
+{
+        first->prev->next = second;
+        second->prev = first->prev;
+        first->prev = second;
+        first->next = second->next;
+        second->next->prev = first;
+        second->next = first;
+}
+
+static inline void list_replace(struct list *orig, struct list *repl)
+{
+        if (orig ==repl)
+                return;
+
+        *repl = *orig;
+        orig->next->prev = repl;
+        orig->prev->next = repl;
+}
+
+static inline void list_switch(struct list *e1, struct list *e2)
+{
+        struct list tmp;
+
+        list_replace(e1, &tmp);
+        list_replace(e2, e1);
+        list_replace(&tmp, e2);
+}
+
+static inline int list_len(struct list *head)
+{
+        struct list *list = head->next;
+        int n = 0;
+        while (list != head) {
+                list = list->next;
+                n++;
+        }
+        return n;
+}
+
+static inline void list_move(struct list *new_head, struct list *old_head)
+{
+        if (list_empty(old_head)) {
+                list_init(new_head);
+                return;
+        }
+
+        *new_head = *old_head;
+        new_head->next->prev = new_head;
+        new_head->prev->next = new_head;
+
+        list_init(old_head);
+}
+
+END_DECL
+
+#endif
diff --git a/src/log.c b/src/log.c
new file mode 100644 (file)
index 0000000..c5d3a47
--- /dev/null
+++ b/src/log.c
@@ -0,0 +1,262 @@
+#include "log.h"
+#include "list.h"
+#include "common.h"
+#include "console.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#define LOG_ENTRY_BUF_SZ 512
+
+static struct list log_q;
+static struct list log_stk;
+static int log_group;
+static int log_disabled;
+
+struct log_entry {
+        struct list q_hook;
+        struct list stk_hook;
+        char buf[LOG_ENTRY_BUF_SZ];
+        char *ptr;
+        int room;
+};
+
+struct log_entry *log_entry_new()
+{
+        struct log_entry *entry = (struct log_entry*)calloc(1, sizeof(*entry));
+        assert(entry);
+        entry->ptr = entry->buf;
+        entry->room = sizeof(entry->buf);
+        return entry;
+}
+
+static void log_entry_del(struct log_entry *entry)
+{
+        free(entry);
+}
+
+static void log_entry_print(struct log_entry *entry, const char *fmt, va_list args)
+{
+        /* If fmt is NULL experimentation shows that vsnprintf returns -1,
+         * which is also the indication that we attempted to overflow the
+         * buffer. To prevent the ambiguity (we want to handle 'nothing
+         * written' differently than 'overflow') check for NULL here. */
+        if (!fmt) {
+                return;
+        }
+
+        int wrote = vsnprintf(entry->ptr, entry->room, fmt, args);
+        if (wrote >= 0) {
+                entry->room -= wrote;
+                entry->ptr += wrote;
+        } else {
+                entry->room = 0;
+        }
+}
+
+void log_flush()
+{
+        struct log_entry *entry;
+
+        if (list_empty(&log_q))
+                return;
+
+        entry = outcast(log_q.next, struct log_entry, q_hook);
+
+        if (entry->ptr != entry->buf) {
+                consolePrint(entry->buf);
+                consoleRepaint();
+                memset(entry->buf, 0, sizeof(entry->buf));
+                entry->ptr = entry->buf;
+                entry->room = sizeof(entry->buf);
+        }
+}
+
+static inline void log_print_queued_msgs()
+{
+        struct list *elem;
+
+        elem = log_q.next;
+
+        while (elem != &log_q) {
+
+                struct log_entry *entry;
+                
+                entry = outcast(elem, struct log_entry, q_hook);
+                elem = elem->next;
+                consolePrint("%s\n", entry->buf);
+                list_remove(&entry->q_hook);
+                log_entry_del(entry);
+        }
+}
+
+static inline void log_flush_queued_msgs(struct log_entry *entry)
+{
+        struct list *elem;
+
+        elem = &entry->q_hook;
+
+        while (elem != &log_q) {
+                entry = outcast(elem, struct log_entry, q_hook);
+                elem = elem->next;
+                list_remove(&entry->q_hook);
+                log_entry_del(entry);
+        }
+}
+
+static inline void log_push(struct log_entry *entry)
+{
+        list_add_tail(&log_q, &entry->q_hook);
+        list_add(&log_stk, &entry->stk_hook);
+        log_begin_group();
+}
+
+static inline void log_pop()
+{
+        assert(! list_empty(&log_stk));
+        
+        /* Pop the topmost entry from the msg stack */
+        list_remove(log_stk.next);
+        
+        /* If the msg stack is now empty then log all msgs on the queue */
+        if (list_empty(&log_stk))
+                log_print_queued_msgs();
+        log_end_group();
+}
+
+void log_abort(void)
+{
+        struct log_entry *entry;
+
+        if (log_disabled)
+                return;
+
+        assert(! list_empty(&log_stk));
+        entry = outcast(log_stk.next, struct log_entry, stk_hook);
+
+        list_remove(log_stk.next);
+        log_flush_queued_msgs(entry);
+        log_end_group();
+}
+
+void log_init(void)
+{
+        list_init(&log_q);
+        list_init(&log_stk);
+        log_group = 0;
+        log_disabled = 0;
+}
+
+void log_begin(const char *fmt, ...)
+{
+        va_list args;
+
+        if (log_disabled)
+                return;
+
+        struct log_entry *entry = log_entry_new();
+        log_push(entry);
+        va_start(args, fmt);
+        log_entry_print(entry, fmt, args);
+        va_end(args);
+}
+
+void log_continue(const char *fmt, ...)
+{
+        va_list args;
+        struct log_entry *entry;
+
+        if (log_disabled)
+                return;
+
+        assert(! list_empty(&log_stk));
+        entry = outcast(log_stk.next, struct log_entry, stk_hook);
+        va_start(args, fmt);
+        log_entry_print(entry, fmt, args);
+        va_end(args);
+}
+
+void log_end(const char *fmt, ...)
+{
+        va_list args;
+        struct log_entry *entry;
+
+        if (log_disabled)
+                return;
+
+        assert(! list_empty(&log_stk));
+        entry = outcast(log_stk.next, struct log_entry, stk_hook);
+        va_start(args, fmt);
+        log_entry_print(entry, fmt, args);
+        va_end(args);
+        log_pop();
+}
+
+void log_msg(const char *fmt, ...)
+{
+        va_list args;
+        struct log_entry *entry = log_entry_new();
+
+        if (log_disabled)
+                return;
+
+        log_push(entry);
+        va_start(args, fmt);
+        log_entry_print(entry, fmt, args);
+        va_end(args);
+        log_pop();        
+}
+
+void log_banner(const char *fmt, ...)
+{
+        struct log_entry *entry;
+        va_list args;
+
+        if (log_disabled) {
+                return;
+        }
+
+        log_begin_group();
+        log_msg("^c+y*********************************^c-");
+        log_begin("^c+y*^c- ");
+        
+        
+        entry = outcast(log_stk.next, struct log_entry, stk_hook);
+        va_start(args, fmt);
+        log_entry_print(entry, fmt, args);
+        va_end(args);
+
+        log_end("");
+        log_msg("^c+y*********************************^c-");
+        log_end_group();
+}
+
+void log_begin_group()
+{
+        if (log_disabled)
+                return;
+
+        log_group++;
+}
+
+void log_end_group()
+{
+        if (log_disabled)
+                return;
+
+        log_group--;
+        if (log_group == 0)
+                consolePrint("\n");
+}
+
+void log_disable()
+{
+        log_disabled++;
+}
+
+void log_enable()
+{
+        log_disabled--;
+}
diff --git a/src/log.h b/src/log.h
new file mode 100644 (file)
index 0000000..a87e461
--- /dev/null
+++ b/src/log.h
@@ -0,0 +1,57 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef log_h
+#define log_h
+
+/* Called on startup */
+extern void log_init(void);
+
+/* A group of messages are all printed with no blank line between them. Blank
+ * lines appear between top-level groups. */
+extern void log_begin_group();
+extern void log_end_group();
+
+/* Begin a message that will start a group and prevent members of the group
+ * from printing until it finishes. This is to de-interleave messages. */
+extern void log_begin(const char *fmt, ...);
+extern void log_continue(const char *fmt, ...);
+extern void log_end(const char *fmt, ...);
+extern void log_abort();
+
+/* log_flush - force a partial entry started with log_begin() to print now
+ * rather than waiting for log_end(). Warning: calling log_abort() after this
+ * will not erase what was written to the console. Normally you don't need to
+ * use log_flush().
+ */
+extern void log_flush();
+
+/* Log a single message as its own group. */
+extern void log_msg(const char *fmt, ...);
+
+extern void log_disable();
+extern void log_enable();
+
+/* Like log_msg, but with fancy borders. */
+extern void log_banner(const char *fmt, ...);
+
+#endif
diff --git a/src/los.c b/src/los.c
new file mode 100644 (file)
index 0000000..ac933b3
--- /dev/null
+++ b/src/los.c
@@ -0,0 +1,104 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "los.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#define los_NUMALGS sizeof(algs)/sizeof(algs[0])
+
+extern int FLOODFILL_Init(struct los *los);
+extern int ANGBAND_Init(struct los *los);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+struct alg_list_entry {
+       const char *name;
+       int (*init) (struct los * los);
+} algs[] = {
+       {
+                "floodfill", FLOODFILL_Init}, {
+                "angband", ANGBAND_Init},};
+
+struct los *los_create(const char *name, int w, int h, int r)
+{
+       struct los *los;
+       unsigned int i;
+
+       /* Check if alg is supported */
+       for (i = 0; i < los_NUMALGS; i++) {
+               if (!strcmp(algs[i].name, name))
+                       break;
+       }
+
+       /* Check if alg was not found */
+       if (i == los_NUMALGS)
+               return 0;
+
+       /* Allocate the "base class" */
+       los = (struct los *) malloc(sizeof(struct los));
+       if (!los)
+               return 0;
+
+       memset(los, 0, sizeof(struct los));
+
+       los->w = w;
+       los->h = h;
+       los->r = r;
+
+       /* Allocate the visibility buffer */
+       los->vmask = (unsigned char *) malloc(w * h);
+       if (!los->vmask)
+               goto fail;
+
+       /* Allocate the alpha buffer */
+       los->alpha = (unsigned char *) malloc(w * h);
+       if (!los->alpha)
+               goto fail;
+
+       /* Initialize the specific algorithm */
+       if (algs[i].init(los) < 0)
+               goto fail;
+
+       return los;
+
+      fail:
+       los_destroy(los);
+       return 0;
+
+}
+
+void los_destroy(struct los *los)
+{
+       if (los->destroy)
+               los->destroy(los);
+       if (los->vmask)
+               free(los->vmask);
+       if (los->alpha)
+               free(los->alpha);
+       free(los);
+}
diff --git a/src/los.h b/src/los.h
new file mode 100644 (file)
index 0000000..aa47c0c
--- /dev/null
+++ b/src/los.h
@@ -0,0 +1,122 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef los_h
+#define los_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ALPHA_TRANSPARENT 0
+#define ALPHA_OPAQUE      12
+
+       struct los {
+
+               /*** Public ***/
+
+               /**
+                 * Width and height specify the maximum area over which an
+                 * algorithm will compute line of sight.
+                 */
+               int w;
+               int h;
+
+               /**
+                 * Radius is an optional parameter. Use it to limit the max
+                 * visible range from the center of the vmask. No matter how
+                 * large you make this, the width and height parameters (above)
+                 * still enforce a max limit on visible range. But you can use
+                 * it to shrink the visible range below what the width and
+                 * height allow.
+                 */
+               int r;
+
+               /**
+                 * 'alpha' points to a 2d array. Each element in the array
+                 * corresponds to a tile on the visible map. The value in each
+                 * element indicates how transparent the corresponding tile
+                 * is. For example, a value of 0 indicates that the tile is
+                 * perfectly opaque and blocks all visibility beyond it,
+                 * whereas a value of 1 indicates that the tile is perfectly
+                 * transparent and does not hamper visibility at all.
+                 *
+                 * Although the los engine is responsible for allocating and
+                 * freeing this buffer, the caller is responsible for filling
+                 * it in before calling the compute() routine.
+                 */
+               unsigned char *alpha;
+
+               /**
+                 * 'vmask' also points to a 2d array. Again, each element
+                 * corresponds to a tile. However, this array stores the result
+                 * of the last los computation.  It's value give the relative
+                 * visibility of a tile. For example, 0 means the tile is
+                 * completely obscured, whereas 1 means the tile is completely
+                 * visible.
+                 *
+                 * The los engine is responsible for allocating and freeing
+                 * this buffer, and also filling it. The caller should consider
+                 * it read-only (but it doesn't really matter).
+                 */
+               unsigned char *vmask;
+
+               /**
+                 * Run the los algorithm and return the results in
+                 * 'vmask'. Note that both 'alpha' and 'vmask' must refer to
+                 * valid pointers.
+                 */
+               void (*compute) (struct los * los);
+
+               /*** Private ***/
+
+               /**
+                 * Free the resources associated with an los engine. This is
+                 * for internal use only -- clients should use los_destroy()
+                 * below instead.
+                 */
+               void (*destroy) (struct los * los);
+
+               void *data;
+
+       };
+
+       /**
+         * Create an los object.  'algorithm' specifies the name of the los
+         * algorithm to use (e.g., "angband" or "floodfill").  'width' and
+         * 'height' are used to size the alpha and vmask buffers.  'radius' is
+         * used by some algorithms to limit line-of-sight to something less
+         * than 'width' or 'height' (angband uses it, floodfill currently does
+         * not).  Returns an los struct or null if one can't be created to meet
+         * the request.
+         */
+       extern struct los *los_create(const char *algorithm, int width, int height,
+                                     int radius);
+
+       /**
+         * Free the resources used by an los object.
+         */
+       extern void los_destroy(struct los *los);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/macros.h b/src/macros.h
new file mode 100644 (file)
index 0000000..5d93f8f
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+// This file needs to be safe for both c and c++ compilation. It should also
+// contain only the most generic types of macros, stuff not really specific to
+// nazghul.
+
+#ifndef macros_h
+#define macros_h
+
+#ifdef __cplusplus
+#define BEGIN_DECL extern "C" {
+#define END_DECL   }
+#else
+#define BEGIN_DECL
+#define END_DECL
+#endif
+
+#define maxstrlen(array) (sizeof((array)) - 1)
+
+#ifndef clamp
+#define clamp(v,a,b) ((v) = (v) < (a) ? (a) : ((v) > (b) ? (b) : (v)))
+#endif
+
+#ifndef normalize
+#define normalize(dv) ((dv)>1?1:((dv)<-1?-1:0))
+#endif
+
+#define DECL_CAST(type,var,ptr) type * var = (type *)(ptr)
+
+#endif
diff --git a/src/magic.c b/src/magic.c
new file mode 100644 (file)
index 0000000..81a3ad0
--- /dev/null
@@ -0,0 +1,326 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2004 Gordon McNutt
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ *
+ */
+
+#include "magic.h"
+#include "debug.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*****************************************************************************
+ *
+ * spell api
+ *
+ *****************************************************************************/
+
+static struct spell *spell_new(char *code)
+{
+        struct spell *spell;
+
+        spell = (struct spell*)calloc(1, sizeof(*spell));
+        assert(spell);
+        
+        spell->code = strdup(code);
+        assert(spell->code);
+
+        return spell;
+}
+
+static void spell_del(struct spell *entry)
+{
+        assert(entry);
+
+        if (entry->code)
+                free(entry->code);
+        free(entry);
+}
+
+int spell_add_reagent(struct spell *spell, ObjectType *reagent)
+{
+        if (spell->n_reagents == MAX_MIX_REAGENTS) {
+                warn("spell_add_reagent: spell %s already maxed out on "\
+                     "reagents\n", spell->code);
+                return -1;
+        }
+
+        spell->reagents[spell->n_reagents++] = reagent;
+        return 0;
+}
+
+/*****************************************************************************
+ *
+ * helper functions
+ *
+ *****************************************************************************/
+
+static int magic_check_code(struct magic *magic, char *code)
+{
+        if (! code)
+                return -1;
+
+        while (*code) {
+                if (! magic->words[(*code - 'A')]) {
+                        warn("magic_check_code: no magic word starts with %c\n",
+                             *code);
+                        return -1;
+                }
+                code++;
+        }
+
+        return 0;
+}
+
+static void magic_del_spell_tree(struct spell *root)
+{
+        if (root->left)
+                magic_del_spell_tree(root->left);
+        if (root->right)
+                magic_del_spell_tree(root->right);
+        spell_del(root);
+}
+
+static int magic_is_code(char code)
+{
+        int index = code - 'A';
+        return (index >= 0 && index < MAX_SPELL_WORDS);
+}
+
+/*****************************************************************************
+ *
+ * public api
+ *
+ *****************************************************************************/
+
+
+/* Initialize at start-of-session prior to loading */
+void magic_init(struct magic *magic)
+{
+        memset(magic->words, 0, sizeof(magic->words));
+        magic->spells = NULL;
+}
+
+/* Cleanup at end-of-session */
+void magic_end_session(struct magic *magic)
+{
+        int i;
+
+        for (i = 0; i < MAX_SPELL_WORDS; i++) {
+                if (NULL != magic->words[i])
+                        free(magic->words[i]);
+                magic->words[i] = NULL;
+        }
+
+        if (magic->spells != NULL) {
+                magic_del_spell_tree(magic->spells);
+                magic->spells = NULL;
+        }
+}
+
+struct spell *magic_add_spell(struct magic *magic, char *code)
+{
+       struct spell *parent = 0;
+       struct spell *current = magic->spells;
+        int dir;
+
+        /* Make sure the code is valid */
+        if (magic_check_code(magic, code))
+                return NULL;
+
+        /* Descend the spell tree to a vacant leaf */
+       while (current) {
+
+                /* Parent always points to last valid node */
+               parent = current;
+
+                dir = strcmp(code, current->code);
+
+                /* Check if a spell was already inserted with this code */
+               if (dir == 0) {
+                        warn("magic_add_spell: there's already a spell with "\
+                             "code '%s'\n", code);
+                       return NULL;
+                }
+               else if (dir < 0)
+                       current = current->left;
+               else
+                       current = current->right;
+       }
+
+        current = spell_new(code);
+
+       if (!parent) {
+                /* First entry (root) */
+               magic->spells = current;
+       } else if (strcmp(code, parent->code) < 0) {
+                /* Left child vacant */
+               parent->left = current;
+       } else {
+                /* Right child vacant */
+               parent->right = current;
+       }
+
+        /* Success */
+       return current;
+
+}
+
+/* Lookup spells when casting them during play */
+struct spell *magic_lookup_spell(struct magic *magic, char *code)
+{
+        struct spell *current;
+        
+        current = magic->spells;
+
+        while (current) {
+
+                int dir = strcmp(code, current->code);
+
+                if (! dir) {
+                        /* Found it! */
+                        return current;
+                } else if (dir < 0) {
+                        current = current->left;
+                } else {
+                        current = current->right;
+                }
+        }
+
+        /* Didn't find it */
+        return NULL;
+}
+
+int magic_add_word(struct magic *magic, char *word)
+{
+        int index = word[0] - 'A';
+
+        if (! magic_is_code(word[0])) {
+                warn("magic_add_word: letter '%c' out of range [A, %c]\n",
+                     word[0], MAX_SPELL_WORDS + 'A' - 1);
+                return -1;
+        }
+
+        if (magic->words[index]) {
+                warn("magic_add_word: cannot add word '%s' because word "\
+                     "'%s' already starts with '%c'\n", word, 
+                     magic->words[index],
+                     word[0]);
+                return -1;
+        }
+
+        magic->words[index] = strdup(word);
+        assert(magic->words[index]);
+
+        return 0;
+}
+
+char *magic_lookup_word(struct magic *magic, char first_letter)
+{
+        int index = first_letter - 'A';
+
+        if (! magic_is_code(first_letter)) {
+                warn("magic_lookup_word: letter '%c' out of range [A, %c]\n",
+                     first_letter, MAX_SPELL_WORDS + 'A' - 1);
+                return NULL;
+        }
+
+        return magic->words[index];
+}
+
+int magic_spell_code_to_name(struct magic *magic, char *buf, int len, 
+                             char *code)
+{
+        int n = 0;
+
+        while (*code) {
+                char *word = magic_lookup_word(magic, *code);
+                if (! word)
+                        return -1;
+                n = snprintf(buf, len, "%s ", word); 
+                if (n < 0)
+                        return -1;
+                buf += n;
+                len -= n;
+                code++;
+        }
+        
+        // back up over the last space
+        if (! *code) {
+                buf--;
+                *buf = 0;
+        }
+
+        return 0;
+}
+
+int magic_spell_name_to_code(struct magic *magic, char *code, int len, 
+                             const char *name)
+{
+        int state = 2, i = 0;
+        const char *ptr = name;
+
+        len--; /* leave space for null terminator */
+
+        while (*ptr && len) {
+                char c = *ptr;
+                ptr++;
+                switch (state) {
+                case 0:
+                        /* looking for start of next word */
+                        if (! isspace(c)) {
+
+                                /* If this is a valid word then store it's
+                                 * first letter in the code buffer, else ignore
+                                 * it. Ignoring it lets us handle things like
+                                 * "vas Flam spell", where we ignore the
+                                 * "spell" part. */
+                                if (magic_is_code(c)) {
+                                        code[i] = c;
+                                        i++;
+                                        len--;
+                                }
+                                state = 1;
+                        }
+                        break;
+                case 1:
+                        /* looking for end of current word */
+                        if (isspace(c)) {
+                                state = 0;
+                        }
+                        break;
+                case 2:
+                                       /* spell names have code in <> */
+                                       if (c == '<') {
+                                               state = 0;              
+                                       }
+                                       break;
+                default:
+                        assert(0);
+                        break;
+                }
+        }
+
+        code[i] = 0; /* null-terminate */
+
+        return 0;
+}
diff --git a/src/magic.h b/src/magic.h
new file mode 100644 (file)
index 0000000..b741fd7
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2004 Gordon McNutt
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ * 
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ * 
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ *
+ */
+
+#ifndef magic_h
+#define magic_h
+
+#include "object.h" /* for ObjectType */
+#include "macros.h"
+
+BEGIN_DECL
+
+/* The number of spell words or "syllables" is limited to the number of letters
+ * in the English alphabet. That's because the first letter of each syllable
+ * uniquely identifies it. */
+#define MAX_SPELL_WORDS 26
+
+/* The max number of reagents allowed in the mixture for a spell. */
+#define MAX_MIX_REAGENTS 8
+
+/* Arbitrary limit on the number of characters (not syllables!) in a full spell
+ * name */
+#define MAX_SPELL_NAME_LENGTH 64
+
+/* Arbitrary limit on the number of syllables in a spell name. */
+#define MAX_SYLLABLES_PER_SPELL 8
+
+/* Spells are stored in a tree indexed by their "code". The code is the first
+ * letter of each word in the spell. For example, An Nox has the code AN. I
+ * also store the mixture here with the associated spell. For cimplicity I
+ * hard-code the max number of reagents permitted in a spell. */
+struct spell {
+        ObjectType *type;
+        char *code;
+        int level;
+        int cost;
+        int context;
+        int action_points;
+        int n_reagents;
+        ObjectType *reagents[MAX_MIX_REAGENTS];
+        struct sprite *sprite;
+        struct spell *left;
+        struct spell *right;
+};
+
+/* One of these is embedded in the global session structure. It manages all the
+ * magic-related information related to a session. */
+struct magic {
+        char *words[MAX_SPELL_WORDS];
+        struct spell *spells;
+};
+
+/* Initialize before loading a new session */
+extern void magic_init(struct magic *);
+
+/* Cleanup at end-of-session */
+extern void magic_end_session(struct magic *);
+
+/* Add a spell during session load. Returns the newly added spell or NULL on
+ * error. */
+extern struct spell *magic_add_spell(struct magic *, char *code);
+
+/* Add a word during session load. Returns 0 on success or -1 on error. */
+extern int magic_add_word(struct magic *, char *word);
+
+/* Lookup a word based on its first letter. Returns NULL on error or if no such
+ * word exists, otherwise the desired word. */
+extern char *magic_lookup_word(struct magic *magic, char first_letter);
+
+/* Lookup spells when casting them during play */
+extern struct spell *magic_lookup_spell(struct magic *, char *code);
+
+/* Add another reagent to a spell mixture during session load. */
+extern int spell_add_reagent(struct spell *spell, ObjectType *reagent);
+
+/* Given a spell code like "VF" convert it to a full name like "Vas Flam" */
+extern int magic_spell_code_to_name(struct magic *magic, char *buf, int len, char *code);
+
+/* Opposite of magic_spell_code_to_name() */
+extern int magic_spell_name_to_code(struct magic *magic, char *buf, int len, const char *name);
+
+
+END_DECL
+
+#endif
diff --git a/src/map.c b/src/map.c
new file mode 100644 (file)
index 0000000..e31776e
--- /dev/null
+++ b/src/map.c
@@ -0,0 +1,1883 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "map.h"
+#include "sky.h"  // For time/date functions
+#include "screen.h"
+#include "place.h"
+#include "player.h"
+#include "sprite.h"
+#include "cursor.h"
+#include "terrain.h"
+#include "Missile.h"
+#include "object.h"
+#include "vmask.h"
+#include "session.h"
+#include "sprite.h"
+#include "nazghul.h"  // for DeveloperMode
+
+#include <SDL.h>
+#include <math.h>
+
+#define PROFILE_REPAINT 0
+#define PROFILE_ANIMATE 0
+
+#define LMAP_W     (VMASK_W)
+#define LMAP_H     (VMASK_H)
+
+#define MVIEW_SZ   (sizeof(struct mview))
+#define LMAP_SZ    (LMAP_W * LMAP_H)
+#define MAX_LIGHTS LMAP_SZ
+#define PEER_ZOOM  2
+
+#define LIT        255
+#define UNLIT      0
+
+#define mview_x(mview)        ((mview)->vrect.x)
+#define mview_y(mview)        ((mview)->vrect.y)
+#define mview_w(mview)        ((mview)->vrect.w)
+#define mview_h(mview)        ((mview)->vrect.h)
+#define mview_center_x(mview) (mview_x(mview) + mview_w(mview) / 2)
+#define mview_center_y(mview) (mview_y(mview) + mview_h(mview) / 2)
+
+/**
+ *  Convert map coords to screen coords 
+ */
+#define MX_TO_SX(x) \
+    (Map.srect.x+((x)-(Map.aview->vrect.x+Map.aview->subrect.x))*TILE_W)
+#define MY_TO_SY(y) \
+    (Map.srect.y+((y)-(Map.aview->vrect.y+Map.aview->subrect.y))*TILE_H)
+
+struct light_source {
+       int x, y, light;
+};
+
+struct mview {
+       struct list list;       /* used internally by map lib */
+       SDL_Rect vrect;         /* map coords of vrect */
+        SDL_Rect subrect;       /* offset into visible subrect of vrect */
+       //char *vmask;          /* visibility mask */
+       int rad;                /* light radius */
+       int zoom;               /* zoom level */
+       int dirty:1;            /* needs repaint */
+        int blackout:1;         /* erase only on repaint */
+};
+
+static struct map {
+       SDL_Rect srect;         /* screen coords of viewer */
+       SDL_Rect latencyRect;   /* screen coords of latency time */
+       SDL_Rect turnaroundRect; /* screen coords of turnaroud time */
+       SDL_Rect locRect;       /* screen coords of locater */
+       SDL_Rect clkRect;       /* screen coords of clock */
+       struct place *place;    /* subject being viewed */
+       struct mview *aview;    /* active view */
+       struct list views;      /* list of all views */
+       struct mview *cam_view;
+        class Object *subject;
+       int cam_x, cam_y, cam_max_x, cam_max_y, cam_min_x, cam_min_y;
+       bool peering;
+       char *vmask;    /* final mask used to render */
+        SDL_Surface *tile_scratch_surf;
+        Uint32 last_repaint;
+        class Object *selected; /* selected object -- don't shade the tile it's
+                                 * on */
+
+        /* FIXME: why is this dynamically allocated when we're using
+         * MAX_LIGHTS? */
+        struct light_source *lights;
+        unsigned char *lmap;
+        unsigned char *tmp_lmap;
+        char is_image_mode : 1;
+} Map;
+
+/**
+ * The callback function prototype for rendering a tile.
+ */
+typedef void (*map_tile_render_t)(struct place *place, int map_x, int map_y,
+                                  int scr_x, int scr_y, int in_los);
+
+
+static void myRmView(struct mview *view, void *data)
+{
+       list_remove(&view->list);
+}
+
+static void mapMergeRects(SDL_Rect *src_rect, unsigned char *src,
+                          SDL_Rect *dst_rect, unsigned char *dst)
+{
+       int r_src, r_src_start, c_src, c_src_start, i_src, r_end, c_end;
+       int r_dst, r_dst_start, c_dst, c_dst_start, i_dst;
+       int tmp;
+
+       // skip identical merges (yes, it happens)
+       if (src == dst)
+               return;
+
+       if (src_rect->x < dst_rect->x) {
+               // Source leftmost
+               tmp = src_rect->x + src_rect->w - dst_rect->x;
+               if (tmp < 0)
+                       return;
+               c_src_start = dst_rect->x - src_rect->x;
+               c_end = c_src_start + tmp;
+               c_dst_start = 0;
+       } else {
+               // Destination leftmost
+               tmp = dst_rect->x + dst_rect->w - src_rect->x;
+               if (tmp < 0)
+                       return;
+               c_src_start = 0;
+               c_end = tmp;
+               c_dst_start = src_rect->x - dst_rect->x;
+       }
+
+       if (src_rect->y < dst_rect->y) {
+               // Source topmost
+               tmp = src_rect->y + src_rect->h - dst_rect->y;
+               if (tmp < 0)
+                       return;
+               r_src_start = dst_rect->y - src_rect->y;
+               r_end = r_src_start + tmp;
+               r_dst_start = 0;
+       } else {
+               // Destination topmost
+               tmp = dst_rect->y + dst_rect->h - src_rect->y;
+               if (tmp < 0)
+                       return;
+               r_src_start = 0;
+               r_end = tmp;
+               r_dst_start = src_rect->y - dst_rect->y;
+       }
+
+       for (r_src = r_src_start, r_dst = r_dst_start; r_src < r_end;
+            r_src++, r_dst++) {
+               for (c_src = c_src_start, c_dst = c_dst_start; c_src < c_end;
+                    c_src++, c_dst++) {
+                        int val;
+                       i_src = r_src * src_rect->w + c_src;
+                       i_dst = r_dst * dst_rect->w + c_dst;
+                        val = dst[i_dst] + src[i_src];
+                       dst[i_dst] = (unsigned char)min(val, 255);
+               }
+       }
+}
+
+static void mapMergeView(struct mview *view, void *data)
+{
+       int r_src, r_src_start, c_src, c_src_start, i_src, r_end, c_end;
+       int r_dst, r_dst_start, c_dst, c_dst_start, i_dst;
+       int tmp;
+        char *vmask;
+
+       /* Skip this view if it is the active view */
+       if (view == Map.aview)
+               return;
+
+        // ---------------------------------------------------------------------
+        // Find the indices to merge from depending on the relationship between
+        // the map view rectangle and the mview being merged.
+        // ---------------------------------------------------------------------
+
+       if (view->vrect.x < Map.aview->vrect.x) {
+               /* This view leftmost (A) */
+               tmp = view->vrect.x + view->vrect.w - Map.aview->vrect.x;
+               if (tmp < 0)
+                       return;
+               c_src_start = Map.aview->vrect.x - view->vrect.x;
+               c_end = c_src_start + tmp;
+               c_dst_start = 0;
+       } else {
+               /* Active view leftmost (A) */
+               tmp = Map.aview->vrect.x + Map.aview->vrect.w - view->vrect.x;
+               if (tmp < 0)
+                       return;
+               c_src_start = 0;
+               c_end = tmp;
+               c_dst_start = view->vrect.x - Map.aview->vrect.x;
+       }
+
+       if (view->vrect.y < Map.aview->vrect.y) {
+               /* This view topmost (A) */
+               tmp = view->vrect.y + view->vrect.h - Map.aview->vrect.y;
+               if (tmp < 0)
+                       return;
+               r_src_start = Map.aview->vrect.y - view->vrect.y;
+               r_end = r_src_start + tmp;
+               r_dst_start = 0;
+       } else {
+               /* Active view topmost (A) */
+               tmp = Map.aview->vrect.y + Map.aview->vrect.h - view->vrect.y;
+               if (tmp < 0)
+                       return;
+               r_src_start = 0;
+               r_end = tmp;
+               r_dst_start = view->vrect.y - Map.aview->vrect.y;
+       }
+
+        // ---------------------------------------------------------------------
+        // From the vmask cache, fetch the vmask corresponding to the tile in
+        // the center of the view from the vmask cache. (This will automatically
+        // create the vmask if it doesn't already exist).
+        // ---------------------------------------------------------------------
+
+        vmask = vmask_get(Map.place, mview_center_x(view), mview_center_y(view));
+        assert(vmask);
+        if (NULL == vmask)
+                return;
+
+        // ---------------------------------------------------------------------
+        // Copy the contents of the view's vmask to the master vmask.
+        // ---------------------------------------------------------------------
+
+       for (r_src = r_src_start, r_dst = r_dst_start; r_src < r_end;
+            r_src++, r_dst++) {
+               for (c_src = c_src_start, c_dst = c_dst_start; c_src < c_end;
+                    c_src++, c_dst++) {
+                       i_src = r_src * VMASK_W + c_src;
+                       i_dst = r_dst * VMASK_W + c_dst;
+                       Map.vmask[i_dst] |= vmask[i_src];
+               }
+       }
+
+}
+
+static void myMarkAsDirty(struct mview *view, void *data)
+{
+       view->dirty = 1;
+}
+
+static void mySetViewLightRadius(struct mview *view, void *data)
+{
+       int rad = *((int*)data);
+       view->rad = rad;
+}
+
+static int mapCalcMaxLightRadius(int light)
+{
+        // until something faster becomes necessary
+        return (int)sqrt((double)light);
+}
+
+#if 0
+// debug
+static void mapDumpRect(char *name, SDL_Rect *rect, unsigned char *data)
+{
+        int x, y, i;
+
+        printf("Rect %s (%d %d %d %d):\n", name, rect->x, rect->y, rect->w,
+               rect->h);
+        i = 0;
+        for (y = 0; y < rect->h; y++) {
+                for (x = 0; x < rect->w; x++, i++) {
+                        printf(" %03d", data[i]);
+                }
+                printf("\n");
+        }
+        printf("\n");
+}
+#endif
+
+/**
+ * Given a light source, add its contribution to the light map (Map.lmap).
+ *
+ * @param light is the light source to add
+ * @param main_view is the view containing the light source
+ */
+static void mapMergeLightSource(struct light_source *light, struct mview *main_view)
+{
+        int radius;
+        int vmask_i;
+        struct mview tmp_view;
+        int x;
+        int y;
+        int map_x;
+        int map_y;
+        int D;
+        char *vmask;
+
+        // Initialize the temporary view to be centered on the light
+        // source. (Note: ignore the subrect, it shouldn't matter)
+        //
+        // REVISIT: not sure I'm calculating vrect.x right: VMASK_W is odd
+        memset(&tmp_view,  0, sizeof(tmp_view));
+        tmp_view.vrect.x = place_wrap_x(Map.place, light->x - (VMASK_W / 2));
+        tmp_view.vrect.y = place_wrap_y(Map.place, light->y - (VMASK_H / 2));
+        tmp_view.vrect.w = VMASK_W;
+        tmp_view.vrect.h = VMASK_H;
+        tmp_view.zoom    = 1;
+
+        radius = min(mapCalcMaxLightRadius(light->light), VMASK_W / 2);
+
+        // Fetch the vmask from the cache.
+        vmask = vmask_get(Map.place, light->x, light->y);
+
+        // For each visible tile in the vmask, calculate how much light is
+        // hitting that tile from the light source. The loop optimizes by only
+        // checking those tiles that are within the radius of the light source.
+        // This optimization makes no difference on my fast box, haven't tested
+        // it yet on my slow one.
+        int min_y = 0;
+        int max_y = VMASK_H;
+        int min_x = 0;
+        int max_x = VMASK_W;
+
+        //dbg("lightmap %d:%d:%s\n", light->x, light->y, Map.place->name);
+
+        for (y = min_y; y < max_y; y++) {
+
+                map_y = place_wrap_y(Map.place, tmp_view.vrect.y + y);
+                vmask_i = y * VMASK_W + min_x;
+                
+                for (x = min_x; x < max_x; x++, vmask_i++) {
+
+                        // skip non-visible tiles
+                        if (vmask[vmask_i] == 0) {
+                                Map.tmp_lmap[vmask_i] = 0;
+                                continue;
+                        }
+                                
+                        map_x = place_wrap_x(Map.place, tmp_view.vrect.x + x);
+
+                        D = place_flying_distance(Map.place, light->x, 
+                                                  light->y, map_x, map_y);
+                        D = D * D + 1;
+                        Map.tmp_lmap[vmask_i] = min(light->light / D, 255);
+                }
+        }
+
+        // Merge this source's lightmap (contained in the vmask we just built)
+        // with the main lightmap.
+        //
+        // Note: try to optimize this by merging only the portion of the vmask
+        // which is within the light radius. In fact, why don't I just limit
+        // the vrect to the radius? Would that work?
+        mapMergeRects(&tmp_view.vrect, Map.tmp_lmap, &main_view->vrect, 
+                      Map.lmap);
+
+}
+
+/**
+ * This clears and rebuilds Map.lmap, which is a grid of values indicating how
+ * much light is hitting each tile. The results are used in mapShadeScene to
+ * darken the scene.
+ *
+ * @param view specifies which part of the map to use
+ */
+static void mapBuildLightMap(struct mview *view)
+{
+        int x;
+        int y;
+        int lt_i;
+        int map_x;
+        int map_y;
+        int ambient_light;
+
+
+        /* Initialize the main lightmap to ambient light levels. */
+        ambient_light = sky_get_ambient_light(&Session->sky);
+        memset(Map.lmap, 
+               (Map.place->underground ? UNLIT : ambient_light),
+               LMAP_SZ);
+
+        /* Optimization: if we're already getting max light everywhere from the
+         * sun then skip further processing. Building a lightmap usually takes
+         * about 1/3 of the time devoted to rendering. */
+        if (! Map.place->underground 
+            && ambient_light == MAX_AMBIENT_LIGHT) {
+                return;
+        }
+
+        /* Build the list of light sources visible in the current map viewer
+         * window. This actually searches outside of the current view to the
+         * entire mview rectangle, so light sources that are just out-of-view
+         * may cast light into the view. */
+        lt_i = 0;
+       for (y = 0; y < LMAP_H; y++) {
+               map_y = place_wrap_y(Map.place, view->vrect.y + y);
+               for (x = 0; x < LMAP_W; x++) {
+                       int light;
+
+                       map_x = place_wrap_x(Map.place, view->vrect.x + x);
+                       light = place_get_light(Map.place, map_x, map_y);
+                       if (!light)
+                               continue;
+
+                       Map.lights[lt_i].x = map_x;
+                       Map.lights[lt_i].y = map_y;
+                       Map.lights[lt_i].light = light;
+                       lt_i++;
+               }
+       }
+        
+       /* Skip further processing if there are no light sources */
+        if (!lt_i) {
+                return;
+        }
+
+
+        /* For each light source build a lightmap centered on that source and
+         * merge it into the main lightmap. */
+        while (lt_i--) {
+                mapMergeLightSource(&Map.lights[lt_i], view);
+        }
+
+}
+
+static void myShadeScene(SDL_Rect *subrect)
+{
+       int x, y;
+       SDL_Rect rect;
+        int lmap_i;
+
+       rect.x = Map.srect.x;
+       rect.y = Map.srect.y;
+       rect.w = TILE_W;
+       rect.h = TILE_H;
+
+        lmap_i = subrect->y * VMASK_W + subrect->x;
+        //lmap_i = 0;
+
+       // Iterate over the tiles in the map window and the corresponding
+       // values in the lightmap simultaneously */
+       for (y = 0; y < MAP_TILE_H; y++, rect.y += TILE_H, 
+                     lmap_i += LMAP_W /*lmap_i += VMASK_W*/) {
+               for (x = 0, rect.x = Map.srect.x;
+                    x < MAP_TILE_W; x++, rect.x += TILE_W) {
+
+                       /* Set the shading based on the lightmap value. The
+                        * lightmap values must be converted to opacity values
+                        * for a black square, so I reverse them by subtracting
+                        * them from LIT. */
+                       screenShade(&rect, LIT - Map.lmap[lmap_i + x]);
+               }
+       }
+}
+
+static inline void myAdjustCameraInBounds(void)
+{
+       if (Map.place->wraps)
+               return;
+
+       Map.cam_x = min(Map.cam_x, Map.cam_max_x);
+       Map.cam_x = max(Map.cam_x, Map.cam_min_x);
+       Map.cam_y = min(Map.cam_y, Map.cam_max_y);
+       Map.cam_y = max(Map.cam_y, Map.cam_min_y);
+}
+
+void mapForEachView(void (*fx) (struct mview *, void *), void *data)
+{
+       struct list *list;
+       list = Map.views.next;
+       while (list != &Map.views) {
+               struct list *tmp;
+               struct mview *view;
+               view = outcast(list, struct mview, list);
+               tmp = list->next;
+               fx(view, data);
+               list = tmp;
+       }
+}
+
+void mapSetLosStyle(const char *los)
+{
+        if (LosEngine) {
+                los_destroy(LosEngine);
+        }
+       LosEngine = los_create(los, VMASK_W, VMASK_H, -1);
+        assert(LosEngine);
+}
+
+static void mapExit(void)
+{
+        if (Map.lights) {
+                free(Map.lights);
+                Map.lights = 0;
+        }
+
+        if (Map.lmap) {
+                free(Map.lmap);
+                Map.lmap = 0;
+        }
+
+        if (Map.tmp_lmap) {
+                free(Map.tmp_lmap);
+                Map.tmp_lmap = 0;
+        }
+
+        if (Map.cam_view) {
+                mapDestroyView(Map.cam_view);
+                Map.cam_view = 0;
+        }
+
+        if (Map.vmask) {
+                free(Map.vmask);
+                Map.vmask = 0;
+        }
+}
+
+int mapInit(void)
+{
+
+       memset(&Map, 0, sizeof(Map));
+
+        Map.lights = (struct light_source*)calloc(MAX_LIGHTS, 
+                                                  sizeof(Map.lights[0]));
+        if (!Map.lights)
+                goto abort;
+
+        /* The lightmap only needs to be as big as the map viewer
+           window. Making it larger does allow for lights outside the field of
+           view to be processed, but this makes dungeons appear too bright - I
+           like them dark and gloomy. */
+        Map.lmap = (unsigned char*)calloc(LMAP_SZ, sizeof(Map.lmap[0]));
+        if (!Map.lmap)
+                goto abort;
+
+        /* This one is used during mapMergeLightSource */
+        Map.tmp_lmap = (unsigned char*)calloc(LMAP_SZ, 
+                                              sizeof(Map.tmp_lmap[0]));
+        if (!Map.tmp_lmap)
+                goto abort;
+
+       if (!(Map.cam_view = mapCreateView()))
+                goto abort;
+
+        Map.vmask = (char*)calloc(VMASK_SZ, sizeof(Map.vmask[0]));
+        if (!Map.vmask)
+                goto abort;
+
+       list_init(&Map.views);
+
+       Map.srect.x   = MAP_X;
+       Map.srect.y   = MAP_Y;
+       Map.srect.w   = MAP_W;
+       Map.srect.h   = MAP_H;
+
+       Map.latencyRect.x = MAP_X;
+       Map.latencyRect.y = MAP_Y;
+       Map.latencyRect.w = ASCII_W * 10;
+       Map.latencyRect.h = ASCII_H;
+
+       Map.turnaroundRect.x = MAP_X;
+       Map.turnaroundRect.y = MAP_Y + ASCII_H;
+       Map.turnaroundRect.w = ASCII_W * 10;
+       Map.turnaroundRect.h = ASCII_H;
+
+       Map.locRect.x = MAP_X;
+       Map.locRect.y = MAP_Y + MAP_H - ASCII_H;
+       Map.locRect.w = ASCII_W * 9;
+       Map.locRect.h = ASCII_H;
+
+       Map.clkRect.w = ASCII_W * 7;
+       Map.clkRect.h = ASCII_H;
+       Map.clkRect.x = MAP_X + MAP_W - Map.clkRect.w;
+       Map.clkRect.y = MAP_Y;
+
+       Map.peering   = false;
+        LosEngine     = NULL;
+
+        Map.tile_scratch_surf = screenCreateSurface(TILE_W, TILE_H);
+        assert(Map.tile_scratch_surf);
+
+       return 0;
+
+abort:
+        mapExit();
+        return -1;
+}
+
+void mapFlash(int mdelay)
+{
+       screenFlash(&Map.srect, mdelay, White);
+}
+
+void mapSetPlace(struct place *place)
+{
+       Map.place = place;
+
+       if (place->wraps)
+               return;
+
+       if (place_w(place) > MAP_TILE_W) {
+               Map.cam_max_x = place_w(place) - (MAP_TILE_W - 1) / 2 - 1;
+               Map.cam_min_x = MAP_TILE_W / 2;
+       } else {
+               Map.cam_min_x = Map.cam_max_x = (place_w(place) + 1)/ 2 - 1;
+       }
+
+       if (place_h(place) > MAP_TILE_W) {
+               Map.cam_max_y = place_h(place) - (MAP_TILE_H - 1) / 2 - 1;
+               Map.cam_min_y = MAP_TILE_H / 2;
+       } else {
+               Map.cam_min_y = Map.cam_max_y = (place_h(place) + 1) / 2 - 1;
+       }
+}
+
+struct mview *mapCreateView(void)
+{
+       struct mview *v;
+
+       /* Allocate a new view */
+       if (!(v = (struct mview *) malloc(MVIEW_SZ)))
+               return 0;
+
+       /* Initialize the new view */
+       memset(v, 0, MVIEW_SZ);
+       list_init(&v->list);
+       v->vrect.w   = VMASK_W;
+       v->vrect.h   = VMASK_H;
+        v->zoom      = 1;
+        v->subrect.w = MAP_TILE_W * v->zoom;
+        v->subrect.h = MAP_TILE_H * v->zoom;
+        v->subrect.x = (v->vrect.w - v->subrect.w) / 2;
+        v->subrect.y = (v->vrect.h - v->subrect.h) / 2;
+
+        //dbg("mapCreateView: return %08lx\n", v);
+
+       return v;
+
+}
+
+void mapDestroyView(struct mview *view)
+{
+        //dbg("mapDestroyView(%08lx)\n", view);
+       free(view);
+}
+
+void mapAddView(struct mview *view)
+{
+        //dbg("mapAddView(%08lx)\n", view);
+       list_add(&Map.views, &view->list);
+}
+
+void mapRmView(struct mview *view)
+{
+        //dbg("mapRmView(%08lx)\n", view);
+       if (view == ALL_VIEWS)
+               mapForEachView(myRmView, 0);
+       else
+               myRmView(view, 0);
+}
+
+void mapCenterView(struct mview *view, int x, int y)
+{
+        x -= view->vrect.w / 2; // back up to corner of vrect
+        y -= view->vrect.h / 2; // back up to corner of vrect
+        view->vrect.x = place_wrap_x(Map.place, x);
+        view->vrect.y = place_wrap_y(Map.place, y);
+}
+
+void mapRepaintClock(void)
+{
+  char * date_time_str = time_HHMM_as_string();
+  if (! DeveloperMode)
+          return;
+  // Show the clock time:
+  screenErase(&Map.clkRect);
+  screenPrint(&Map.clkRect, 0, "%s", date_time_str);
+  screenUpdate(&Map.clkRect);
+} // mapRepaintClock()
+
+/**
+ *  converts points so they appear correctly on wrapping maps 
+ */
+static void map_convert_point_to_vrect(int *x, int *y)
+{
+        SDL_Rect *vrect = &Map.aview->vrect;
+  
+        // If the view rect extends past the right side of the map, and x is
+        // left of the view rect, then convert x to be right of the view rect.
+        if ((vrect->x + vrect->w) > place_w(Map.place) && 
+            *x < vrect->x) {
+                *x += place_w(Map.place);
+        }
+        
+        // Likewise if the view rect extends beyond the southern edge of the
+        // map, and y is less than the top of the view rect, then convert y to
+        // be south of the view rect.
+        if ((vrect->y + vrect->h) > place_h(Map.place) && 
+            *y < vrect->y) {
+                *y += place_h(Map.place);
+        }
+}
+
+static void map_paint_cursor(void)
+{
+        int x, y;
+
+        if (!Session->crosshair->is_active())
+                return;
+
+        /* Convert to view rect offset */
+        x = Session->crosshair->getX();
+        y = Session->crosshair->getY();
+        map_convert_point_to_vrect(&x, &y);
+        if (!point_in_rect(x, y, &Map.aview->vrect)) {
+                return;
+        }
+
+        /* Paint it */
+        sprite_paint(Session->crosshair->getSprite(), 0, 
+                    MX_TO_SX(x), MY_TO_SY(y));
+
+}
+
+/**
+ * Paint the terrain sprite for a tile.
+ *
+ * @param place The place to use as the tile source.
+ * @param map_x The tile coordinate in the place.
+ * @param map_y The tile coordinate in the place.
+ * @param scr_x The screen pixel coordinate to blit to.
+ * @param scr_y The screen pixel coordinate to blit to.
+ * @param in_los Zero iff the tile is not in player LOS.
+ */
+static void map_paint_tile_terrain(struct place *place, int map_x, int map_y,
+                                   int scr_x, int scr_y, int in_los)
+{
+        if (in_los) {
+
+                /* This tile is in player LOS, so paint normally. */
+                struct terrain *terrain = place_get_terrain(place, map_x, map_y);
+                struct sprite *sprite = terrain->sprite;
+                sprite_paint(sprite, 0, scr_x, scr_y);
+
+        } else if (ShowAllTerrain || XrayVision) {
+
+                /* This tile is not in player LOS, but the command-line option
+                 * to show all terrain or the special XrayVision flag is in
+                 * effect, so paint the terrain but then shade it. */
+                struct terrain *terrain = place_get_terrain(place,map_x,map_y);
+                struct sprite *sprite = terrain->sprite;
+                sprite_paint(sprite, 0, scr_x, scr_y);
+                                
+                SDL_Rect shade_rect;
+                shade_rect.x = scr_x;
+                shade_rect.y = scr_y;
+                shade_rect.w = TILE_W;
+                shade_rect.h = TILE_H;
+                screenShade(&shade_rect, 128);
+        }
+
+}
+
+/**
+ * Paint the object sprites for a tile.
+ *
+ * @param place The place to use as the tile source.
+ * @param map_x The tile coordinate in the place.
+ * @param map_y The tile coordinate in the place.
+ * @param scr_x The screen pixel coordinate to blit to.
+ * @param scr_y The screen pixel coordinate to blit to.
+ * @param in_los Zero iff the tile is not in player LOS.
+ */
+static void map_paint_tile_objects(struct place *place, int map_x, int map_y,
+                                   int scr_x, int scr_y, int in_los)
+{
+        if (in_los) {
+
+                /* The tile is visible, so paint the objects normally. */
+                place_paint_objects(place, map_x, map_y, scr_x, scr_y);
+
+                /* If the crosshair is active but this tile is not in range
+                 * then shade the tile. */
+                if (Session->crosshair->is_active() &&
+                    Session->crosshair->isRangeShaded() &&
+                    ! Session->crosshair->inRange(map_x, map_y)) {
+                        SDL_Rect shade_rect;
+                        shade_rect.x = scr_x;
+                        shade_rect.y = scr_y;
+                        shade_rect.w = TILE_W;
+                        shade_rect.h = TILE_H;
+                        screenShade(&shade_rect, 128);
+                }
+        }
+}
+
+/**
+ * Loop over the map tiles shown in the map viewer, invoking a callback
+ * function for each tile.
+ *
+ * @param place The place viewed.
+ * @param region The part of the place covered by the visibility mask. Units
+ * are tiles.
+ * @param dest The screen rectangle of the viewer. Units are pixels.
+ * @param mask The visibility mask for the region. Each entry in the mask
+ * covers one tile.
+ * @param subrect The part of the place under the viewer (this is contained
+ * within the region). Units are tiles.
+ * @param tile_w Tile dimension in pixels.
+ * @param tile_h Tile dimension in pixels.
+ */
+static void map_render_loop(struct place *place, 
+                            SDL_Rect * region,
+                            SDL_Rect * dest,
+                            unsigned char *mask,
+                            SDL_Rect * subrect,
+                            int tile_h, 
+                            int tile_w,
+                            map_tile_render_t tile_render)
+{
+       int row;
+       int col;
+       int map_y; /* in rows */
+       int map_x; /* in cols */
+       int scr_x; /* in pixels */
+       int scr_y; /* in pixels */
+        int mask_i;
+       bool use_mask;
+
+       if (place->wraps) {
+               region->x = place_wrap_x(place, region->x);
+               region->y = place_wrap_y(place, region->y);
+       }
+
+        /* 
+           +-----------------------------------------------------------------+
+           | region/mask                                                     |
+           |                                                                 |
+           |                    +-------------------------+                  |
+           |                    | subrect                 |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    |                         |                  |
+           |                    +-------------------------+                  |
+           |                                                                 |
+           |                                                                 |
+           +-----------------------------------------------------------------+
+        */
+
+       use_mask = (mask != NULL);
+       map_y = region->y + subrect->y;
+        mask_i = (subrect->y * region->w) + subrect->x;
+
+       for (row = 0; row < subrect->h; row++, map_y++, mask_i += region->w) {
+
+                /* Test if the row is off-map */
+               if (place->wraps) {
+                       map_y = place_wrap_y(place, map_y);
+               } else if (map_y < 0) {
+                       continue;
+               } else if (map_y >= place->terrain_map->h) {
+                       break;
+               }
+                
+                /* Set the screen pixel row */
+               scr_y = row * tile_h + dest->y;
+
+                /* Set the initial map column for this row */
+               map_x = region->x + subrect->x;
+
+               for (col = 0; col < subrect->w; col++, map_x++) {
+
+                        int in_los;
+
+                        /* Test if the column is off-map */
+                       if (place->wraps) {
+                               map_x = place_wrap_x(place, map_x);
+                       } else if (map_x < 0) {
+                               continue;
+                       } else if (map_x >= place->terrain_map->w) {
+                               break;
+                       }
+
+                        /* Set the screen pixel column */
+                       scr_x = col * tile_w + dest->x;
+
+                        /* Set the LOS flag. */
+                        in_los = (!use_mask || mask[mask_i + col]);
+
+                        /* Invoke the callback function that does the rendering
+                         * for the tile. */
+                        tile_render(place, map_x, map_y, scr_x, scr_y, in_los);
+               }
+       }
+
+}
+
+static void mapPaintPlace(struct place *place, 
+                          SDL_Rect * region,   /* portion of place covered by
+                                                * the vmask */
+                          SDL_Rect * dest,     /* screen rectangle */
+                          unsigned char *mask, /* visibility mask for entire
+                                                * region */
+                          SDL_Rect * subrect,  /* sub-rectangle within region
+                                                * that the map viewer sees */
+                          int tile_h, 
+                          int tile_w)
+{
+        /* In order to render giant characters properly over the terrain of
+         * neighboring tiles, rendering must be done in two passes. The first
+         * pass renders the terrain, the second the objects. */
+        map_render_loop(place, region, dest, mask,  subrect, tile_h, tile_w,
+                        map_paint_tile_terrain);
+        map_render_loop(place, region, dest, mask,  subrect, tile_h, tile_w,
+                        map_paint_tile_objects);
+       place->dirty = 0;
+}
+
+
+static void mapRepaintCoordinates(void)
+{
+        if (! DeveloperMode) {
+                return;
+        }
+
+        if (player_party->isOnMap()) {
+                screenPrint(&Map.locRect, 0, "[%d,%d]", player_party->getX(), 
+                            player_party->getY());
+                return;
+        }
+        
+        if (NULL != Map.subject)
+                screenPrint(&Map.locRect, 0, "[%d,%d]", Map.subject->getX(), 
+                            Map.subject->getY());
+}
+
+static void mapRepaintTurnaround(void)
+{
+        extern int G_turnaround;
+
+        if (! DeveloperMode)
+                return;
+
+       screenPrint(&Map.turnaroundRect, 0, "TA: %d", G_turnaround);
+}
+
+extern int G_latency_start;
+static void mapRepaintLatency(void)
+{
+        static int latency = 0;
+
+        if (! DeveloperMode)
+                return;
+
+        latency = SDL_GetTicks() - G_latency_start;
+
+        //printf("repaint: %d\n", latency);
+        screenPrint(&Map.latencyRect, 0, "LAT: %d", latency);
+        screenUpdate(&Map.latencyRect);
+}
+
+/**
+ * This is the main paint routine. 
+ *
+ * @param view defines which part of the map to show
+ * @param flags controls controls policies of whether and what to paint
+ */
+static void mapRepaintView(struct mview *view, int flags)
+{
+       int t1, t2, t3, t4, t5, t6, t7, t8;
+
+       Map.aview = view;
+
+       if (flags & REPAINT_IF_DIRTY && !view->dirty)
+               return;
+
+        if (flags & REPAINT_IF_OLD
+            && (SDL_GetTicks() - Map.last_repaint) < (Uint32)TickMilliseconds
+            && (Map.last_repaint < SDL_GetTicks()))
+                return;
+
+        Map.last_repaint = SDL_GetTicks();
+       view->dirty = 0;
+
+        G_latency_start = SDL_GetTicks();
+
+       t1 = SDL_GetTicks();
+
+       screenErase(&Map.srect);
+
+       t2 = SDL_GetTicks();
+
+        if (Map.aview->blackout) {
+                // In blackout mode leave the screen erased
+                goto done_painting_place;
+        }
+
+       if (Map.aview->zoom > 1) {
+                sprite_zoom_out(Map.aview->zoom);
+               screenZoomOut(Map.aview->zoom);
+               t5 = SDL_GetTicks();
+               mapPaintPlace(Map.place, &view->vrect, &Map.srect, 
+                              0/* vmask */, &view->subrect, 
+                              TILE_W / Map.aview->zoom, 
+                              TILE_H / Map.aview->zoom);
+               t6 = SDL_GetTicks();
+               screenZoomIn(Map.aview->zoom);
+                sprite_zoom_in(Map.aview->zoom);
+       } else if (flags & REPAINT_NO_LOS) {
+                t5 = SDL_GetTicks();
+               mapPaintPlace(Map.place, &view->vrect, &Map.srect, 0, 
+                              &view->subrect, TILE_W, TILE_H);
+               t6 = SDL_GetTicks();
+       } else {
+
+                // ------------------------------------------------------------
+                // Map.vmask serves as the "master" vmask. Start by zeroing it
+                // out so that by default nothing is in line-of-sight. Then
+                // iterate over all the active views (each player party member
+                // has an active view, spells may add others), and for each
+                // view merge it's vmask onto the master. The result is the
+                // line-of-sight for all party members is always visible to the
+                // player.
+                // ------------------------------------------------------------
+
+                memset(Map.vmask, 0, VMASK_SZ);
+               t3 = SDL_GetTicks();
+               mapForEachView(mapMergeView, 0);
+                //vmask_dump(Map.vmask);
+               t4 = SDL_GetTicks();
+               mapBuildLightMap(view);
+               t5 = SDL_GetTicks();
+               mapPaintPlace(Map.place, &view->vrect, &Map.srect,
+                              (unsigned char *) Map.vmask, &view->subrect,
+                              TILE_W, TILE_H);
+               t6 = SDL_GetTicks();
+                if (! XrayVision) {
+                        myShadeScene(&view->subrect);
+                }
+               t7 = SDL_GetTicks();
+                map_paint_cursor();
+
+                // After shading, repaint the tile with the selected object so
+                // that it shows up brightly even in darkness.
+                if (Map.selected 
+                    && Map.selected->getPlace() == Map.place)
+                        mapUpdateTile(Map.place,
+                                      Map.selected->getX(),
+                                      Map.selected->getY());
+       }
+
+ done_painting_place:
+
+        mapRepaintCoordinates();
+       mapRepaintClock();
+        mapRepaintTurnaround();
+       screenUpdate(&Map.srect);
+
+        // ---------------------------------------------------------------------
+        // Repaint the latency AFTER the screenUpdate because we want that to
+        // be part of the time measurement.
+        // ---------------------------------------------------------------------
+
+        mapRepaintLatency();
+
+        t8 = SDL_GetTicks();
+
+       if (PROFILE_REPAINT) {
+         printf("Total time=%d\n", t8 - t1);
+         printf("    erase screen=%d\n", t2 - t1);
+         printf("          memcpy=%d\n", t3 - t2);
+         printf("    merge vmasks=%d\n", t4 - t3);
+         printf("  build lightmap=%d\n", t5 - t4);
+         printf("     paint place=%d\n", t6 - t5);
+         printf("           shade=%d\n", t7 - t6);
+         printf("   update screen=%d\n", t8 - t7);
+       }
+}
+
+static int mapXToViewX(int x)
+{
+        SDL_Rect *vrect = &Map.aview->vrect;
+        int x2 = x - vrect->x;
+        if (x2 < 0
+            && place_is_wrapping(Map.place)
+            && (vrect->x + vrect->w) > place_w(Map.place))
+                x2 += place_w(Map.place);
+        return x2;
+}
+
+static int mapYToViewY(int y)
+{
+        SDL_Rect *vrect = &Map.aview->vrect;
+        int y2 = y - vrect->y;
+        if (y2 < 0
+            && place_is_wrapping(Map.place)
+            && (vrect->y + vrect->h) > place_h(Map.place))
+                y2 += place_h(Map.place);
+        return y2;
+}
+
+int mapTileIsWithinViewport(int x, int y)
+{
+        SDL_Rect *vrect = &Map.aview->vrect;
+        int vx = mapXToViewX(x);
+        int vy = mapYToViewY(y);
+        if (vx < 0
+            || vx >= vrect->w
+            || vy < 0
+            || vy >= vrect->h)
+                return 0;
+        return 1;
+}
+
+unsigned char mapTileLightLevel(int x, int y)
+{
+        int vx = mapXToViewX(x);
+        int vy = mapYToViewY(y);
+        return Map.lmap[vy * LMAP_W + vx];
+}
+
+int mapTileIsVisible(int x, int y)
+{       
+        SDL_Rect *vrect = &Map.aview->vrect;
+        int vx = mapXToViewX(x);
+        int vy = mapYToViewY(y);
+
+        // check if coords in vrect
+        if (vx < 0
+            || vx >= vrect->w
+            || vy < 0
+            || vy >= vrect->h)
+                return 0;
+
+        // If zoomed out then don't bother checking the vmask.
+        if (Map.aview->zoom > 1)
+                return 1;
+
+        // Return if the tile is marked as visible
+        return Map.vmask[vy * vrect->w + vx];
+            
+}
+void mapMarkAsDirty(struct mview *view)
+{
+       if (view == ALL_VIEWS)
+               mapForEachView(myMarkAsDirty, 0);
+       else
+               myMarkAsDirty(view, 0);
+}
+
+void mapSetRadius(struct mview *view, int rad)
+{
+       if (view == ALL_VIEWS)
+               mapForEachView(mySetViewLightRadius, (void *) &rad);
+       else
+               mySetViewLightRadius(view, (void *) &rad);
+}
+
+int mapGetRadius(struct mview *view)
+{
+       return view->rad;
+}
+
+void mapGetMapOrigin(int *x, int *y)
+{
+       assert(Map.aview);
+       *x = Map.aview->vrect.x + Map.aview->subrect.x;
+       *y = Map.aview->vrect.y + Map.aview->subrect.y;
+}
+
+void mapGetScreenOrigin(int *x, int *y)
+{
+       *x = Map.srect.x;
+       *y = Map.srect.y;
+}
+
+void mapGetTileDimensions(int *w, int *h)
+{
+        *w = TILE_W / Map.aview->zoom;
+        *h = TILE_H / Map.aview->zoom;
+}
+
+void mapSetActiveView(struct mview *view)
+{
+       Map.aview = view;
+        //dbg("mapSetActiveView: aview=[%d %d]\n", Map.aview->vrect.x, Map.aview->vrect.y);
+}
+
+void mapCenterCamera(int x, int y)
+{
+       Map.cam_x = x;
+       Map.cam_y = y;
+
+       Map.cam_x = place_wrap_x(Map.place, Map.cam_x);
+       Map.cam_y = place_wrap_y(Map.place, Map.cam_y);
+
+       myAdjustCameraInBounds();
+       mapCenterView(Map.cam_view, Map.cam_x, Map.cam_y);
+}
+
+void mapMoveCamera(int dx, int dy)
+{
+       mapCenterCamera(Map.cam_x + dx, Map.cam_y + dy);
+}
+
+void mapUpdate(int flags)
+{
+        if (Map.is_image_mode)
+                return;
+
+       mapRepaintView(Map.cam_view, flags);
+}
+
+void mapSetDirty(void)
+{
+        if (Map.cam_view != NULL)
+                Map.cam_view->dirty = 1;
+}
+
+void mapJitter(bool val)
+{
+       Map.srect.x = MAP_X;
+       Map.srect.y = MAP_Y;
+       Map.srect.w = MAP_W;
+       Map.srect.h = MAP_H;
+
+       if (val) {
+               Map.srect.x += (rand() % 5) - 2;
+               Map.srect.y += (rand() % 5) - 2;
+       }
+}
+
+void mapPeer(bool val)
+{
+       int dx, dy;
+       // Peering will apply to the camera view. Set the scale factor and
+       // adjust the pertinent rectangle dimensions.
+        Map.peering = val;
+       if (val) {
+               Map.cam_view->zoom = PEER_ZOOM;
+               dx = (Map.cam_view->vrect.w / 2) * (PEER_ZOOM - 1);
+               dy = (Map.cam_view->vrect.h / 2) * (PEER_ZOOM - 1);
+               Map.cam_view->vrect.x -= dx;
+               Map.cam_view->vrect.y -= dy;
+               Map.cam_view->vrect.w *= PEER_ZOOM;
+               Map.cam_view->vrect.h *= PEER_ZOOM;
+       } else {
+               Map.cam_view->zoom = 1;
+               Map.cam_view->vrect.w /= PEER_ZOOM;
+               Map.cam_view->vrect.h /= PEER_ZOOM;
+               dx = (Map.cam_view->vrect.w / 2) * (PEER_ZOOM - 1);
+               dy = (Map.cam_view->vrect.h / 2) * (PEER_ZOOM - 1);
+               Map.cam_view->vrect.x += dx;
+               Map.cam_view->vrect.y += dy;
+       }
+
+        Map.cam_view->subrect.w = MAP_TILE_W * Map.cam_view->zoom;
+        Map.cam_view->subrect.h = MAP_TILE_H * Map.cam_view->zoom;
+        Map.cam_view->subrect.x = (Map.cam_view->vrect.w - 
+                                   Map.cam_view->subrect.w) / 2;
+        Map.cam_view->subrect.y = (Map.cam_view->vrect.h - 
+                                   Map.cam_view->subrect.h) / 2;
+
+        mapCenterCamera(Map.cam_x, Map.cam_y); // recenter
+}
+
+void mapTogglePeering(void)
+{
+        mapPeer(!Map.peering);
+        mapCenterCamera(Map.cam_x, Map.cam_y); // recenter
+        mapUpdate(0);
+}
+
+void mapGetCameraFocus(struct place **place, int *x, int *y)
+{
+        *place = Map.place;
+        *x = Map.cam_x;
+        *y = Map.cam_y;
+}
+
+int mapIsInCameraView(struct place *place, int x, int y)
+{
+        int min;
+        int max;
+
+        if (place != Map.place)
+                return 0;
+
+        min = Map.cam_view->subrect.x + Map.cam_view->vrect.x;
+        max = min + Map.cam_view->subrect.w;
+
+        if (x < min || x >= max)
+                return 0;
+
+        min = Map.cam_view->subrect.y + Map.cam_view->vrect.y;
+        max = min + Map.cam_view->subrect.h;
+
+        if (y < min || y >= max)
+                return 0;
+        
+        return 1;
+}
+
+void mapBlackout(int val)
+{
+        Map.cam_view->blackout = !!val;
+}
+
+static void mapPaintProjectile(SDL_Rect *rect, struct sprite *sprite,
+                               SDL_Surface *surf, int dur, int currentframe, bool beam)
+{
+       // The rect coordinates are in SCREEN coordinates (not map) so I need
+       // to do some clipping here to make sure we don't paint off the map
+       // viewer.
+       if (rect->x < MAP_X || rect->y < MAP_Y ||
+           ((rect->x + rect->w) > (MAP_X + MAP_W)) ||
+           ((rect->y + rect->h) > (MAP_Y + MAP_H)))
+               return;
+
+       // Save the backdrop of the new location
+       if (!beam)
+               screenCopy(rect, NULL, surf);
+
+       // Paint the missile at the new location
+        sprite_zoom_out(Map.aview->zoom);
+        screenZoomOut(Map.aview->zoom);
+       sprite_paint_frame(sprite, currentframe, rect->x, rect->y);
+        sprite_zoom_in(Map.aview->zoom);
+        screenZoomIn(Map.aview->zoom);
+
+       screenUpdate(rect);
+
+       SDL_Delay(dur);
+
+       // Erase the missile by blitting the background
+       if (!beam)
+       {
+               screenBlit(surf, NULL, rect);
+               screenUpdate(rect);
+       }
+}
+
+void mapPaintDamage(int x, int y)
+{
+        int tile_w, tile_h;
+        SDL_Rect rect;
+
+        if (!mapTileIsVisible(x, y))
+                return;
+
+        mapGetTileDimensions(&tile_w, &tile_h);
+        rect.w = tile_w;
+        rect.h = tile_h;
+        rect.x = MX_TO_SX(x);
+        rect.y = MY_TO_SY(y);
+
+        /* Sometimes a damage flash doesn't make sense to the player unless the
+         * map view is updated first. For example, a character that gets 2x the
+         * normal action points per turn might move and then attack. The move
+         * won't be shown until the map is updated. */
+        mapUpdate(REPAINT_IF_DIRTY);
+
+        mapPaintProjectile(&rect, Session->damage_sprite, 
+                           Map.tile_scratch_surf, 100, 0, false);
+}
+
+//paint damage, but with custom sprite
+void mapFlashSprite(int x, int y, struct sprite *sprite)
+{
+        int tile_w, tile_h;
+        SDL_Rect rect;
+
+        if (!mapTileIsVisible(x, y))
+                return;
+
+        mapGetTileDimensions(&tile_w, &tile_h);
+        rect.w = tile_w;
+        rect.h = tile_h;
+        rect.x = MX_TO_SX(x);
+        rect.y = MY_TO_SY(y);
+
+        /* Sometimes a damage flash doesn't make sense to the player unless the
+         * map view is updated first. For example, a character that gets 2x the
+         * normal action points per turn might move and then attack. The move
+         * won't be shown until the map is updated. */
+        mapUpdate(REPAINT_IF_DIRTY);
+
+        mapPaintProjectile(&rect, sprite, 
+                           Map.tile_scratch_surf, 100, 0, false);
+}
+
+void mapAnimateProjectile(int Ax, int Ay, int *Bx, int *By, 
+                          struct sprite *sprite, struct place *place,
+                          class Missile *missile, float range)
+{
+       // 
+       // Derived from Kenny Hoff's Bresenhaum impl at
+       // http://www.cs.unc.edu/~hoff/projects/comp235/bresline/breslin1.txt
+       // (no license or copyright noted)
+       // 
+       int framecount = sprite_num_frames(sprite);
+       int currentframe = 0;
+       
+       int t1, t2;
+       SDL_Surface * surf;     // for saving/restoring the background
+
+       t1 = SDL_GetTicks();
+
+       // Get tile dimensions
+       int tile_w;
+       int tile_h;
+       mapGetTileDimensions(&tile_w, &tile_h);
+       
+       // Half tile offset- missiles fly from and to the middle of a tile
+       int tile_w_half = tile_w/2;
+       int tile_h_half = tile_h/2;
+       
+       MissileType *mistype = missile->getObjectType();
+       bool canEnter = missile->canEnter();
+       
+       // Create a scratch surface for saving/restoring the background
+       surf = Map.tile_scratch_surf;
+       assert(surf);
+       
+       // Get the map coordinates of the view origin (upper left corner)
+       int Ox, Oy;
+       mapGetMapOrigin(&Ox, &Oy);
+
+       // Get the screen coordinates of the map viewer origin
+       int Sx, Sy;
+       mapGetScreenOrigin(&Sx, &Sy);
+
+       // Copy the place coordinates of the origin of flight. I'll walk these
+       // along as the missile flies and check for obstructions.
+       int Px, Py, oPx, oPy, orx, ory;
+       Px = Ax;
+       Py = Ay;
+       orx = Ax;
+       ory = Ay;
+
+       // Convert to screen coordinates. (I need to keep the original
+       // B-coordinates for field effects at the bottom of this routine).
+       int sBx;
+       int sBy;
+       
+       if (place_is_wrapping(place))
+       {
+               if (Ax > Ox)
+                     Ax = (Ax - Ox) * tile_w + Sx;
+               else
+                     Ax = (place_w(place) - Ox + Ax)  * tile_w + Sx;
+               if (Ay >= Oy)
+                     Ay = (Ay - Oy) * tile_h + Sy;
+               else
+                     Ay = (place_h(place) - Oy + Ay)  * tile_h + Sy;
+               
+               if (*Bx >= Ox)
+                     sBx = (*Bx - Ox) * tile_w + Sx;
+               else
+                     sBx = (place_w(place) - Ox + *Bx) * tile_w + Sx;
+               if (*By >= Oy)
+                     sBy = (*By - Oy) * tile_h + Sy;
+               else
+                     sBy = (place_h(place) - Oy + *By)  * tile_h + Sy;
+       } 
+       else
+       {
+               Ax = (Ax - Ox) * tile_w + Sx;
+               Ay = (Ay - Oy) * tile_h + Sy;
+               sBx = (*Bx - Ox) * tile_w + Sx;
+               sBy = (*By - Oy) * tile_h + Sy;
+       }
+       
+       // Create the rect which bounds the missile's sprite (used to update
+       // that portion of the screen after blitting the sprite).
+       SDL_Rect rect;
+       rect.x = Ax;
+       rect.y = Ay;
+       rect.w = TILE_W;
+       rect.h = TILE_H;
+       // Get the distance components
+       int dX = sBx - rect.x;
+       int dY = sBy - rect.y;
+       int AdX = abs(dX);
+       int AdY = abs(dY);
+
+       // Select the sprite orientation based on direction of travel
+       if (sprite)
+       {
+               if ((sprite_facings_list(sprite) & 495) == 495) //nsew + diagonals
+               {
+                       sprite_set_facing(sprite, vector_to_8facing(dX, dY));
+               }
+               else if ((sprite_facings_list(sprite) & 170) == 170) //nsew only
+               {
+                       sprite_set_facing(sprite, vector_to_dir(dX, dY));
+               }
+       }
+
+       // Moving left?
+       int Xincr = (rect.x > sBx) ? -1 : 1;
+       // adjust for rounding errors
+       if (rect.x < sBx)
+       {
+               tile_w_half--;
+       }
+
+       // Moving down?
+       int Yincr = (rect.y > sBy) ? -1 : 1;
+       // adjust for rounding errors
+       if (rect.y < sBy)
+       {
+               tile_h_half--;
+       }
+       
+       int dPr, dPru, P, i , Xsubincr, Ysubincr;
+       int oldx, oldy, tempx, tempy;
+               
+       //number of steps between missile repaints
+       int paintloopsize = 20; 
+       
+       // Walk the x-axis?
+       if (AdX >= AdY)
+       {
+               dPr = AdY << 1;
+               dPru = dPr - (AdX << 1);
+               P = dPr - AdX;
+               Xsubincr = Xincr;
+               Ysubincr = 0;
+               if (range > 0.5) // floating point hence error margins
+               {
+                       i = TILE_W * (place_w(place) + 2); // == "enough": its actually checked in the loop instead
+               }
+               else
+               { 
+                       i = AdX;        
+               }
+                if (AdX==0 && AdY==0) {
+                    // Fix for 2364311: avoid divide-by-zero
+                    paintloopsize = 0;
+                } else {
+                    paintloopsize = paintloopsize * (AdX*AdX)/((AdX*AdX)+(AdY*AdY));
+                }
+       }
+       else
+       {
+               dPr = AdX << 1;
+               dPru = dPr - (AdY << 1);
+               P = dPr - AdY;  
+               Xsubincr = 0;
+               Ysubincr = Yincr;
+
+               if (range > 0.5) // floating point hence error margins
+               {
+                       i = TILE_H * (place_h(place) + 2); // == "enough": its actually checked in the loop instead
+               }
+               else
+               { 
+                       i = AdY;        
+               }
+               paintloopsize = paintloopsize * (AdY*AdY)/((AdX*AdX)+(AdY*AdY));
+       }
+       
+       // firing past selected range, so work out the map edges if need be.
+       bool checkEdge = ((range >= 1) && !(place_is_wrapping(place)));
+       
+       oldx = rect.x;
+       oldy = rect.y;
+       
+       int paintloop = paintloopsize;  
+
+       bool beam = missile->getObjectType()->isBeam();
+       
+       // For each step
+       for (; i >= 0; i--)
+       {       
+               oPx = Px;
+               oPy = Py;
+               Px = place_wrap_x(place, ((tile_w_half + rect.x - Sx) / tile_w + Ox));
+               Py = place_wrap_y(place, ((tile_h_half + rect.y - Sy) / tile_h + Oy));
+               
+               if (oPx != Px || oPy != Py)
+               {                       
+                       // check edge if required
+                       if (checkEdge)
+                       {
+                               if (Px < 0 || Py < 0 || Px >= place_w(place) || Py >= place_h(place))
+                                       goto done;              
+                       }
+                               
+                       // check range if required
+                       if (range>1)
+                       {
+                               if (range < place_flying_distance(place, orx, ory, Px, Py))
+                               {
+                                       //need to back up one square, since we the missile shouldnt have gotten this far
+                                       Px = oPx;
+                                       Py = oPy;
+                                       goto done;
+                               }
+                       }
+               
+                       // check if blocked by terrain
+                       if (!missile->enterTile(place, Px, Py))
+                               goto done;
+                       
+                       
+                       //check if callback indicates blocked
+                       if (canEnter & !mistype->fireEnterTile(missile, place, Px, Py))
+                               goto done;
+               }
+               
+               if (paintloop == 0)
+               {
+                       // if have done paintloop steps, redraw sprite
+                       paintloop = paintloopsize;
+                       if (mapTileIsVisible(Px, Py) && sprite)                 
+                       {
+                               tempx = rect.x;
+                               tempy = rect.y;
+                               rect.x = (rect.x + oldx)/2;
+                               rect.y = (rect.y + oldy)/2;
+                               
+                               mapPaintProjectile(&rect, sprite, surf, 15, currentframe, beam);                
+                               if (framecount > 1)  
+                                       currentframe=(currentframe+1)%framecount;
+                               
+                               rect.x = oldx = tempx;
+                               rect.y = oldy = tempy;
+                                       
+                               mapPaintProjectile(&rect, sprite, surf, 15, currentframe, beam);                
+                               if (framecount > 1)  
+                                       currentframe=(currentframe+1)%framecount;               
+                       }
+                       else if (framecount > 1)
+                       {
+                               currentframe=(currentframe+2)%framecount;
+                       }
+               }
+               paintloop--;
+               
+               if (P > 0)
+               {
+                       rect.x += Xincr;
+                       rect.y += Yincr;
+                       P += dPru;
+               }
+               else
+               {
+                       rect.x += Xsubincr;
+                       rect.y += Ysubincr;
+                       P += dPr;
+               }
+       }
+      done:
+       // erase the missile
+       // mapRepaintView(NULL, REPAINT_ACTIVE);
+       if (beam)
+               SDL_Delay(100);
+       
+       mapUpdate(0);
+       
+       // restore the missile sprite to the default facing
+       if (sprite)
+               sprite_set_facing(sprite, SPRITE_DEF_FACING);
+
+  *Bx = Px;
+  *By = Py;
+
+       t2 = SDL_GetTicks();
+
+       if (PROFILE_ANIMATE) {
+         printf("mapAnimateProjectile: %d msec\n", t2 - t1);
+       }
+}
+
+void mapAttachCamera(class Object *subject)
+{
+        Map.subject = subject;
+}
+
+void mapDetachCamera(class Object *subject)
+{
+        Map.subject = NULL;
+}
+
+void mapUpdateTile(struct place *place, int x, int y)
+{
+        struct terrain *terrain;
+        int index;
+        char *vmask;
+        SDL_Rect rect;
+
+        //dbg("mapUpdateTile %d:%d:%s\n", x, y, place->name);
+
+        if (NULL == Map.aview)
+                return;
+        
+
+        // ---------------------------------------------------------------------
+        // Assume we want the active view as it was last rendered. Calculate
+        // the screen coordinates of the given map location. Check if the
+        // coordinates are in the map viewer and abort if not.
+        // ---------------------------------------------------------------------
+
+        if (place != Map.place)
+                return;
+
+        rect.x = (x - (Map.aview->vrect.x + Map.aview->subrect.x)) 
+                * TILE_W/Map.aview->zoom + Map.srect.x;
+        if (rect.x < Map.srect.x || rect.x > (Map.srect.x + Map.srect.w 
+                                              - TILE_W/Map.aview->zoom))
+                return;
+
+        rect.y = (y - (Map.aview->vrect.y + Map.aview->subrect.y)) 
+                * TILE_H/Map.aview->zoom + Map.srect.y;
+        if (rect.y < Map.srect.y || rect.y > (Map.srect.y + Map.srect.h 
+                                              - TILE_H/Map.aview->zoom))
+                return;
+
+        // ---------------------------------------------------------------------
+        // Erase the tile.
+        // ---------------------------------------------------------------------
+
+        rect.w = TILE_W/Map.aview->zoom;
+        rect.h = TILE_H/Map.aview->zoom;
+        screenErase(&rect);
+
+        terrain = place_get_terrain(place, x, y);
+
+        if (Map.aview->zoom > 1) {
+
+                // ------------------------------------------------------------
+                // When zoomed ignore LOS. The vmasks aren't big enough to
+                // cover the area viewed.
+                // ------------------------------------------------------------
+                
+                sprite_zoom_out(Map.aview->zoom);
+               screenZoomOut(Map.aview->zoom);
+                sprite_paint(terrain->sprite, 0, rect.x, rect.y);
+                place_paint_objects(place, x, y, rect.x, rect.y);
+                sprite_zoom_in(Map.aview->zoom);
+               screenZoomIn(Map.aview->zoom);
+
+        } else {
+
+                // ------------------------------------------------------------
+                // If the place is not in line-of-sight then don't paint the
+                // object(s) there. Paint the terrain iff ShowAllTerrain or
+                // XrayVision are in effect.
+                // ------------------------------------------------------------
+
+                vmask = Map.vmask;
+                index = ((y - Map.aview->vrect.y) * Map.aview->vrect.w) 
+                        + (x - Map.aview->vrect.x);
+
+                if (vmask[index] || ShowAllTerrain || XrayVision) {
+                        sprite_paint(terrain->sprite, 0, rect.x, rect.y);
+                }
+
+                if (vmask[index]) {
+                        place_paint_objects(place, x, y, rect.x, rect.y);
+                }
+
+                // If the selected object is not on this tile then shade it
+                if (! Map.selected
+                    || Map.selected->getPlace() != Map.place
+                    || Map.selected->getX() != x
+                    || Map.selected->getY() != y)                
+                        screenShade(&rect, LIT - Map.lmap[index]);
+
+        }
+
+        if (x == Session->crosshair->getX() && y == Session->crosshair->getY())
+                map_paint_cursor();
+
+        
+        
+
+        screenUpdate(&rect);
+
+}
+
+void mapSetSelected(class Object *obj)
+{
+        if (Map.selected == obj)
+                return;
+
+        if (Map.selected) {
+                obj_dec_ref(Map.selected);
+                Map.selected = NULL;
+        }
+
+        Map.selected = obj;
+        if (obj)
+                obj_inc_ref(obj);
+}
+
+int mapScreenToPlaceCoords(int *x, int *y)
+{
+    if (! point_in_rect(*x, *y, &Map.srect)) {
+        return -1;
+    }
+    int px = ((*x - Map.srect.x) * Map.aview->zoom) / TILE_W + Map.aview->vrect.x + Map.aview->subrect.x;
+    int py = ((*y - Map.srect.y) * Map.aview->zoom) / TILE_H + Map.aview->vrect.y + Map.aview->subrect.y;
+    
+    if (place_off_map(Map.place, px, py)) {
+        return -1;
+    }
+
+    *x = place_wrap_x(Map.place, px);
+    *y = place_wrap_y(Map.place, py);
+    return 0;
+}
+
+void mapSetImage(SDL_Surface *image)
+{
+        Map.is_image_mode = 1;
+        if (image) {
+                /* center the image over the map */
+                SDL_Rect rect = Map.srect;
+                if (image->w < Map.srect.w) {
+                        rect.x = Map.srect.x + (Map.srect.w - image->w) / 2;
+                        rect.w = image->w;
+                }
+                if (image->h < Map.srect.h) {
+                        rect.y = Map.srect.y + (Map.srect.h - image->h) / 2;
+                        rect.h = image->h;
+                }
+                screenErase(&Map.srect);
+                screenBlit(image, NULL, &rect);
+        } else {
+                screenErase(&Map.srect);
+        }
+        screenUpdate(&Map.srect);
+}
+
+void mapClearImage(void)
+{
+        Map.is_image_mode = 0;
+}
+
+void mapBlitImage(SDL_Surface *image, Uint32 x, Uint32 y)
+{
+        SDL_Rect rect;
+
+        rect.x = Map.srect.x + x;
+        rect.y = Map.srect.y + y;
+        rect.w = Map.srect.w - x;
+        rect.h = Map.srect.h - y;
+
+        screenBlit(image, NULL, &rect);
+        screenUpdate(&Map.srect);
+}
diff --git a/src/map.h b/src/map.h
new file mode 100644 (file)
index 0000000..b662db2
--- /dev/null
+++ b/src/map.h
@@ -0,0 +1,126 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef map_h
+#define map_h
+
+#include "macros.h"
+#include <SDL.h>
+
+BEGIN_DECL
+
+/* In general, this is valid for functions which take only a 'view' arg */
+#define ALL_VIEWS ((struct mview *)-1)
+
+/* Flags for mapRepaintView() */
+#define REPAINT_IF_DIRTY 1     /* repaint iff the view is dirty */
+#define REPAINT_NO_LOS   2     /* don't apply LOS */
+#define REPAINT_IF_OLD   4      /* repaint iff last repaint < tick ms ago */
+
+extern int map_use_circular_vision_radius;
+
+struct mview;
+struct place;
+
+extern int mapInit(void);
+extern void mapFlash(int mdelay);
+extern void mapSetPlace(struct place *place);
+
+extern struct mview *mapCreateView(void);
+extern void mapDestroyView(struct mview *view);
+extern void mapAddView(struct mview *view);
+extern void mapRmView(struct mview *mview);
+extern void mapCenterView(struct mview *view, int x, int y);
+extern void mapRecomputeLos(struct mview *view);
+extern void mapSetRadius(struct mview *view, int rad);
+extern int mapGetRadius(struct mview *view);
+
+// Hacked in to support missile animation:
+extern void mapGetMapOrigin(int *x, int *y);
+extern void mapGetScreenOrigin(int *x, int *y);
+
+extern void mapCenterCamera(int x, int y);
+extern void mapMoveCamera(int dx, int dy);
+extern void mapUpdate(int flags);
+extern void mapSetDirty(void);
+
+extern void mapRepaintClock(void);
+extern void mapJitter(bool val);       // added for tremor
+extern void mapPeer(bool val);
+extern void mapTogglePeering(void);
+
+extern void mapGetCameraFocus(struct place **place, int *x, int *y);
+extern int mapIsInCameraView(struct place *place, int x, int y);
+
+extern int mapTileIsWithinViewport(int x, int y);
+extern int mapTileIsVisible(int x, int y);
+extern unsigned char mapTileLightLevel(int x, int y);
+
+extern void mapBlackout(int val); // for sleeping in town
+
+// The destination (dx, dy) point is an in-out parm, upon return it
+// points to the location where the missile actually landed (in case it
+// was blocked in its path)
+extern void mapAnimateProjectile(int ox, int oy, int *dx, int *dy, 
+                                 struct sprite *sprite, 
+                                 struct place *place,
+                                 class Missile *missile,
+                                 float range);
+
+extern void mapAttachCamera(class Object *subject);
+extern void mapDetachCamera(class Object *subject);
+extern void mapSetLosStyle(const char *los);
+extern void mapUpdateTile(struct place *place, int x, int y);
+extern void mapPaintDamage(int x, int y);
+extern void mapSetSelected(class Object *obj);
+extern void mapFlashSprite(int x, int y, struct sprite *sprite);
+
+extern int mapScreenToPlaceCoords(int *x, int *y);
+
+/**
+ * Instead of showing the current place, show an image. This lasts until
+ * mapClearImage() is called.
+ *
+ * @param image The image to show. If null, the map is erased instead (ie,
+ * blacked-out).
+ */
+extern void mapSetImage(SDL_Surface *image);
+
+/**
+ * Turn off the image set via mapSetImage() and resume showing the current
+ * place.
+ */
+extern void mapClearImage(void);
+
+/**
+ * Blit an image onto the map window. This lasts until something else is
+ * painted over it. The image will be clipped to fit within the map
+ * window. This function will update the screen before returning.
+ *
+ * @param image is the image to show. It should not be NULL.
+ * @param x is the pixel offset within the map window to blit it.
+ * @param y is the pixel offset within the map window to blit it.
+ */
+extern void mapBlitImage(SDL_Surface *image, Uint32 x, Uint32 y);
+
+END_DECL
+
+#endif
diff --git a/src/menus.c b/src/menus.c
new file mode 100644 (file)
index 0000000..738910b
--- /dev/null
@@ -0,0 +1,1816 @@
+/* $Id: menus.c,v 1.41 2010/08/26 05:56:21 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "menus.h"
+
+#include "ascii.h"
+#include "cfg.h"
+#include "conv.h"
+#include "cmd.h"
+#include "cmdwin.h"
+#include "console.h"
+#include "event.h"
+#include "foogod.h"
+#include "log.h"
+#include "list.h"
+#include "map.h"
+#include "screen.h"
+#include "status.h"
+#include "file.h"
+#include "nazghul.h"
+
+#include "session.h" /* added for demo */
+#include "place.h" /* added for demo */
+#include "sprite.h" /* added for demo */
+#include "tick.h" /* added for demo */
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <png.h>
+#include <time.h>
+#include <SDL_image.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#define LOADSAVE_HINT "\005\006=scroll ENT=select DEL=delete ESC=exit"
+
+/**
+ * Enable this option to have the a "L)oad Game" menu item in addition to the
+ * "J)ourney Onward" menu item. When this is enabled J)ourney Onward
+ * automatically picks the last saved game. Otherwise, J)ourney Onward works
+ * like L)oad Game, providing a list of all saved games, with the most recently
+ * saved one at the top.
+ */
+#ifndef CONFIG_LOAD_GAME_OPTION
+#define CONFIG_LOAD_GAME_OPTION 0
+#endif
+
+/**
+ * Information about saved game files.
+ */
+typedef struct saved_game {
+        struct list list;        /**< For menu_saved_games list */
+        char *fname;             /**< Filename (w/o path) */
+        char *path;              /**< Full pathname to save file */
+        time_t timestamp;        /**< Last modification time */
+        int ref;                 /**< Reference count on this struct */
+        SDL_Surface *screenshot; /**< Map screenshot */
+        char is_current;         /**< is this the currently loaded game? */
+} saved_game_t;
+
+/**
+ * The context used for the menu_scroll function. This keeps track of the
+ * currently selected saved game from the menu and communicates a player abort
+ * back to the menu code.
+ */
+typedef struct {
+        saved_game_t *save; /**< Currently highlighted saved game */
+        char *entry;        /**< Currently highlighted string entry */
+        char *hotkeys;      /**< Hotkey characters, in order of listing */
+        const char **menu;        /**< Menu strings */
+        int n_menu;         /**< Number of menu strings */
+        const char *title;        /**< Menu title */
+        char abort : 1;     /**< The player aborted the selection */
+} menu_scroll_data_t;
+
+
+/**
+ * The list of saved games, built when we evaluate the saved-game script for
+ * the load and save menus.
+ */
+static struct list menu_saved_games;
+
+/**
+ * Keep track of the name of the currently loaded game so we can mark it in the
+ * load and save menus.
+ */
+static saved_game_t *menu_current_saved_game = 0;
+
+/**
+ * This is what the Save Game menu shows for the new game option.
+ */
+static const char *MENU_NEW_GAME_STR = "N)ew Saved Game";
+
+/**
+ * This is a hack added to support demo mode. I'll try to explain, because it's
+ * convoluted. Normally (before I added demo support) the main menu runs an
+ * event loop by calling eventHandle(), which returns when the user makes a
+ * choice.
+ *
+ * For demo mode, I added an extra wrinkle. When I setup the demo I push a tick
+ * handler (I mean animation ticks, which are usually disabled until we start
+ * the game, but for demo mode I need them). The tick handler calls
+ * place_exec() to run the demo. The idea is we would run the demo more or less
+ * concurrently with our processing of user keystrokes in the main menu, but of
+ * course we're doing it all on a single thread.
+ *
+ * Running place_exec() on every tick caused a lot of latency in our response
+ * to handling user keypresses. So I added the first hack: place_exec() will
+ * call eventHandlePending() after processing each object. That gives us a
+ * chance to process user keystrokes more frequently while the demo is
+ * running. The simplified call tree when the user hits <enter> to select a
+ * menu item is something like this:
+ *
+ * main_menu
+ * `-eventHandle
+ *   `-menu_demo_tick_handler
+ *     `-place_exec
+ *       `-eventHandlePending
+ *
+ * Normally we're directly in eventHandle when the player presses <enter>, and
+ * we fall back to main_menu and handle the selection. But if we're in
+ * eventHandlePending this doesn't happen, and we keep on handling events, so
+ * the player perceives this as a dropped keystroke.
+ *
+ * To "fix" it I added the main_menu_handled variable. This causes the
+ * menu_demo_tick_handler to return a value that kicks eventHandle out of its
+ * loop when the user selects <enter>.
+ */
+int main_menu_handled = 0;
+
+/**
+ * Another hack for demos! What fun. Little flag to let the main menu code know
+ * that the demo is done and doesn't need to keep running any more, thanks.
+ */
+int demo_done = 0;
+
+/**
+ * Delete a saved game struct and all it's strings. Don't call this, use
+ * saved_game_unref().
+ *
+ * @param save The struct to delete.
+ */
+static void saved_game_del(saved_game_t *save)
+{
+        assert(! save->ref);
+
+        if (save->fname)
+                free(save->fname);
+        if (save->path)
+                free(save->path);
+        if (save->screenshot)
+                SDL_FreeSurface(save->screenshot);
+        free(save);
+}
+
+/**
+ * Infer the filename of a screenshot from the filename for the saved game.
+ *
+ * @param save The saved game that goes with the screenshot.
+ * @returns The full pathname to the screenshot file. The caller should free()
+ * the string when done using it.
+ */
+static char *saved_game_mk_screenshot_fname(saved_game_t *save)
+{
+        char *s_fname = (char*)malloc(strlen(save->path)+5);
+        assert(s_fname);
+        sprintf(s_fname, "%s.png", save->path);
+        return s_fname;
+}
+
+/**
+ * Create a new saved game struct and populate it's fields. This makes a copy
+ * of the fname, creates a copy of the full pathname, and gets the modification
+ * time of the file.
+ *
+ * @param fname Name of the saved game file.
+ * @returns The new struct or 0 if there was a problem accessing the file or
+ * allocating memory.
+ */
+static saved_game_t *saved_game_new(char *fname)
+{
+        struct stat fileinfo;
+        char *s_fname = 0;
+        saved_game_t *save = (saved_game_t*)malloc(sizeof(*save));
+        if (!save) {
+                warn("Could not alloc save\n");
+                return 0;
+        }
+
+        memset(save, 0, sizeof(*save));
+        
+        list_init(&save->list);        
+
+        /* Keep a copy of the file name. */
+        save->fname = strdup(fname);
+        if (! save->fname) {
+                warn("Could not alloc fname\n");
+                goto abort;
+        }
+
+        /* Build the full path. */
+        save->path = file_mkpath(cfg_get("saved-games-dirname"), fname);
+        if (!save->path) {
+                warn("Could not alloc filename\n");
+                goto abort;
+        }
+
+        /* Get the timestamp on the file. */
+        if (! stat(save->path, &fileinfo)) {
+                save->timestamp = fileinfo.st_mtime;
+        } else {
+                /* This is probably a new save that hasn't been written to file
+                 * yet. Use the current time as it's timestamp. */
+                save->timestamp = time(0);
+        }
+
+        /* Load the screenshot. Ignore failure. */
+        s_fname = saved_game_mk_screenshot_fname(save);
+        if (file_exists(s_fname)) {
+                save->screenshot = IMG_Load(s_fname);
+        }
+        free(s_fname);
+
+        save->ref = 1;
+        return save;
+
+ abort:
+        saved_game_del(save);
+        return 0;
+}
+
+/**
+ * Release a reference to a saved game struct. This could destroy it.
+ *
+ * @param save The struct to release.
+ */
+static void saved_game_unref(saved_game_t *save)
+{
+        assert(save->ref);
+        save->ref--;
+        if (!save->ref) {
+                saved_game_del(save);
+        }
+}
+
+/**
+ * Called when the user kills the window during the main menu. Exits the
+ * program.
+ *
+ * @param kh Unused
+ * @returns Nothing, the program exits.
+ */
+static bool main_menu_quit_handler(struct QuitHandler *kh)
+{
+        exit(0);
+        return(0); /* for Sun compiler */
+}
+
+/**
+ * Shows the game credits in the status window.
+ */
+static void show_credits(void)
+{
+        struct KeyHandler kh;
+        const char *title = "Credits";
+        const char *text = 
+                "Engine Programming\n"\
+                "...Gordon McNutt\n"\
+                "...Kris Parker\n"\
+                "...Sam Glasby\n"\
+                "...Tim Douglas\n"\
+                "...Janne Johansson\n"\
+                "...Karl Garrison\n"\
+                "Build System\n"\
+                "...Andreas Bauer\n"\
+                "Game Scripting\n"\
+                "...Gordon McNutt\n"\
+                "...Kris Parker\n"\
+                "...Sam Glasby\n"
+                "Art Provided by\n"\
+                "...Joshua Steele\n"\
+                "...David Gervais\n"\
+                "...Kris Parker\n"
+                "...Kevin Gabbert\n"\
+                "...Gordon McNutt\n"\
+                "...Sam Glasby\n"\
+                "...Steve Riberdy\n"\
+                "Music Provided by\n"\
+                "...Jim Paterson\n"\
+                ;
+
+        statusSetPageText(title, text);
+        statusSetMode(Page);
+        consolePrint("[Hit ESC to continue]\n");
+
+        kh.fx = scroller;
+        kh.data = NULL;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+}
+
+/**
+ * Prompts the user to confirm that they want to overwrite a saved game.
+ *
+ * @returns 1 On confirm, 0 on cancel.
+ */
+static int confirm_selection()
+{
+        int yesno;
+        log_msg("Existing saved game will be overwritten! Are you sure?");
+        cmdwin_clear();
+        cmdwin_spush("Confirm");
+        cmdwin_spush("<y/n>");
+        getkey(&yesno, yesnokey);
+        cmdwin_pop();
+        if (yesno=='y') {
+                cmdwin_spush("yes!");
+                log_msg("Ok!");
+                return 1;
+        } else {
+                cmdwin_spush("no!");
+                log_msg("Canceled!");
+                return 0;
+        }
+}
+
+/**
+ * Add another saved game to the list. This is called as a result of executing
+ * the saved-games script, which is just a sequence of (kern-add-saved-game
+ * <fname>) procedure calls, each of which lands here. Based on the filename
+ * we'll build out the other info associated with the saved game like the
+ * timestamp and screenshot image. This also adds the saved game to the list in
+ * order sorted by timestamp, using a simple insertion sort algorithm.
+ *
+ * @param fname The name of the saved game file.
+ */
+void menu_add_saved_game(char *fname)
+{
+        struct list *lptr;
+
+        /* Create a new saved game list element. */
+        saved_game_t *save = saved_game_new(fname);
+        if (!save) {
+                warn("menu_add_saved_game: could not add '%s'\n", fname);
+                return;
+        }
+
+        /* Insert it in the list ordered by timestamp. Find the first saved
+         * game in the list which has a timestamp after this one.  */
+        lptr = menu_saved_games.next;
+        while (lptr != &menu_saved_games) {
+                saved_game_t *save2 = outcast(lptr, saved_game_t, list);
+                if (save->timestamp > save2->timestamp) {
+                        break;
+                }
+                lptr = lptr->next;
+        }
+
+        /* Insert this one previous to it. Works for empty lists, too. */
+        list_add_tail(lptr, &save->list);
+}
+
+/**
+ * Print the saved game's name, timestamp and other info for display in the
+ * status window.
+ *
+ * @param buf The string buffer to hold the printed line.
+ * @param n The size in bytes of the string buffer (including a terminating 
+ * NULL).
+ * @param fname The name of the saved game file, not including the full path.
+ */
+static int sprintf_game_info(char *buf, int n, saved_game_t *save, char hotkey)
+{
+        struct tm *timeinfo;
+        int ret = -1;
+        char datebuf[n];
+        int padlen;
+        char mark = ' ';
+
+        /* Convert the timestamp from epoch to a time structure. */
+        timeinfo = localtime(&save->timestamp);
+
+        /* Print the date to a temp buffer to see how big it is. */
+        snprintf(datebuf, n, "%02d:%02d %02d/%02d/%d", timeinfo->tm_hour, 
+                 timeinfo->tm_min, timeinfo->tm_mon, timeinfo->tm_mday, 
+                 1900+timeinfo->tm_year);
+
+        /* Calculate necessary padding to right-justify the date. */
+        padlen = n - (strlen(save->fname) 
+                      + strlen(datebuf) 
+                      + 3 
+                      + (hotkey ? 3 : 0));
+
+        /* We'll mark the current game with an '*'. */
+        if (save->is_current) {
+                mark = '*';
+        }
+
+        /* Print to the buffer. */
+        if (hotkey) {
+                snprintf(buf, n, "%c) %s %*c%c%s", hotkey, save->fname, 
+                         padlen, ' ', mark, datebuf);
+        } else {
+                snprintf(buf, n, "%s %*c%c%s", save->fname, 
+                         padlen, ' ', mark, datebuf);
+        }
+        return ret;
+                 
+}
+
+/**
+ * Extract the filename from the menu entry strings used in the load and save
+ * game menus.
+ * @returns A strdup'd copy of the fname.
+ */
+static char *menu_entry_to_fname(char *entry)
+{
+        char *fname, *end;
+        int mod;
+
+        /* Most saved games entries start with x), where x is a 0-9 */
+        if (isdigit(entry[0]) && ')' == entry[1]) {
+                entry += 3;
+        }
+
+        end = strchr(entry, ' ');
+        mod = end ? 1 : 0;
+        if (mod)
+                *end = 0;
+        fname = strdup(entry);
+        assert(fname);
+        if (mod)
+                *end = ' ';
+        return fname;
+}
+
+/**
+ * Reset the current saved game.
+ * @param save A pointer to the new saved game struct.
+ */
+static void menu_set_current_saved_game(saved_game_t *save)
+{
+        if (menu_current_saved_game) {
+                menu_current_saved_game->is_current = 0;
+                saved_game_unref(menu_current_saved_game);
+                menu_current_saved_game = 0;
+        }
+        menu_current_saved_game = save;
+        if (save) {
+                save->is_current = 1;
+                save->ref++;
+                /* Move it to the front of the list. */
+                list_remove(&save->list);
+                list_add(&menu_saved_games, &save->list);
+        }
+}
+
+/**
+ * Search the list of saved games for one with the given file name.
+ *
+ * @param fname Filename to search for.
+ * @returns The saved game with the matching filename, or 0 if none found.
+ */
+static saved_game_t *saved_game_lookup(char *fname)
+{
+        struct list *lptr;
+        list_for_each(&menu_saved_games, lptr) {
+                saved_game_t *save = outcast(lptr, saved_game_t, list);
+                if (! strcmp(fname, save->fname))
+                        return save;
+        }
+        return 0;
+}
+
+/**
+ * Show a screenshot over the map viewer with the words "SCREEN SHOT" in the
+ * middle.
+ *
+ * @param screenshot The image to show, or 0 to just show a blank screen. For a
+ * blank screen the words "SCREEN SHOT" are still printed.
+ */
+static void menu_show_screenshot(SDL_Surface *screenshot)
+{
+        static const char *MENU_SCREEN_SHOT_STR = "^c+ySCREEN SHOT^c-";
+        SDL_Rect rect;
+
+        mapSetImage(screenshot);
+        rect.x = (((MAP_X + MAP_W) / 2) - (5 * ASCII_W));
+        rect.y = (MAP_Y + MAP_H)/4;
+        rect.w = strlen(MENU_SCREEN_SHOT_STR);
+        rect.h = ASCII_H;
+        screenPrint(&rect, 0, MENU_SCREEN_SHOT_STR);
+
+        rect.w *= ASCII_W;
+        screenUpdate(&rect);
+}
+
+/**
+ * Get the highlighted menu item from the status viewer and figure out which
+ * saved game it corresponds to.
+ *
+ * @returns The saved game struct that goes with the menu entry, or 0 if the
+ * "New Game" option is highlighted.
+ */
+static saved_game_t *menu_scroller_get_selected()
+{
+        char *fname;
+        char *entry_str = (char*)statusGetSelected(String);
+        if (!entry_str) {
+                return 0;
+        }
+        if (! strcmp(entry_str, MENU_NEW_GAME_STR)) {
+                return 0;
+        }
+        fname = menu_entry_to_fname(entry_str);
+        return saved_game_lookup(fname);
+}
+
+/**
+ * Rewrite the saved-game script, using the current list of saved games.
+ *
+ * @returns -1 on error, 0 on success.
+ */
+static int menu_rewrite_saves()
+{
+        FILE *file;
+        struct list *lptr;
+        char *fname = cfg_get("save-game-filename");
+
+        file = file_open_in_save_dir(fname, "w");
+        if (! file) {
+                warn("Problem updating %s: %s\n", fname, file_get_error());
+                return -1;
+        }
+        
+        list_for_each(&menu_saved_games, lptr) {
+                saved_game_t *save = outcast(lptr, saved_game_t,  list);
+                fprintf(file, "(kern-add-save-game \"%s\")\n", save->fname);
+        }
+
+        fclose(file);
+        return 0;
+}
+
+/**
+ * Prompt the user to delete the currently highlighted save-game. This checks
+ * if the highlighted entry is a valid save game, prompts the user to confirm
+ * the deletetion, deletes the save file and the screenshot file, removes the
+ * saved game struct from the list, unrefs it, and re-writes the saved game
+ * script.
+ *
+ * If the save-game or screenshot files can't be deleted the operation warns
+ * the user but continues to remove and unreference the saved game. It will
+ * appear again the next time nazghul is restarted.
+ */
+static void menu_prompt_to_delete(menu_scroll_data_t *data)
+{
+        char *selstr = 0;
+        saved_game_t *save = 0;
+        int yesno = 0;
+        int i1, i2;
+
+        /* Check if user tried to delete the N)ew Saved Game option */
+        selstr =  (char*)statusGetSelected(String);
+        if (! strcmp(selstr, MENU_NEW_GAME_STR))
+                return;
+
+        /* Get the saved game struct for the selection. */
+        save =  menu_scroller_get_selected();
+        if (!save)
+                return;
+
+        /* Prompt to confirm. */
+        log_begin("Delete %s?", save->fname);
+        log_flush();
+        cmdwin_clear();
+        cmdwin_push("Delete-");
+        cmdwin_push("<y/n>");
+        getkey(&yesno, yesnokey);
+        cmdwin_pop();
+
+        /* If confirmation denied then cancel. */
+        if (yesno == 'n') {
+                cmdwin_spush("abort!");
+                log_end(" Canceled!");
+                return;
+        }
+
+        /* Confirmed, try to delete the save file. Abort if it doesn't work. */
+        cmdwin_push("yes!");
+        statusFlashSelected(Red);
+        if (unlink(save->path)) {
+                log_continue(" WARNING! Failed to delete save file %s: %s", 
+                        save->path, strerror(errno));
+        }
+
+        /* Try to delete the screenshot. Warn the user and continue if it
+         * doesn't work. */
+        if (save->screenshot) {
+                char *scr_fname = saved_game_mk_screenshot_fname(save);
+                if (unlink(scr_fname)) {
+                        log_continue(" WARNING! Failed to delete screenshot "\
+                                     "file %s: %s:", scr_fname, 
+                                     strerror(errno));
+                }
+                free(scr_fname);
+        }
+
+        /* Remove and unreference the saved game struct. */
+        list_remove(&save->list);
+        if (save == menu_current_saved_game) {
+                menu_set_current_saved_game(0);
+        }
+        saved_game_unref(save);
+
+        /* Re-write the saved game script. */
+        menu_rewrite_saves();
+
+        /* Reshuffle all the menu entries to close the gap and reset the status
+         * menu list. */
+        i1 = statusGetSelectedIndex(String);
+        assert(i1 >= 0);
+        for (i2 = i1; i2 < data->n_menu-1; i2++) {
+                data->menu[i2] = data->menu[i2+1];
+        }
+        data->menu[i2] = 0;
+        data->n_menu--;
+        statusSetStringList(data->title, data->n_menu, data->menu);
+
+        /* Disable repainting while re-setting the mode to avoid the ugly
+         * flashes on the top line. */
+        statusDisableRepaint();
+        statusSetMode(StringList);
+        statusEnableRepaint();
+
+        statusSetSelectedIndex(i1 ? (i1 - 1) : 0);
+        /*statusRepaint();*/
+
+        log_end(" Removed!");
+}
+
+/**
+ * Scroll the status window for the load/save menus. As the player scrolls over
+ * a saved game, show its screenshot on the map window.
+ *
+ * @param kh Keyhandler with the menu context as its data element.
+ * @param key The key pressed by the player.
+ * @param keymod Reflects the status of the SHIFT, CTRL and ALT keys.
+ * @returns 0 to keep the Status window in scroll mode, 1 to end it.
+ */
+int menu_scroller(struct KeyHandler * kh, int key, int keymod)
+{
+       menu_scroll_data_t *data = (menu_scroll_data_t *) kh->data;
+        enum StatusScrollDir dir;
+        int i1;
+
+        if (data->hotkeys && key < 128) {
+                char ckey = (char)key;
+                char *hotkey = strchr(data->hotkeys, ckey);
+                if (hotkey) {
+                        int index = hotkey - data->hotkeys;
+                        printf("ckey=%c index=%d\n", ckey, index);
+                        statusSetSelectedIndex(index);
+                        statusFlashSelected(Green);
+                        data->entry = (char*)statusGetSelected(String);
+                        data->save = menu_scroller_get_selected();
+                        return 1;
+                }
+        }
+
+       switch (key) {
+       case KEY_NORTH:
+                dir = ScrollUp;
+               break;
+       case KEY_SOUTH:
+                dir = ScrollDown;
+               break;
+       case SDLK_PAGEUP:
+                dir = ScrollPageUp;
+               break;
+       case SDLK_PAGEDOWN:
+                dir = ScrollPageDown;
+               break;
+        case SDLK_HOME:
+                dir = ScrollTop;
+                break;
+        case SDLK_END:
+                dir = ScrollBottom;
+                break;
+       case SDLK_RETURN:
+       case SDLK_SPACE:
+        case KEY_HERE:
+       case '\n':
+                i1 = statusGetSelectedIndex(String);
+                statusFlashSelected(Green);
+                data->entry = (char*)statusGetSelected(String);
+                data->save = menu_scroller_get_selected();
+               return 1;
+       case SDLK_ESCAPE:
+       case 'q':
+                data->abort = 1;
+               return 1;
+        case SDLK_DELETE:
+        case 'd':
+                menu_prompt_to_delete(data);
+                return data->n_menu ? 0 : 1;
+       default:
+                return 0;
+       }
+
+        statusScroll(dir);
+        data->entry = (char*)statusGetSelected(String);
+        data->save = menu_scroller_get_selected();
+        menu_show_screenshot(data->save ? data->save->screenshot : 0);
+
+       return 0;
+}
+
+/**
+ * Scroll the status window for the main menu.
+ *
+ * @param kh Keyhandler with the menu context as its data element.
+ * @param key The key pressed by the player.
+ * @param keymod Reflects the status of the SHIFT, CTRL and ALT keys.
+ * @returns 0 to keep the Status window in scroll mode, 1 to end it.
+ */
+int main_menu_scroller(struct KeyHandler * kh, int key, int keymod)
+{
+       menu_scroll_data_t *data = (menu_scroll_data_t *) kh->data;
+        enum StatusScrollDir dir;
+
+        if (data->hotkeys && key < 128) {
+                char ckey = (char)key;
+                char *hotkey = strchr(data->hotkeys, ckey);
+                if (hotkey) {
+                        int index = hotkey - data->hotkeys;
+                        printf("ckey=%c index=%d\n", ckey, index);
+                        statusSetSelectedIndex(index);
+                        data->entry = (char*)statusGetSelected(String);
+                        return 1;
+                }
+        }
+
+       switch (key) {
+       case KEY_NORTH:
+                dir = ScrollUp;
+               break;
+       case KEY_SOUTH:
+                dir = ScrollDown;
+               break;
+       case SDLK_PAGEUP:
+                dir = ScrollPageUp;
+               break;
+       case SDLK_PAGEDOWN:
+                dir = ScrollPageDown;
+               break;
+       case SDLK_RETURN:
+       case SDLK_SPACE:
+        case KEY_HERE:
+       case '\n':
+                data->entry = (char*)statusGetSelected(String);
+                main_menu_handled = 1;
+               return 1;
+       case SDLK_ESCAPE:
+       case 'q':
+                data->abort = 1;
+                main_menu_handled = 1;
+               return 1;
+       default:
+                return 0;
+       }
+
+        statusScroll(dir);
+        data->entry = (char*)statusGetSelected(String);
+
+       return 0;
+}
+
+/**
+ * Get a suitable hotkey for the numeral.
+ *
+ * @param i The number of the hotkey.
+ * @returns ASCII 0-9 or NULL if i is out of range.
+ */
+static char menu_hotkey(int i)
+{
+        return (i < 10) ? (i + '0') : 0;
+}
+
+/**
+ * Find the most recently saved game.
+ *
+ * @returns A copy of the full pathname of the most recently saved game, or 0
+ * if there are no saved games.
+ */
+char * journey_onward(void)
+{
+        char *ret = 0;
+        saved_game_t *save;
+
+        if (list_empty(&menu_saved_games)) {
+                return 0;
+        }
+
+        /* Since the saved game list is kept sorted by modification time, the
+         * first element in the list is the most recent. */
+        save = outcast(menu_saved_games.next, saved_game_t, list);
+        ret = strdup(save->path);
+        menu_set_current_saved_game(save);
+        return ret;
+}
+
+/**
+ * Give the user a choice of saved games to load, with the most recently saved
+ * always at the top for easy access. If there is only one saved game then
+ * don't bother asking, just load it directly.
+ *
+ * @returns A copy of the full pathname of the game file to load, or 0 if the
+ * player canceled.
+ */
+char * load_game_menu(void)
+{
+        const char **menu = 0;
+        char *menubuf, *menubufptr;
+        int n = 0;
+        int i = 0;
+        struct list *lptr = 0;
+        struct KeyHandler kh;
+       menu_scroll_data_t data;
+        char *selection = 0;
+        enum StatusMode omode = statusGetMode();
+        int linew = STAT_CHARS_PER_LINE;
+
+        /* If there is only one saved game then just load it without prompting
+         * the user. */
+        if (1 == list_len(&menu_saved_games)) {
+                return journey_onward();
+        }
+
+        memset(&data, 0, sizeof(data));
+
+        /* Allocate the memory for the menu strings. */
+        n = list_len(&menu_saved_games);
+        menubuf = (char*)calloc(n, linew+1);
+        assert(menubuf);
+        menu = (const char**)calloc(n, sizeof(menu[0]));
+        assert(menu);
+
+        data.hotkeys = (char*)calloc(n + 1, 1);
+        assert(data.hotkeys);
+        data.menu = menu;
+        data.n_menu = n;
+        data.title = "Load Game";
+
+        /* Add each saved game to the menu list. */
+        menubufptr = menubuf;
+        list_for_each(&menu_saved_games, lptr) {
+                saved_game_t *save = outcast(lptr, saved_game_t, list);
+                menu[i] = menubufptr;
+                data.hotkeys[i] = menu_hotkey(i);
+                sprintf_game_info(menubufptr, linew+1, save, data.hotkeys[i]);
+                menubufptr += linew+1;
+                i++;
+        }
+
+        foogodSetHintText(LOADSAVE_HINT);
+        foogodSetMode(FOOGOD_HINT);
+        statusSetStringList(data.title, n, menu);
+        statusSetMode(StringList);
+
+        /* Setup the initial screen shot */
+        if (list_empty(&menu_saved_games)) {
+                menu_show_screenshot(0);
+        } else {
+                saved_game_t *save = outcast(menu_saved_games.next, 
+                                             saved_game_t, list);
+                menu_show_screenshot(save->screenshot);
+        }
+
+        kh.fx = menu_scroller;
+        kh.data = &data;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+        /* If the player selected something then build the full pathname for
+         * return. */
+        if (! data.abort
+            && data.save) {
+                selection = strdup(data.save->path);
+                assert(selection);
+                menu_set_current_saved_game(data.save);
+        }
+
+        mapClearImage();
+
+        /* If the original status mode was already StringList don't reset the
+         * mode, this will cause status to highlight the top list entry of our
+         * list and it looks funny while we're loading the game. */
+        if (omode != StringList)
+                statusSetMode(omode);
+
+        foogodSetMode(FOOGOD_DEFAULT);
+        free(menu);
+        free(menubuf);
+        free(data.hotkeys);
+
+        return selection;
+}
+
+/**
+ * Filter characters we don't want to show in filenames.
+ *
+ * @param key A keypress code, usually ASCII.
+ * @returns 1 to reject the character, 0 to allow it.
+ */
+static int menu_fname_filter(int key)
+{
+        if (isalnum(key)
+            || (key=='_')
+            || (key=='-')
+            || (key=='.')) {
+                return 0;
+        } else {
+                return 1;
+        }
+}
+
+/**
+ * Get a file name from the player.
+ * @returns A strdup'd copy of the filename.
+ */
+static char *prompt_for_fname()
+{
+        char buf[32];
+
+        log_msg("Enter the new filename.");
+        cmdwin_clear();
+        cmdwin_push("Filename: ");
+
+        if (ui_getline_filtered(buf, sizeof(buf),  menu_fname_filter)) {
+                return strdup(buf);
+        }
+        return 0;
+}
+
+/**
+ * Let the player select a file to save the current game.
+ *
+ * @returns A strdup'd copy of the name of the file to save to, or 0 if the
+ * player aborts. The filename is NOT the full path, like some of the other
+ * menu functions return, because we're not going to load anything with the
+ * result.
+ */
+char * save_game_menu(void)
+{
+        const char **menu = 0;
+        char *menubuf, *menubufptr;
+        int n = 0;
+        int i = 0;
+        struct list *lptr = 0;
+        struct KeyHandler kh;
+        menu_scroll_data_t data;
+        enum StatusMode omode = statusGetMode();
+        int linew = STAT_CHARS_PER_LINE;
+        saved_game_t *selected_game = 0;
+
+        memset(&data, 0, sizeof(data));
+
+        /* Allocate the string buffers to display the menu. */
+        n = list_len(&menu_saved_games) + 1;
+        menubuf = (char*)calloc(n, linew+1);
+        assert(menubuf);
+        menu = (const char**)calloc(n, sizeof(menu[0]));
+        assert(menu);
+
+        data.hotkeys = (char*)calloc(n+1, 1);
+        assert(data.hotkeys);
+        data.menu = menu;
+        data.n_menu = n;
+        data.title = "Save Game";
+
+        /* Prepare to fill in the menu list. */
+        i = 0;
+        menubufptr = menubuf;
+
+        /* The first entry is always the New Save Game option. */
+        sprintf(menubufptr, MENU_NEW_GAME_STR);
+        data.hotkeys[i] = 'n';
+        menu[i++] = menubufptr;
+        menubufptr += linew+1;
+
+        /* Is there a game already loaded? */
+        if (menu_current_saved_game) {
+
+                /* It should be first in the list of saved games. */
+                assert(menu_saved_games.next 
+                       == &menu_current_saved_game->list);
+                
+                data.hotkeys[i] = menu_hotkey(i);
+
+                /* Put it as the next item in the menu. */
+                sprintf_game_info(menubufptr, linew+1, 
+                                  menu_current_saved_game, data.hotkeys[i]);
+                menu[i++] = menubufptr;
+                menubufptr += linew+1;
+        }
+
+        /* Prepare to list the remaining saved games. */
+        if (menu_current_saved_game) {
+                lptr = menu_current_saved_game->list.next;
+        } else {
+                lptr = menu_saved_games.next;
+        }
+
+        /* The remaining saved games are in timestamp order on the list; add
+         * them to the menu in this order. */
+        while (lptr != &menu_saved_games) {
+                saved_game_t *save = outcast(lptr, saved_game_t, list);
+                lptr = lptr->next;
+                menu[i] = menubufptr;
+                data.hotkeys[i] = menu_hotkey(i);
+                sprintf_game_info(menubufptr, linew+1, save, data.hotkeys[i]);
+                menubufptr += linew+1;
+                i++;
+        }
+
+        foogodSetHintText(LOADSAVE_HINT);
+        foogodSetMode(FOOGOD_HINT);
+
+        /* Setup the menu in the status window. */
+        statusSetStringList(data.title, n, menu);
+        statusSetMode(StringList);
+        
+        /* Highlight the current saved game. */
+        if (menu_current_saved_game) {
+                statusSetSelectedIndex(1);
+        }
+
+        /* Show the initial screenshot. */
+        menu_show_screenshot(menu_current_saved_game 
+                             ? menu_current_saved_game->screenshot
+                             : 0);
+
+reselect:
+        kh.fx = menu_scroller;
+        kh.data = &data;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+        if (data.abort) {
+                selected_game = 0;
+                goto done;
+        }
+
+        /* Did the player select an existing saved game? */
+        if (data.save) {
+
+                /* Yes. Overwrite? */
+                if (confirm_selection()) {
+                        selected_game = data.save;
+                } else {
+                        goto reselect;
+                }
+        }
+
+        /* No. Did player abort? */
+        else if (!data.abort) {
+
+                /* No. Must be a new saved game. */
+                struct list *lptr;
+                char *new_name = prompt_for_fname();
+                if (!new_name)
+                        goto reselect;
+
+                /* Did player re-type an existing filename? */
+                list_for_each(&menu_saved_games, lptr) {
+                        saved_game_t *exist = outcast(lptr, saved_game_t, 
+                                                      list);
+                        if (!strcmp(new_name, exist->fname)) {
+
+                                /* Yes. Confirm overwrite? */
+                                if (!confirm_selection()) {
+                                        /* No. Reselect. */
+                                        free(new_name);
+                                        goto reselect;
+                                }
+
+                                /* Ok, overwrite. Nothing new to add to the
+                                 * saved-game script. */
+                                break;
+                        }
+                }
+                
+                /* Replace the "New Saved Game" menu line with what the player
+                   typed. */
+                strncpy(menubuf, new_name, linew);
+                
+                /* Add a new saved game struct to the list. */
+                selected_game = saved_game_new(new_name);
+                list_add(&menu_saved_games, &selected_game->list);
+                
+                /* Re-write the saved games file to add the new
+                 * save. */
+                menu_rewrite_saves();
+
+                free(new_name);
+        }
+
+        /* Save selected? */
+        if (selected_game) {
+
+                char *s_fname = saved_game_mk_screenshot_fname(selected_game);
+                SDL_Rect rect;
+
+                /* Does it have an old screenshot? */
+                if (selected_game->screenshot) {
+                        /* Yes. Get rid of it. */
+                        SDL_FreeSurface(selected_game->screenshot);
+                        selected_game->screenshot = 0;
+                }
+
+                /* Restore map view so we can get a new screenshot. */
+                mapClearImage();
+                mapUpdate(0);
+
+                /* Take a new screenshot. */
+                rect.x = MAP_X;
+                rect.y = MAP_Y;
+                rect.w = MAP_W;
+                rect.h = MAP_H;
+                screenCapture(s_fname, &rect);
+                selected_game->screenshot = IMG_Load(s_fname);
+                menu_set_current_saved_game(selected_game);
+                free(s_fname);
+        }
+
+ done:
+        /* Restore the original status mode before deleting the list. */
+        statusSetMode(omode);
+        foogodSetMode(FOOGOD_DEFAULT);
+        foogodRepaint();
+        mapClearImage();
+
+        free(menu);
+        free(menubuf);
+        free(data.hotkeys);
+
+        if (selected_game) {
+                return strdup(selected_game->fname);
+        }
+        return 0;
+}
+
+static bool menus_demo_tick_handler(struct TickHandler *th)
+{
+        static int in_tick = 0; /* hack: prevent recursive entry */
+        if (Session && !in_tick) {
+                in_tick = 1;
+                Tick++;
+                sprite_advance_ticks(1);
+                if (Place) {
+                        place_exec(Place);
+                }
+                in_tick = 0;
+        }
+
+        if (Quit) {
+                demo_done = 1;
+        }
+
+        /* See the comment over main_menu_handled. */
+        return (bool)(main_menu_handled || demo_done);
+}
+
+char * main_menu(void)
+{
+        static const char *START_NEW_GAME="S)tart New Game";
+        static const char *JOURNEY_ONWARD="J)ourney Onward";
+        static const char *LOAD_GAME="L)oad Game";
+        static const char *CREDITS="C)redits";
+        static const char *QUIT="Q)uit";
+        static const char *TUTORIAL="T)utorial";
+        static const char *SETTINGS = "S(e)ttings";
+        static const char *DEMO = "Show (I)ntro";
+        const char *menu[8];
+        char hotkeys[8+1];
+        int n_items = 0;
+        struct KeyHandler kh;
+        menu_scroll_data_t data;
+        char *selection = NULL;
+       struct QuitHandler qh;
+        static char *new_game_fname =
+                file_mkpath(cfg_get("include-dirname"),
+                            cfg_get("new-game-filename"));
+        static char *tutorial_fname =  
+                file_mkpath(cfg_get("include-dirname"),
+                            cfg_get("tutorial-filename"));
+        char *load_fname = 0;
+        char *save_game_fname = cfg_get("save-game-filename");
+        struct TickHandler th;
+        int show_demo_option = 0;
+        static int first_time = 1;
+        char *demo_fname = 0;
+
+        /* If the player has a saved game, then he's already seen the
+         * demo. Don't make him wait to load it before he can continue his
+         * game. */
+        int run_demo = ! file_exists_in_save_dir(save_game_fname);
+
+        /* setup main menu quit handler so player can click close window to
+         * exit */
+       qh.fx = main_menu_quit_handler;
+       eventPushQuitHandler(&qh);
+
+        /* Does the config file mention a demo? */
+        if (cfg_get("demo-filename")) {
+                demo_fname = file_mkpath(cfg_get("include-dirname"),
+                                         cfg_get("demo-filename"));
+
+                /* Can we find it? */
+                if (file_exists(demo_fname)) {
+                        
+                        /* Have we already run the demo once? */
+                        if (! run_demo || ! first_time) {
+
+                                /* Show the demo as a menu option but don't
+                                 * automatically start it. */
+                                show_demo_option = 1;
+
+                        } else {
+                                /* Setup the demo to run in parallel with the
+                                 * main menu. */
+                                run_demo = 1;
+                                session_load(demo_fname);
+                                foogodSetMode(FOOGOD_DEFAULT);
+                                Session->is_demo = 1;
+                                session_run_hook(Session, 
+                                                 new_game_start_hook, "p", 
+                                                 Session->player);
+                                th.fx = menus_demo_tick_handler;
+                                eventPushTickHandler(&th);
+                                Quit = false;
+                                cfg_set("demo-has-run", "yes");
+                        }
+                }
+        }
+
+
+ start_main_menu:
+        n_items = 0;
+        cmdwin_clear();
+
+        if (! run_demo) {
+                nazghul_splash();
+        }
+
+        /* check for a previously saved game to Journey Onward */
+        if (file_exists_in_save_dir(save_game_fname)) {
+                menu[n_items] = JOURNEY_ONWARD;
+                hotkeys[n_items] = 'j';
+                n_items++;
+                if (CONFIG_LOAD_GAME_OPTION) {
+                        menu[n_items] = LOAD_GAME;
+                        hotkeys[n_items] = 'l';
+                        n_items++;
+                }
+        }
+
+        /* check for the default script for Start New Game */
+        if (file_exists(new_game_fname)) {
+                menu[n_items] = START_NEW_GAME;
+                hotkeys[n_items] = 's';
+                n_items++;
+        }
+
+        /* check for a tutorial script for Tutorial */
+        if (file_exists(tutorial_fname)) {
+                menu[n_items] = TUTORIAL;
+                hotkeys[n_items] = 't';
+                n_items++;
+        }
+
+        /* check for demo */
+        if (show_demo_option) {
+                menu[n_items] = DEMO;
+                hotkeys[n_items] = 'i';
+                n_items++;
+        }
+
+        menu[n_items] = SETTINGS;
+        hotkeys[n_items] = 'e';
+        n_items++;
+
+        menu[n_items] = CREDITS;
+        hotkeys[n_items] = 'c';
+        n_items++;
+
+        menu[n_items] = QUIT;
+        hotkeys[n_items] = 'q';
+        n_items++;
+
+        hotkeys[n_items] = 0;
+
+        foogodSetHintText("\005\006=scroll ENT=select");
+        foogodSetMode(FOOGOD_HINT);
+        statusSetStringList("Main Menu", n_items, menu);
+        statusSetMode(StringList);
+
+        data.hotkeys = hotkeys;
+        data.entry = NULL;
+        kh.fx   = main_menu_scroller;
+        kh.data = &data;
+        main_menu_handled = 0;
+
+        /* If running a demo then start/resume it. */
+        if (run_demo) {
+                tick_run();
+        }
+
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+
+        /* Did we come back because the demo is done? */
+        if (demo_done) {
+
+                /* Yep. Setup for plain old splash and show the demo as a menu
+                 * option. */
+                run_demo = 0;
+                show_demo_option = 1;
+                demo_done = 0;
+                Quit = false;
+                session_del(Session); /* wish me luck! */
+                Session = 0;
+                tick_pause();
+                eventPopTickHandler();
+        }
+
+
+        /* Pause the demo while running the submenus. This is really only
+         * necessary for the load_game_menu(). */
+        if (run_demo) {
+                tick_pause();
+        }
+
+        selection = data.entry;
+        if (! selection) {
+                goto start_main_menu;
+        }
+
+        if (! strcmp(selection, START_NEW_GAME)) {
+                load_fname = new_game_fname;
+                assert(load_fname);
+        }
+        else if (! strcmp(selection, JOURNEY_ONWARD)) {
+                if (CONFIG_LOAD_GAME_OPTION) {
+                        load_fname = journey_onward();
+                } else {
+                        load_fname = load_game_menu();
+                }
+                if (! load_fname)
+                        goto start_main_menu;
+        }
+        else if (CONFIG_LOAD_GAME_OPTION
+                 && ! strcmp(selection, LOAD_GAME)) {                
+                load_fname = load_game_menu();
+                if (!load_fname)
+                        goto start_main_menu;
+        }
+        else if (! strcmp(selection, SETTINGS)) {
+                options_menu();
+                goto start_main_menu;
+        }
+        else if (! strcmp(selection, CREDITS)) {
+                show_credits();
+                goto start_main_menu;
+        }
+        else if (! strcmp(selection, TUTORIAL)) {
+                load_fname = tutorial_fname;
+        }
+        else if (! strcmp(selection, QUIT)) {
+                exit(0);
+        }
+        else if (! strcmp(selection, DEMO)) {
+                /* FIXME: this means that once the demo is started, it won't
+                 * appear as an option again until the user selects to leave
+                 * the main menu and then comes back. Currently there is no way
+                 * to tell when the demo is done, so we don't know when it's ok
+                 * to put the option back in. */
+                show_demo_option = 0;
+                run_demo = 1;
+
+                session_load(demo_fname);
+                Session->is_demo = 1;
+                foogodSetMode(FOOGOD_DEFAULT);
+                session_run_hook(Session, new_game_start_hook, "p", Session->player);
+                th.fx = menus_demo_tick_handler;
+                eventPushTickHandler(&th);
+                Quit = false;
+                goto start_main_menu;
+        }
+        else {
+                fprintf(stderr, "Invalid selection: '%s'\n", selection);
+                exit(-1);
+        }
+
+        /* turn off status while new session is loading */
+        statusSetMode(DisableStatus);
+        foogodSetMode(FOOGOD_DEFAULT);
+
+        /* pop main menu quit handler, new one will be pushed in play.c */
+        eventPopQuitHandler();
+
+        /* Cleanup after the demo. */
+        if (run_demo) {
+                tick_pause();
+                eventPopTickHandler();
+        }
+        
+        first_time = 0;
+        return load_fname;
+}
+
+int menu_init(void)
+{
+        char *fname = cfg_get("save-game-filename");
+        list_init(&menu_saved_games);
+        if (file_exists_in_save_dir(fname)) {
+                file_load_from_save_dir(fname);
+        }
+        return 0;
+}
+
+/*****************************************************************************
+ * Options Menu
+ */
+#include "cmd.h" /* for yesnokey() */
+#include "sound.h" 
+
+#define OPTION_MAXNAMESTRLEN 32
+#define OPTION_MAXVALSTRLEN  16
+#define OPTION_MAXMENUSTRLEN (OPTION_MAXNAMESTRLEN + OPTION_MAXVALSTRLEN + 4)
+
+enum {
+        OPTION_SCREEN_DIMS = 0,
+        OPTION_SOUND_ENABLE,
+        OPTION_MUSIC_VOLUME,
+        OPTION_KEYWORD_HIGHLIGHTING,
+        OPTION_NUMOPTIONS /* keep last */
+};
+
+struct option {
+        const char *name;
+        const char *comment;
+        const char *key;
+        const char *val;
+        char *entry_val;
+        char *startup_val;
+        void (*handler)(struct option *);
+        void (*enable)(int val);
+        char restart : 1;
+        char changed : 1;
+        char restart_on_enable : 1;
+};
+
+static void option_screen_dims(struct option *opt);
+static void option_yes_no(struct option *opt);
+static void option_music(struct option *opt);
+
+#define DECL_OPTION(name,comment,key,handler) \
+    { name, comment, key, 0, 0, 0, handler, NULL, 0, 0 }
+
+#define DECL_YESNO_OPTION(name,comment,key,handler,ctrl,roo) \
+    { name, comment, key, 0, 0, 0, handler, ctrl, 0, 0, roo }
+
+static struct option options[OPTION_NUMOPTIONS] = {
+        DECL_OPTION("Screen Size", "Set the dimensions of the game screen.", 
+                    "screen-dims", option_screen_dims),
+        DECL_YESNO_OPTION("Sound", "Turn sound on or off.",
+                          "sound-enabled", option_yes_no, sound_enable, 1),
+        DECL_OPTION("Music Volume", "Adjust volume of builtin music.", 
+                    "music-volume", option_music),
+        DECL_YESNO_OPTION("Keyword Highlighting", 
+                          "Highlight keywords in conversations with NPC's.",
+                          "keyword-highlighting", option_yes_no,
+                          conv_enable_keyword_highlighting, 0),
+};
+
+/* option_screen_dims -- let player select desired screen size from a list */
+static void option_screen_dims(struct option *opt)
+{
+#       define ADD_SCREEN_DIM(dim,mapw) (dim),
+        const char *menu[] = {
+#               include "screen_dims.h"
+        };
+        struct KeyHandler kh;
+       struct ScrollerContext data;
+        
+        log_msg("Choose your screen size");
+        cmdwin_clear();
+        cmdwin_spush("Screen size");
+        cmdwin_spush("<select>");
+
+        statusSetStringList("Screen Dimensions", array_sz(menu), menu);
+        statusSetMode(StringList);
+        data.selection = NULL;
+        data.selector  = String;
+        kh.fx   = scroller;
+        kh.data = &data;
+        eventPushKeyHandler(&kh);
+        eventHandle();
+        eventPopKeyHandler();
+
+        if (!data.selection) {
+                return;
+        }
+
+        if (! strcmp((char*)data.selection, opt->startup_val)) {
+                opt->restart = 0;
+        } else {
+                opt->restart = 1;
+        }
+
+        opt->val = (char*)data.selection;
+}
+
+/**
+ * Handler for simple yes-or-no options.
+ *
+ * @param opt is the option to modify.
+ */
+static void option_yes_no(struct option *opt)
+{
+        if (!strcmp(opt->val, "yes")) {
+                opt->val = "no";
+                opt->enable(0);
+                opt->restart = 0;
+        } else {
+                opt->val = "yes";
+                opt->enable(1);
+                if (strcmp(opt->startup_val, "yes")) {
+                        opt->restart = opt->restart_on_enable;
+                } else {
+                        opt->restart = 0;
+                }
+        }
+}
+
+/* option_sound -- prompt player to enable music at given level */
+static void option_music(struct option *opt)
+{
+       const char *menu[] = {
+               "Off","25%","50%","75%","100%"
+       };
+       struct KeyHandler kh;
+       struct ScrollerContext data;
+       
+       log_msg("Choose music volume");
+       cmdwin_clear();
+       cmdwin_spush("Volume");
+       cmdwin_spush("<select>");
+       
+       
+       statusSetStringList("Music Volume", array_sz(menu), menu);
+       statusSetMode(StringList);
+       data.selection = NULL;
+       data.selector  = String;
+       kh.fx   = scroller;
+       kh.data = &data;
+       eventPushKeyHandler(&kh);
+       eventHandle();
+       eventPopKeyHandler();
+       
+       if (!data.selection)
+       {
+               return;
+       }
+       
+       opt->val = (char*)data.selection;
+       set_music_volume((char*)data.selection);
+
+}
+
+static int options_save(void)
+{
+        int i;
+        char *fname = cfg_get("options-script-filename");
+        FILE *file = file_open_in_save_dir(fname, "w");
+        if (!file) {
+                warn("Could not open '%s': %s\n", fname, strerror(errno));
+                return -1;
+        }
+
+        fprintf(file, 
+                ";; %s -- This file contains user-specified options that override the\n"
+                ";; game defaults.\n"
+                "(kern-cfg-set \n\n",
+                fname);
+
+        for (i = 0; i < OPTION_NUMOPTIONS; i++) {
+                fprintf(file, ";; %s\n \"%s\" \"%s\"\n\n",
+                        options[i].comment,
+                        options[i].key,
+                        options[i].val);
+        }
+
+        fprintf(file, ")\n");
+        fclose(file);
+
+        return 0;
+}        
+
+/* options_menu -- show the user-configurable options. Upon exit prompt to save
+ * the current settings to the options file. */
+void options_menu(void)
+{
+        int i;
+        int yesno;
+        int any_changed = 0;
+        int any_restart = 0;
+        char menu_strings[OPTION_NUMOPTIONS][OPTION_MAXMENUSTRLEN] = {};
+        const char *menu[OPTION_NUMOPTIONS];
+        struct KeyHandler kh;
+       struct ScrollerContext data;
+
+        /* Get current values and build the menu list. */
+        for (i = 0; i < OPTION_NUMOPTIONS; i++) {
+
+                /* Make a copy of the original value on startup. */
+                if (! options[i].startup_val) {
+                        options[i].startup_val = strdup(cfg_get(options[i].key));
+                }
+
+                /* Make a copy of the values on entry. */
+                options[i].entry_val = strdup(cfg_get(options[i].key));
+
+                /* Clear the flags on entry */
+                options[i].changed = 0;
+
+                /* Init the current val. */
+                options[i].val = cfg_get(options[i].key);
+
+                /* Build the menu entry. */
+                snprintf(menu_strings[i], OPTION_MAXMENUSTRLEN,
+                         "%s [%s] %s",
+                         options[i].name,
+                         options[i].val,
+                         options[i].restart ? "(restart)" : ""
+                        );
+
+                /* Add it to the menu list. */
+                menu[i] = menu_strings[i];
+        }
+
+        /* Menu loop */
+        for (;;) {
+
+                /* Setup status browser (do this every time through the loop,
+                 * as the handler functions might change things) */
+                cmdwin_clear();
+                cmdwin_spush("Settings");
+                cmdwin_push("<select/ESC>");
+                foogodSetHintText(SCROLLER_HINT);
+                foogodSetMode(FOOGOD_HINT);
+                statusSetStringList("Settings", OPTION_NUMOPTIONS, 
+                                    (const char**)menu);
+                statusSetMode(StringList);
+                data.selection = NULL;
+                data.selector  = String;
+                kh.fx   = scroller;
+                kh.data = &data;
+                eventPushKeyHandler(&kh);
+                eventHandle();
+                eventPopKeyHandler();
+
+                /* Player ESC */
+                if (! data.selection) {
+                        break;
+                }
+
+                /* Handle the option */
+                for (i = 0; i < OPTION_NUMOPTIONS; i++) {
+
+                        if (strcmp((char*)data.selection, menu[i])) {
+                                continue;
+                        }
+                        
+                        /* Invoke the option handler. */
+                        options[i].handler(&options[i]);
+
+                        /* Update the menu string. */
+                        options[i].changed = strcmp(options[i].entry_val, 
+                                                    options[i].val);
+                        snprintf(menu_strings[i], OPTION_MAXMENUSTRLEN,
+                                 "%s [%s] %c %s",
+                                 options[i].name,
+                                 options[i].val,
+                                 options[i].changed ? '*' : ' ',
+                                 options[i].restart ? "(restart)" : ""
+                                );
+
+                        break;
+                }
+        }
+
+        cmdwin_clear();
+        foogodSetMode(FOOGOD_DEFAULT);
+
+        /* If none of the options changed from their entry values then return
+         * without bothering the player. */
+        for (i = 0; i < OPTION_NUMOPTIONS; i++) {
+                any_changed |= options[i].changed;
+                any_restart |= options[i].restart;
+        }
+        if (! any_changed) {
+                return;
+        }
+
+        /* Prompt to save */
+        log_msg("Save settings?");
+        cmdwin_spush("Save");
+        cmdwin_push("<y/n>");
+        getkey(&yesno, yesnokey);
+        cmdwin_pop();
+
+        if (yesno == 'y') {
+                /* Set everything and save to the options file. */
+                for (i = 0; i < OPTION_NUMOPTIONS; i++) {
+                        cfg_set(options[i].key, options[i].val);
+                }
+                if (options_save()) {
+                        log_msg("Error while saving!");
+                } else {
+                        log_msg("Settings saved!");
+                        if (any_restart) {
+                                log_msg("NOTE: some of your changes won't "
+                                        "take effect until you Quit and "
+                                        "restart the program. Sorry for the "
+                                        "inconvenience.");
+                        }
+                }
+        } else {
+                log_msg("Settings unchanged.");
+        }        
+}
+
+void menu_startup_error(const char *fmt, ...)
+{
+       va_list args;
+       char buf[128], *ptr;
+        SDL_Rect rect;
+        int len;
+       struct QuitHandler qh;
+
+        SCREEN_W = 320;
+        SCREEN_H = 240;
+        screenInit();
+        asciiInit();
+        eventInit();
+
+       va_start(args, fmt);
+       vsnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+
+        len = strlen(buf);
+        ptr = buf;
+        rect.x = 0;
+        rect.y = 0;
+        rect.w = screenWidth();
+        rect.h = ASCII_H;
+
+        screenPrint(&rect, 0, "^c+r*** STARTUP ERROR ***^c-");
+        rect.y += ASCII_H;
+
+        /* Print the error message, wrapping lines to make it fit on the
+         * screen. */
+        while (len) {
+                int n = min(len, rect.w/ASCII_W);
+
+                screenPrint(&rect, 0, ptr);
+                len -= n;
+                ptr += n;
+                rect.y += ASCII_H;
+        }
+
+        screenUpdate(0);
+
+        /* Wait for the user to close the window. */
+       qh.fx = main_menu_quit_handler;
+       eventPushQuitHandler(&qh);
+
+        /* This will block until the use closes the message window, which
+         * terminates the program. */
+       eventHandle();
+}
diff --git a/src/menus.h b/src/menus.h
new file mode 100644 (file)
index 0000000..eda4584
--- /dev/null
@@ -0,0 +1,52 @@
+/* $Id: menus.h,v 1.6 2010/08/26 05:56:21 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef menus_h
+#define menus_h
+
+/**
+ * Initializes the menus for first-use. The cfg script must be loaded before
+ * calling this.
+ *
+ * @returns 0 on success, -1 on error.
+ */
+extern int menu_init(void);
+
+extern char *main_menu(void);
+
+/**
+ * Let the player choose from the available saved games.
+ *
+ * @return The full pathname of the save file.
+ */
+extern char *load_game_menu(void);
+extern char *save_game_menu(void);
+extern void menu_add_saved_game(char *fname);
+extern void options_menu(void);
+
+/**
+ * Called when the game cannot fully initialize itself to present the normal
+ * UI. This is to support players on OS's that don't show stdout and stderr on
+ * a console.
+ *
+ * @param fmt The printf-formatted error message.
+ */
+void menu_startup_error(const char *fmt, ...);
+
+#endif
diff --git a/src/mmode.c b/src/mmode.c
new file mode 100644 (file)
index 0000000..e862fe7
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "mmode.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct mmode * mmode_new(char *tag, char *name, int index)
+{
+        struct mmode *mmode = (struct mmode*)calloc(1, sizeof(*mmode));
+        assert(mmode);
+        mmode->tag = strdup(tag);
+        assert(mmode->tag);
+        mmode->name = strdup(name);
+        assert(mmode->name);
+        mmode->index = index;
+        return mmode;
+}
+
+void mmode_del(struct mmode *mmode)
+{
+        if (mmode->tag)
+                free(mmode->tag);
+        if (mmode->name)
+                free(mmode->name);
+        free(mmode);
+}
diff --git a/src/mmode.h b/src/mmode.h
new file mode 100644 (file)
index 0000000..b9afc08
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef mmode_h
+#define mmode_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+struct mmode {
+        char *tag;
+        char *name;  /* for UI selection */
+        int index;   /* into passability table (see ptable.h) */
+};
+
+#define mmode_name(mmode) ((mmode)->name)
+#define mmode_index(mmode) ((mmode)->index)
+
+extern struct mmode * mmode_new(char *tag, char *name, int index);
+extern void mmode_del(struct mmode *mmode);
+
+END_DECL
+
+#endif
diff --git a/src/nazghul.c b/src/nazghul.c
new file mode 100644 (file)
index 0000000..3d18bf3
--- /dev/null
@@ -0,0 +1,392 @@
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "../config.h"
+#include "foogod.h"
+#include "constants.h"
+#include "file.h"
+#include "dimensions.h"
+#include "screen.h"
+#include "sound.h"
+#include "play.h"
+#include "event.h"
+#include "combat.h"
+#include "images.h"
+#include "sprite.h"
+#include "player.h"
+#include "place.h"
+#include "wind.h"
+#include "cmdwin.h"
+#include "formation.h"
+#include "map.h"
+#include "vmask.h"
+#include "status.h"
+#include "log.h"
+#include "tick.h"
+#include "cmd.h"
+#include "session.h"
+#include "kern.h"
+#include "cfg.h"
+#include "menus.h"
+#include "nazghul.h"
+#include "conv.h"
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <SDL.h>
+#include <SDL_image.h>
+#include <SDL_thread.h>
+#include <unistd.h>
+#include <getopt.h>
+
+/* Name of the file to load the game from. */
+static char *nazghul_load_fname = 0;
+
+int FullScreenMode = 0;
+int DeveloperMode = 0;
+int ExitProgram = 0;
+
+static char program_name[] = "nazghul";
+
+static void print_version(void)
+{
+        printf("%s %s\n", program_name, PACKAGE_VERSION);
+        printf("Copyright (C) 2003 Gordon McNutt, Sam Glasby\n"
+               "%s comes with NO WARRANTY,\n"
+               "to the extent permitted by law.\n"
+               "You may redistribute copies of %s\n"
+               "under the terms of the GNU General Public License.\n"
+               "For more information about these matters,\n"
+               "see the file named COPYING.\n",
+               program_name, program_name
+                );
+}
+
+static void print_usage(void)
+{
+       printf("Usage:  %s [options] <load-file>\n"
+              "Options: \n"
+               "    -h:        help\n"
+               "    -v: version\n"
+               "    -d: developer mode\n"
+               "    -f: fullscreen mode\n"
+              "    -t: tick <period in msec> \n"
+              "    -a: animation <period in ticks> \n"
+              "    -s: sound <0 to disable> \n"
+              "    -R: recorder <filename>    \n"
+              "    -P: playback <filename>  \n"
+              "    -S: speed <playback ms delay> \n"
+               "    -I: game data dir\n"
+               "    -G: save game dir\n"
+               "    -r: screen size <pixels> (eg, 640x480)\n"
+               "    -T: show all terrain\n"
+               "<load-file>\n",
+               program_name);
+}                              // print_usage()
+
+static void parse_args(int argc, char **argv)
+{
+       int c = 0;
+
+       TickMilliseconds = MS_PER_TICK;
+       AnimationTicks = ANIMATION_TICKS;
+
+       while ((c = getopt(argc, argv, "t:a:s:TdfR:S:P:I:G:vhr:")) != -1) {
+               switch (c) {
+               case 't':
+                       TickMilliseconds = atoi(optarg);
+                       break;
+               case 'a':
+                       AnimationTicks = atoi(optarg);
+                       break;
+               case 's':
+                        cfg_set("sound-enabled", 
+                                atoi(optarg) != 0 ? "yes" : "no");
+                       break;
+               case 'T':
+                       ShowAllTerrain = 1;
+                       break;
+                case 'd':
+                        DeveloperMode = 1;
+                        break;
+                case 'f':
+                        FullScreenMode = 1;
+                        break;
+               case 'R':
+                        /* Set the filename for recording keystrokes. */
+                       cfg_set("record-filename", optarg);
+                       break;
+               case 'S':
+                        /* Set the speed to play back recorded keystrokes. */
+                        cfg_set("playback-speed", optarg);
+                       break;
+               case 'P':
+                        /* Set the file to play back keystrokes from. */
+                        cfg_set("playback-filename", optarg);
+                       break;
+               case 'I':
+                        /* Set the directory for read-only game and cfg
+                         * files. */
+                       cfg_set("include-dirname", optarg);
+                       break;
+               case 'G':
+                        /* Set the directory for read-write game and cfg
+                         * files. */
+                       cfg_set("saved-games-dirname", optarg);
+                       break;
+                case 'v':
+                        print_version();
+                        exit(0);
+                        break;
+                case 'h':
+                        print_usage();
+                        exit(0);
+                case 'r':
+                        /* set the screen dimensions */
+                        cfg_set("screen-dims", optarg);
+                        break;
+                case '?':
+                default:
+                       print_usage();
+                       exit(-1);
+                        break;
+               }               // switch (c)
+       }                       // while (c)
+
+        // --------------------------------------------------------------------
+        // Any remaining option is assumed to be the save-file to load the game
+        // from. If there is none then abort.
+        // --------------------------------------------------------------------
+
+        if (optind < argc) {
+                nazghul_load_fname = argv[optind];
+        }
+}                              // parse_args()
+
+/**
+ * This initializes the various submodules.
+ */
+static void nazghul_init_internal_libs(void)
+{
+        struct lib_entry {
+                const char *name;
+                int (*init)(void);
+        };
+
+        struct lib_entry libs[] = {
+                { "commonInit",     commonInit     },
+                { "screenInit",     screenInit     },
+                { "asciiInit",      asciiInit      },
+                { "sprite_init",    sprite_init    },
+                { "eventInit",      eventInit      },
+                { "windInit",       windInit       },
+                { "formation_init", formation_init },
+                { "astar_init",     astar_init     },
+                { "cmdwin_init",    cmdwin_init    },
+                { "consoleInit",    consoleInit    },
+                { "mapInit",        mapInit        },
+                { "vmask_init",     vmask_init     },
+                { "combatInit",     combatInit     },
+                { "statusInit",     statusInit     },
+                { "foogodInit",     foogodInit     },
+                { "menu_init",      menu_init      },
+                { "conv_init",      conv_init      }
+        };
+
+        int i;
+
+        for (i = 0; i < array_sz(libs); i++) {
+                if (libs[i].init() < 0) {
+                        /* this will not return: */
+                        menu_startup_error("Error in %s", libs[i].name);
+                }
+        }
+
+        log_init();
+
+        if (!strcmp("yes", cfg_get("sound-enabled"))) {
+                sound_init();
+                music_init();
+                set_music_volume(cfg_get("music-volume"));
+        }
+
+}
+
+/* nazghul_splash -- show the splash image */
+void nazghul_splash(void)
+{
+        static SDL_Surface *splash = 0;
+        SDL_Rect rect;
+
+        /* The first time through load the splash image from a file. */
+        if (! splash) {
+                char *dims = cfg_get("screen-dims");
+                const char *suffix = "-splash-image-filename";
+                char *key;
+                char *basename;
+                char *filename;
+                
+                /* Build a key for the splash image filename based on the
+                 * screen dimensions. */
+                key = (char*)malloc(strlen(dims) + strlen(suffix) + 1);
+                assert(key);
+                strcpy(key, dims);
+                strcat(key, suffix);
+                
+                /* Lookup the filename. */
+                basename = cfg_get(key);
+                if (! basename) {
+                        warn("cfg_get: no key matches '%s'", key);
+                        free(key);
+                        return;
+                }
+                free(key);
+                
+                /* Look for the splash image, check the include dir first, then
+                 * check the current working dir */
+                filename = file_mkpath(cfg_get("include-dirname"), basename);
+                if (filename) {
+                        splash = IMG_Load(filename);
+                        free(filename);
+                }
+                if (! splash) {
+                        warn("IMG_Load failed: %s\n", SDL_GetError());
+                        return;
+                }
+
+        }
+
+        rect.x = MAP_X;
+        rect.y = MAP_Y;
+        rect.w = MAP_W;
+        rect.h = MAP_H;
+        screenErase(&rect);
+
+        /* Fill out the screen destination rect */
+        rect.x = max(0, (MAP_W - splash->w) / 2) + MAP_X;
+        rect.y = max(0, (MAP_H - splash->h) / 2) + MAP_Y;
+        rect.w = min(splash->w, MAP_W);
+        rect.h = min(splash->h, MAP_H);
+
+        screenBlit(splash, NULL, &rect);
+        screenUpdate(&rect);
+}
+
+/* init_default_cfg -- initialize the global cfg settings to start-up defaults
+ * and prepare it for loading the cfg script */
+static void init_default_cfg()
+{
+        cfg_init();
+        cfg_set("init-script-filename", "kern-init.scm");
+        cfg_set("options-script-filename", "options.scm");
+        cfg_set("splash-image-filename", "splash.png");
+        cfg_set("screen-dims", "1280x960" /*"640x480"*/);
+        cfg_set("sound-enabled", "yes");
+        cfg_set("music-volume", "100%");
+        cfg_set("keyword-highlighting", "yes");
+}
+
+int main(int argc, char **argv)
+{
+        int print_version = 1;
+
+        /* Initialize the cfg environment before parsing args. */
+        init_default_cfg();
+
+       parse_args(argc, argv);
+
+        /* Load the cfg script after parsing args */
+        if (file_load_from_include_dir(cfg_get("init-script-filename"))) {
+                menu_startup_error("Error loading %s: %s", 
+                                   cfg_get("init-script-filename"), 
+                                   file_get_error());
+        }
+
+        /* Load the options script */
+        if (file_exists_in_save_dir(cfg_get("options-script-filename"))) {
+                if (file_load_from_save_dir
+                    (cfg_get("options-script-filename"))) {
+                        warn("Could not load options script\n");
+                }
+        }
+
+        if (dimensions_init()) {
+                err("dimensions_init() failed\n");
+                exit(-1);
+        }
+
+        nazghul_init_internal_libs();
+
+        tick_start(TickMilliseconds);
+
+ main_loop:
+        /* blank out the whole screen */
+        screenErase(NULL);
+        screenUpdate(NULL);
+
+        /* pause animation tick generation */
+        tick_pause();
+
+        /* Show the splash screen on startup */
+        nazghul_splash();
+        
+        /* The first time we start print the vesrsion info. */
+        if (print_version) {
+                print_version = 0;
+                log_banner("^c+bNazghul version^c- ^c+G%s^c-", PACKAGE_VERSION );
+        }
+
+        /* paint the border for the first time */
+        screen_repaint_frame();
+
+        /* if no load file specified on the command line then run the main
+         * menu */
+        if (! nazghul_load_fname)
+                nazghul_load_fname = main_menu();
+
+        /* Clear out the vmask cache */
+        vmask_flush_all();
+
+        /* run the game, don't return until the user quits */
+       playRun(nazghul_load_fname);
+
+        /* cleanup modules that need it */
+        eventExit();
+
+        /* FIXME: need to free nazghul_load_fname */
+        /* reset save file so main menu runs */
+        nazghul_load_fname=0;
+
+        /* ExitProgram is set when the player closes the window; in that case
+         * drop out of the program without showing the main menu again. */
+        if (! ExitProgram) {
+                /* In the past, memory leaks made this a bad idea. Let's give
+                 * it another go and try to work through them if they crop up
+                 * again. */
+                goto main_loop;
+        }
+
+        tick_kill();
+
+       return 0;
+}
+
diff --git a/src/nazghul.h b/src/nazghul.h
new file mode 100644 (file)
index 0000000..979baf2
--- /dev/null
@@ -0,0 +1,34 @@
+/* $Id: nazghul.h,v 1.1 2007/12/05 03:49:27 gmcnutt Exp $
+ *
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef nazghul_h
+#define nazghul_h
+
+extern int FullScreenMode;
+extern int DeveloperMode;
+extern int ExitProgram;
+
+/**
+ * The main menu uses this to rest the splash image if the user enters the load
+ * menu but then changes his mind and backs out to the main menu.
+ */
+void nazghul_splash(void);
+
+
+#endif
diff --git a/src/node.c b/src/node.c
new file mode 100644 (file)
index 0000000..315ed26
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003, 2004 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "node.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+struct node *node_new(void *data)
+{
+        struct node *node;
+
+        node = (struct node *)calloc(1, sizeof(*node));
+        assert(node);
+        node->ptr = data;
+        node->ref = 1;
+        return node;
+}
+
+struct node *node_new_keyed(void *data, int key)
+{
+        struct node *node;
+
+        node = node_new(data);
+        node_key(node) = key;
+
+        return node;
+}
+
+void node_unref(struct node *node)
+{
+        assert(node->ref);
+        node->ref--;
+        if (! node->ref)
+                free(node);
+}
+
+void node_foldr(struct node *head,
+                void (*fx)(struct node *node, void *data),
+                void *data)
+{
+        struct node *i;
+        struct node *p;
+
+        i = node_next(head);
+
+        while (i != head) {
+                p = i;
+                i = node_next(i);
+
+                fx(p, data);
+        }
+}
+
+int node_list_len(struct node *head)
+{
+        struct node *node = node_next(head);
+        int n = 0;
+        while (node != head) {
+                node = node_next(node);
+                n++;
+        }
+        return n;
+}
+
+void node_list_unlink_and_unref(struct node *head)
+{
+        struct node *node = node_next(head);
+        while (node != head) {
+                struct node *tmp = node_next(node);
+                node_remove(node);
+                node_unref(node);
+                node = tmp;
+        }
+}
diff --git a/src/node.h b/src/node.h
new file mode 100644 (file)
index 0000000..003f510
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003, 2004 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef node_h
+#define node_h
+
+#include "macros.h"
+#include "olist.h"
+
+BEGIN_DECL
+
+struct node {
+        struct olist olist;
+        void *ptr;
+        int ref;
+};
+
+
+#define nodelst(n) (&((n)->olist.list))
+#define nodekeyedlst(n) (&((n)->olist))
+#define node_next(n) ((struct node *)((n)->olist.list.next))
+#define node_prev(n) ((struct node *)((n)->olist.list.prev))
+#define node_key(n) ((n)->olist.key)
+#define node_add(n1,n2) list_add(nodelst(n1), nodelst(n2))
+#define node_addref(n) ((n)->ref++)
+#define node_add_keyed(n1, n2) olist_add(nodekeyedlst(n1), nodekeyedlst(n2))
+#define node_add_tail(n1,n2) list_add_tail(nodelst(n1), nodelst(n2))
+#define node_for_each(head,ptr) \
+        for ((ptr) = node_next(head); (ptr) != (head); (ptr) = node_next(ptr))
+#define node_init(n) { list_init(nodelst(n)); (n)->ptr = NULL; }
+#define node_list_empty(n) (list_empty(nodelst(n)))
+#define node_remove(n) list_remove(nodelst(n))
+#define node_switch(a,b) (list_switch(nodelst(a), nodelst(b)))
+#define node_lookup(n, key) (struct node*)(olist_lookup(nodekeyedlst(n),(key), 0))
+
+extern struct node *node_new(void *data);
+extern struct node *node_new_keyed(void *data, int key);
+extern void node_unref(struct node *node);
+extern void node_foldr(struct node *node,
+                       void (*fx)(struct node *node, void *data),
+                       void *data);
+extern int node_list_len(struct node *head);
+extern void node_list_unlink_and_unref(struct node *head);
+END_DECL
+
+#endif /* node_h */
diff --git a/src/object.c b/src/object.c
new file mode 100644 (file)
index 0000000..0b61795
--- /dev/null
@@ -0,0 +1,2379 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//e
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "conv.h"
+#include "gob.h"
+#include "object.h"
+#include "session.h"
+#include "place.h"
+#include "character.h"
+#include "map.h"
+#include "sprite.h"
+#include "screen.h"
+#include "console.h"
+#include "sound.h"
+#include "player.h"
+#include "terrain.h"
+#include "vmask.h"
+#include "Field.h"
+#include "dice.h"
+#include "effect.h"
+#include "mmode.h"
+#include "combat.h"  // for combat_get_state()
+#include "log.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*****************************************************************************/
+
+//
+// These GIFC_CAN_* bits need to match the script:
+//
+#define GIFC_CAN_GET          (1<<0)
+#define GIFC_CAN_USE          (1<<1)
+#define GIFC_CAN_EXEC         (1<<2)
+#define GIFC_CAN_OPEN         (1<<3)
+#define GIFC_CAN_HANDLE       (1<<4)
+#define GIFC_CAN_STEP         (1<<5)
+#define GIFC_CAN_ATTACK       (1<<6)
+#define GIFC_CAN_MIX          (1<<7)
+#define GIFC_CAN_ENTER        (1<<8)
+#define GIFC_CAN_CAST         (1<<9)
+#define GIFC_CAN_BUMP         (1<<10)
+#define GIFC_CAN_HIT_LOCATION (1<<11)
+#define GIFC_CAN_BUY          (1<<12)
+#define GIFC_CAN_SEARCH       (1<<13)
+#define GIFC_CAN_SENSE        (1<<14)
+#define GIFC_CAN_XAMINE       (1<<15)
+#define GIFC_CAN_DESCRIBE     (1<<16)
+#define GIFC_CAN_ON_ATTACK     (1<<17)
+
+ObjectType::ObjectType()
+{
+        assert(false);
+}
+
+ObjectType::ObjectType(const char *tag, const char *sname, struct sprite *sprite_, 
+                       enum layer layer_)
+        : sprite(sprite_), layer(layer_), speed(0), required_action_points(0), 
+          max_hp(0), gifc(NULL), gifc_cap(0), gob(NULL), pluralName(NULL)
+{
+       this->tag = strdup(tag);
+        assert(this->tag);
+
+        if (sname) {
+                this->name = strdup(sname);
+                assert(this->name);
+        } else {
+                this->name = 0;
+        }
+}
+
+ObjectType::~ObjectType()
+{
+       if (tag)
+               free(tag);
+       if (name)
+               free(name);
+        if (gifc)
+                closure_unref(gifc);
+        if (pluralName)
+                free(pluralName);
+        if (gob)
+                gob_unref(gob);
+}
+
+void ObjectType::setPluralName(char *val)
+{
+        if (pluralName)
+                free(pluralName);
+        if (val)
+                pluralName=strdup(val);
+        else
+                pluralName=NULL;
+}
+
+char *ObjectType::getPluralName()
+{
+        return pluralName;
+}
+
+bool ObjectType::init(char *tag, char *name, enum layer layer,
+                     struct sprite *sprite)
+{
+       this->tag = strdup(tag);
+       this->name = strdup(name);
+       this->sprite = sprite;
+       this->layer = layer;
+       return (this->tag != 0 && this->name != 0);
+}
+
+class Object *ObjectType::createInstance()
+{
+       return new Object(this);
+}
+
+void ObjectType::setSprite(struct sprite *sprite)
+{
+       this->sprite = sprite;        
+}
+
+static int endsWith(const char *word, const char *end)
+{
+        int wlen=strlen(word)-1;
+        int elen=strlen(end)-1;
+
+        if (wlen<elen)
+                return 0;
+        
+        while (elen>=0) {
+                if (word[wlen--]!=end[elen--])
+                        return 0;
+        }
+
+        return 1;
+}
+
+void ObjectType::describeType(int count)
+{
+       if (1 == count) {
+               if (isvowel(name[0]))
+                       log_continue("an ");
+               else
+                       log_continue("a ");
+               log_continue("%s", getName());
+       } else if (getPluralName()) {
+                log_continue("some %s (%d)", getPluralName(), count);
+        } else {
+                if (endsWith(name, "s")
+                    || endsWith(name, "sh"))
+                        log_continue("some %ses (%d)", getName(), count);
+                else
+                        log_continue("some %ss (%d)", getName(), count);
+       }
+}
+
+void ObjectType::describe(Object *obj)
+{
+        if (hasDescribeHook()) {
+                runDescribeHook(obj);
+                return;
+        }
+
+        describeType(obj->getCount());
+}
+
+bool ObjectType::isType(int classID) 
+{
+        return (classID == OBJECT_TYPE_ID);
+}
+
+int ObjectType::getType()
+{
+        return OBJECT_TYPE_ID;
+}
+
+const char *ObjectType::getTag()
+{
+        return tag;
+}
+
+const char *ObjectType::getName()
+{
+        return name;
+}
+
+struct sprite *ObjectType::getSprite()
+{
+        return sprite;
+}
+
+enum layer ObjectType::getLayer()
+{
+        return layer;
+}
+
+bool ObjectType::isVisible()
+{
+        return true;
+}
+
+int ObjectType::getSpeed()
+{
+        return speed;
+}
+
+int ObjectType::getRequiredActionPoints()
+{
+        return required_action_points;
+}
+
+int ObjectType::getMaxHp()
+{
+        return max_hp;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// hook_list api
+//
+//////////////////////////////////////////////////////////////////////////////
+#define hook_list_init(hl) do { list_init(&(hl)->list); (hl)->lock = 0; } while (0)
+#define hook_list_add(hl,en) (list_add(&(hl)->list, (en)))
+#define hook_list_lock(hl) (++(hl)->lock)
+#define hook_list_unlock(hl) ((hl)->lock--)
+#define hook_list_first(hl) ((hl)->list.next)
+#define hook_list_end(hl) (&(hl)->list)
+#define hook_list_empty(hl) (list_empty(&(hl)->list))
+#define hook_list_for_each(hl,ptr) list_for_each(&(hl)->list, (ptr))
+#define hook_list_locked(hl) ((hl)->lock)
+#define hook_list_trylock(hl) (hook_list_locked(hl) ? 0 : hook_list_lock(hl))
+#define hook_list_tryunlock(hl,lock) ((lock) ? hook_list_unlock(hl) : 0)
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// hook_entry api
+//
+//////////////////////////////////////////////////////////////////////////////
+
+#define HEF_INVALID (1<<0)
+#define HEF_DETECTED (1<<1)
+#define HEF_STARTED  (1<<2)
+
+#define hook_entry_invalidate(he) ((he)->flags |= HEF_INVALID)
+#define hook_entry_detected(he) ((he)->flags & HEF_DETECTED)
+#define hook_entry_detect(he) ((he)->flags |= HEF_DETECTED)
+#define hook_entry_gob(he) ((he)->gob->p)
+#define hook_entry_started(he) ((he)->started)
+#define hook_entry_set_started(he) ((he)->started=1)
+
+hook_entry_t *hook_entry_new(struct effect *effect, struct gob *gob)
+{
+        hook_entry_t *entry;
+
+        entry = (hook_entry_t*)calloc(1, sizeof(*entry));
+        assert(entry);
+        list_init(&entry->list);
+        entry->effect = effect;
+        entry->gob = gob;
+        gob_ref(gob);
+        
+        if (effect_will_expire(effect)) {
+                clock_alarm_set(&entry->expiration, effect->duration);
+        }
+
+        //dbg("hook_entry_new: %p\n", entry);
+        return entry;
+}
+
+void hook_entry_del(hook_entry_t *entry)
+{
+        //dbg("hook_entry_del: %p\n", entry);
+        if (entry->gob)
+                gob_unref(entry->gob);
+        free(entry);
+}
+
+void hook_entry_save(hook_entry_t *entry, struct save *save)
+{
+        // Note: saved effects are loaded in kern.c:kern_mk_char() & attached
+        // via restoreEffect().
+
+        save->enter(save, "(list\n");
+        save->write(save, "%s\n", entry->effect->tag);
+        if (entry->gob)
+                gob_save(entry->gob, save);
+        else
+                save->write(save, "nil\n");
+        save->write(save, "%d\n", entry->flags);
+        clock_alarm_save(entry->expiration, save);
+        save->exit(save, ")\n");
+}
+
+static inline int hook_entry_is_invalid(hook_entry_t *entry)
+{
+        return ((entry->flags & HEF_INVALID) ||
+                (effect_will_expire(entry->effect) &&
+                 clock_alarm_is_expired(&entry->expiration)));
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Object class methods
+//
+//////////////////////////////////////////////////////////////////////////////
+
+void Object::init(int x, int y, struct place *place, class ObjectType * type)
+{
+        // fixme: obsolete?
+       this->type = type;
+       setX(x);
+       setY(y);
+       setPlace(place);
+}
+
+void Object::init(class ObjectType * type)
+{
+       this->type = type;
+}
+
+bool Object::tryToRelocateToNewPlace(struct place *newplace, 
+                                     int newx, int newy,
+                                     struct closure *cutscene)
+{
+        obj_inc_ref(this);
+        place_remove_object(getPlace(), this);
+
+        if (cutscene) {
+                
+                mapUpdate(0);
+                closure_exec(cutscene, NULL);
+                
+        }
+
+        setPlace(newplace);
+        setX(newx);
+        setY(newy);
+        place_add_object(getPlace(), this);
+        obj_dec_ref(this);
+        changePlaceHook();
+        return true;
+}
+
+////
+// Trigger the topmost sense mechanism on a tile, using this as the subject
+//
+// @param tilePlace place the tile is in
+// @param tileX coord of tile
+// @param tileY coord of tile
+//
+void Object::triggerSense(struct place *tilePlace, int tileX, int tileY)
+{
+        Object *mech = place_get_object(tilePlace, tileX, tileY, mech_layer);
+        if (mech 
+            && mech != this 
+            && mech->getObjectType()->canSense()) {
+                mech->getObjectType()->sense(mech, this);
+        }
+}
+
+////
+// Trigger the topmost step mechanism on a tile, using this as the subject
+//
+// @param tilePlace place the tile is in
+// @param tileX coord of tile
+// @param tileY coord of tile
+//
+void Object::triggerStep(struct place *tilePlace, int tileX, int tileY)
+{
+        Object *mech = place_get_object(tilePlace, tileX, tileY, mech_layer);
+        if (mech 
+            && mech != this 
+            && mech->getObjectType()->canStep()) {
+                mech->getObjectType()->step(mech, this);
+        }
+}
+
+////
+// Run the step and sense triggers on tile entry using this as the subject,
+// flags permitting.
+//
+// @param tilePlace place the tile is in
+// @param tileX coord of tile
+// @param tileY coord of tile
+// @param flags relocation flags which specify what types of triggers to avoid
+//
+void Object::triggerOnTileEntry(struct place *tilePlace, int tileX, int tileY,
+                                int flags)
+{
+        bool sense = !(flags & REL_NOSENSE);
+        bool step = !(flags & REL_NOSTEP);
+
+        if (sense) {
+                triggerSense(tilePlace, tileX, tileY);
+        }
+
+        if (step) {
+                triggerStep(tilePlace, tileX, tileY);
+        }
+}
+
+////
+// Run the sense trigger on tile exit using this as the subject, flags
+// permitting.
+//
+// @param tilePlace place the tile is in
+// @param tileX coord of tile
+// @param tileY coord of tile
+// @param flags relocation flags which specify what types of triggers to avoid
+//
+void Object::triggerOnTileExit(struct place *tilePlace, int tileX, int tileY,
+                               int flags)
+{
+        bool sense = ! (flags & REL_NOSENSE);
+
+        if (sense) {
+                triggerSense(tilePlace, tileX, tileY);
+        }
+}
+
+void Object::relocate(struct place *newplace, int newx, int newy, int flags,
+                      struct closure *place_switch_hook)
+{
+        int volume;
+        int distance;
+        struct place *foc_place;
+        int foc_x, foc_y;
+        struct place *oldPlace = getPlace(); // remember for tile exit
+        int oldX = getX(); // remember for tile exit
+        int oldY = getY(); // remember for tile exit
+
+        assert(newplace);
+
+        if (isOnMap()) {
+
+                assert(getPlace());
+
+                if (newplace == getPlace()) {
+
+                        // Moving from one tile to another in the same place.
+                        if (place_switch_hook) {
+
+                                // A cut scene was specified (this happens for
+                                // moongate entry, for example). Remove the
+                                // object, play the cut scene, and put the
+                                // object back down at the new location.
+                                mapUpdate(0);
+                                setOnMap(false);
+                                rmView();
+                                obj_inc_ref(this);
+                                place_remove_object(getPlace(), this);
+
+                                closure_exec(place_switch_hook, NULL);
+
+                                setPlace(newplace);
+                                setX(newx);
+                                setY(newy);
+                                place_add_object(newplace, this);
+                                obj_dec_ref(this);
+                                setOnMap(true);
+                                addView();
+
+                        } else {
+
+                                place_move_object(newplace, this, newx, newy);
+                                setX(newx);
+                                setY(newy);
+                        }
+
+                } else {
+
+                        // Place-to-place movement, where the object is on the
+                        // map. This is a special case for character objects so
+                        // use an overloadable method to implement it.
+                        if (! tryToRelocateToNewPlace(newplace, newx, newy,
+                                                      place_switch_hook)) {
+                                return;
+                        }
+
+                        // This object may no longer be on a map as a result of
+                        // the above call. If so then finish processing.
+                        if (! isOnMap()) {
+
+                                // Run the exit triggers before returning
+                                if (oldPlace) {
+                                        triggerOnTileExit(oldPlace, oldX, oldY, flags);
+                                }
+
+                                return;
+                        }
+                }
+
+        } else {
+
+                // Place-to-place movement, where the object is off-map in the
+                // old place. I assume by default it will be on-map in the new
+                // place and let changePlaceHook() fix things up if necessary.
+                setPlace(newplace);
+                setX(place_wrap_x(newplace, newx));
+                setY(place_wrap_y(newplace, newy));
+                place_add_object(getPlace(), this);
+                setOnMap(true);
+                addView();
+                changePlaceHook();
+
+        }
+
+        // Run the exit triggers.
+        if (oldPlace) {
+                triggerOnTileExit(oldPlace, oldX, oldY, flags);
+        }
+        
+        mapSetDirty();
+
+        // It's possible that changePlaceHook() removed this object from the
+        // map. This certainly happens when the player party moves from town to
+        // wilderness, for example. In this case I probably want to skip all of
+        // what follows. I ABSOLUTELY want to skip the call to updateView() at
+        // the end, and in fact I changed updateView() to assert if this object
+        // is not on the map.
+        if (! isOnMap())
+                return;
+
+        // Attenuate movement sound based on distance from the camera's focal
+        // point.
+        volume = SOUND_MAX_VOLUME;
+        mapGetCameraFocus(&foc_place, &foc_x, &foc_y);
+        if (foc_place == getPlace()) {
+                distance = place_flying_distance(foc_place, foc_x, foc_y, 
+                                                 getX(), getY());
+                if (distance > 1)
+                        volume = (volume * (20 - distance))/20;
+                if (volume > 0)
+                       sound_play(get_movement_sound(), volume);
+        }
+
+        // If the camera is attached to this object then update it to focus on
+        // the object's new location.
+        if (isCameraAttached()) {
+                mapCenterCamera(getX(), getY());
+        }
+        
+        updateView();
+
+       // Run the entry triggers.
+       triggerOnTileEntry(getPlace(), getX(), getY(), flags);
+}
+
+void Object::setOnMap(bool val)
+{
+        is_on_map = val;
+}
+
+void Object::remove()
+{
+       obj_inc_ref(this);
+       if (isOnMap())
+       {
+               struct place *oldPlace = getPlace(); // remember for tile exit
+               int oldX = getX(); // remember for tile exit
+               int oldY = getY(); // remember for tile exit
+               setOnMap(false);
+               rmView();
+               
+               place_remove_object(getPlace(), this);
+               
+               // Run the exit triggers.
+               if (oldPlace)
+               {
+                       triggerOnTileExit(oldPlace, oldX, oldY, 0);
+               }
+               
+                if (isOpaque()) {
+                        vmask_flush_all();
+                }
+
+               // Note: do NOT call setPlace(NULL) here. When the player party
+               // object is removed from the map it still needs to "know" what
+               // place the members are in.
+       }
+       endTurn();
+       attachCamera(false);
+       obj_dec_ref(this);
+}
+
+void Object::paint(int sx, int sy)
+{
+       struct sprite *sprite = getSprite();
+       if (sprite) {
+                int origFacing = sprite_get_facing(sprite);
+                sprite_set_facing(sprite, facing);
+                if (TimeStop
+                    && isPlayerControlled()) {
+                        sprite_paint(sprite, 
+                                     sprite_frame + Session->time_stop_ticks, 
+                                     sx, sy);
+                } else {
+                        sprite_paint(sprite, sprite_frame, sx, sy);
+                }
+                sprite_set_facing(sprite, origFacing);
+        }
+}
+
+void Object::describe()
+{
+        assert(getObjectType()); // else implement this method in subclass
+        getObjectType()->describe(this);
+        if (!isVisible()) {
+                log_continue(" (invisible)");
+        }
+        if (isSubmerged()) {
+                log_continue(" (submerged)");
+        }
+}
+
+void Object::examine()
+{
+        assert(getObjectType()); // else implement this method in subclass
+        describe();
+
+        //todo: dont have examiner to pass in to ifc
+        if (getObjectType()->canXamine()) {
+                log_end(":");
+                getObjectType()->xamine(this, this);
+                log_begin("");
+        }
+}
+
+sound_t *Object::get_movement_sound()
+{
+        return NULL_SOUND;
+}
+
+class Object *Object::clone()
+{
+        // gmcnutt: added support for an optional quantity field for placed
+        // objects.
+
+        class Object *obj;
+
+        obj = getObjectType()->createInstance();
+        obj->setPlace(getPlace());
+        obj->setX(getX());
+        obj->setY(getY());
+
+        // FIXME: should assign the new object a unique script tag
+
+        return obj;
+}
+
+//////////////////////////////////////////////////
+
+bool Object::isType(int classID) 
+{
+        return (classID == OBJECT_ID);
+}
+int Object::getType() 
+{
+        return OBJECT_ID;
+}
+
+Object::Object()
+{
+        type = NULL;
+        setup();
+}
+
+Object::Object(class ObjectType * type) 
+{
+        this->type = type;
+        setup();
+}
+
+void Object::setup()
+{
+        int i;
+
+        clink     = NULL;
+        turn_list = NULL;
+
+        for (i = 0; i < OBJ_NUM_HOOKS; i++) {
+                hook_list_init(&hooks[i]);
+        }
+
+        x               = -1;
+        y               = -1;
+        place           = NULL;
+        selected        = false;
+        destroyed       = false;
+        tag             = 0;
+        action_points   = 0; /* FIXME: assumes no debt */
+        control_mode    = CONTROL_MODE_AUTO;
+        camera_attached = false;
+        hp              = 0;
+        is_on_map       = false;
+        conv            = NULL;
+        view            = NULL;
+        saved           = 0;
+        handle          = 0;
+        refcount        = 0;
+        count           = 1;
+        gob             = NULL;
+        current_sprite  = NULL;
+        opacity         = false;
+        light           = 0;
+        temporary       = false;
+        forceEffect     = false;
+        pclass          = PCLASS_NONE;
+        ttl             = -1; // everlasting by default
+        started         = false;
+        facing          = SPRITE_DEF_FACING;
+        ignoreTimeStop  = false;
+        submerged       = false;
+        portrait        = NULL;
+
+        if (getObjectType() && ! getObjectType()->isVisible())
+                visible = 0;
+        else
+                visible = 1;
+
+        // Four is the typical max number of frames, so using more will not
+        // help (it won't hurt either, sprites.c will ensure the frame is
+        // within what the sprite will actually support).
+        sprite_frame = rand() % 4;
+}
+
+Object::~Object()
+{
+        int i;
+
+        if (refcount) {
+                dbg("refcount=%d\n", refcount);
+                assert(! refcount);
+        }
+
+        //dbg("destroying %d %08lx %s\n", refcount, this, getName());
+
+        if (handle) {
+                session_rm(Session, handle);
+                handle = 0;
+        }
+        if (tag) {
+                free(tag);
+                tag = 0;
+        }
+
+        if (gob)
+                gob_del(gob);
+
+        if (getView()) {
+                rmView();
+                mapDestroyView(getView());
+                setView(NULL);                
+        }                
+
+        if (conv) {
+                conv_unref(conv);
+        }
+
+        // For each type of hook...
+        for (i = 0; i < OBJ_NUM_HOOKS; i++) {
+
+                // Shouldn't be destroying the object while one of its hook
+                // lists is locked.
+                assert(! hook_list_locked(&hooks[i]));
+
+                // This is a hack to workaround a bug due to a design flaw. A
+                // request has been logged to fix the design flaw [SF
+                // 1568398]. It will be a "deep" fix, and I expect it to add
+                // lots of new bugs, so I'm going to see if this relatively
+                // easy change will get us by a bit longer.
+                //
+                // The bug is this: we land here in the process of a
+                // session_del() call. Some of our effects have already been
+                // destroyed. In hookForEach() it will inspect some of these
+                // effects, not knowing that they are destroyed, and cause a
+                // crash. So instead of using hookForEach() I'm going to
+                // destroy the lists by hand right here without calling any
+                // hook removal closures or anything like that.
+                struct list *lptr;
+                struct hook_list *hl;
+                hl = &hooks[i];
+                lptr = hook_list_first(hl);
+                while (lptr != hook_list_end(hl)) {
+                        hook_entry_t *he = outcast(lptr, hook_entry_t, list);
+                        lptr = lptr->next;
+                        list_remove(&he->list);
+                        hook_entry_del(he);
+                }
+        }
+}
+
+int Object::getX()
+{
+        return x;
+}
+
+int Object::getY()
+{
+        return y;
+}
+
+struct place *Object::getPlace()
+{
+        return place;
+}
+
+struct sprite *Object::getSprite()
+{
+        if (current_sprite)
+                return current_sprite;
+        if (type)
+                return type->getSprite();
+        return NULL;
+}
+
+bool Object::isSelected()
+{
+        return selected;
+}
+
+enum layer Object::getLayer(void)
+{
+        // subtle: ~Being runs, calls ~Object, calls hookForEach to delete all
+        // the hooks, but there's an invalid hook which gets it's rm closure
+        // invoked. In that closure it calls kern-obj-is-being, which lands us
+        // here instead of Being::getLayer() because of where we are in the
+        // destructor chain, and Being's have no object type... hopefully since
+        // the object is being destroyed it doesn't really matter what the
+        // layer is.
+        if (getObjectType())
+                return getObjectType()->getLayer();
+        else
+                return null_layer;
+}
+
+const char *Object::getName(void)
+{
+        if (type)
+                return type->getName();
+        return "<no type>";
+}
+
+class ObjectType *Object::getObjectType()
+{
+        return type;
+}
+
+bool Object::isDestroyed()
+{
+        return destroyed;
+}
+
+
+void Object::setX(int x)
+{
+        this->x = x;
+}
+
+void Object::setY(int y)
+{
+        this->y = y;
+}
+
+void Object::changeX(int dx)
+{
+        this->x += dx;
+}
+
+void Object::changeY(int dy)
+{
+        this->y += dy;
+}
+
+void Object::setPlace(struct place *place)
+{
+        this->place = place;
+}
+
+void Object::select(bool val)
+{
+        if (val == isSelected())
+                return;
+
+        if (val) {
+                mapSetSelected(this);
+        } else if (isSelected()) {
+                mapSetSelected(NULL);
+        }
+
+        selected = val;
+        mapUpdateTile(getPlace(), getX(), getY());        
+        //mapUpdate(0);
+}
+
+void Object::destroy()
+{
+        destroyed = true;
+        if (isSelected())
+                select(false);
+        remove();
+}
+
+int Object::getLight()
+{
+        return light;
+}
+
+void Object::exec()
+{
+        startTurn();
+        if (getObjectType()->canExec())
+                getObjectType()->exec(this);
+        endTurn(); // warn: might destroy this!
+        Object::decrementTTL(this); // might destroy the object!
+}
+
+void Object::synchronize()
+{
+}
+
+bool Object::isVisible()
+{
+        //return getObjectType()->isVisible();
+        return visible > 0;
+}
+
+void Object::setVisible(bool val)
+{
+       if (val)
+               visible++;
+       else {
+               visible--;
+                if (visible < 0 && getName()) {
+                        printf("%s: %d\n", getName(), visible);
+                }
+        }
+}
+
+bool Object::isSubmerged()
+{
+        return submerged;
+}
+
+void Object::setSubmerged(bool val)
+{
+        submerged = val;
+}
+
+bool Object::isShaded()
+{
+        return isSubmerged();
+}
+
+void Object::setOpacity(bool val)
+{
+        // If the opacity is changing then invalidate the view mask cache in
+        // the surrounding area.
+        if (val != opacity && isOnMap())
+                vmask_invalidate(getPlace(), getX(), getY(), 1, 1);                
+
+        opacity = val;
+}
+
+bool Object::isOpaque()
+{
+        return opacity;
+}
+
+bool Object::joinPlayer()
+{
+        return false;
+}
+
+int Object::getActivity()
+{
+        return 0;
+}
+
+int Object::getActionPointsPerTurn()
+{
+        int baseAP = (int)(getSpeed() * session_get_time_accel());
+
+        // If 'Quicken' is in effect then give player-controlled objects bonus
+        // action points per turn.
+        if (Quicken > 0 && isPlayerControlled()) {
+                return baseAP * 2;
+        }
+
+        // If 'TimeStop' is in effect then give action points ONLY to
+        // player-controlled objects.
+        if (TimeStop && ! isPlayerControlled()) {
+                return 0;
+        }
+
+        return baseAP;
+}
+
+void Object::applyEffect(closure_t *effect)
+{
+        closure_exec(effect, "p", this);
+}
+
+void Object::burn()
+{
+}
+
+void Object::sleep()
+{
+}
+
+sound_t *Object::getDamageSound()
+{
+        return NULL_SOUND;
+}
+
+void Object::damage(int amount)
+{
+        // Paint the red "*" damage symbol over the character's icon on the map
+        if (isOnMap()) {
+                mapPaintDamage(getX(), getY());        
+                sound_play(getDamageSound(), SOUND_MAX_VOLUME);
+        }
+
+        runHook(OBJ_HOOK_DAMAGE, 0);
+}
+
+void Object::inflictDamage(int amount, class Character *attacker)
+{
+    damage(amount);
+}
+
+int Object::getActionPoints()
+{
+        return action_points;
+}
+
+void Object::decActionPoints(int points)
+{
+        setActionPoints(action_points - points);
+}
+
+void Object::endTurn()
+{
+       if (action_points > 0)
+       {
+               setActionPoints(0);
+       }
+}
+
+void Object::startTurn()
+{
+        setActionPoints(action_points + getActionPointsPerTurn());
+        runHook(OBJ_HOOK_START_OF_TURN, 0);
+}
+
+int Object::getSpeed()
+{
+        return getObjectType()->getSpeed();
+}
+
+int Object::getRequiredActionPoints()
+{
+        return getObjectType()->getRequiredActionPoints();
+}
+
+bool Object::isOnMap()
+{
+        return is_on_map;
+}
+
+bool Object::isDead()
+{
+        return false;
+}
+
+enum control_mode Object::getControlMode()
+{
+        return control_mode;
+}
+
+void Object::setControlMode(enum control_mode mode)
+{
+    control_mode = mode;
+}
+
+void Object::attachCamera(bool val)
+{
+        if (camera_attached == val)
+                return;
+
+        camera_attached = val;
+
+        if (val)
+                mapAttachCamera(this);
+        else
+                mapDetachCamera(this);
+}
+
+bool Object::isCameraAttached()
+{
+        return camera_attached;
+}
+
+bool Object::isTurnEnded()
+{
+        return (getActionPoints() <= 0 ||
+                isDead() ||
+                Quit);
+}
+
+bool Object::isPlayerPartyMember()
+{
+        return false;
+}
+
+bool Object::addToInventory(class Object *object)
+{
+        return false;
+}
+
+bool Object::hasInInventory(class ObjectType *object)
+{
+        return false;
+}
+
+void Object::heal(int amount)
+{
+        amount = min(amount, getMaxHp() - hp);
+        hp += amount;
+}
+
+bool Object::isPlayerControlled()
+{
+        return false;
+}
+
+int Object::getMaxHp()
+{
+        return getObjectType()->getMaxHp();
+}
+
+int Object::getHp()
+{
+        return hp;
+}
+
+bool Object::isCompanionOf(class Object *other)
+{
+        return false;
+}
+
+int Object::getPclass()
+{
+        return pclass;
+}
+
+void Object::setPclass(int val)
+{
+        pclass = val;
+}
+
+int Object::getMovementCost(int pclass)
+{        
+        if (pclass == PCLASS_NONE)
+                return 0;
+
+        struct mmode *mmode = getMovementMode();
+        if (! mmode)
+                return PTABLE_IMPASSABLE;
+
+        return ptable_get(session_ptable(), mmode->index, pclass);
+}
+
+bool Object::isPassable(int pclass)
+{
+        return (getMovementCost(pclass) != PTABLE_IMPASSABLE);
+}
+
+bool Object::putOnMap(struct place *new_place, int new_x, int new_y, int r,
+                      int flags)
+{
+        // --------------------------------------------------------------------
+        // Put an object on a map. If possible, put it at (new_x, new_y). If
+        // that's not possible then put it at some other (x, y) such that:
+        // 
+        // o (x, y) is with radius r of (new_x, new_y)
+        //
+        // o The object can find a path from (x, y) to (new_x, new_y)
+        //
+        // If no such (x, y) exists then return false without placing the
+        // object.
+        // --------------------------------------------------------------------
+
+        char *visited;
+        char *queued;
+        bool ret = false;
+        int i;
+        int rx;
+        int ry;
+        int *q_x;
+        int *q_y;
+        int index;
+        int q_head;
+        int q_tail;
+        int q_size;
+        int x_offsets[] = { -1, 1, 0, 0 };
+        int y_offsets[] = { 0, 0, -1, 1 };
+        
+        printf("Putting %s near (%d %d)\n", getName(), new_x, new_y);
+
+        // --------------------------------------------------------------------
+        // Although the caller specified a radius, internally I use a bounding
+        // box. Assign the upper left corner in place coordinates. I don't
+        // *think* I have to worry about wrapping coordinates because all the
+        // place_* methods should do that internally.
+        // --------------------------------------------------------------------
+
+        rx = new_x - (r / 2);
+        ry = new_y - (r / 2);
+
+        // --------------------------------------------------------------------
+        // Initialize the 'visited' table and the coordinate search queues. The
+        // queues must be large enough to hold all the tiles in the bounding
+        // box, plus an extra ring around it. The extra ring is for the case
+        // where we enqueue the neighbors of tiles that are right on the edge
+        // of the bounding box. We won't know the neighbors are bad until we
+        // pop them off the queue and check them.
+        // --------------------------------------------------------------------
+
+        q_size = r * r;
+
+        visited = (char*)calloc(sizeof(char), q_size);
+        if (NULL == visited)
+                return false;
+                
+        q_x = (int*)calloc(sizeof(int), q_size);
+        if (NULL == q_x) {
+                goto free_visited;
+        }
+
+        q_y = (int*)calloc(sizeof(int), q_size);
+        if (NULL == q_y) {
+                goto free_q_x;
+        }
+
+        queued = (char*)calloc(sizeof(char), q_size);
+        if (NULL == queued)
+                goto free_q_y;
+
+        // --------------------------------------------------------------------
+        // Enqueue the preferred location to start the search.
+        // --------------------------------------------------------------------
+
+#define INDEX(x,y) (((y)-ry) * r + ((x)-rx))
+
+        q_head        = 0;
+        q_tail        = 0;
+        q_x[q_tail]   = new_x;
+        q_y[q_tail]   = new_y;
+        index         = INDEX(new_x, new_y);
+        assert(index >= 0);
+        assert(index < q_size);
+        queued[index] = 1;
+        q_tail++;
+
+        // --------------------------------------------------------------------
+        // Run through the search queue until it is exhausted or a safe
+        // position has been found.
+        // --------------------------------------------------------------------
+
+        while (q_head != q_tail) {
+
+                // ------------------------------------------------------------
+                // Dequeue the next location to check.
+                // ------------------------------------------------------------
+
+                new_x = q_x[q_head];
+                new_y = q_y[q_head];
+                q_head++;
+
+                printf("Checking (%d,%d)...", new_x, new_y);
+
+                // ------------------------------------------------------------
+                // Has the location already been visited? (If not then mark it
+                // as visited now).
+                // ------------------------------------------------------------
+                
+                index = INDEX(new_x, new_y);
+                assert(index >= 0);
+                assert(index < q_size);
+
+                if (0 != visited[index]) {
+                        printf("already checked\n");
+                        continue;
+                }
+                visited[index] = 1;
+
+                // ------------------------------------------------------------
+                // Is the location off the map or impassable?
+                // ------------------------------------------------------------
+                
+                if (place_off_map(new_place, new_x, new_y) ||
+                    ! place_is_passable(new_place, new_x, new_y, this, flags)){
+                        continue;
+                }
+
+                // ------------------------------------------------------------
+                // Is the location occupied or hazardous?
+                // ------------------------------------------------------------
+
+                if ((! (flags & PFLAG_IGNOREBEINGS) &&
+                     place_is_occupied(new_place, new_x, new_y)) ||
+                    (! (flags & PFLAG_IGNOREHAZARDS) &&
+                     place_is_hazardous(new_place, new_x, new_y))) {
+
+                        printf("occupied or hazardous\n");
+
+                        // ----------------------------------------------------
+                        // This place is not suitable, but its neighbors might
+                        // be. Put them on the queue.
+                        // ----------------------------------------------------
+
+                        for (i = 0; i < array_sz(x_offsets); i++) {
+
+                                int neighbor_x;
+                                int neighbor_y;
+                                int neighbor_index;
+
+                                neighbor_x = new_x + x_offsets[i];
+                                neighbor_y = new_y + y_offsets[i];
+
+                                // --------------------------------------------
+                                // Is the neighbor outside the search radius?
+                                // --------------------------------------------
+
+                                if (neighbor_x < rx        ||
+                                    neighbor_y < ry        ||
+                                    neighbor_x >= (rx + r) ||
+                                    neighbor_y >= (ry + r)) {
+                                        continue;
+                                }
+                                
+                                // --------------------------------------------
+                                // Has the neighbor already been queued?
+                                // --------------------------------------------
+
+                                neighbor_index = INDEX(neighbor_x, neighbor_y);
+                                assert(neighbor_index >= 0);
+                                assert(neighbor_index < (q_size));
+
+                                if (queued[neighbor_index])
+                                        continue;
+
+                                // --------------------------------------------
+                                // Enqueue the neighbor
+                                // --------------------------------------------
+
+                                assert(q_tail < (q_size));
+
+                                q_x[q_tail] = neighbor_x;
+                                q_y[q_tail] = neighbor_y;
+                                q_tail++;
+                                queued[neighbor_index] = 1;
+                        }
+                        
+                        continue;
+                }
+
+                // ------------------------------------------------------------
+                // I've found a good spot, and I know that I can pathfind back
+                // to the preferred location from here because of the manner in
+                // which I found it.
+                //
+                // Note: we don't want to activate step triggers while doing
+                // this. One example of why this is bad is if we get here by
+                // coming through a moongate on a town map. If the moongate is
+                // in a state where it leads to itself we could end up
+                // re-entering it with the relocate call below if we allowed
+                // stepping.
+                // ------------------------------------------------------------
+
+                printf("OK!\n");
+                relocate(new_place, new_x, new_y, REL_NOSTEP, NULL);
+                ret = true;
+
+                goto done;
+        }
+
+        // --------------------------------------------------------------------
+        // Didn't find anyplace suitable. Return false. If the caller wants to
+        // force placement I'll leave it to their discretion.
+        // --------------------------------------------------------------------
+
+        printf("NO PLACE FOUND!\n");
+
+ done:
+        free(queued);
+ free_q_y:
+        free(q_y);
+ free_q_x:
+        free(q_x);
+ free_visited:
+        free(visited);
+
+        return ret;
+
+}
+
+struct mview *Object::getView()
+{
+        return view;
+}
+
+int Object::getVisionRadius()
+{
+        return 0;
+}
+
+void Object::addView()
+{
+        if (NULL != getView()) {
+                mapAddView(getView());
+                updateView();
+        }
+}
+
+void Object::rmView()
+{
+        if (NULL != getView()) {
+                mapRmView(getView());
+        }
+}
+
+void Object::updateView()
+{
+        assert(isOnMap());
+
+        if (NULL != getView()) {
+                mapCenterView(getView(), getX(), getY());
+                mapSetRadius(getView(), min(getVisionRadius(), MAX_VISION_RADIUS));
+                mapSetDirty();
+        }
+}
+
+void Object::setView(struct mview *new_view)
+{
+        view = new_view;
+}
+
+void Object::changePlaceHook()
+{
+}
+
+int Object::getDx()
+{
+        return dx;
+}
+
+int Object::getDy()
+{
+        return dy;
+}
+bool Object::canWanderTo(int newx, int newy)
+{
+        return true;
+}
+enum MoveResult Object::move(int dx, int dy)
+{
+        return NotApplicable;
+}
+
+void Object::save(struct save *save)
+{
+        // Create the object within a 'let' block
+        save->enter(save, "(let ((kobj (kern-mk-obj %s %d\n", 
+                    getObjectType()->getTag(), 
+                    getCount());
+        saveHooks(save);
+        save->write(save, ")))\n");
+
+        // Assign the tag.
+        if (tag) {
+                save->write(save, "(kern-tag '%s kobj)\n", tag);
+        }
+
+        // Save the gob binding.
+        if (getGob()) {
+                save->enter(save, "(bind kobj\n");
+                gob_save(getGob(), save);
+                save->exit(save, ")\n");
+        }
+
+        // Save time-to-live.
+        if (getTTL() != -1) {
+                save->write(save, "(kern-obj-set-ttl kobj %d)\n",
+                            getTTL());
+        }
+
+        // Set the custom sprite.
+        if (current_sprite) {
+                save->enter(save, "(kern-obj-set-sprite kobj\n");
+                sprite_save(current_sprite, save);
+                save->exit(save, ")\n");
+        }
+
+        // Set the facing
+        if (SPRITE_DEF_FACING != facing) {
+                save->write(save, "(kern-obj-set-facing kobj %d)\n", facing);
+        }
+
+        // Set the ignore-time-stop flag
+        if (ignoreTimeStop) {
+                save->write(save, "(kern-obj-set-ignore-time-stop kobj #t)\n");
+        }
+
+        // Set the submerged flag
+        if (submerged) {
+                save->write(save, "(kern-obj-set-submerged kobj #t)\n");
+        }
+
+        // Close the 'let' block, returning kobj as the last thing evaluated.
+        save->exit(save, "kobj)\n");
+
+}
+
+
+#define VALID_HOOK_ID(id) ((id) >= 0 && (id) < OBJ_NUM_HOOKS)
+
+void Object::hookForEach(int hook_id, 
+                         int (*cb)(struct hook_entry *entry, void *data),
+                         void *data)
+{
+        struct list *elem;
+        struct hook_list *hl;
+        int locked;
+
+        //dbg("hookForEach entry\n");
+
+        assert(VALID_HOOK_ID(hook_id));
+        hl = &hooks[hook_id];
+
+        // Lock the hook list to prevent any removals or entry deletions while
+        // we're running it.
+        locked = hook_list_trylock(hl);
+
+        elem = hook_list_first(hl);
+        while (elem != hook_list_end(hl)) {
+        
+                hook_entry_t *entry;
+
+                entry = outcast(elem, hook_entry_t, list);
+                elem = elem->next;
+
+                // Check if the entry is invalid. Invalid entries are entries
+                // that somebody tried to remove while we had the hook list
+                // locked. Since we have the lock, we can remove/delete them
+                // now.
+                if (hook_entry_is_invalid(entry)) {
+                        if (locked) {
+                                //dbg("hookForEach: delete %p\n", entry);
+                                if (entry->effect->rm)
+                                        closure_exec(entry->effect->rm, "lp", 
+                                                     hook_entry_gob(entry), 
+                                                     this);
+                                list_remove(&entry->list);
+                                hook_entry_del(entry);
+                        }
+                        continue;
+                }
+
+                // Invoke the callback on the hook entry... this is the part
+                // that does anything interesting. If it returns non-zero then
+                // we skip running the rest of the hooks.
+                if (cb(entry, data))
+                        break;
+                        
+                if (isDestroyed())
+                        break;
+        }
+
+        hook_list_tryunlock(hl, locked);
+        //dbg("hookForEach exit\n");
+
+}
+
+static int object_start_effect(struct hook_entry *entry, void *data)
+{
+        if (entry->effect->restart
+            && ! hook_entry_started(entry)) {
+                hook_entry_set_started(entry);
+                closure_exec(entry->effect->restart, "lp", hook_entry_gob(entry),
+                             data);
+        }
+        return 0;
+}
+
+void Object::start(void)
+{
+        int i;
+
+        // Don't start effects multiple times.
+        if (started) {
+                return;
+        }
+        started = true;
+
+        forceEffect = true;
+        for (i = 0; i < OBJ_NUM_HOOKS; i++) {
+                hookForEach(i, object_start_effect, this);
+        }
+        forceEffect = false;
+}
+
+struct add_hook_hook_data {
+        struct effect *effect;
+        char reject : 1;
+};
+
+int object_run_add_hook_hook(hook_entry_t *entry, void *data)
+{
+        struct add_hook_hook_data *context;
+        context = (struct add_hook_hook_data *)data;
+        if (entry->effect->exec &&
+            closure_exec(entry->effect->exec, "lp", hook_entry_gob(entry),
+                         context->effect))
+                context->reject = 1;
+        return context->reject;
+}
+
+int object_find_effect(hook_entry_t *entry, void *data)
+{
+        struct add_hook_hook_data *context;
+        context = (struct add_hook_hook_data *)data;
+        if (entry->effect == context->effect)
+                context->reject = 1;
+        return context->reject;
+}
+
+bool Object::addEffect(struct effect *effect, struct gob *gob)
+{
+        hook_entry_t *entry;
+        struct add_hook_hook_data data;
+        int hook_id = effect->hook_id;
+        
+        assert(VALID_HOOK_ID(effect->hook_id));
+
+        // Hack: NPC's don't go through a keystroke handler. For these,
+        // substitute the start-of-turn-hook for the keystroke-hook.
+        if (effect->hook_id == OBJ_HOOK_KEYSTROKE &&
+            ! isPlayerControlled())
+                hook_id = OBJ_HOOK_START_OF_TURN;
+
+        // Use the same data structure to search for the effect and to check
+        // for countereffects.
+        data.effect = effect;
+        data.reject = 0;
+
+        // For non-cumulative effects Check if the effect is already applied.
+        if (! effect->cumulative) {
+                hookForEach(hook_id, object_find_effect, &data);
+                if (data.reject)
+                        return false;
+        }
+
+        // If we're starting up the object then "force" effects to be applied,
+        // without checking for immunities. This works around the
+        // script-kernel-script recursion that will otherwise occur, and which
+        // will make summoning creatures with native effects not work from the
+        // script.
+        if (! forceEffect) {
+
+                // Run the add-hook entries to see if any of these will block
+                // this new entry from being added. This is how immunities are
+                // implemented, BTW.
+                hookForEach(OBJ_HOOK_ADD_HOOK, object_run_add_hook_hook, 
+                            &data);
+
+                if (data.reject) {
+                        return false;
+                }
+        }
+
+        // Run the "apply" procedure of the effect if it has one.
+        if (effect->apply) {
+                closure_exec(effect->apply, "lp", gob? gob->p : NULL, this);
+        }
+
+        entry = hook_entry_new(effect, gob);
+        hook_entry_set_started(entry);
+
+        // Roll to see if the character detects the effect (it won't show up in
+        // stats if not)
+        if (dice_roll("1d20") > effect->detect_dc) {
+                hook_entry_detect(entry);
+        }
+
+        hook_list_add(&hooks[hook_id], &entry->list);
+
+        // gmcnutt: I saw a crash on reload because we ran through this code
+        // before the player party was created in the new session, and the
+        // status window tried to access it because of this next call. I don't
+        // think we need to be updating status for every object, anyway, only
+        // party members.
+        if (isPlayerControlled()) {
+                statusRepaint();
+        }
+
+        return true;
+}
+
+void Object::restoreEffect(struct effect *effect, struct gob *gob, int flags, 
+                           clock_alarm_t expiration)
+{
+        hook_entry_t *entry;
+
+        assert(VALID_HOOK_ID(effect->hook_id));
+
+        // Note: do NOT run the "apply" procedure of the effect here (already
+        // tried this - causes script recursion while loading which as we know
+        // aborts the load prematurely). Instead the "restart" procedure will
+        // be run as part of our start() method, called on all objects near the
+        // end of session_load().
+
+        entry = hook_entry_new(effect, gob);
+        entry->flags = flags;
+        entry->expiration = expiration;
+        hook_list_add(&hooks[effect->hook_id], &entry->list);
+
+}
+
+struct object_run_hook_entry_data {
+        Object *obj;
+        const char *fmt;
+        va_list args;
+};
+
+static int object_run_hook_entry(struct hook_entry *entry, void *data)
+{
+        struct object_run_hook_entry_data *info;
+        info = (struct object_run_hook_entry_data *)data;
+
+        if (entry->effect->exec)
+                return closure_execlpv(entry->effect->exec, 
+                                       hook_entry_gob(entry),
+                                       info->obj,
+                                       info->fmt, 
+                                       info->args);
+        return 0;
+}
+
+void Object::runHook(int hook_id, const char *fmt, ...)
+{
+        struct object_run_hook_entry_data data;
+
+        data.obj = this;
+        data.fmt = fmt;
+        va_start(data.args, fmt);
+        hookForEach(hook_id, object_run_hook_entry, &data);
+        va_end(data.args);
+}
+
+void Object::saveHooks(struct save *save)
+{
+        int i;
+
+        save->write(save, ";; hooks\n");
+        save->enter(save, "(list\n");
+        for (i = 0; i < OBJ_NUM_HOOKS; i++) {
+                struct list *elem;
+                hook_list_for_each(&hooks[i], elem) {
+                        hook_entry_t *entry;
+                        entry = outcast(elem, hook_entry_t, list);
+                        hook_entry_save(entry, save);
+                }
+        }
+        save->exit(save, ")\n");
+}
+
+bool Object::removeEffect(struct effect *effect)
+{
+        struct list *elem;
+        struct hook_list *hl;
+        int hook_id = effect->hook_id;
+
+        assert(VALID_HOOK_ID(effect->hook_id));
+        
+        // Hack: NPC's don't go through a keystroke handler. For these,
+        // substitute the start-of-turn-hook for the keystroke-hook.
+        if (effect->hook_id == OBJ_HOOK_KEYSTROKE &&
+            ! isPlayerControlled())
+                hook_id = OBJ_HOOK_START_OF_TURN;
+
+        hl = &hooks[hook_id];
+
+        elem = hook_list_first(hl);
+        while (elem != hook_list_end(hl)) {
+                hook_entry_t *entry;
+
+                entry = outcast(elem, hook_entry_t, list);
+                elem = elem->next;
+
+                if (hook_entry_is_invalid(entry))
+                        // Already pending removal.
+                        continue;
+
+                if (effect == entry->effect) {
+
+                        // If the hook list is locked we can't remove/delete
+                        // the entry, but if we mark it invalid then the
+                        // runHooks() method will eventually clean it up.
+                        if (hook_list_locked(hl)) {
+                                hook_entry_invalidate(entry);
+                        } else {
+                                if (entry->effect->rm)
+                                        closure_exec(entry->effect->rm, "lp", 
+                                                     hook_entry_gob(entry), 
+                                                     this);
+                                list_remove(&entry->list);
+                                hook_entry_del(entry);
+                        }
+
+                        statusRepaint();
+
+                        return true;
+                }
+        }
+
+        return false;
+}
+
+int Object::getCount()
+{
+        return count;
+}
+
+void Object::setCount(int c)
+{
+        count = c;
+}
+
+bool ObjectType::isUsable()
+{
+        return (gifc_cap & GIFC_CAN_USE);
+}
+
+bool ObjectType::isReadyable()
+{
+        return isType(ARMS_TYPE_ID);
+}
+
+bool ObjectType::isMixable()
+{
+        return (gifc_cap & GIFC_CAN_MIX);
+}
+
+bool ObjectType::isCastable()
+{
+        return (gifc_cap & GIFC_CAN_CAST);
+}
+
+bool ObjectType::canExec()
+{
+        return (gifc_cap & GIFC_CAN_EXEC);
+}
+
+bool ObjectType::canStep()
+{
+        return (gifc_cap & GIFC_CAN_STEP);
+}
+
+bool ObjectType::canSense()
+{
+        return (gifc_cap & GIFC_CAN_SENSE);
+}
+
+bool ObjectType::canXamine()
+{
+        return (gifc_cap & GIFC_CAN_XAMINE);
+}
+
+bool ObjectType::canAttack()
+{
+        return (gifc_cap & GIFC_CAN_ATTACK);
+}
+
+bool ObjectType::canEnter()
+{
+        return (gifc_cap & GIFC_CAN_ENTER);
+}
+
+bool ObjectType::canGet()
+{
+        // Hack: arms types not converted over to use gifc's yet
+        return (gifc_cap & GIFC_CAN_GET);
+}
+
+bool ObjectType::canBuy()
+{
+        return (gifc_cap & GIFC_CAN_BUY);
+}
+
+bool ObjectType::canSearch()
+{
+        return (gifc_cap & GIFC_CAN_SEARCH);
+}
+
+bool ObjectType::canOpen()
+{
+        return (gifc_cap & GIFC_CAN_OPEN);
+}
+
+bool ObjectType::canBump()
+{
+        return (gifc_cap & GIFC_CAN_BUMP);
+}
+
+int ObjectType::open(Object *obj, Object *opener)
+{
+        return closure_exec(gifc, "ypp", "open", obj, opener);
+}
+
+int ObjectType::bump(Object *obj, Object *bumper)
+{
+        return closure_exec(gifc, "ypp", "bump", obj, bumper);
+}
+
+bool ObjectType::canHandle()
+{
+        return (gifc_cap & GIFC_CAN_HANDLE);
+}
+
+int ObjectType::handle(Object *obj, Object *handler)
+{
+        return closure_exec(gifc, "ypp", "handle", obj, handler);
+}
+
+bool ObjectType::canHitLocation()
+{
+        return (gifc_cap & GIFC_CAN_HIT_LOCATION);
+}
+
+int ObjectType::hitLocation(Object *obj, Object *attacker, Object *target, struct place *place, int x, int y, int dam)
+{
+        return closure_exec(gifc, "yppppddd", "hit-loc", obj, attacker, target, place, x, y, dam);
+}
+
+int ObjectType::step(Object *obj, Object *stepper)
+{
+        return closure_exec(gifc, "ypp", "step", obj, stepper);
+}
+
+int ObjectType::sense(Object *obj, Object *stepper)
+{
+        return closure_exec(gifc, "ypp", "sense", obj, stepper);
+}
+
+int ObjectType::xamine(Object *obj, Object *xaminer)
+{
+        return closure_exec(gifc, "ypp", "xamine", obj, xaminer);
+}
+
+int ObjectType::attack(Object *obj, Object *stepper)
+{
+        return closure_exec(gifc, "ypp", "attack", obj, stepper);
+}
+
+bool ObjectType::canOnAttack()
+{
+        return (gifc_cap & GIFC_CAN_ON_ATTACK);
+}
+
+int ObjectType::onAttack(Object *obj, Object *stepper)
+{
+        return closure_exec(gifc, "yp", "on-attack", stepper);
+}
+
+int ObjectType::enter(Object *obj, Object *stepper)
+{
+        return closure_exec(gifc, "ypp", "enter", obj, stepper);
+}
+
+int ObjectType::exec(Object *obj)
+{
+        return closure_exec(gifc, "yp", "exec", obj);
+}
+
+int ObjectType::use(Object *user)
+{
+        return closure_exec(gifc, "ypp", "use", this, user);
+}
+
+int ObjectType::cast(Object *caster)
+{
+        return closure_exec(gifc, "yp", "cast", caster);
+}
+
+int ObjectType::get(Object *obj, Object *getter)
+{
+        return closure_exec(gifc, "ypp", "get", obj, getter);
+}
+
+int ObjectType::buy(Object *buyer, int q)
+{
+        return closure_exec(gifc, "ypd", "buy", buyer, q);
+}
+
+int ObjectType::search(Object *obj, Object *searcher)
+{
+        return closure_exec(gifc, "ypp", "search", obj, searcher);
+}
+
+closure_t *ObjectType::getGifc()
+{
+        return gifc;
+}
+
+void ObjectType::setGifc(closure_t *g, int cap)
+{
+        // out with the old
+        if (gifc) {
+                closure_unref(gifc);
+                gifc = NULL;
+                gifc_cap = 0;
+        }
+
+        // in with the new
+        if (g) {
+                closure_ref(g);
+                gifc = g;
+                gifc_cap = cap;
+        }
+}
+
+void ObjectType::setGob(struct gob *g)
+{
+        if (gob) {
+                gob_unref(gob);
+                gob = 0;
+        }
+
+        if (g) {
+                gob = g;
+                gob_ref(g);
+        }
+}
+
+struct gob * ObjectType::getGob()
+{
+        return gob;
+}
+
+bool ObjectType::hasDescribeHook()
+{
+        return (gifc_cap & GIFC_CAN_DESCRIBE);
+}
+
+void ObjectType::runDescribeHook(Object *obj)
+{
+        closure_exec(gifc, "ypd", "describe", obj, obj->getCount());
+}
+
+bool ObjectType::isQuestItem()
+{
+        return questItemFlag;
+}
+
+void ObjectType::setQuestItemFlag(bool val)
+{
+        questItemFlag = val;
+}
+
+struct mmode *ObjectType::getMovementMode()
+{
+   return movementMode;
+}
+
+void ObjectType::setMovementMode(struct mmode *mmode)
+{
+       movementMode = mmode;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////
+// Object
+
+bool Object::add(ObjectType *type, int amount)
+{
+        return false; // subclasses will overload
+}
+
+bool Object::takeOut(ObjectType *type, int amount)
+{
+        return false; // subclasses will overload
+}
+
+bool Object::addFood(int amount)
+{
+        return false; // subclasses will overload
+}
+
+bool Object::addGold(int amount)
+{
+        return false; // subclasses will overload
+}
+
+void Object::setGob(struct gob *g)
+{
+        gob = g;
+}
+
+struct gob * Object::getGob()
+{
+        return gob;
+}
+
+void Object::setSprite(struct sprite *sprite)
+{
+        current_sprite = sprite;
+}
+
+void Object::step(Object *stepper)
+{        
+        if (! getObjectType() ||
+            ! getObjectType()->canStep())
+                return;
+
+        getObjectType()->step(this, stepper);
+}
+
+void Object::sense(Object *stepper)
+{        
+        if (! getObjectType() ||
+            ! getObjectType()->canSense())
+                return;
+
+        getObjectType()->sense(this, stepper);
+}
+
+void Object::attack(Object *stepper)
+{        
+        if (! getObjectType() ||
+            ! getObjectType()->canAttack())
+                return;
+
+        getObjectType()->attack(this, stepper);
+}
+
+void Object::onAttack(Object *user)
+{        
+        if (! getObjectType() ||
+            ! getObjectType()->canOnAttack())
+                return;
+
+        getObjectType()->onAttack(this, user);
+}
+
+struct conv *Object::getConversation()
+{
+        return conv;
+}
+
+void Object::setConversation(struct conv *val)
+{
+        // out with the old
+        if (conv) {
+                conv_unref(conv);
+                conv = NULL;
+        }
+
+        // in with the new
+        if (val) {
+                conv_ref(val);
+                conv = val;
+        }
+}
+
+bool Object::canEnter()
+{
+        return (getObjectType() && getObjectType()->canEnter());
+}
+
+void Object::enter(Object *enterer)
+{
+        getObjectType()->enter(this, enterer);
+}
+
+bool Object::canStep()
+{
+        return (getObjectType() && getObjectType()->canStep());
+}
+
+bool Object::canSense()
+{
+        return (getObjectType() && getObjectType()->canSense());
+}
+
+void Object::setLight(int val)
+{
+        light = val;
+        if (light < 0)
+                light = 0;
+}
+
+bool Object::isTemporary()
+{
+        return temporary;
+}
+
+void Object::setTemporary(bool val)
+{
+        temporary = val;
+}
+
+struct mmode *Object::getMovementMode()
+{
+        return getObjectType()->getMovementMode();
+}
+
+void Object::setMovementMode(struct mmode *mmode)
+{
+        // nop
+}
+
+Object *Object::getSpeaker()
+{
+        return this;
+}
+
+void Object::resetActionPoints()
+{
+        setActionPoints(0);
+}
+
+void Object::setActionPoints(int amount)
+{
+        action_points = amount;
+        if (isPlayerControlled()) {
+                statusRepaint();
+        }
+}
+
+void obj_inc_ref(Object *obj)
+{
+        obj->refcount++;
+#if 0
+        if (obj->getName() && ! strcmp(obj->getName(), "player party"
+                                       /*"The Wanderer"*/)) {
+                printf("obj_inc_ref: %d\n", obj->refcount);
+        }
+#endif
+}
+
+void obj_dec_ref(Object *obj)
+{
+        assert((obj)->refcount >= 0);
+        (obj)->refcount--;
+#if 0
+        if (obj->getName() && ! strcmp(obj->getName(), "player party"
+                                       /*"The Wanderer"*/)) {
+                printf("obj_dec_ref: %d\n", obj->refcount);
+        }
+#endif
+        if (! obj->refcount)
+                delete obj;
+}
+
+int Object::getTTL(void) { return ttl; }
+
+bool Object::surreptitiouslyRemove()
+{
+        // crasher fix: check for player party; this may be called on boot if
+        // the load file has (kern-obj-set-ttl kobj 0). That scenario happens
+        // when an object's ttl is expired but the player is still in LOS, and
+        // then the player saves the game.
+
+        if (!isOnMap()) {
+                return false;
+        }
+
+        if (player_party
+            && getPlace()==player_party->getPlace()
+            && (place_flying_distance(player_party->getPlace(),
+                                      player_party->getX(),
+                                      player_party->getY(),
+                                      getX(),
+                                      getY())
+                < player_party->getVisionRadius())
+            && place_in_los(player_party->getPlace(),
+                            player_party->getX(),
+                            player_party->getY(),
+                            getPlace(),
+                            getX(),
+                            getY())) {
+                return false;
+        }
+
+        remove();
+        return true;
+}
+
+void Object::setTTL(class Object *obj, int val)
+{
+        obj->ttl = val;
+        if (!obj->ttl) {
+                obj->surreptitiouslyRemove(); // may destroy obj!
+        }
+}
+
+void Object::decrementTTL(class Object *obj)
+{
+        // don't decrement if everlasting
+        if (-1==obj->getTTL())
+                return;
+
+        if (0==obj->getTTL()) {
+                obj->surreptitiouslyRemove(); // may destroy obj!
+                return;
+        }
+
+        obj->setTTL(obj, obj->getTTL() - 1); // may destroy obj!
+}
+
+bool Object::isStationary()
+{
+        return false;
+}
+
+bool Object::setFacing(int val)
+{
+       if (!sprite_can_face(getSprite(), val))
+               return false;
+       facing = val;
+       return true;
+}
+
+int Object::getFacing()
+{
+       return facing;
+}
+
+bool Object::ignoresTimeStop()
+{
+        return ignoreTimeStop;
+}
+
+void Object::setIgnoreTimeStop(bool val)
+{
+        ignoreTimeStop = val;
+}
+
+struct sprite *Object::getPortrait()
+{ 
+        return portrait; 
+}
+
+void Object::setPortrait(struct sprite *sprite) 
+{ 
+        portrait = sprite; 
+}
diff --git a/src/object.h b/src/object.h
new file mode 100644 (file)
index 0000000..e73aac3
--- /dev/null
@@ -0,0 +1,527 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef object_h
+#define object_h
+
+#include "clock.h"
+#include "list.h"
+#include "olist.h"
+#include "closure.h"
+#include "console.h"           // SAM: for DEBUG purposes...
+#include "sound.h"
+
+#include <assert.h>
+
+
+// Wrappers for session_add() and session_rm() that do the ref-counting.
+#define session_add_obj(session, obj, dtor, save, start)                      \
+        do {                                                                  \
+                obj_inc_ref((obj));                                           \
+                (obj)->handle = session_add((session), (obj), (dtor), (save), \
+                                            (start));                         \
+        } while (0)
+
+#define session_rm_obj(session, obj)                                          \
+        do {                                                                  \
+                session_rm((session), (obj)->handle);                         \
+                obj_dec_ref((obj));                                           \
+        } while (0)
+
+/* Hack: until movement modes implemented in objects */
+#define obj_mmode(obj) ((obj)->getMovementMode())
+
+/* Hooks id's */
+#define OBJ_HOOK_START_OF_TURN 0  /* after ap assigned at start of turn      */
+#define OBJ_HOOK_ADD_HOOK      1  /* whan a new effects is added             */
+#define OBJ_HOOK_DAMAGE        2  /* when the object takes damage            */
+#define OBJ_HOOK_KEYSTROKE     3  /* when PC is given a command              */
+#define OBJ_HOOK_NIL           4  /* never (effect just exists)              */
+#define OBJ_HOOK_ON_DEATH      5  /* character just died                     */
+#define OBJ_HOOK_READY_EQUIP   6  /* PC readies                              */
+#define OBJ_HOOK_UNREADY_EQUIP 7  /* PC unreadies                            */
+#define OBJ_HOOK_MOVE_DONE     8  /* character just moved                    */
+#define OBJ_HOOK_ATTACK_DONE   9  /* character just attacked                 */
+#define OBJ_HOOK_CAST_DONE     10 /* character just cast a spell             */
+#define OBJ_HOOK_DROP_DONE     11 /* character just dropped something        */
+#define OBJ_HOOK_YUSE_DONE     12 /* character just yused a skill            */
+#define OBJ_HOOK_GET_DONE      13 /* character just got something            */
+#define OBJ_HOOK_HANDLE_DONE   14 /* character just handled something        */
+#define OBJ_HOOK_OPEN_DONE     15 /* character just opened something         */
+#define OBJ_HOOK_READY_DONE    16 /* character finished equipping            */
+#define OBJ_HOOK_TALK_DONE     17 /* character finished talking              */
+#define OBJ_HOOK_USE_DONE      18 /* character finished using something      */
+#define OBJ_HOOK_MIX_DONE      19 /* character finished using something      */
+#define OBJ_HOOK_KAMP_START    20 /* character about to start camping        */
+#define OBJ_NUM_HOOKS          21 /* total number of object hooks            */
+
+/* Relocation flags. Used to avoid triggers in special cases. */
+#define REL_NOSTEP    (1<<0)                     /* don't trigger "step"     */
+#define REL_NOSENSE   (1<<1)                     /* don't trigger "sense"    */
+#define REL_NOTRIG    (REL_NOSTEP|REL_NOSENSE)   /* don't trigger anything   */
+
+// Note: if you change the layers you'll probably need to change the save
+//       file
+// Proper rendering depends on keeping these in order!
+enum layer {
+       null_layer       = 0,
+        tfeat_layer      = 1,
+       mech_layer       = 2,
+       portal_layer     = 3,
+       vehicle_layer    = 4,
+        bed_layer        = 5,
+       container_layer  = 6,
+       item_layer       = 7,
+       field_layer      = 8,
+       being_layer      = 9,
+       projectile_layer = 10,
+       cursor_layer     = 11
+};
+
+enum control_mode {
+        CONTROL_MODE_AUTO = 0,
+        CONTROL_MODE_PLAYER,
+        CONTROL_MODE_IDLE,
+        CONTROL_MODE_FOLLOW,
+        CONTROL_MODE_TASK
+};
+
+enum MoveResult {
+        MovedOk,
+        ExitedMap,
+        EngagedEnemy,
+        WasOccupied,
+        WasImpassable,
+        SlowProgress,
+        SwitchedOccupants,
+        CouldNotSwitchOccupants,
+        OffMap, // and no parent
+        NotFollowMode,
+        CantRendezvous,
+        NotApplicable,
+        ChangedFacing,
+        AvoidedHazard,
+        OutOfRange,
+        NoDestination,
+        UserCanceled,
+        StationaryObject,
+        NotInVehicle
+};
+
+struct inv_entry {
+       struct list list;
+       struct list auxlist;
+       int count;
+       int ref;
+       class ObjectType *type;
+};
+
+struct filter {
+        bool (*fx)(struct inv_entry *ie, void *fdata);
+        void *fdata;
+};
+
+typedef struct hook_entry {
+        struct list list;
+        struct effect *effect;
+        struct gob *gob;
+        clock_alarm_t expiration;
+        int flags;
+        char started : 1; /* unsaved flag */
+} hook_entry_t;
+
+class ObjectType {
+
+      public:
+       virtual bool isType(int classID);
+       virtual int getType();
+       ObjectType();
+        ObjectType(const char *tag, const char *name, struct sprite *sprite, 
+                   enum layer layer);
+       virtual ~ObjectType();
+       virtual bool init(char *tag, char *name, enum layer layer, 
+                          struct sprite * sprite);
+        virtual void setSprite(struct sprite *sprite);
+       virtual const char *getTag();
+       virtual const char *getName();
+       virtual struct sprite *getSprite();
+       virtual enum layer getLayer();
+       virtual class Object *createInstance();
+       virtual bool isVisible();
+       virtual void describe(Object *obj);
+        virtual int getSpeed();
+        virtual int getMaxHp();
+   virtual void setMovementMode(struct mmode *mmode);
+       virtual struct mmode *getMovementMode(); 
+       
+        // This might turn out to be too vague. We'll see.
+        virtual int getRequiredActionPoints();
+
+        // This version of describe() can't run any hooks; it's used for
+        // inventory descriptions, where there are no object instances.
+        void describeType(int count);
+
+        bool isUsable();    // items, etc
+        bool isReadyable(); // arms
+        bool isMixable();   // reagents
+        bool isCastable();  // spells
+        bool canExec();     // mechs, etc
+        bool canGet();
+        bool canOpen();
+        bool canStep();
+        bool canHandle();
+        bool canSense();
+        bool canXamine();
+        bool canAttack();
+        bool canOnAttack();
+        bool canEnter();
+        bool canBump(); // attempted entry onto same tile
+        bool canHitLocation(); // weapon hitting a target location
+        bool canBuy(); // has a hook for 'buy'
+        bool canSearch(); // has a hook for 'search'
+        bool isQuestItem();
+
+        // These return the result of closure_exec:
+        int use(Object *user);
+        int exec(Object *obj);
+        int get(Object *obj, Object *getter);
+        int open(Object *obj, Object *opener);
+        int step(Object *obj, Object *stepper);
+        int sense(Object *obj, Object *stepper);
+        int xamine(Object *obj, Object *xaminer);              
+        int handle(Object *obj, Object *handler);
+        int attack(Object *obj, Object *attacker);
+        int onAttack(Object *obj, Object *attacker);
+        int enter(Object *obj, Object *enterer);
+        int cast(Object *caster);
+        int bump(Object *obj, Object *bumper);
+        int hitLocation(Object *obj, Object *attacker, Object *target, struct place *place, int x, int y, int dam);
+        int buy(Object *buyer, int q);
+        int search(Object *obj, Object *searcher);
+
+        closure_t *getGifc();
+        void setGifc(closure_t *gifc, int cap);
+
+        void setPluralName(char *val);
+        void setGob(struct gob *gob);
+        struct gob * getGob();
+        void setQuestItemFlag(bool val);
+
+
+      protected:
+       char *tag;
+       char *name;
+       struct sprite *sprite;
+       enum layer layer;
+        int speed;
+        int required_action_points;
+        int max_hp;
+
+        /* ghulscript-interface (gifc) */
+        closure_t *gifc;
+        int gifc_cap;
+        struct gob *gob;
+        struct mmode *movementMode;
+
+ private:
+        bool hasDescribeHook();
+        void runDescribeHook(Object *obj);
+
+        char *pluralName;
+        char *getPluralName();
+        bool questItemFlag;
+};
+
+class Object {
+
+      public:
+       virtual bool isType(int classID);
+       virtual int getType();
+
+       Object(class ObjectType * type); // preferred constructor
+
+        Object();
+       virtual ~Object();
+       virtual void init(int x, int y, struct place *place,
+                         class ObjectType * type);
+       virtual void init(class ObjectType * type);
+
+        virtual sound_t *getDamageSound();
+        virtual sound_t *get_movement_sound();
+        virtual int getActivity();
+        virtual enum control_mode getControlMode();
+        virtual int getCount();
+        virtual int getHp();
+       virtual enum layer getLayer(void);
+       virtual int getLight();
+        virtual int getMaxHp();
+       virtual const char *getName(void);
+       virtual class ObjectType *getObjectType();
+       virtual struct place *getPlace();
+        virtual int getRequiredActionPoints();
+        virtual int getSpeed();
+        virtual struct mview *getView();
+       virtual int getVisionRadius();
+       virtual int getX();
+       virtual int getY();
+        virtual int getDx();
+        virtual int getDy();
+
+        virtual bool isCompanionOf(class Object *other);
+       virtual bool isDestroyed();
+        virtual bool isOnMap();
+        virtual bool isDead();
+       virtual bool isSelected();
+        virtual bool isTurnEnded();
+        virtual bool isCameraAttached();
+        virtual bool isPlayerPartyMember();
+        virtual bool isPlayerControlled();
+        virtual bool canWanderTo(int x, int y);
+
+        virtual void addView();
+        virtual void rmView();
+        virtual void updateView();
+        virtual bool addToInventory(class Object *object);
+        virtual bool hasInInventory(class ObjectType *type);
+        virtual void attachCamera(bool val);
+       virtual void heal(int amount);
+        virtual void save(struct save *save);
+        virtual void setLight(int val);
+        virtual void setOnMap(bool val);
+       virtual void setX(int x);
+       virtual void setY(int y);
+       virtual void changeX(int dx);
+       virtual void changeY(int dy);
+        virtual void setCount(int count);
+       virtual void setPlace(struct place *place);
+       virtual void select(bool val);
+       virtual void destroy();
+       virtual void relocate(struct place *newplace, int newx, int newy, 
+                              int flags = 0,
+                              struct closure *place_switch_hook = NULL);
+       virtual void remove();
+        virtual void start();
+       virtual bool isVisible();
+        virtual void setVisible(bool val);
+       virtual bool isSubmerged();
+        virtual void setSubmerged(bool val);
+       virtual bool isShaded();
+       virtual void describe();
+               virtual void examine();
+       virtual void paint(int sx, int sy);
+        virtual class Object *clone();
+       virtual bool joinPlayer(void);     
+       virtual void synchronize();
+        virtual void exec();
+        virtual int getActionPointsPerTurn();
+        virtual void applyEffect(closure_t *effect);
+        virtual int getActionPoints();
+        virtual void resetActionPoints();
+        virtual void burn();
+        virtual void sleep();
+        virtual void damage(int amount);
+        virtual void inflictDamage(int amount,class Character *attacker);
+        virtual void decActionPoints(int points);
+        virtual void setActionPoints(int amount);
+        virtual void endTurn();
+        virtual void startTurn();
+        virtual void setControlMode(enum control_mode);
+        virtual bool putOnMap(struct place *place, int x, int y, int r, 
+                              int flags /* PFLAG_* (see place.h) */);
+        virtual void setView(struct mview *view);
+        virtual void changePlaceHook();
+        virtual MoveResult move(int dx, int dy);
+
+        // Hook/effect API.
+        virtual void hookForEach(int hook_id, 
+                                 int (*cb)(struct hook_entry *entry, 
+                                           void *data),
+                                 void *data);
+        virtual bool addEffect(struct effect *effect, struct gob *gob);
+        virtual void restoreEffect(struct effect *effect, struct gob *gob, 
+                                   int flags, clock_alarm_t expiration);
+        virtual void runHook(int hook_id, const char *fmt, ...);
+        virtual void saveHooks(struct save *save);
+        virtual bool removeEffect(struct effect *effect);
+        
+
+        // Virtual container ops
+        virtual bool addFood(int quantity);
+        virtual bool addGold(int quantity);
+        virtual bool add(ObjectType *type, int amount);
+        virtual bool takeOut(ObjectType *type, int amount);        
+
+        // ghulscript-object (gob) access.
+        void setGob(struct gob *gob);
+        struct gob * getGob();
+
+        // State variables affected by script execution
+        virtual void setSprite(struct sprite *sprite);
+       virtual struct sprite *getSprite(); 
+
+        virtual void setOpacity(bool opaque);
+       virtual bool isOpaque();
+        virtual bool tryToRelocateToNewPlace(struct place *place, 
+                                             int x, int y,
+                                             struct closure *cutscene);
+
+        // Proxies into script signals
+        bool canEnter();
+        bool canStep();
+               bool canSense();
+        void step(Object *stepper);
+               void sense(Object *stepper);
+        void attack(Object *attacker);
+        void onAttack(Object *user);
+        void enter(Object *enterer);
+
+        // Conversation interface
+        void setConversation(struct conv *conv);
+        virtual struct conv *getConversation();
+        virtual Object *getSpeaker();
+
+        virtual bool isTemporary();
+        virtual void setTemporary(bool val);
+
+        virtual int getMovementCost(int pclass);
+        virtual struct mmode *getMovementMode();
+        virtual void setMovementMode(struct mmode *mmode);
+        virtual bool isPassable(int pclass);
+        virtual void setPclass(int val);
+        virtual int getPclass();
+        virtual bool isStationary();
+
+        int getTTL(void);
+        // These two might destroy the object so make them class methods:
+        static void setTTL(class Object *obj, int val);
+        static void decrementTTL(class Object *obj);
+
+        bool ignoresTimeStop();
+        void setIgnoreTimeStop(bool val);
+        
+        struct node *clink; // points back to node in container's list
+
+       char *tag;
+       struct list list;       // for the loader, not the place
+
+        struct node *turn_list; /* points back to node in place's turn list */
+
+        // The session handle for removing/checking the orphan list
+        void *handle;
+
+        // The session id of the last save.
+        int saved;
+
+        /* The reference count. Use the obj_inc_ref() and obj_dec_ref() macros
+         * to change this. obj_dec_ref() will destroy the object when this hits
+         * zero. */
+        int refcount;
+
+        bool setFacing(int facing);
+        int getFacing();
+        struct sprite *getPortrait();
+        void setPortrait(struct sprite *sprite);
+
+      protected:
+        virtual void setup();
+
+       class ObjectType * type;
+       int x;
+       int y;
+        int dx;
+        int dy;
+        int count;
+       struct place *place;
+       bool selected;
+       bool destroyed;
+        int action_points;
+        enum control_mode control_mode;
+        bool camera_attached;
+       int hp;
+        bool is_on_map;
+       struct conv *conv;
+        struct mview *view;
+        int light;
+        bool temporary;
+
+        struct hook_list {
+                struct list list;
+                int lock;
+        } hooks[OBJ_NUM_HOOKS];
+
+        // (Possibly null) pointer to this object's corresponding ghulscript
+        // object.
+        struct gob *gob;
+
+        // Used to shadow the ObjectType sprite for objects whose sprite is
+        // determined by their gob state (like mechs).
+        struct sprite *current_sprite;
+        bool opacity;
+
+        // Used for invisibility;
+        int visible;
+
+        // Forces addEffect() to add the given effect without allowing the
+        // "add-hook-hook" effects to prevent it. Used by start().
+        bool forceEffect;
+
+        // For fields, mechs and other objects that affect passability:
+        int pclass;
+
+        // Time to live: if > 0, this is decremented whenever the object
+        // executes a turn. When it falls to zero the object is removed from
+        // the map, which will destroy it once nothing else references
+        // it. Defaults to -1 (ie, infinite).
+        int ttl;
+
+ private:
+        bool surreptitiouslyRemove();
+        bool started;
+        void triggerSense(struct place *tilePlace, int tileX, int tileY);
+        void triggerStep(struct place *tilePlace, int tileX, int tileY);
+        void triggerOnTileEntry(struct place *tilePlace, int tileX, int tileY,
+                                int flags);
+        void triggerOnTileExit(struct place *tilePlace, int tileX, int tileY,
+                               int flags);
+        int facing;
+        bool ignoreTimeStop;
+
+        // Each object has its own sprite_frame, which breaks up the
+        // "synchronized dancing" problem. It also allows us to animate only
+        // player-controlled characters during Time Stop.
+        int sprite_frame;
+
+        // Used for critters that can go underwater.
+        bool submerged;
+
+        struct sprite *portrait;
+};
+
+#include "macros.h"
+BEGIN_DECL
+
+extern void obj_inc_ref(Object *obj);
+extern void obj_dec_ref(Object *obj);
+#define obj_dec_ref_safe(obj) do { if ((obj)) obj_dec_ref(obj); } while (0)
+
+END_DECL
+
+#endif                         // object_h
diff --git a/src/objectfreezer.c b/src/objectfreezer.c
new file mode 100644 (file)
index 0000000..488dee3
--- /dev/null
@@ -0,0 +1,154 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "objectfreezer.h"
+#include "tree.h"
+#include "list.h"
+#include <stdlib.h>
+#include <assert.h>
+
+struct objectfreezernode* new_objectfreezernode(char *key)
+{
+       objectfreezernode *newnode= (struct objectfreezernode *) malloc(sizeof(struct objectfreezernode));
+       assert(newnode);
+       newnode->treenode.key.s_key = (char *) malloc((strlen(key)+1) * sizeof(char));
+       assert(newnode->treenode.key.s_key);
+       strcpy(newnode->treenode.key.s_key,key);
+       newnode->treenode.key_type=tree_s_key;
+       newnode->treenode.left=NULL;
+       newnode->treenode.right=NULL;
+       newnode->treenode.p=NULL;
+       list_init(&(newnode->objectlist));
+       return newnode;
+}
+
+struct objectfreezerlist* new_objectfreezerlistnode(class Object *value, int x, int y)
+{
+       objectfreezerlist *newnode= (struct objectfreezerlist *) malloc(sizeof(struct objectfreezerlist));
+       assert(newnode);
+       newnode->objectlist.next=NULL;
+       newnode->objectlist.prev=NULL;
+       newnode->x=x;
+       newnode->y=y;
+       newnode->obj=value;
+       return newnode;
+}
+
+struct objectfreezernode* freezer_ensureFreezerTreeNode(char *key)
+{
+       struct tree* ofntree = tree_s_search(Session->freezer, key);
+       if (ofntree == NULL)
+       {
+               ofntree = (tree *)new_objectfreezernode(key);
+               tree_insert(&(Session->freezer),ofntree);
+       }
+       return (objectfreezernode *) ofntree;
+}
+
+void freezer_freezeObject(char *key, int x, int y, class Object *o)
+{
+       struct objectfreezernode *ofn = freezer_ensureFreezerTreeNode(key);
+       struct objectfreezerlist *ofln = new_objectfreezerlistnode(o,x,y);
+       list_add(&(ofn->objectlist),(list *)ofln);
+}
+
+class Object* freezer_thawObject(char* key,int* xout, int* yout)
+{
+       struct tree* ofntree = tree_s_search(Session->freezer, key);
+       if (ofntree == NULL)
+       {
+               return NULL;
+       }
+       struct objectfreezernode *ofn = (objectfreezernode *) ofntree;
+       struct objectfreezerlist *ofln = (objectfreezerlist *) ofn->objectlist.next;
+       list_remove((list *) ofln);
+       class Object* objtemp = ofln->obj;
+       *xout = ofln->x;
+       *yout = ofln->y;
+       free(ofln);
+       //check if that was the last entry- if so, delete tree node
+       if (list_empty(&(ofn->objectlist)))
+       {
+               tree_delete(&(Session->freezer), ofntree);
+               free(ofn->treenode.key.s_key);
+               free(ofn);
+       }
+       return objtemp;
+}
+
+void freezer_save(save_t *save)
+{
+       if (!Session->freezer)
+       {
+               return;
+       }
+       struct tree* ofntree= Session->freezer;
+       for (ofntree = tree_minimum(ofntree);ofntree;ofntree = tree_successor(ofntree))
+       {
+               struct objectfreezernode *ofn = (objectfreezernode *) ofntree;
+               struct list* ofllist;
+               list_for_each(&(ofn->objectlist),ofllist)
+               {
+                       struct objectfreezerlist *ofln = (objectfreezerlist *) ofllist;
+                       save->write(save, "(kern-obj-freeze \n");
+                       ofln->obj->save(save);
+                       save->write(save, " \"%s\" %d %d)\n",ofntree->key.s_key,ofln->x,ofln->y);
+               }
+       }
+}
+
+void freezer_del()
+{
+       struct tree* ofntree;
+       for(ofntree=Session->freezer;ofntree;ofntree=Session->freezer)
+       {
+               struct objectfreezernode *ofn = (objectfreezernode *) ofntree;
+               while (!list_empty(&(ofn->objectlist)))
+               {
+                       struct objectfreezerlist *ofln = (objectfreezerlist *) ofn->objectlist.next;
+                       list_remove((list *) ofln);
+                       free(ofln);
+               }
+               tree_delete(&(Session->freezer), ofntree);
+               free(ofn->treenode.key.s_key);
+               free(ofn);
+       }
+}
+
+void freezer_start_contents()
+{
+       if (!Session->freezer)
+       {
+               return;
+       }
+       struct tree* ofntree= Session->freezer;
+       for (ofntree = tree_minimum(ofntree);ofntree;ofntree = tree_successor(ofntree))
+       {
+               struct objectfreezernode *ofn = (objectfreezernode *) ofntree;
+               struct list* ofllist;
+               list_for_each(&(ofn->objectlist),ofllist)
+               {
+                       struct objectfreezerlist *ofln = (objectfreezerlist *) ofllist;
+                       ofln->obj->start();
+               }
+       }
+}
diff --git a/src/objectfreezer.h b/src/objectfreezer.h
new file mode 100644 (file)
index 0000000..3509493
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef objectfreezer_h
+#define objectfreezer_h
+
+#include "tree.h"
+#include "list.h"
+#include "session.h"
+
+struct objectfreezerlist {
+       struct list objectlist;
+       int x;
+       int y;
+       class Object *obj;
+};
+
+struct objectfreezernode {
+       struct tree treenode;
+       struct list objectlist;
+};
+
+struct objectfreezernode* new_objectfreezernode(char *key);
+struct objectfreezerlist* new_objectfreezerlistnode(Object *value, int x, int y, objectfreezerlist *list);
+
+void freezer_freezeObject(char* key, int x, int y, class Object *o);
+class Object* freezer_thawObject(char* key,int* xout, int* yout);
+void freezer_save(save_t *save);
+void freezer_del();
+void freezer_start_contents();
+
+#endif
diff --git a/src/occ.c b/src/occ.c
new file mode 100644 (file)
index 0000000..bad7c09
--- /dev/null
+++ b/src/occ.c
@@ -0,0 +1,106 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "gob.h"
+#include "occ.h"
+#include "object.h"
+#include "sprite.h"
+#include "common.h"
+#include "skill_set.h"
+
+#include <string.h>
+#include <stdlib.h>
+
+static void occ_del(struct occ *occ)
+{
+       if (!occ)
+               return;
+       if (occ->tag)
+               free(occ->tag);
+       if (occ->name)
+               free(occ->name);
+        if (occ->gob)
+                gob_del(occ->gob);
+        if (occ->skills)
+                skill_set_unref(occ->skills);
+        free(occ);
+}
+
+extern struct occ *occ_new(const char *tag,
+                           const char *name,
+                           float magic,
+                           int hp_mod,
+                           int hp_mult,
+                           int mp_mod,
+                           int mp_mult,
+                           int hit_mod,
+                           int def_mod,
+                           int dam_mod,
+                           int arm_mod)
+{
+       struct occ *occ = 0;
+
+       occ = (struct occ*)calloc(1, sizeof(*occ));;
+        assert(occ);
+
+        occ->tag = strdup(tag);
+        assert(occ->tag);
+
+        occ->name = strdup(name);
+        assert(occ->name);
+
+        occ->magic = magic;
+        occ->hp_mod = hp_mod;
+        occ->hp_mult = hp_mult;
+        occ->mp_mod = mp_mod;
+        occ->mp_mult = mp_mult;
+        occ->hit_mod = hit_mod;
+        occ->def_mod = def_mod;
+        occ->dam_mod = dam_mod;
+        occ->arm_mod = arm_mod;
+
+        assert(occ->tag);
+        assert(occ->name);
+
+        return occ;
+}
+
+extern void occ_unref(struct occ* occ)
+{
+        assert(occ->refcount > 0);
+        occ->refcount--;
+        if (! occ->refcount)
+                occ_del(occ);
+}
+
+void occ_set_skills(struct occ *occ, struct skill_set *skills)
+{
+        if (occ->skills) {
+                skill_set_unref(skills);
+                occ->skills = 0;
+        }
+
+        if (skills) {
+                skill_set_ref(skills);
+                occ->skills = skills;
+        }
+}
diff --git a/src/occ.h b/src/occ.h
new file mode 100644 (file)
index 0000000..3417150
--- /dev/null
+++ b/src/occ.h
@@ -0,0 +1,74 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef occ_h
+#define occ_h
+
+#include "list.h"
+#include "closure.h"
+
+#define occ_ref(occ) ((occ)->refcount++)
+
+struct typical_items {
+       int prob;
+       class ObjectType *type;
+       int n_max;
+};
+
+struct occ {
+       struct list list;
+       char *tag;
+       char *name;
+       float magic;
+
+        int hp_mod;   /* part of base hp contributed by occupation */
+        int hp_mult;  /* additional hp per-level contributed by occupation  */
+        int mp_mod;   /* similar, for mana */
+        int mp_mult;  /* similar, for mana */
+
+        int hit_mod;  /* unused */
+        int def_mod;  /* unused */
+        int dam_mod;  /* unused */
+        int arm_mod;  /* unused */
+        
+        int xpval; /* reward for killing this type */
+        int refcount;
+               
+        struct gob *gob;
+        struct skill_set *skills;
+};
+
+extern struct occ *occ_new(const char *tag,
+                           const char *name,
+                           float magic,
+                           int hp_mod,
+                           int hp_mult,
+                           int mp_mod,
+                           int mp_mult,
+                           int hit_mod,
+                           int def_mod,
+                           int dam_mod,
+                           int arm_mod);
+
+extern void occ_unref(struct occ *occ);
+extern void occ_set_skills(struct occ *occ, struct skill_set *skills);
+
+#endif
diff --git a/src/olist.c b/src/olist.c
new file mode 100644 (file)
index 0000000..a381f3e
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "olist.h"
+#include "common.h"
+
+struct olist *olist_lookup(struct olist *head, int key, int first)
+{
+       struct list *l;
+       struct olist *i, *last = 0;
+
+       list_for_each(&head->list, l) {
+               i = outcast(l, struct olist, list);
+               if (i->key == key) {
+                       if (first)
+                               return i;
+                       last = i;
+               } else if (last != 0)
+                       return last;
+       }
+       return last;
+}
+
+void olist_add(struct olist *head, struct olist *node)
+{
+       struct list *l;
+       struct olist *i;
+
+       list_for_each(&head->list, l) {
+               i = outcast(l, struct olist, list);
+               if (i->key > node->key)
+                       break;
+       }
+
+       list_add_aux(l->prev, l, &node->list);
+}
diff --git a/src/olist.h b/src/olist.h
new file mode 100644 (file)
index 0000000..61f6931
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef olist_h
+#define olist_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "list.h"
+
+#define olist_init(ol) list_init(&(ol)->list)
+
+       struct olist {
+               struct list list;
+               int key;
+       };
+
+       extern struct olist *olist_lookup(struct olist *head, int key,
+                                         int first);
+       extern void olist_add(struct olist *head, struct olist *node);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/opdefines.h b/src/opdefines.h
new file mode 100644 (file)
index 0000000..452a48b
--- /dev/null
@@ -0,0 +1,194 @@
+    _OP_DEF(opexe_0, "load",                           1,  1,       TST_STRING,                      OP_LOAD             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_T0LVL            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_T1LVL            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_READ_INTERNAL    )
+    _OP_DEF(opexe_0, "gensym",                         0,  0,       0,                               OP_GENSYM           )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_VALUEPRINT       )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_EVAL             )
+#if USE_TRACING
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_REAL_EVAL        )
+#endif
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_E0ARGS           )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_E1ARGS           )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_APPLY            )
+#if USE_TRACING
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_REAL_APPLY       )
+    _OP_DEF(opexe_0, "tracing",                        1,  1,       TST_NATURAL,                     OP_TRACING          )
+#endif
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_DOMACRO          )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LAMBDA           )
+    _OP_DEF(opexe_0, "make-closure",                   1,  2,       TST_PAIR TST_ENVIRONMENT,        OP_MKCLOSURE        )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_QUOTE            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_DEF0             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_DEF1             )
+    _OP_DEF(opexe_0, "defined?",                       1,  2,       TST_SYMBOL TST_ENVIRONMENT,      OP_DEFP             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_BEGIN            )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_IF0              )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_IF1              )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_SET0             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_SET1             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET0             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET1             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET2             )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET0AST          )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET1AST          )
+    _OP_DEF(opexe_0, 0,                                0,  0,       0,                               OP_LET2AST          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_LET0REC          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_LET1REC          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_LET2REC          )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_COND0            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_COND1            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_DELAY            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_AND0             )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_AND1             )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_OR0              )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_OR1              )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_C0STREAM         )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_C1STREAM         )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_MACRO0           )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_MACRO1           )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_CASE0            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_CASE1            )
+    _OP_DEF(opexe_1, 0,                                0,  0,       0,                               OP_CASE2            )
+    _OP_DEF(opexe_1, "eval",                           1,  2,       TST_ANY TST_ENVIRONMENT,         OP_PEVAL            )
+    _OP_DEF(opexe_1, "apply",                          1,  INF_ARG, TST_NONE,                        OP_PAPPLY           )
+    _OP_DEF(opexe_1, "call-with-current-continuation", 1,  1,       TST_NONE,                        OP_CONTINUATION     )
+#if USE_MATH
+    _OP_DEF(opexe_2, "inexact->exact",                 1,  1,       TST_NUMBER,                      OP_INEX2EX          )
+    _OP_DEF(opexe_2, "exp",                            1,  1,       TST_NUMBER,                      OP_EXP              )
+    _OP_DEF(opexe_2, "log",                            1,  1,       TST_NUMBER,                      OP_LOG              )
+    _OP_DEF(opexe_2, "sin",                            1,  1,       TST_NUMBER,                      OP_SIN              )
+    _OP_DEF(opexe_2, "cos",                            1,  1,       TST_NUMBER,                      OP_COS              )
+    _OP_DEF(opexe_2, "tan",                            1,  1,       TST_NUMBER,                      OP_TAN              )
+    _OP_DEF(opexe_2, "asin",                           1,  1,       TST_NUMBER,                      OP_ASIN             )
+    _OP_DEF(opexe_2, "acos",                           1,  1,       TST_NUMBER,                      OP_ACOS             )
+    _OP_DEF(opexe_2, "atan",                           1,  2,       TST_NUMBER,                      OP_ATAN             )
+    _OP_DEF(opexe_2, "sqrt",                           1,  1,       TST_NUMBER,                      OP_SQRT             )
+    _OP_DEF(opexe_2, "expt",                           2,  2,       TST_NUMBER,                      OP_EXPT             )
+    _OP_DEF(opexe_2, "floor",                          1,  1,       TST_NUMBER,                      OP_FLOOR            )
+    _OP_DEF(opexe_2, "ceiling",                        1,  1,       TST_NUMBER,                      OP_CEILING          )
+    _OP_DEF(opexe_2, "truncate",                       1,  1,       TST_NUMBER,                      OP_TRUNCATE         )
+    _OP_DEF(opexe_2, "round",                          1,  1,       TST_NUMBER,                      OP_ROUND            )
+#endif
+    _OP_DEF(opexe_2, "+",                              0,  INF_ARG, TST_NUMBER,                      OP_ADD              )
+    _OP_DEF(opexe_2, "-",                              1,  INF_ARG, TST_NUMBER,                      OP_SUB              )
+    _OP_DEF(opexe_2, "*",                              0,  INF_ARG, TST_NUMBER,                      OP_MUL              )
+    _OP_DEF(opexe_2, "/",                              1,  INF_ARG, TST_NUMBER,                      OP_DIV              )
+    _OP_DEF(opexe_2, "quotient",                       1,  INF_ARG, TST_INTEGER,                     OP_INTDIV           )
+    _OP_DEF(opexe_2, "remainder",                      2,  2,       TST_INTEGER,                     OP_REM              )
+    _OP_DEF(opexe_2, "modulo",                         2,  2,       TST_INTEGER,                     OP_MOD              )
+    _OP_DEF(opexe_2, "car",                            1,  1,       TST_PAIR,                        OP_CAR              )
+    _OP_DEF(opexe_2, "cdr",                            1,  1,       TST_PAIR,                        OP_CDR              )
+    _OP_DEF(opexe_2, "cons",                           2,  2,       TST_NONE,                        OP_CONS             )
+    _OP_DEF(opexe_2, "set-car!",                       2,  2,       TST_PAIR TST_ANY,                OP_SETCAR           )
+    _OP_DEF(opexe_2, "set-cdr!",                       2,  2,       TST_PAIR TST_ANY,                OP_SETCDR           )
+    _OP_DEF(opexe_2, "char->integer",                  1,  1,       TST_CHAR,                        OP_CHAR2INT         )
+    _OP_DEF(opexe_2, "integer->char",                  1,  1,       TST_NATURAL,                     OP_INT2CHAR         )
+    _OP_DEF(opexe_2, "char-upcase",                    1,  1,       TST_CHAR,                        OP_CHARUPCASE       )
+    _OP_DEF(opexe_2, "char-downcase",                  1,  1,       TST_CHAR,                        OP_CHARDNCASE       )
+    _OP_DEF(opexe_2, "symbol->string",                 1,  1,       TST_SYMBOL,                      OP_SYM2STR          )
+    _OP_DEF(opexe_2, "atom->string",                   1,  1,       TST_ANY,                         OP_ATOM2STR         )
+    _OP_DEF(opexe_2, "string->symbol",                 1,  1,       TST_STRING,                      OP_STR2SYM          )
+    _OP_DEF(opexe_2, "string->atom",                   1,  1,       TST_STRING,                      OP_STR2ATOM         )
+    _OP_DEF(opexe_2, "make-string",                    1,  2,       TST_NATURAL TST_CHAR,            OP_MKSTRING         )
+    _OP_DEF(opexe_2, "string-length",                  1,  1,       TST_STRING,                      OP_STRLEN           )
+    _OP_DEF(opexe_2, "string-ref",                     2,  2,       TST_STRING TST_NATURAL,          OP_STRREF           )
+    _OP_DEF(opexe_2, "string-set!",                    3,  3,       TST_STRING TST_NATURAL TST_CHAR, OP_STRSET           )
+    _OP_DEF(opexe_2, "string-append",                  0,  INF_ARG, TST_STRING,                      OP_STRAPPEND        )
+    _OP_DEF(opexe_2, "substring",                      2,  3,       TST_STRING TST_NATURAL,          OP_SUBSTR           )
+    _OP_DEF(opexe_2, "vector",                         0,  INF_ARG, TST_NONE,                        OP_VECTOR           )
+    _OP_DEF(opexe_2, "make-vector",                    1,  2,       TST_NATURAL TST_ANY,             OP_MKVECTOR         )
+    _OP_DEF(opexe_2, "vector-length",                  1,  1,       TST_VECTOR,                      OP_VECLEN           )
+    _OP_DEF(opexe_2, "vector-ref",                     2,  2,       TST_VECTOR TST_NATURAL,          OP_VECREF           )
+    _OP_DEF(opexe_2, "vector-set!",                    3,  3,       TST_VECTOR TST_NATURAL TST_ANY,        OP_VECSET     )
+    _OP_DEF(opexe_3, "not",                            1,  1,       TST_NONE,                        OP_NOT              )
+    _OP_DEF(opexe_3, "boolean?",                       1,  1,       TST_NONE,                        OP_BOOLP            )
+    _OP_DEF(opexe_3, "eof-object?",                    1,  1,       TST_NONE,                        OP_EOFOBJP          )
+    _OP_DEF(opexe_3, "null?",                          1,  1,       TST_NONE,                        OP_NULLP            )
+    _OP_DEF(opexe_3, "=",                              2,  INF_ARG, TST_NUMBER,                      OP_NUMEQ            )
+    _OP_DEF(opexe_3, "<",                              2,  INF_ARG, TST_NUMBER,                      OP_LESS             )
+    _OP_DEF(opexe_3, ">",                              2,  INF_ARG, TST_NUMBER,                      OP_GRE              )
+    _OP_DEF(opexe_3, "<=",                             2,  INF_ARG, TST_NUMBER,                      OP_LEQ              )
+    _OP_DEF(opexe_3, ">=",                             2,  INF_ARG, TST_NUMBER,                      OP_GEQ              )
+    _OP_DEF(opexe_3, "symbol?",                        1,  1,       TST_ANY,                         OP_SYMBOLP          )
+    _OP_DEF(opexe_3, "number?",                        1,  1,       TST_ANY,                         OP_NUMBERP          )
+    _OP_DEF(opexe_3, "string?",                        1,  1,       TST_ANY,                         OP_STRINGP          )
+    _OP_DEF(opexe_3, "integer?",                       1,  1,       TST_ANY,                         OP_INTEGERP         )
+    _OP_DEF(opexe_3, "real?",                          1,  1,       TST_ANY,                         OP_REALP            )
+    _OP_DEF(opexe_3, "char?",                          1,  1,       TST_ANY,                         OP_CHARP            )
+#if USE_CHAR_CLASSIFIERS
+    _OP_DEF(opexe_3, "char-alphabetic?",               1,  1,       TST_CHAR,                        OP_CHARAP           )
+    _OP_DEF(opexe_3, "char-numeric?",                  1,  1,       TST_CHAR,                        OP_CHARNP           )
+    _OP_DEF(opexe_3, "char-whitespace?",               1,  1,       TST_CHAR,                        OP_CHARWP           )
+    _OP_DEF(opexe_3, "char-upper-case?",               1,  1,       TST_CHAR,                        OP_CHARUP           )
+    _OP_DEF(opexe_3, "char-lower-case?",               1,  1,       TST_CHAR,                        OP_CHARLP           )
+#endif
+    _OP_DEF(opexe_3, "port?",                          1,  1,       TST_ANY,                         OP_PORTP            )
+    _OP_DEF(opexe_3, "input-port?",                    1,  1,       TST_ANY,                         OP_INPORTP          )
+    _OP_DEF(opexe_3, "output-port?",                   1,  1,       TST_ANY,                         OP_OUTPORTP         )
+    _OP_DEF(opexe_3, "procedure?",                     1,  1,       TST_ANY,                         OP_PROCP            )
+    _OP_DEF(opexe_3, "pair?",                          1,  1,       TST_ANY,                         OP_PAIRP            )
+    _OP_DEF(opexe_3, "list?",                          1,  1,       TST_ANY,                         OP_LISTP            )
+    _OP_DEF(opexe_3, "environment?",                   1,  1,       TST_ANY,                         OP_ENVP             )
+    _OP_DEF(opexe_3, "vector?",                        1,  1,       TST_ANY,                         OP_VECTORP          )
+    _OP_DEF(opexe_3, "eq?",                            2,  2,       TST_ANY,                         OP_EQ               )
+    _OP_DEF(opexe_3, "eqv?",                           2,  2,       TST_ANY,                         OP_EQV              )
+    _OP_DEF(opexe_4, "force",                          1,  1,       TST_ANY,                         OP_FORCE            )
+    _OP_DEF(opexe_4, 0,                                0,  0,       0,                               OP_SAVE_FORCED      )
+    _OP_DEF(opexe_4, "write",                          1,  2,       TST_ANY TST_OUTPORT,             OP_WRITE            )
+    _OP_DEF(opexe_4, "write-char",                     1,  2,       TST_CHAR TST_OUTPORT,            OP_WRITE_CHAR       )
+    _OP_DEF(opexe_4, "display",                        1,  2,       TST_ANY TST_OUTPORT,             OP_DISPLAY          )
+    _OP_DEF(opexe_4, "newline",                        0,  1,       TST_OUTPORT,                     OP_NEWLINE          )
+    _OP_DEF(opexe_4, "error",                          1,  INF_ARG, TST_NONE,                        OP_ERR0             )
+    _OP_DEF(opexe_4, 0,                                0,  0,       0,                               OP_ERR1             )
+    _OP_DEF(opexe_4, "reverse",                        1,  1,       TST_PAIR,                        OP_REVERSE          )
+    _OP_DEF(opexe_4, "list*",                          1,  INF_ARG, TST_NONE,                        OP_LIST_STAR        )
+    _OP_DEF(opexe_4, "append",                         0,  INF_ARG, TST_NONE,                        OP_APPEND           )
+    _OP_DEF(opexe_4, "put",                            3,  3,       TST_NONE,                        OP_PUT              )
+    _OP_DEF(opexe_4, "get",                            2,  2,       TST_NONE,                        OP_GET              )
+    _OP_DEF(opexe_4, "quit",                           0,  1,       TST_NUMBER,                      OP_QUIT             )
+    _OP_DEF(opexe_4, "gc",                             0,  0,       0,                               OP_GC               )
+    _OP_DEF(opexe_4, "gc-verbose",                     0,  1,       TST_NONE,                        OP_GCVERB           )
+    _OP_DEF(opexe_4, "new-segment",                    0,  1,       TST_NUMBER,                      OP_NEWSEGMENT       )
+    _OP_DEF(opexe_4, "oblist",                         0,  0,       0,                               OP_OBLIST           )
+    _OP_DEF(opexe_4, "current-input-port",             0,  0,       0,                               OP_CURR_INPORT      )
+    _OP_DEF(opexe_4, "current-output-port",            0,  0,       0,                               OP_CURR_OUTPORT     )
+    _OP_DEF(opexe_4, "open-input-file",                1,  1,       TST_STRING,                      OP_OPEN_INFILE      )
+    _OP_DEF(opexe_4, "open-output-file",               1,  1,       TST_STRING,                      OP_OPEN_OUTFILE     )
+    _OP_DEF(opexe_4, "open-input-output-file",         1,  1,       TST_STRING,                      OP_OPEN_INOUTFILE   )
+#if USE_STRING_PORTS
+    _OP_DEF(opexe_4, "open-input-string",              1,  1,       TST_STRING,                      OP_OPEN_INSTRING    )
+    _OP_DEF(opexe_4, "open-output-string",             1,  1,       TST_STRING,                      OP_OPEN_OUTSTRING   )
+    _OP_DEF(opexe_4, "open-input-output-string",       1,  1,       TST_STRING,                      OP_OPEN_INOUTSTRING )
+#endif
+    _OP_DEF(opexe_4, "close-input-port",               1,  1,       TST_INPORT,                      OP_CLOSE_INPORT     )
+    _OP_DEF(opexe_4, "close-output-port",              1,  1,       TST_OUTPORT,                     OP_CLOSE_OUTPORT    )
+    _OP_DEF(opexe_4, "interaction-environment",        0,  0,       0,                               OP_INT_ENV          )
+    _OP_DEF(opexe_4, "current-environment",            0,  0,       0,                               OP_CURR_ENV         )
+    _OP_DEF(opexe_5, "read",                           0,  1,       TST_INPORT,                      OP_READ             )
+    _OP_DEF(opexe_5, "read-char",                      0,  1,       TST_INPORT,                      OP_READ_CHAR        )
+    _OP_DEF(opexe_5, "peek-char",                      0,  1,       TST_INPORT,                      OP_PEEK_CHAR        )
+    _OP_DEF(opexe_5, "char-ready?",                    0,  1,       TST_INPORT,                      OP_CHAR_READY       )
+    _OP_DEF(opexe_5, "set-input-port",                 1,  1,       TST_INPORT,                      OP_SET_INPORT       )
+    _OP_DEF(opexe_5, "set-output-port",                1,  1,       TST_OUTPORT,                     OP_SET_OUTPORT      )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDSEXPR          )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDLIST           )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDDOT            )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDQUOTE          )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDQQUOTE         )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDQQUOTEVEC      )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDUNQUOTE        )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDUQTSP          )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_RDVEC            )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_P0LIST           )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_P1LIST           )
+    _OP_DEF(opexe_5, 0,                                0,  0,       0,                               OP_PVECFROM         )
+    _OP_DEF(opexe_6, "length",                         1,  1,       TST_LIST,                        OP_LIST_LENGTH      )
+    _OP_DEF(opexe_6, "assq",                           2,  2,       TST_NONE,                        OP_ASSQ             )
+    _OP_DEF(opexe_6, "get-closure-code",               1,  1,       TST_NONE,                        OP_GET_CLOSURE      )
+    _OP_DEF(opexe_6, "closure?",                       1,  1,       TST_NONE,                        OP_CLOSUREP         )
+    _OP_DEF(opexe_6, "macro?",                         1,  1,       TST_NONE,                        OP_MACROP           )
+#if USE_REENTER
+    _OP_DEF(opexe_ghul, 0,                             0,  0,       0,                               OP_EXIT_REENTER     )
+#endif
+#undef _OP_DEF
diff --git a/src/pinfo.h b/src/pinfo.h
new file mode 100644 (file)
index 0000000..cab0b03
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef pinfo_h
+#define pinfo_h
+
+// ----------------------------------------------------------------------------
+// The ugly position_info struct is used by the algorithm which places party
+// members on a map. It is unsightly, but not wholy foul, and will likely live
+// on for a while until the placement algorithm is completely revisited.
+// ----------------------------------------------------------------------------
+
+struct position_info {
+
+        struct place *place; // The place where the members are getting
+                             // distributed.
+
+        int x, y;            // The "home position". The placement rectangle
+                             // (see below) will be centered on this
+                             // location. If the placement algorithm fails to
+                             // find a safe place to put a member (due to
+                             // passability, etc) it will put the member
+                             // here. In extreme cases the whole party may get
+                             // stacked on this one location.
+
+        int dx, dy;          // The orientation vector (most formations are
+                             // directional). Typically set to the last
+                             // direction the party was travelling in.
+
+        int rx, ry, rw, rh;  // The placement rectangle.
+
+        int px, py;          // The initial preferred location of a party
+                             // member (this is set just before running the
+                             // placement algorithm on a member). This depends
+                             // on the "order" of the member in the party, the
+                             // formation, and the direction vector.
+
+        class Object *subject; // Use the subject being positioned instead of
+                               // the obsolete pmask.
+
+        bool find_party;     // When running the placement algorithm, true iff
+                             // the party member must be able to pathfind back
+                             // to the party coordinates.
+
+        int placed;          // Count of the number of party members actually
+                             // placed. Used to detect when none of a party
+                             // found a location.
+
+        struct formation *formation;     // The formation to use when placing
+                                         // party members.
+
+
+};
+
+#endif
diff --git a/src/place.c b/src/place.c
new file mode 100644 (file)
index 0000000..2bd51ad
--- /dev/null
@@ -0,0 +1,2479 @@
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+/* 12/14/2002 Sam Glasby added place_get_terrain()
+ */
+#include "sound.h"
+#include "place.h"
+#include "sprite.h"
+#include "terrain.h"
+#include "hash.h"
+#include "screen.h"
+#include "player.h"
+#include "sky.h"
+#include "console.h"
+#include "wq.h"
+#include "Field.h"
+#include "vehicle.h"
+#include "session.h"
+#include "log.h"
+#include "factions.h"
+#include "vmask.h"
+#include "combat.h"
+#include "event.h" /* for demo */
+#include "kern_intvar.h"
+
+// #define DEBUG
+// #undef debug_h
+#include "debug.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#ifndef PLACE_PROFILE
+#define PLACE_PROFILE 0
+#endif
+
+#define HIGHLIGHT_W 2
+#define HIGHLIGHT_H 2
+
+#define BLOCKS_PASSABILITY -1
+#define IGNORES_PASSABILITY 0
+#define ALLOWS_PASSABILITY  1
+
+#define WRAP(c,max) (((c) + (max)) % (max))
+#define WRAP_DISTANCE(a,b,max) (min((a) + (max) - (b), (b) - (a)))
+#define INDEX(x,y,w) ((x) + (y) * (w))
+#define WRAP_COORDS(place, x, y) do { \
+        if ((place)->wraps) { \
+                (x) = place_wrap_x((place), (x)); \
+                (y) = place_wrap_y((place), (y)); \
+        } \
+} while(0)
+
+#define TERRAIN(p,x,y) ((p)->terrain_map->terrain[(y) * \
+   (p)->terrain_map->w + (x)])
+
+struct place_pathfind_context {
+       struct place *place;
+       int target_x;
+       int target_y;
+       int pflags;
+        class Object *requestor;
+};
+
+typedef struct closure_list {
+        struct list list;
+        closure_t *closure;
+} closure_list_t;
+
+struct place *Place;
+
+/* Tile API ******************************************************************/
+struct tile {
+       struct olist hashlink;
+       struct node objstack;
+        struct place *subplace;
+       class Vehicle *vehicle;
+       int objects;
+       int lock;
+};
+static struct tile *tile_new(int hashkey)
+{
+       struct tile *tile;
+       CREATE(tile, struct tile, 0);
+       olist_init(&tile->hashlink);
+       tile->hashlink.key = hashkey;
+       node_init(&tile->objstack);
+       return tile;
+}
+static void tile_del(struct tile *tile)
+{
+        /* 
+         * FIXME! use a straightforward refcount on the tile instead of an
+         * explicit lock
+         */
+       // Locking prevents me from destroying a tile while the place_for_each
+       // algorithm is using it.
+       if (!tile->lock) {
+               assert(!tile->objects);
+               list_remove(&tile->hashlink.list);
+                //dbg("tile_del: tile=%08lx\n", tile);
+               free(tile);
+       }
+}
+static void tile_for_each_object(struct tile *tile,
+                                 void (*fx)(class Object *obj, void *data),
+                                 void *data)
+{
+        struct node *elem;
+        class Object *obj;
+
+        for (elem = node_next(&tile->objstack); elem != &tile->objstack; ) {
+               obj = (class Object *)elem->ptr;
+                elem = node_next(elem);
+                fx(obj, data);
+       }
+
+        if (tile->vehicle)
+                fx(tile->vehicle, data);
+}
+
+static Object *tile_get_filtered_object(struct tile *tile, int (*filter)(Object*))
+{
+        struct node *elem;
+        class Object *obj;
+
+        /* Traverse the list in reverse order, so the first item returned is
+         * the one shown by the UI as topmost in the pile. */
+        for (elem = node_prev(&tile->objstack); elem != &tile->objstack; ) {
+               obj = (class Object *)elem->ptr;
+                elem = node_prev(elem);
+                if (filter(obj))
+                        return obj;
+       }
+
+        if (tile->vehicle && filter(tile->vehicle))
+                return tile->vehicle;
+
+        return NULL;
+}
+
+static Object *tile_get_top_object_at_layer(struct tile *tile, enum layer layer)
+{
+        struct node *node;
+
+        node = node_lookup(&tile->objstack, layer);
+        if (node)
+                return (Object*)node->ptr;
+        
+        return NULL;
+}
+
+static int tile_get_light(struct tile *tile)
+{
+        struct node *node = NULL;
+        int light = 0;
+        class Object *obj = NULL;
+
+       /* Check for a vehicle */
+       if (tile->vehicle)
+               light += tile->vehicle->getLight();
+
+       /* Check all objects */
+       node_for_each(&tile->objstack, node) {
+               obj = (class Object *)node->ptr;
+               light += obj->getLight();
+       }
+
+        return light;
+}
+
+static int tile_is_transparent(struct tile *tile)
+{
+       struct node *elem;
+       class Object *obj;
+
+        for (elem = node_next(&tile->objstack); elem != &tile->objstack; ) {
+               obj = (class Object *)elem->ptr;
+                elem = node_next(elem);
+                if (obj->isOpaque())
+                        return 0;
+       }
+
+       return 1;
+}
+
+static void tile_remove_object(struct tile *tile, class Object *object)
+{
+       if (object->isType(VEHICLE_ID)) {
+                if (tile->vehicle == object) {
+                        tile->vehicle = 0;
+                        tile->objects--;
+                }
+                /* 30Jul2003 gmcnutt: otherwise this vehicle must be occupied,
+                 * in which case it does not occupy the tile (it's occupant
+                 * does). */
+       } else {
+                /* Splice out the object's container link node and release
+                 * it. */
+                assert(object->clink);
+                node_remove(object->clink);
+                node_unref(object->clink);
+                object->clink = NULL;
+                tile->objects--;
+       }
+
+
+       if (!tile->objects) {
+               tile_del(tile);
+       }
+
+        obj_dec_ref(object);
+}
+
+static void tile_add_object(struct tile *tile, class Object *object)
+{
+        obj_inc_ref(object);
+
+       if (object->isType(VEHICLE_ID)) {
+               if (tile->vehicle) {
+                        assert(0);
+                }
+               tile->vehicle = (class Vehicle *) object;
+               tile->objects++;
+                return;
+       }
+
+        /* Create a new container link node for the object and add it to the
+         * tile's object stack. */
+        assert(!object->clink);
+        object->clink = node_new_keyed(object, object->getLayer());
+        node_add_keyed(&tile->objstack, object->clink);
+
+       tile->objects++;
+}
+
+static int tile_add_subplace(struct tile *tile, struct place *place)
+{
+        if (tile->subplace)
+                return -1;
+
+        tile->subplace = place;
+        tile->objects++;
+        return 0;
+}
+
+static void tile_remove_subplace(struct tile *tile)
+{
+        if (tile->subplace) {
+                tile->subplace = 0;
+                tile->objects--;
+        }
+
+       if (!tile->objects) {
+               tile_del(tile);
+       }
+}
+
+static void tile_paint(struct tile *tile, int sx, int sy)
+{
+       struct node *node;
+       Object *obj;
+       struct sprite *sprite;
+
+        /* Check for a subplace. The temp combat place won't have a sprite. */
+        if (tile->subplace && tile->subplace->sprite) {
+                assert(tile->subplace->sprite);
+                sprite_paint(tile->subplace->sprite, 0, sx, sy);
+        }
+
+       /* Check for a vehicle */
+       if (tile->vehicle) {
+               tile->vehicle->paint(sx, sy);
+       }
+
+       node_for_each(&tile->objstack, node) {
+               obj = (Object*)node->ptr;
+               sprite = obj->getSprite();
+               if (!sprite)
+                       continue;
+
+               // Handle invisible objects and alpha-blending when
+               // invisible objects are revealed. If the global "reveal" flag
+               // is not set then do not paint invisible objects. Otherwise
+               // temporarily set the object's sprite to 'shaded' and paint
+               // it. After painting I need to clear the shaded flags in case
+               // other objects use this sprite, too.
+
+               if (!obj->isVisible()) {
+                       if (!Reveal && !obj->isShaded())
+                               continue;
+                       sprite_fade(sprite);
+               } else if (obj->isShaded()) {
+                        sprite_fade(sprite);
+                }
+
+               obj->paint(sx, sy);
+
+               if (obj->isSelected()) {
+                        /* Highlight */
+                        SDL_Rect rect;
+                        rect.x = sx;
+                        rect.y = sy;
+                        rect.w = TILE_W;
+                        rect.h = TILE_H;
+                        screenHighlight(&rect);
+                }
+
+                // Paint a red box around hostiles, green around allies, and
+                // yellow around neutrals.
+                else if (Session->show_boxes
+                         && Session->subject 
+                         && obj->getLayer() == being_layer) {
+                        SDL_Rect rect;
+                        Uint32 color = Yellow;
+                        rect.x = sx;
+                        rect.y = sy;
+                        rect.w = TILE_W;
+                        rect.h = TILE_H;
+                        if (are_allies(Session->subject, (Being*)obj))
+                                color = Green;
+                        else if (are_hostile(Session->subject, (Being*)obj))
+                                color = Red;
+                        screenHighlightColored(&rect, color);
+                }
+
+               if (sprite_is_faded(sprite))
+                       sprite_unfade(sprite);
+       }
+}
+
+/*****************************************************************************/
+
+static void place_for_each_tile(struct place *place, 
+                                void (*fx)(struct tile *tile, void *data), 
+                                void *data);
+
+static inline int place_is_diagonal(struct place *place, int from_x, 
+                                    int from_y, int to_x, int to_y)
+{
+        /* FIXME: probably doesn't work on wrapping places... */
+        int dx = from_x - to_x;
+        int dy = from_y - to_y;
+        return (((dx==1) || (dx==-1))
+                && ((dy==1) || (dy==-1)));
+}
+
+static void place_set_default_edge_entrance(struct place *place)
+{
+        /* Northwest: lower right corner */
+        place->edge_entrance[NORTHWEST][0] = place_w(place) - 1;
+        place->edge_entrance[NORTHWEST][1] = place_h(place) - 1;
+
+        /* North: lower center */
+        place->edge_entrance[NORTH][0] = place_w(place) / 2;
+        place->edge_entrance[NORTH][1] = place_h(place) - 1;
+
+        /* Northeast: lower left corner */
+        place->edge_entrance[NORTHEAST][0] = 0;
+        place->edge_entrance[NORTHEAST][1] = place_h(place) - 1;
+
+        /* West: right center */
+        place->edge_entrance[WEST][0] = place_w(place) - 1;
+        place->edge_entrance[WEST][1] = place_h(place) / 2;
+
+        /* Here: center */
+        place->edge_entrance[HERE][0] = place_w(place) / 2;
+        place->edge_entrance[HERE][1] = place_h(place) / 2;
+
+        /* East: left center */
+        place->edge_entrance[EAST][0] = 0;
+        place->edge_entrance[EAST][1] = place_h(place) / 2;
+
+        /* Southwest: upper right corner */
+        place->edge_entrance[SOUTHWEST][0] = place_w(place) - 1;
+        place->edge_entrance[SOUTHWEST][1] = 0;
+
+        /* South: upper center */
+        place->edge_entrance[SOUTH][0] = place_w(place) / 2;
+        place->edge_entrance[SOUTH][1] = 0;
+
+        /* Southeast: upper left corner */
+        place->edge_entrance[SOUTHEAST][0] = 0;
+        place->edge_entrance[SOUTHEAST][1] = 0;
+}
+
+/*****************************************************************************
+ * place_init_turn_list - abstract wrapper for simple init
+ *****************************************************************************/
+static void place_init_turn_list(struct place *place)
+{
+        node_init(&place->turn_list);
+}
+
+/*****************************************************************************
+ * place_add_to_turn_list - add an object to the turn list
+ *****************************************************************************/
+static void place_add_to_turn_list(struct place *place, Object *object)
+{
+        struct node *node;
+
+        /* The object should not be pointing to an existing node. */
+        assert(! object->turn_list);
+
+        /* Create a new node that points to the object. */
+        node = node_new(object);
+
+        /* Link the object back to its node. */
+        object->turn_list = node;
+
+        /* Add the node to the turn list. */
+        node_add(&place->turn_list, node);
+}
+
+/*****************************************************************************
+ * place_remove_from_turn_list - safely remove an object from the turn list
+ *****************************************************************************/
+static void place_remove_from_turn_list(struct place *place, Object *object)
+{
+
+        struct node *node;
+
+        /* Get a convenience pointer to the node which holds the object */
+        node = object->turn_list;
+
+        /* Should be valid */
+        assert(node);
+
+        /* Note: this is a bit subtle. If it just so happens that we are in the
+         * process of running place_exec, there is a chance that the object we
+         * are removing here is the next object to be processed in the
+         * turn_list. In this special case we must setup the next object after
+         * this to be processed instead. This can happen when one object
+         * destroys or picks up another object on its turn. */
+        if (place->turn_elem == node) {
+                place->turn_elem = node_next(node);
+        }
+
+        /* Unlink the node from the turn list. */
+        node_remove(node);
+
+        /* Zero out the object's link to the node */
+        object->turn_list = NULL;
+
+        /* Release the node for destruction. */
+        node_unref(node);
+}
+
+struct place *place_new(const char *tag,
+                        const char *name, 
+                        struct sprite *sprite,
+                        struct terrain_map *terrain_map,
+                        int wraps,
+                        int underground,
+                        int wilderness,
+                        int wild_combat)
+                        
+{
+       struct place *place;
+        
+       CREATE(place, struct place, 0);
+
+       place->tag = strdup(tag);
+        assert(place->tag);
+
+       place->name = strdup(name);
+        assert(place->name);
+
+       place->objects = hash_create(31);
+        assert(place->objects);
+
+        place->magic = PLACE_MAGIC;
+        place->sprite = sprite;
+
+        /* Give the place its own copy of the original map so it can modify it
+         * at run-time (a clever implementation would do copy-on-write...) */
+       place->terrain_map = terrain_map_clone(terrain_map, NULL);
+
+        place->scale = wilderness ? WILDERNESS_SCALE : NON_WILDERNESS_SCALE;
+       place->original_terrain_map = terrain_map;
+       place->wraps = wraps;
+        place->underground = underground;
+        place->wilderness = wilderness;
+        place->is_wilderness_combat = wild_combat;
+
+        place_init_turn_list(place);
+        list_init(&place->subplaces);
+        list_init(&place->container_link);
+        list_init(&place->on_entry_hook);
+        place->turn_elem = &place->turn_list;
+
+        place_set_default_edge_entrance(place);
+        
+
+       return place;
+}
+
+void place_del_tile_object_visitor(class Object *obj, void *data)
+{
+        // Called by tile_for_each_object()
+        struct tile *tile = (struct tile*)data;
+        tile_remove_object(tile, obj);
+}
+
+void place_del_tile_visitor(struct tile *tile, void *data)
+{
+        // Called by place_for_each_tile()
+        tile->lock++;
+        tile_for_each_object(tile, place_del_tile_object_visitor, tile);
+        if (tile->subplace) {
+                //place_del(tile->subplace);
+                tile_remove_subplace(tile);
+        }
+        tile->lock--;
+        tile_del(tile);
+}
+
+static void place_del_on_entry_hook(struct place *place)
+{
+        struct list *elem = place->on_entry_hook.next;
+        while (elem != &place->on_entry_hook) {
+                closure_list_t *node = (closure_list_t*)elem;
+                elem = elem->next;
+                list_remove(&node->list);
+                closure_unref(node->closure);
+                free(node);
+        }
+}
+
+void place_del(struct place *place)
+{
+        // --------------------------------------------------------------------
+        // If the place is locked then we cannot delete it now. Mark it for
+        // death so that it will be deleted when unlocked.
+        // --------------------------------------------------------------------
+
+        //dbg("place_del(%s)\n", place->name);
+
+        if (place_is_locked(place)) {
+                place_mark_for_death(place);
+                return;
+        }
+
+        // Destroy all tiles, objects and subplaces recursively.
+        place_for_each_tile(place, place_del_tile_visitor, 0);
+        hash_destroy(place->objects);
+
+        //dbg("place_del %s\n", place->tag);
+
+       if (place->tag)
+               free(place->tag);
+       if (place->name)
+               free(place->name);
+       if (place->terrain_map)
+               terrain_map_unref(place->terrain_map);
+
+        place_del_on_entry_hook(place);
+
+       free(place);
+}
+
+static int place_generic_is_passable(class Object *subject, int flags, 
+                                     int pclass, struct closure *effect)
+{
+        // Is it passable?
+        if (subject->isPassable(pclass))
+                return 1;
+
+        // Is the caller actually trying to move the subject there?
+        if (0 == (flags & PFLAG_MOVEATTEMPT))
+                return 0;
+
+        // Is there an effect to apply on failed entry?
+        if (effect) {
+                subject->applyEffect(effect);
+        }
+
+        return 0;
+}
+
+static int place_terrain_is_passable(struct place *place, int x, int y,
+                                     class Object *subject, int flags)
+{
+       struct terrain *terrain;
+
+       terrain = place->terrain_map->terrain[y * place->terrain_map->w + x];
+
+        // Can we use the generic passability test?
+        if (flags & PFLAG_IGNOREVEHICLES)
+                return place_generic_is_passable(subject, flags, 
+                                                 terrain_pclass(terrain),
+                                                 terrain->effect);
+
+        // Is the terrain passable?
+        if (subject->isPassable(terrain_pclass(terrain)))
+                return 1;
+
+        // Is there a vehicle there?
+        if (place_get_vehicle(place, x, y))
+                return 1;
+
+        // Is the caller actually trying to move the subject there?
+        if (0 == (flags & PFLAG_MOVEATTEMPT))
+                return 0;
+
+        // Does the terrain apply an effect on failed entry?
+        if (terrain->effect) {
+                subject->applyEffect(terrain->effect);
+        }
+
+        return 0;
+}
+
+static int place_field_is_passable(struct place *place, int x, int y,
+                                   class Object *subject, int flags)
+{
+       class Field *field;
+
+        // Is there a field there?
+       field = (class Field *) place_get_object(place, x, y, field_layer);
+       if (! field)
+                return 1;
+
+        return place_generic_is_passable(subject, flags,
+                                         field->getPclass(),
+                                         field->getObjectType()->effect);
+}
+
+static int place_obj_is_passable(class Object *obj,
+                                class Object *subject, int flags)
+{
+        int pclass = obj->getPclass();
+
+        // Does the object care about passability?
+        if (pclass == PCLASS_NONE)
+                return IGNORES_PASSABILITY;
+
+        // Is the obj passable?
+        if (subject->isPassable(obj->getPclass()))
+                return ALLOWS_PASSABILITY;
+
+        return BLOCKS_PASSABILITY;
+
+}
+
+int place_is_passable(struct place *place, int x, int y,
+                     class Object *subject, int flags)
+{
+       class Object *mech;
+        int tfeat_pass = IGNORES_PASSABILITY;
+
+       // For a wrapping place, wrap out-of-bounds x,y
+       // For a non-wrapping place, return impassable.
+       if (place->wraps) {
+               x = WRAP(x, place->terrain_map->w);
+               y = WRAP(y, place->terrain_map->h);
+       } else if (y < 0 || y >= place->terrain_map->h ||
+                  x < 0 || x >= place->terrain_map->w)
+               return 0;
+
+        // Does the caller want to check terrain features?
+        if (0 == (flags & PFLAG_IGNORETFEAT)) {
+                class Object *tfeat = NULL;
+                
+                tfeat = place_get_object(place, x, y, tfeat_layer);
+                if (tfeat) {
+                        tfeat_pass = place_obj_is_passable(tfeat, subject, 
+                                                           flags);
+
+                        // Does it specifically block passability?
+                        if (tfeat_pass == BLOCKS_PASSABILITY)
+                                return 0;
+                }
+        }
+
+        // Does the caller want to check terrain, and if so is there no
+        // overriding terrain feature?
+        if (0 == (flags & PFLAG_IGNORETERRAIN) &&
+            IGNORES_PASSABILITY == tfeat_pass) {
+
+                // Is the terrain passable?
+                if (! place_terrain_is_passable(place, x, y, subject, flags))
+                        return 0;
+        }
+
+        // Does the caller want to check fields?
+        if (0 == (flags & PFLAG_IGNOREFIELDS)) {
+
+                // Is the field passable?
+                if (! place_field_is_passable(place, x, y, subject, flags))
+                        return 0;
+
+        }
+
+               // Does the caller want to check mechs?
+               if (0 == (flags & PFLAG_IGNOREMECHS)) {
+                       
+                       // Is the mech passable?
+                       mech = place_get_object(place, x, y, mech_layer);
+                       if (mech &&
+                           (place_obj_is_passable(mech, subject, flags) == 
+                            BLOCKS_PASSABILITY))
+                               return 0;
+               }
+
+       return 1;
+}
+
+int place_move_is_passable(struct place *place, int from_x, int from_y,
+                           int to_x, int to_y,
+                           class Object *subject, int flags)
+{
+        /* check destination tile */
+        if (! place_is_passable(place, to_x, to_y, subject, flags)) {
+                return 0;
+        }
+
+        /* check if this is a one-tile diagonal move then check both adjacent
+         * neighbors. */
+        if (place_is_diagonal(place, from_x, from_y, to_x, to_y)
+            && ! place_is_passable(place, from_x, to_y, subject, flags & ~PFLAG_MOVEATTEMPT)
+            && ! place_is_passable(place, to_x, from_y, subject, flags & ~PFLAG_MOVEATTEMPT)) {
+                return 0;
+        }
+
+        return 1;
+}
+
+
+int place_is_occupied(struct place *place, int x, int y)
+{
+        WRAP_COORDS(place, x, y);
+       return (place_get_object(place, x, y, being_layer) != 0);
+}
+
+static struct tile *place_lookup_tile(struct place *place, int x, int y)
+{
+       struct olist *olist;
+       if (place_off_map(place, x, y))
+               return 0;
+       olist = hash_lookup(place->objects, INDEX(x, y, place_w(place)));
+       if (!olist)
+               return 0;
+       return outcast(olist, struct tile, hashlink);
+}
+
+static struct tile *place_create_and_add_tile(struct place *place, int x, 
+                                              int y)
+{
+       struct tile *tile;
+       tile = tile_new(INDEX(x, y, place_w(place)));
+       if (!tile)
+               return 0;
+       hash_add(place->objects, &tile->hashlink);
+        //dbg("place_create_and_add_tile: place=%s tile=%08lx x=%d y=%d\n", place->name, tile, x, y);
+       return tile;
+}
+
+struct tile *placeGetTile(struct place *place, int x, int y)
+{
+       struct tile *tile = place_lookup_tile(place, x, y);
+       if (tile)
+               return tile;
+       return place_create_and_add_tile(place, x, y);
+}
+
+void place_paint_objects(struct place *place, int mx, int my,
+                         int sx, int sy)
+{
+       struct tile *tile;
+
+       tile = place_lookup_tile(place, mx, my);
+       if (!tile)
+               return;
+
+        tile_paint(tile, sx, sy);
+}
+
+int place_visibility(struct place *place, int x, int y)
+{
+       struct terrain *terrain;
+       struct tile *tile;
+
+       if (place->wraps) {
+               x = WRAP(x, place->terrain_map->w);
+               y = WRAP(y, place->terrain_map->h);
+       } else if (x < 0 || x >= place->terrain_map->w || y < 0 ||
+                  y >= place->terrain_map->h)
+               return ALPHA_OPAQUE;
+
+       terrain = place->terrain_map->terrain[y * place->terrain_map->w + x];
+       if (!terrain)
+                return ALPHA_OPAQUE;
+
+       tile = place_lookup_tile(place, x, y);
+       if (tile && ! tile_is_transparent(tile))
+                return ALPHA_OPAQUE;
+
+        return terrain->alpha;
+}
+
+unsigned int place_walking_distance(struct place *place,
+                                   int x0, int y0, int x1, int y1)
+{
+       int dx;
+       int dy;
+
+       if (place->wraps) {
+               dx = WRAP_DISTANCE(min(x0, x1), max(x0, x1),
+                                  place->terrain_map->w);
+               dy = WRAP_DISTANCE(min(y0, y1), max(y0, y1),
+                                  place->terrain_map->h);
+       } else {
+               dx = max(x0, x1) - min(x0, x1);
+               dy = max(y0, y1) - min(y0, y1);
+       }
+
+       return dx + dy;
+}
+
+int place_flying_distance(struct place *place,
+                                  int x0, int y0, int x1, int y1)
+{
+       int dx;
+       int dy;
+
+        place_get_direction_vector(place, x0, y0, x1, y1, &dx, &dy);
+        dx = abs(dx);
+        dy = abs(dy);
+
+       // This approx comes from the angband LOS source, and overestimates
+       // about one tile per fifteen tiles of distance.
+       return ((dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1)));
+}
+
+void place_get_direction_vector(struct place *place, int x0, int y0, int x1, 
+                               int y1, int *dx, int *dy)
+{
+        int east, west, north, south;
+
+        // fixme: is this code assuming that (x0,y0) and (x1,y1) are already
+        // wrapped?
+
+        if (! place->wraps) {
+                *dx = x1 - x0;
+                *dy = y1 - y0;
+                return;
+        }
+
+        // Four possibilities for dx:
+        //
+        // |    x0-->x1    | (a) direct east
+        // |<--x0     x1<--| (b) west across map boundary
+        // |    x1<--x0    | (c) direct west
+        // |-->x1     x0-->| (d) east across map boundary
+        //
+        // Note that since west is always to the left, it is a negative vector.
+        // We compute it as a positive value to make it easy to compare against
+        // east, but convert it to negative before returning it as dx.
+
+        if (x1 > x0) {
+                east = x1 - x0;
+                west = x0 + place->terrain_map->w - x1;
+        } else {
+                west = x0 - x1;
+                east = x1 + place->terrain_map->w - x0;
+        }
+
+        if (west < east)
+                *dx = -west;
+        else
+                *dx = east;
+
+        // Four possibilities for dy:
+        //
+        // ---------------
+        //      ^       |
+        // y0   |   y1  v
+        // |    y0  ^   y1
+        // v        |
+        // y1       y0
+        //      y1      y0
+        //      ^       |
+        //      |       V
+        // ---------------
+        // (a) (b) (c) (d)
+        //
+        // (a) direct south
+        // (b) north across map boundary
+        // (c) direct north
+        // (d) south across map boundary
+        //
+        // Note that north is always a negative vector.
+
+        if (y1 > y0) {
+                south = y1 - y0;
+                north = y0 + place->terrain_map->h - y1;
+        } else {
+                north = y0 - y1;
+                south = y1 + place->terrain_map->h - y0;
+        }
+
+        if (north < south)
+                *dy = -north;
+        else
+                *dy = south;
+}
+
+void place_move_object(struct place *place, Object * object, 
+                       int newx, int newy)
+{
+       struct tile *old_tile;
+        struct tile *new_tile;
+
+        if (newx == object->getX() &&
+            newy == object->getY())
+                return;
+
+        old_tile = place_lookup_tile(place, object->getX(), object->getY());
+       assert(old_tile);
+
+        new_tile = place_lookup_tile(place, newx, newy);
+
+       if (!new_tile) {
+               new_tile = place_create_and_add_tile(place, newx, newy);
+                assert(new_tile);
+       }
+        
+        obj_inc_ref(object);
+        tile_remove_object(old_tile, object);
+        tile_add_object(new_tile, object);
+        obj_dec_ref(object);
+}
+
+int place_add_object(struct place *place, Object * object)
+{
+       struct tile *tile = place_lookup_tile(place, object->getX(),
+                                             object->getY());
+
+       if (!tile) {
+               tile = place_create_and_add_tile(place, object->getX(),
+                                                object->getY());
+               if (!tile)
+                       return -1;
+       }
+
+        tile_add_object(tile, object);
+        place_add_to_turn_list(place, object);
+        mapSetDirty();
+       return 0;
+}
+
+void place_remove_object(struct place *place, Object * object)
+{
+       struct tile *tile = place_lookup_tile(place, object->getX(),
+                                             object->getY());
+       assert(tile);
+
+        obj_inc_ref(object);
+        tile_remove_object(tile, object);
+        place_remove_from_turn_list(place, object);
+        obj_dec_ref(object);
+
+}
+
+Object *place_get_object(struct place *place, int x, int y, enum layer layer)
+{
+       struct tile *tile;
+
+        WRAP_COORDS(place, x, y);
+
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return 0;
+
+        return tile_get_top_object_at_layer(tile, layer);
+}
+
+Object *place_get_filtered_object(struct place *place, int x, int y, int (*filter)(Object*))
+{
+       struct tile *tile;
+
+        WRAP_COORDS(place, x, y);
+
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return 0;
+
+        return tile_get_filtered_object(tile, filter);
+}
+
+class Party *place_get_Party(struct place * place, int x, int y)
+{
+       Object *object;
+
+        WRAP_COORDS(place, x, y);
+
+       // fixme: this will get Character's, too... and be careful because the
+       // pathfinding code appears to rely on this fact.
+       object = place_get_object(place, x, y, being_layer);
+       if (!object)
+               return 0;
+
+       if (!object->isType(PARTY_ID))
+               return 0;
+
+       return (class Party *) object;
+}
+
+class Vehicle *place_get_vehicle(struct place * place, int x, int y)
+{
+       struct tile *tile;
+
+        WRAP_COORDS(place, x, y);
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return 0;
+       return tile->vehicle;
+}
+
+struct terrain_map *place_get_combat_terrain_map(struct place *place,
+                                                int x, int y)
+{
+       struct terrain *terrain;
+
+        WRAP_COORDS(place, x, y);
+       terrain = place->terrain_map->terrain[y * place->terrain_map->w + x];
+       return terrain_combat_map(terrain);
+}
+
+/* Pathfinding ***************************************************************/
+
+static int place_pathfind_is_valid_location(
+        struct place_pathfind_context *context, int from_x, int from_y,
+        int x, int y)
+{
+       class Object *portal;
+
+        //dbg("[%d %d]...", x, y);
+
+        /* I used to check this after passability, but it really belongs first.
+         * In several cases the target location may not be passable but if the
+         * seeker can get adjacent to it that will be good enough. If this is
+         * not what the caller wants, they need to se the PFLAG_ADJACENTNOTOK
+         * flag. */
+       if ((!(context->pflags & PFLAG_ADJACENTNOTOK))
+            && x == context->target_x 
+            && y == context->target_y) {
+                //dbg("ok\n");
+               return 1;
+        }
+
+       if (!place_move_is_passable(context->place, from_x, from_y, x, y, 
+                                    context->requestor, context->pflags)) {
+                //dbg("impassable\n");
+               return 0;
+        }
+
+        // --------------------------------------------------------------------
+        // Check if the caller is blocked by an occupant on this tile.
+        // --------------------------------------------------------------------
+
+       if (0 == (context->pflags & PFLAG_IGNOREBEINGS)) {
+                class Object *occupant;
+                occupant = place_get_object(context->place, x, y, being_layer);
+                if (occupant != NULL) {
+                        if (0 == (context->pflags & PFLAG_IGNORECOMPANIONS) ||
+                            ! context->requestor->isCompanionOf(occupant)) {
+                                //dbg("occupied!\n");
+                                return 0;
+                        }
+                }
+        }
+
+       // --------------------------------------------------------------------
+       // I used to penalize portals in the heuristic routine, but that was
+       // back in the day when I would pathfind for the player on a
+       // right-click. Any more pathfinding is used exclusively for NPCs (or
+       // PC's in follow mode) and I NEVER want them to enter a portal unless
+       // they explicitly want to (and currently they never do). Likewise for
+       // open moongates.
+        //
+        // Addendum: portals are now mechs with "step" signal handlers. The
+        // code below avoids any mechanism which responds to the "step" signal,
+        // including non-portals. That's fine, because anything which responds
+        // to "step" is probably something I want to avoid.
+        //
+        // Addendum 2: fix for SF Bug #[ 1523230 ] "pathfinding across
+        // mechs". Added the new IGNORESTEPTRIG flag and wrapped the following
+        // with a check. Currently the only time this flag should be set is in
+        // pathfinding done by player party member's in Follow Mode.
+        // --------------------------------------------------------------------
+
+       if (0 == (context->pflags & PFLAG_IGNORESTEPTRIG)) {
+                if ((portal = 
+                     place_get_object(context->place, x, y, mech_layer)) 
+                    && portal->canStep()) {
+                        //dbg("portal!\n");
+                        return 0;
+                }
+        }
+
+        //dbg("ok\n");
+       return 1;
+}
+
+static void place_pathfind_heuristic(struct astar_search_info *info,
+                                     int *goodness, int *cost, 
+                                     int from_x, int from_y)
+{
+       struct terrain *terrain;
+       struct place_pathfind_context *context;
+
+       context = (struct place_pathfind_context *) info->context;
+
+       /* The basic goodness is walking distance. Duplicate that algorithm
+        * except pay attention to the info->flags. */
+
+       if ((info->flags & ASTAR_HORZ) == 0) {
+               // Yes, we are interested in the x coordinate of the
+               // destination.
+               if (context->place->wraps) {
+                       *goodness -= WRAP_DISTANCE(min(info->x0, info->x1),
+                                                  max(info->x0, info->x1),
+                                               context->place->terrain_map->w);
+               } else {
+                       *goodness -= max(info->x0, info->x1) - 
+                                min(info->x0, info->x1);
+               }
+       }
+
+       if ((info->flags & ASTAR_VERT) == 0) {
+               // Yes, we are interested in the y coordinate of the
+               // destination.
+               if (context->place->wraps) {
+                       *goodness -= WRAP_DISTANCE(min(info->y0, info->y1),
+                                                  max(info->y0, info->y1),
+                                               context->place->terrain_map->h);
+               } else {
+                       *goodness -= max(info->y0, info->y1) -
+                                min(info->y0, info->y1);
+               }
+       }
+
+        /* Add the terrain cost. */
+        *cost += place_get_diagonal_movement_cost(context->place, from_x, 
+                                                  from_y, info->x0, info->y0, 
+                                                  context->requestor, PFLAG_IGNOREMECHS);
+
+       /* And penalize tiles with hazards on them. I really should assign
+        * different penalties to different hazerds. */
+       terrain = place_get_terrain(context->place, info->x0, info->y0);
+       if (terrain->effect)
+               *cost += kern_intvar_get("AP_TOTAL:normal_human") * 9;
+
+       if (place_get_object(context->place, info->x0, info->y0,
+                            field_layer) != NULL)
+               *cost += kern_intvar_get("AP_TOTAL:normal_human") * 9;
+}
+
+/* If pathfinding over a nontrivial distance, make a quick check to see if a
+ * path is impossible due to impassable terrain surrounding the target. This is
+ * an optimization hack to avoid the worst-case search time where a path cannot
+ * be found.
+ */
+static int place_find_path_impossible(struct place_pathfind_context *context)
+{
+        /* Check final destination */
+        if ((context->pflags & PFLAG_ADJACENTNOTOK) 
+            && ! place_is_passable(context->place, context->target_x, 
+                                   context->target_y, context->requestor, 
+                                   context->pflags)) {
+                return 0;
+        }
+
+        /* check four neighbors */
+        if (place_pathfind_is_valid_location(context,
+                                             context->target_x,
+                                             context->target_y,
+                                             context->target_x-1,
+                                             context->target_y)
+            || place_pathfind_is_valid_location(context,
+                                                context->target_x,
+                                                context->target_y,
+                                                context->target_x+1,
+                                                context->target_y)
+            || place_pathfind_is_valid_location(context,
+                                                context->target_x,
+                                                context->target_y,
+                                                context->target_x,
+                                                context->target_y-1)
+            || place_pathfind_is_valid_location(context,
+                                                context->target_x,
+                                                context->target_y,
+                                                context->target_x,
+                                                context->target_y+1))
+                return 0;
+
+        /* all 4 neighbors impassable so forget it */
+        return 1;
+
+}
+
+struct astar_node *place_find_path(struct place *place, 
+                                   struct astar_search_info *info, 
+                                   class Object *requestor)
+{
+       struct astar_node *path;
+       struct place_pathfind_context context;
+        int t1;
+
+       /* Store the target location as the context */
+       context.place = place;
+       context.target_x = info->x1;
+       context.target_y = info->y1;
+       context.pflags = info->flags;
+        context.requestor = requestor;
+
+        if (place_find_path_impossible(&context))
+                return NULL;
+        
+       /* Fill out the search information */
+       info->is_valid_location =
+           (int (*)(void *, int, int, int, int))
+                place_pathfind_is_valid_location;
+       info->heuristic = place_pathfind_heuristic;
+       info->width = place_w(place);
+       info->height = place_h(place);
+       info->wraps = place->wraps;
+       info->context = &context;
+
+       /* Run the pathfinding alg */
+        t1 = SDL_GetTicks();
+       path = astar_search(info);
+        ////dbg("place_find_path: %d msecs\n", SDL_GetTicks() - t1);
+
+       return path;
+
+}
+
+/**
+ *  Calls place_find_path with the search info setup to seek a map edge.x
+ */
+struct astar_node *place_find_path_to_edge(struct place *place, int x0, int y0,
+                                           int edgedir, int pflags,
+                                           class Object *requestor)
+{
+        struct astar_search_info info;
+
+        info.x0 = x0;
+        info.y0 = y0;
+        info.flags = pflags;
+        
+        /* setup search info to seek the map edge */
+        switch (edgedir) {
+        case NORTH:
+                info.x1 = 0;
+                info.y1 = 0;
+                info.flags |= ASTAR_HORZ;
+                break;
+        case SOUTH:
+                info.x1 = 0;
+                info.y1 = place_h(place)-1;
+                info.flags |= ASTAR_HORZ;
+                break;
+        case EAST:
+                info.x1 = place_w(place)-1;
+                info.y1 = 0;
+                info.flags |= ASTAR_VERT;
+                break;
+        case WEST:
+                info.x1 = 0;
+                info.y1 = place_h(place)-1;
+                info.flags |= ASTAR_VERT;
+                break;
+        default:
+                return 0;
+        }
+
+        return place_find_path(place, &info, requestor);
+
+}
+
+int place_get_light(struct place *place, int x, int y)
+{
+       int light;
+       struct tile *tile;
+
+        if (place->wraps) {
+                x = place_wrap_x(place, x);
+                y = place_wrap_y(place, y);
+        }
+
+       /* Check if the coordinates are off-map */
+       else if (place_off_map(place, x, y))
+               return 0;
+
+       /* Assign lighting from terrain */
+       light =
+           place->terrain_map->terrain[y * place->terrain_map->w + x]->light;
+
+       /* Assign lighting from tile objects */
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return light;
+        light += tile_get_light(tile);
+
+       return light;
+}
+
+void place_synchronize(struct place *place)
+{
+        session_synch_sched_chars(Session);
+}
+
+static void place_run_on_entry_hook(struct place *place)
+{
+        struct list *elem;
+        list_for_each(&place->on_entry_hook, elem) {
+                closure_list_t *node = (closure_list_t*)elem;
+                closure_exec(node->closure, "pp", place, player_party);
+        }
+}
+
+void place_enter(struct place *place)
+{
+        place_run_on_entry_hook(place);
+        place_synchronize(place);
+}
+
+int place_get_movement_cost(struct place *place, int x, int y, 
+                            class Object *obj, int flags)
+{
+        int cost;
+        struct terrain *t;
+        class Object *tfeat = NULL;
+        class Object *mech = NULL;
+        
+        WRAP_COORDS(place, x, y);
+
+        /* Terrain features override terrain */
+        tfeat = place_get_object(place, x, y, tfeat_layer);
+        if (tfeat) {
+                return obj->getMovementCost(tfeat->getPclass());
+        }
+
+                 t = TERRAIN(place, x, y);
+        cost = obj->getMovementCost(terrain_pclass(t));
+
+        /* Impassable terrain must have a vehicle that makes it passable; use
+         * the cost of vehicle movement */
+        if (PTABLE_IMPASSABLE == cost) {
+                class Vehicle *vehicle;
+                vehicle = place_get_vehicle(place, x, y);
+                if (vehicle)
+                        cost = vehicle->getMovementCost(terrain_pclass(t));
+        }
+        
+       // Is the mech passable?
+       //(place_obj_is_passable(mech, subject, flags) == 
+       //    BLOCKS_PASSABILITY))
+       //       return 0;
+               
+       if (0 == (flags & PFLAG_IGNOREMECHS))
+       {
+              mech = place_get_object(place, x, y, mech_layer);
+              if (mech)
+              {
+                       int mechcost = obj->getMovementCost(mech->getPclass());
+                       if (mechcost > cost)
+                       {
+                               cost = mechcost;
+                       }
+                       }
+               }
+
+        return cost;
+}
+
+int place_get_diagonal_movement_cost(struct place *place, 
+                                     int from_x, int from_y, 
+                                     int to_x, int to_y, class Object *obj,int flags)
+{
+        int cost = place_get_movement_cost(place, to_x, to_y, obj, flags);
+
+        /* Multiply cost of diagonals by 1.4 (pythagorean theorem) */
+        if (place_is_diagonal(place, from_x, from_y, to_x, to_y)) {
+                cost *= 14;
+                cost /= 10;
+        }
+
+        return cost;
+}
+
+int place_is_hazardous(struct place *place, int x, int y)
+{
+        WRAP_COORDS(place, x, y);
+       struct terrain *t = TERRAIN(place, x, y);
+       if (t->effect)
+                return 1;        
+        if (place_get_object(place, x, y, field_layer) != NULL)
+                return 1; 
+       return 0;
+}
+
+void place_set_terrain(struct place *place, int x, int y,
+                      struct terrain *terrain)
+{
+        WRAP_COORDS(place, x, y);
+       TERRAIN(place, x, y) = terrain;
+}
+
+struct terrain *place_get_terrain(struct place *place, int x, int y)
+{
+        WRAP_COORDS(place, x, y);
+       if (place_off_map(place, x, y))
+               return NULL;
+       x = place_wrap_x(place, x);
+       y = place_wrap_y(place, y);
+       return TERRAIN(place, x, y);
+}
+
+static void place_describe_terrain(struct place *place, int x, int y)
+{
+       struct terrain *t = place_get_terrain(place, x, y);
+       log_continue("%s", t->name);        
+}
+
+static int place_describe_objects(struct place *place, int x, int y, 
+                                  int first_thing_listed)
+{
+
+       struct node *l;
+       struct tile *tile;
+       Object *obj = NULL, *prev_obj = NULL;
+       class ObjectType *type = NULL;
+        int n_types;
+        int n_described = 0;
+
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return n_described;
+        
+        // Let's make things simple. Inefficient, but simple. Efficiency is not
+        // so critical here. We'll do this in two passes. Pass one will count
+        // the number of things we need to list. Pass two will print the things
+        // with the proper punctuation.
+
+        // Step 1: count the number of different types of things we need to
+        // list (multiple counts of one type of thing count as 1)
+
+        type = NULL;
+        n_types = 0;
+
+        if (tile->subplace) {
+
+                // ------------------------------------------------------------
+                // FIXME: This has not been fully debugged. It works ok when
+                // there are no objects on the tile, but I don't think the
+                // 'ands' and commas are correct if there are.
+                // ------------------------------------------------------------
+                log_continue(" and the entrance to %s", tile->subplace->name);
+        }
+
+       node_for_each(&tile->objstack, l) {
+
+               obj = (Object *)l->ptr;
+
+               if (obj->getLayer() == cursor_layer)
+                        // Special case: don't describe the cursor
+                        continue;
+
+                if (! obj->isVisible() && ! Reveal && ! obj->isShaded())
+                        continue;
+                
+                // hack: objects without names are assumed to be invisible
+                if (! obj->getName())
+                        continue;
+                
+                if(obj->getObjectType() != type
+                   || ! obj->getObjectType()) {
+                        
+                        // We just found a new type of thing (we know because
+                        // it's different from the last type of thing).
+                       type = obj->getObjectType();
+                        if (obj->isVisible() || Reveal || obj->isShaded())
+                                n_types++;
+                        
+               }
+       }
+
+        if (tile->vehicle && (tile->vehicle->isVisible() || Reveal || 
+                              obj->isShaded()))
+                n_types++;
+
+        if (n_types == 0)
+                // Nothing to list so we're done.
+                return n_described;
+
+
+        // Step 2: now we actually list the things, using the count to help us
+        // decide how to punctuate.
+
+        type = NULL;
+        prev_obj = NULL;
+
+       node_for_each(&tile->objstack, l) {
+
+               obj = (Object *)l->ptr;
+
+               if (obj->getLayer() == cursor_layer)
+                        // Special case: don't describe the cursor
+                        continue;
+
+                if (! obj->isVisible() && ! Reveal && ! obj->isShaded())
+                        continue;
+
+                // hack: objects without names are assumed to be invisible
+                if (! obj->getName())
+                        continue;
+                
+               if (prev_obj == NULL) {
+
+                        // This is the first type of thing we need to
+                        // list. Don't print it until we find out how many
+                        // there are.
+                       type = obj->getObjectType();
+
+               } else if (obj->getObjectType() != type
+                           || !obj->getObjectType()) {
+
+                        // We just found a new type of thing (we know because
+                        // it's different from the last type of thing). Now we
+                        // can print the last type of thing since we know how
+                        // many there are of it.
+
+                        if (prev_obj->isVisible() || Reveal || 
+                            prev_obj->isShaded()) {
+                                if (first_thing_listed) {
+                                        first_thing_listed = 0;
+                                } else {
+                                        if (n_types == 1)
+                                                log_continue(" and ");
+                                        else
+                                                log_continue(", ");
+                                }
+
+                                prev_obj->describe();
+                                n_described++;
+                                n_types--;
+                        }
+
+                       type = obj->getObjectType();
+
+               }
+
+                prev_obj = obj;
+       }
+
+        // Now we have to print the last object in the stack.
+        if (prev_obj && (prev_obj->isVisible()  || Reveal || 
+                         prev_obj->isShaded())) {
+                if (!first_thing_listed) {
+                        if (n_types == 1)
+                                log_continue(" and ");
+                        else
+                                log_continue(", ");
+                }
+
+                prev_obj->describe();
+                n_described++;
+                n_types--;
+        }
+
+        if (tile->vehicle && (tile->vehicle->isVisible() || Reveal || 
+                              obj->isShaded())) {
+                if (n_types == 1)
+                        log_continue(" and ");
+                else
+                        log_continue(", ");
+                tile->vehicle->describe();
+                n_described++;
+                n_types--;
+        }
+
+        return n_described;
+
+}                              // myPlaceDescribeObjects()
+
+static void place_examine_objects(struct place *place, int x, int y)
+{
+       //can simplify from place_describe, since entries will have their own
+       //lines.
+       struct node *l;
+       struct tile *tile;
+       Object *obj = NULL;
+
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return;
+
+       if (tile->subplace) {
+                log_continue("\nthe entrance to %s", tile->subplace->name);
+       }
+       
+       node_for_each(&tile->objstack, l) {
+               obj = (Object *)l->ptr;
+
+               if (obj->getLayer() == cursor_layer)
+                               // Special case: don't describe the cursor
+                               continue;
+
+               if (! obj->isVisible() && ! Reveal && ! obj->isShaded())
+                               continue;
+
+               // hack: objects without names are assumed to be invisible
+               if (! obj->getName())
+                               continue;
+         
+               log_end("");
+               log_begin("");   
+               obj->examine();   
+        }
+
+        if (tile->vehicle && (tile->vehicle->isVisible() || Reveal || 
+                              obj->isShaded())) {
+               log_end("");
+               log_begin("");   
+                tile->vehicle->examine();
+        }
+}                              // place_examine_objects()
+
+void place_describe(struct place *place, int x, int y, int flags)
+{
+        int count = 0;
+
+        WRAP_COORDS(place, x, y);
+
+       if (place_off_map(place, x, y)) {
+               log_continue("nothing!");
+               return;
+       }
+        if (flags & PLACE_DESCRIBE_TERRAIN) {
+                place_describe_terrain(place, x, y);
+                count = 1;
+        }
+        if (flags & PLACE_DESCRIBE_OBJECTS)
+                count += place_describe_objects(place, x, y, 
+                                       (flags & PLACE_DESCRIBE_TERRAIN) == 0);
+        if (!count)
+                log_continue("nothing!");
+}
+
+void place_examine(struct place *place, int x, int y)
+{
+       WRAP_COORDS(place, x, y);
+
+       if (place_off_map(place, x, y)) {
+               log_continue("nothing!");
+               return;
+       }
+       
+    place_describe_terrain(place, x, y);
+       place_examine_objects(place, x, y);
+}
+
+void place_for_each_tile(struct place *place, 
+                         void (*fx)(struct tile *tile, void *data), void *data)
+{
+       int i;
+       struct olist *tileList;
+       struct list *tileElem, *tileTmp;
+       struct tile *tile;
+        int count = 0;
+
+        /* Note: took the !Quit check out of these loops because this is called
+         * as part of place_del(), so that check means we never delete any
+         * objects! */
+
+       /* for each bucket */
+       for (i = 0; i < place->objects->n /*&& !Quit*/; i++) {
+
+               tileList = &place->objects->buckets[i];
+               tileElem = tileList->list.next;
+               assert(tileElem->prev == &tileList->list);
+
+               /* for each tile */
+               while (tileElem != &tileList->list /*&& !Quit*/) {
+
+                       tileTmp = tileElem->next;
+                       tile = outcast(tileElem, struct tile, hashlink.list);
+                        
+                        /* invoke the function on the tile */
+                        tile->lock++;
+                        fx(tile, data);
+                        tile->lock--;
+                       if (!tile->objects)
+                               tile_del(tile);
+                        
+                       tileElem = tileTmp;
+                        count++;
+               }
+       }
+}
+
+struct forobj_tile_visitor_info {
+        void (*fx) (class Object *, void *data);
+        void *data;
+};
+
+void place_forobj_tile_visitor(struct tile *tile, void *data)
+{
+        struct forobj_tile_visitor_info *info;
+        info = (struct forobj_tile_visitor_info*)data;
+        tile_for_each_object(tile, info->fx, info->data);
+}
+
+void place_for_each_object(struct place *place, 
+                           void (*fx) (class Object *, void *data),
+                          void *data)
+{
+        struct forobj_tile_visitor_info info;
+        info.fx = fx;
+        info.data = data;
+        place_for_each_tile(place, place_forobj_tile_visitor, &info);
+}
+
+static void place_remove_and_destroy_object(class Object *obj, void *unused)
+{
+        obj_inc_ref(obj);
+        obj->remove();
+        obj_dec_ref(obj);
+}
+
+void place_remove_and_destroy_all_objects(struct place *place)
+{
+        place_for_each_object(place, place_remove_and_destroy_object, NULL);
+}
+
+void place_apply_tile_effects(struct place *place, class Object *obj)
+{
+        class Object *tfeat;
+        class Field *field;
+
+        assert(! obj->isDestroyed());
+
+        // --------------------------------------------------------------------
+        // First check for a terrain feature, which will override any terrain
+        // effects.
+        // --------------------------------------------------------------------
+        tfeat = place_get_object(place, obj->getX(), obj->getY(), tfeat_layer);
+        if (tfeat) {
+                if (tfeat->canStep())
+                        tfeat->step(obj);
+        } else {
+                struct terrain *terrain;                
+                terrain = place_get_terrain(place, obj->getX(), obj->getY());
+                if (terrain->effect) {
+                        obj->applyEffect(terrain->effect);
+                }
+        }
+
+        // --------------------------------------------------------------------
+        // Check if the terrain or feature effect destroyed the object.
+        // --------------------------------------------------------------------
+        if (obj->isDestroyed())
+                return;
+        
+        // --------------------------------------------------------------------
+        // Now apply effects from any fields on that tile.
+        // --------------------------------------------------------------------
+        field = (class Field *)place_get_object(place, 
+                                                obj->getX(),
+                                                obj->getY(), 
+                                                field_layer);
+        if (field && 
+            field != obj && 
+            field->getObjectType()->effect) {
+                obj->applyEffect(field->getObjectType()->effect);
+        }
+
+}
+
+static int place_timed_obj_exec(Object *obj)
+{
+        int time = SDL_GetTicks();
+        obj->exec();
+/*         if (obj->isPlayerControlled()) */
+/*                 return 0; */
+        return SDL_GetTicks() - time;
+        
+}
+
+/***************************************************************************** 
+ * place_exec - run all the objects in a place through one turn
+ *****************************************************************************/
+void place_exec(struct place *place)
+{
+        class Object *obj = NULL;
+        int times = 0;
+
+        /* FIXME: not sure if we still need this assert */
+        assert(Place == place);
+        
+        /* Prevent destruction of the place. */
+        place_lock(place);
+        
+        /* Flush ambient noises one cycle */
+        sound_flush_ambient();
+        
+        /* Start with the first node */
+        place->turn_elem = node_next(&place->turn_list);
+
+        /* Loop over all nodes or until the player quits or dies. */
+        while (place->turn_elem != &place->turn_list
+               && ! Quit
+               && ! player_party->allDead()
+               && ! Reload
+               && place == Place /* otherwise projectiles and damage flashes
+                                  * from the old place are shown in the new
+                                  * place until the turn is over when the
+                                  * player does a switch */
+                ) {
+
+                /* Keep a pointer to the object in the node */
+                obj = (class Object *)place->turn_elem->ptr;
+                obj_inc_ref(obj);
+
+                /* Advance the node pointer now in case we need to remove the
+                 * object while running it. */
+                place->turn_elem = node_next(place->turn_elem);
+
+                /* Check the global time stop thread. Only the player gets to
+                 * move during time stop and no tile effects are applied to
+                 * anything. */
+                if (TimeStop) {
+                        if (obj->isPlayerControlled()
+                            || obj->ignoresTimeStop()) {
+                                obj->exec();
+                        }
+                } else {
+                        /* 'run' the object */
+                        int t = place_timed_obj_exec(obj);
+                        if (PLACE_PROFILE) {
+                                printf("%32s: %d ticks\n", obj->getName(), t);
+                                times += t;
+                        }
+
+                        /* Apply terrain, field and any other environmental
+                         * effects. */
+                        if (obj->isOnMap()
+                            && null_layer != obj->getLayer()
+                                ) {
+                                /* Bugfix: as a result of executing its turn,
+                                 * the object may now be in a different
+                                 * place! */
+                                t = SDL_GetTicks();
+                                place_apply_tile_effects(obj->getPlace(), obj);
+                                times += (SDL_GetTicks() - t);
+                        }
+                }
+
+                /* Check if the object was destroyed. */
+                if (obj->isDestroyed()) {
+
+                        /* Don't delete the player party here, that will be
+                         * handled by the caller. */
+                        if (obj == player_party) {
+                                place_unlock(place);
+                                obj_dec_ref(obj);
+                                return;
+                        }
+
+                        /* Make sure the object was already removed. */
+                        assert(! obj->isOnMap());
+
+                        /* Used to destroy the object explicitly here with
+                         * delete. Now rely on the unref at the bottom of the
+                         * loop to destory it. */
+                }
+
+                /* check for end of combat */
+                //if (combat_get_state() != COMBAT_STATE_DONE) {
+                        combat_analyze_results_of_last_turn();
+                //}
+
+                obj_dec_ref(obj);
+
+                /* Reduce the latency of keystroke handling while running the
+                 * demo in parallel with the menus. */
+                if (Session->is_demo) {
+                        eventHandlePending();
+                }
+        }
+
+        if (PLACE_PROFILE) {
+                printf("*** place_exec: total=%d\n", times);
+        }
+
+        /* Allow the place to be destroyed. */
+        place_unlock(place);
+}
+
+void place_clip_to_map(struct place *place, int *x, int *y)
+{
+       if (place->wraps)
+               return;
+
+       *x = max(*x, 0);
+       *x = min(*x, place_w(place) - 1);
+       *y = max(*y, 0);
+       *y = min(*y, place_h(place) - 1);
+}
+
+// fixme -- combine with mapAnimateProjectile(), use callback for animation
+int place_los_blocked(struct place *place, int Ax, int Ay, int Bx, int By)
+{
+        // Should be called from source to target. Does not test for los on
+        // target tile itself, but stops one short. So opaque tiles are visible
+        // if they are the destination.
+
+        // Apply the bresenhaum algorithm to walk the line from (x0, y0) to
+        // (x1, y1) and check for visibility at each step. Note that the real
+        // intention here is to see if I can fire an arrow from one point to
+        // another. The missile flight code in Missile:animate() uses a test
+        // for visibility on each tile to determine if a missile is blocked in
+        // its flight path.
+
+        int steps = 0;
+
+        //Ax = place_wrap_x(place, Ax);
+        //Ay = place_wrap_y(place, Ay);
+        //Bx = place_wrap_x(place, Bx);
+        //By = place_wrap_y(place, By);
+
+        int Px = Ax;
+        int Py = Ay;
+
+        // Get the distance components
+        int dX = Bx - Ax;
+        int dY = By - Ay;
+        int AdX = abs(dX);
+        int AdY = abs(dY);
+
+        // Moving left?
+        int Xincr = (Ax > Bx) ? -1 : 1;
+
+        // Moving down?
+        int Yincr = (Ay > By) ? -1 : 1;
+
+        // Walk the x-axis
+        if (AdX >= AdY) {
+
+                int dPr = AdY << 1;
+                int dPru = dPr - (AdX << 1);
+                int P = dPr - AdX;
+
+                // For each x
+                for (int i = AdX; i >= 0; i--) {
+
+                        if (steps > 1 && i > 0) {
+                                if (!place_visibility(place, Px, Py))
+                                        return 1;
+                        }
+
+                        steps++;
+
+                        if (P > 0) {
+                                Px += Xincr;
+                                Py += Yincr;
+                                P += dPru;
+                        }
+                        else {
+                                Px += Xincr;
+                                P += dPr;
+                        }
+                }
+        }
+        // Walk the y-axis
+        else {
+                int dPr = AdX << 1;
+                int dPru = dPr - (AdY << 1);
+                int P = dPr - AdY;
+
+                // For each y
+                for (int i = AdY; i >= 0; i--) {
+
+                        if (steps > 1 && i > 0) {
+                                if (!place_visibility(place, Px, Py))
+                                        return 1;
+                        }
+
+                        steps++;
+
+                        if (P > 0) {
+                                Px += Xincr;
+                                Py += Yincr;
+                                P += dPru;
+                        }
+                        else {
+                                Py += Yincr;
+                                P += dPr;
+                        }
+                }
+        }
+
+        return 0;
+}
+
+/*****************************************************************************
+ * place_contains_hostile -- helper utility to scan for hostiles
+ *****************************************************************************/
+int place_contains_hostiles(struct place *place, Being *subject)
+{
+        struct node *node;
+        class Object *obj;
+        
+        node_for_each(&place->turn_list, node) {
+                obj = (class Object *)node->ptr;
+                if (! obj_is_being(obj))
+                        continue;
+                if (are_hostile((Being*)obj, subject))
+                        return 1;
+        }
+
+        return 0;
+}
+
+static void place_save_object(class Object *object, void *data)
+{
+        struct save *save;
+        save = (struct save*)data;
+        save->enter(save, "(list\n");
+        object->save(save);
+        save->exit(save, "%d %d)\n", object->getX(), object->getY());
+}
+
+static void place_save_objects(struct place *place, struct save *save)
+{
+        struct node *pnode;
+
+        /* Two subtle points about this process:
+           1. to preserve order, save backwards, because the list will be
+              reloaded backwards
+           2. the object which is currently being exec'd gets saved at the head
+              of the list; this ensure that when we restart, the order of exec
+              will continue right where it left off
+         */
+
+        save->enter(save, "(list ;; objects in %s\n", place->tag);
+
+        pnode = node_prev(place->turn_elem);
+        do {
+                pnode = node_prev(pnode);
+                if (pnode != &place->turn_list) {
+                        place_save_object((class Object*)pnode->ptr, save);
+                }
+        } while (pnode != node_prev(place->turn_elem));
+
+        save->exit(save, ") ;; end of objects in %s\n", place->tag);
+}
+
+void place_add_on_entry_hook(struct place *place, closure_t *hook_fx)
+{
+        closure_list_t *node = (closure_list_t*)malloc(sizeof(*node));
+        assert(node);
+        node->closure = hook_fx;
+        list_add(&place->on_entry_hook, &node->list);
+}
+
+static void place_save_hooks(struct place *place, struct save *save)
+{
+        struct list *elem;
+
+        if (list_empty(&place->on_entry_hook)) {
+                save->write(save, "nil ;; on-entry-hook\n");
+                return;
+        }
+
+        save->enter(save, "(list ;; on-entry-hooks\n");
+        list_for_each(&place->on_entry_hook, elem) {
+                closure_list_t *node = (closure_list_t*)elem;
+                closure_save(node->closure, save);
+        }
+        save->exit(save, ")\n");
+}
+
+static void place_save_edge_entrances(struct place *place, struct save *save)
+{
+        int dir;
+
+        save->enter(save, "(list ;; edge entrances\n");
+        for (dir = 0; dir < NUM_PLANAR_DIRECTIONS; dir++) {
+                save->write(save, "(list %3d %3d %3d) ;; %s\n", dir,
+                            place->edge_entrance[dir][0],
+                            place->edge_entrance[dir][1],
+                            directionToString(dir));
+        }
+        save->exit(save, ")\n");
+}
+
+void place_save(struct save *save, void *val)
+{
+        struct place *place;
+        struct list *elem;
+        int i;
+
+        place = (struct place *)val;
+
+        if (place->saved == save->session_id) {
+                /* Already saved once for this session, so do nothing. NOTE: If
+                 * someone is trying to reference this place they need to peek
+                 * in here and use the tag if the place is already saved. It's
+                 * not always valid for me to just write the tag here
+                 * automatically. ADDENDUM: not possible when the session is
+                 * ripping through its entries to save them (unless I add
+                 * another wrapper for place_save), and it turns out to be
+                 * harmless. It puts the occasional place var alone in the
+                 * script, but the interpreter just evaluates it and goes on.
+                 */
+                save->write(save, "%s\n", place->tag);
+                return;
+        }
+
+        place->saved = save->session_id;
+        place->saving_now = 1;
+
+        save->enter(save, "(kern-mk-place '%s \"%s\"\n",
+                    place->tag, 
+                    place->name);
+        save->write(save, "%s ;; sprite\n", 
+                    place->sprite ? sprite_get_tag(place->sprite) : "nil");
+        terrain_map_save(save, place->terrain_map);
+        save->write(save, "%s %s %s %s\n",
+                    place->wraps ? "#t" : "#f",
+                    place->underground ? "#t" : "#f",
+                    place->wilderness ? "#t" : "#f",
+                    place->is_wilderness_combat ? "#t" : "#f"
+                );
+
+        /* Save all subplaces recursively. */
+
+        save->write(save, ";; subplaces\n");
+        if (list_empty(&place->subplaces)) {
+                save->write(save, "nil\n");
+        } else {
+                save->enter(save, "(list\n");
+                list_for_each(&place->subplaces, elem) {
+                        struct place *subplace;
+                        subplace = outcast(elem, struct place, container_link);
+                        assert(subplace->location.place = place);
+                        save->enter(save, "(list\n");
+                        place_save(save, subplace);
+                        save->exit(save, "%d %d) ;; coords of %s\n", 
+                                   subplace->location.x, 
+                                   subplace->location.y,
+                                   subplace->tag);
+                }
+                save->exit(save, ") ; end of subplaces\n");
+        }
+
+        /* Save the neighbors recursively.  Subtle note: because neighborness
+         * is a symmetric relationship, and scheme does not permit forward
+         * declarations, and I don't want to use tags in lieue of recursive
+         * definitions, I don't reference neighbors that have already been
+         * saved. The neighborly relation was already recorded when the
+         * neighbor was saved, and it will be duly restored when the neighbor
+         * is loaded, so we don't need to do it here. Furthermore, we CANNOT do
+         * it here because we are probably dead smack in the middle of the save
+         * routine for that neighbor, so we can't refer to it yet.
+         *
+         * Even more subtle: if the neighbor is in the process of being saved
+         * right now, but it is not our immediate parent in the save call
+         * stack, then upon return to it it will NOT save the neighborly
+         * relation if it thinks we already saved it here! For this reason I
+         * added the "saving_now" flag. If the neighbor is saved, but not
+         * saving now, then I can safely return to its scheme variable name
+         * now, and should do so to preserve the relation.
+         */
+
+        /* first check if there are any unsaved neighbors */
+        for (i = 0; i < array_sz(place->neighbors); i++) {
+                if (place->neighbors[i]
+                    //&& place->neighbors[i]->saved != save->session_id
+                    && ! place->neighbors[i]->saving_now
+                        )
+                        break;
+        }
+
+        if (i == array_sz(place->neighbors)) {
+                /* nope */
+                save->write(save, "nil ;; neighbors\n");
+        } else {
+                /* yep */
+                save->enter(save, "(list\n");
+                for (i = 0; i < array_sz(place->neighbors); i++) {
+                        if (place->neighbors[i]
+                            //&& place->neighbors[i]->saved != save->session_id
+                            && ! place->neighbors[i]->saving_now
+                                ) {
+                                save->enter(save, "(list\n");
+                                place_save(save, place->neighbors[i]);
+                                save->exit(save, "%d)\n", i);
+                        }
+                }
+                save->exit(save, ") ;; end neighbors of %s\n",  place->tag);
+        }
+
+        /* Save the contents */
+
+        //save->enter(save, "(list ;; objects in %s\n", place->tag);
+        //place_for_each_object(place, place_save_object, save);
+        //save->exit(save, ") ;; end of objects in %s\n", place->tag);
+        place_save_objects(place, save);
+        place_save_hooks(place, save);
+        place_save_edge_entrances(place, save);
+        save->exit(save, ") ;; end of place %s\n\n", place->tag);
+        place->saving_now = 0;
+}
+
+static void place_start_object(class Object *object, void *data)
+{
+        object->start();
+}
+
+void place_start(void *val)
+{
+        struct place *place;
+        struct list *elem;
+
+        place = (struct place *)val;
+
+        /* Don't start places multiple times. It tends to screw up things, like
+         * starting cumulative effects on objects multiple times. */
+        if (place->started) {
+                return;
+        }
+        place->started = 1;
+
+        // --------------------------------------------------------------------
+        // Start all subplaces recursively.
+        // --------------------------------------------------------------------
+
+        list_for_each(&place->subplaces, elem) {
+                struct place *subplace;
+                subplace = outcast(elem, struct place, container_link);
+                place_start(subplace);
+        }
+
+        // --------------------------------------------------------------------
+        // Save the contents.
+        // --------------------------------------------------------------------
+
+        place_for_each_object(place, place_start_object, NULL);
+}
+
+int place_add_subplace(struct place *place, struct place *subplace, 
+                       int x, int y)
+{
+       struct tile *tile;
+
+        if (place_off_map(place, x, y))
+                return 0;
+
+        tile = place_lookup_tile(place, x, y);
+
+       if (!tile) {
+               tile = place_create_and_add_tile(place, x, y);
+               if (!tile)
+                       return -1;
+       }
+        
+        /* Bugfix: combat_enter() was calling this and not checking the return
+         * value. If combat was started over a town this would fail, but combat
+         * would proceed normally. This caused two problems: 1. If we saved in
+         * such a combat the game would fail to reload. Or, 2. when
+         * combat_exit() called it would remove the town! The temp combat place
+         * doesn't really need to be attached to the tile, as long as it gets
+         * on the subplace list it will be properly saved/loaded.
+         */
+        if (!subplace->is_wilderness_combat) {
+                if (tile_add_subplace(tile, subplace))
+                        return -1;
+        }
+
+        // Why was I doing this?
+/*         if (subplace->handle) { */
+/*                 session_rm(Session, subplace->handle); */
+/*                 subplace->handle = 0; */
+/*         } */
+
+        subplace->location.place = place;
+        subplace->location.x = x;
+        subplace->location.y = y;
+
+        list_add(&place->subplaces, &subplace->container_link);
+       return 0;
+}
+
+struct place *place_get_subplace(struct place *place, int x, int y)
+{
+       struct tile *tile;
+
+        WRAP_COORDS(place, x, y);
+
+       tile = place_lookup_tile(place, x, y);
+       if (!tile)
+               return 0;
+        return tile->subplace;
+}
+
+void place_remove_subplace(struct place *place, struct place *subplace)
+{
+        /* Bugfix: if wilderness combat is initiated over a town, on exit the
+         * town would be removed from the map! See comments in
+         * place_add_subplace() */
+        if (! subplace->is_wilderness_combat) {
+                struct tile *tile;
+                tile = place_lookup_tile(place, subplace->location.x, 
+                                         subplace->location.y);
+                assert(tile);
+                tile_remove_subplace(tile);
+        }
+        list_remove(&subplace->container_link);
+        // FIXME: make it an orphan?
+}
+
+void place_for_each_object_at(struct place *place, int x, int y, 
+                              void (*fx)(class Object *, void *), void *data)
+{
+        struct tile *tile;
+
+        tile = place_lookup_tile(place, x, y);
+        if (tile)
+                tile_for_each_object(tile, fx, data);
+}
+
+static void place_remove_and_destroy_temporary_object(class Object *obj, 
+                                                      void *unused)
+{
+        if (obj->isTemporary()) {
+                place_remove_and_destroy_object(obj, unused);
+        }
+}
+
+void place_exit(struct place *place)
+{
+        place_for_each_object(place, place_remove_and_destroy_temporary_object,
+                              NULL);
+}
+
+void place_unlock(struct place *place)
+{
+        assert(place->lock);
+
+        place->lock--;
+
+        if (!place->lock && place_is_marked_for_death(place))
+                place_del(place);
+}
+
+int place_get_edge_entrance(struct place *place, int dir, int *x, int *y)
+{
+        if (dir < 0 || dir >= NUM_PLANAR_DIRECTIONS)
+                return -1;
+
+        *x = place->edge_entrance[dir][0];
+        *y = place->edge_entrance[dir][1];
+
+        return 0;
+}
+
+int place_set_edge_entrance(struct place *place, int dir, int x, int y)
+{
+        if (dir < 0 || dir >= NUM_PLANAR_DIRECTIONS)
+                return -1;
+
+        if (x < 0 || x >= place_w(place) ||
+            y < 0 || y >= place_h(place))
+                return -1;
+
+        place->edge_entrance[dir][0] = x;
+        place->edge_entrance[dir][1] = y;
+
+        return 0;
+}
+
+struct place *place_get_neighbor(struct place *place, int dir)
+{
+    if (dir < 0 || dir >= NUM_DIRECTIONS) {
+        return NULL;
+    }
+    return place->neighbors[dir];
+}
+
+int place_in_los(struct place *p1, int x1, int y1,
+                   struct place *p2, int x2, int y2)
+{
+        char *vmask;
+        int x3, y3;
+
+        /* Get the vmask for the origin (viewer's coords) */
+        vmask = vmask_get(p1, x1, y1);
+
+        /* Translate (x2, y2) into vmask coordinates. Notationally, let:
+
+              a = vector from place origin to (x1, y1)
+              b = vector from place origin to (x2, y2)
+              o = vector from place origin to vmask origin
+
+           We already know a, b and (a - o) = (VMASK_W/2, VMASK_H/2). We need
+           to solve for (b - o) and then wrap if the place supports wrapping.
+
+              b - a + (a - o) = b - o
+        */
+
+        x3 = place_wrap_x(p1, x2 - x1 + VMASK_W/2);
+        y3 = place_wrap_y(p1, y2 - y1 + VMASK_H/2);
+
+        if (x3 < 0 ||
+            y3 < 0 ||
+            x3 >= VMASK_W ||
+            y3 >= VMASK_H)
+                return 0;
+
+        return vmask[x3 + y3 * VMASK_W];
+}
+
+void place_set_neighbor(struct place *place, int dir, struct place *neighbor)
+{
+        int opdir = directionToOpposite(dir); 
+       
+        /* unlink current neighbors */
+        if (place->neighbors[dir]) {
+                place->neighbors[dir]->neighbors[opdir] = 0;
+        }
+
+        if (neighbor && neighbor->neighbors[opdir]) {
+                neighbor->neighbors[opdir]->neighbors[dir] = 0;
+        }
+
+        /* link new neighbors */
+        place->neighbors[dir] = neighbor;
+        if (neighbor)
+                neighbor->neighbors[opdir] = place;
+}
+
+void place_set_terrain_map(struct place *place, struct terrain_map *map)
+{
+        if (map == place->terrain_map)
+                return;
+
+        if (place->terrain_map) {
+                terrain_map_unref(place->terrain_map);
+                place->terrain_map = 0;
+        }
+
+        if (map) {
+                place->terrain_map = terrain_map_clone(map, 0);
+        }
+}
diff --git a/src/place.h b/src/place.h
new file mode 100644 (file)
index 0000000..4255c64
--- /dev/null
@@ -0,0 +1,351 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+/* 12/14/2002 Sam Glasby added place_get_terrain()
+ */
+#ifndef place_hdr
+#define place_hdr
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "terrain_map.h"
+#include "list.h"
+#include "node.h"
+#include "object.h"
+#include "Party.h"
+#include "astar.h"
+#include "common.h"
+#include "sky.h"
+#include "sound.h"
+
+#include <SDL.h>
+
+#define place_w(p) ((p)->terrain_map->w)
+#define place_h(p) ((p)->terrain_map->h)
+#define place_index(p,x,y) ((y) * place_w(p) + (x))
+#define place_name(p) ((p)->name)
+#define place_is_wilderness(p) ((p)->wilderness)
+#define place_is_town(p) (!(p)->wilderness)
+#define place_is_dungeon(p) (! (p)->wilderness)
+#define place_is_wrapping(p) ((p)->wraps)
+#define place_get_item(p,x,y) place_get_object((p),(x),(y),item_layer)
+#define place_get_parent(p) ((p)->location.place)
+#define place_get_scale(p) ((p)->scale)
+#define place_get_x(p) ((p)->location.x)
+#define place_get_y(p) ((p)->location.y)
+#define place_is_wilderness_combat(p) ((p)->is_wilderness_combat)
+#define place_lock(p) ((p)->lock++)
+/* place_unlock() is a function (see below) */
+#define place_is_locked(p) ((p)->lock)
+#define place_mark_for_death(p) ((p)->marked_for_death = 1)
+#define place_is_marked_for_death(p) ((p)->marked_for_death)
+#define place_max_distance(p) (place_w(p) + place_h(p))
+#define place_get_all_objects(p) (&(p)->turn_list)
+#define place_get_terrain_map(p) ((p)->terrain_map)
+
+#define PFLAG_HORZ             (1 << 0) /* matches ASTAR_HORZ */
+#define PFLAG_VERT             (1 << 1) /* matches ASTAR_VERT */
+#define PFLAG_IGNOREMECHS      (1 << 2)
+#define PFLAG_IGNOREBEINGS     (1 << 3)
+#define PFLAG_IGNOREVEHICLES   (1 << 4)
+#define PFLAG_IGNORECOMPANIONS (1 << 5)
+#define PFLAG_MOVEATTEMPT      (1 << 6)
+#define PFLAG_IGNORETERRAIN    (1 << 7) /* used by Object::putOnMap */
+#define PFLAG_IGNOREHAZARDS    (1 << 8) /* used by Object::putOnMap */
+#define PFLAG_IGNOREFIELDS     (1 << 9) /* used by Object::putOnMap */
+#define PFLAG_IGNORETFEAT      (1 << 10)
+#define PFLAG_IGNORESTEPTRIG   (1 << 11)
+#define PFLAG_ADJACENTNOTOK    (1 << 12)
+
+// Flags for placeDescribe:
+#define PLACE_DESCRIBE_TERRAIN (1 << 0)
+#define PLACE_DESCRIBE_OBJECTS (1 << 1)
+#define PLACE_DESCRIBE_ALL     (~0)
+
+struct location;
+struct place;
+struct hash;
+
+struct location {
+        struct place *place;
+        int x;
+        int y;
+};
+
+#define PLACE_MAGIC PLACE_ID
+
+struct place {
+
+        // 'magic' is used by the loader to type-check a pointer passed in from
+        // the script.
+        int magic;
+
+        struct node turn_list;   /* list of objects to exec each turn */
+        struct node *turn_elem;  /* iterator over above list */
+
+        struct location location;
+        struct place *neighbors[NUM_DIRECTIONS];
+        char *tag;
+        char *name;
+        struct sprite *sprite;
+        struct terrain_map *original_terrain_map;
+        struct terrain_map *terrain_map;
+        struct hash *objects;
+        int scale;
+        bool wraps;
+        bool dirty;
+        bool underground;
+        bool is_wilderness_combat;
+        bool wilderness;
+
+        // Hack: need this so I can remove the tmp wild combat place after
+        // loading it from a game that saved during combat.
+        void *handle;
+
+        struct list subplaces;      /* list of subplaces */
+        struct list container_link; /* list hook for a subplace */
+        struct list on_entry_hook;  /* on-entry hook */
+
+        int saved;
+        int lock;
+        int marked_for_death : 1;
+        int saving_now : 1;
+        int started : 1;
+
+        /* Coordinates used to position the player in a subplace when he enters
+         * from the edge: */
+        int edge_entrance[NUM_PLANAR_DIRECTIONS][2];
+};
+
+extern struct place *Place;
+
+extern struct place *place_new(const char *tag,
+                               const char *name,
+                               struct sprite *sprite,
+                               struct terrain_map *terrain_map,
+                               int wraps,
+                               int underground,
+                               int wilderness,
+                               int wilderness_combat
+                               );
+
+#ifdef MAP_REGIONS
+
+/* The new region api */
+
+typedef struct region {
+        char *tag;
+        char *name;
+        struct location loc;
+        struct terrain_map *map;
+        struct list objects;
+        struct list subplaces;
+} region_t;
+
+typedef struct region_map {
+        int w;
+        int h;
+        region_t *map;
+} region_map_t;
+
+extern region_t *region_new(char *tag, char *name, struct terrain_map *map);
+extern void region_del(region_t*);
+extern int region_add_object(region_t *, Object *, int x, int y);
+extern int region_rm_object(region_t *, Object *);
+extern int region_add_subplace(region_t *, struct place*, int x int y);
+extern int region_rm_subplace(region_t *, struct place*);
+extern void region_paste_to_place(region_t*, struct place*, int x, int y);
+extern void region_copy_from_place(region_t*, struct place*, int x, int y);
+extern int regions_are_compatible(region_t *a, region_t *b);
+extern struct place *place_new(char *tag,char *name, struct sprite *sprite,
+                               region_map_t *rmap,
+                               int wraps,
+                               int underground,
+                               int wilderness,
+                               int wilderness_combat);
+#endif
+
+extern void place_del(struct place *place);
+
+extern int place_is_passable(struct place *place, int x, int y,
+                             class Object *passer, int flags);
+
+extern int place_is_occupied(struct place *place, int x, int y);
+
+extern int place_visibility(struct place *place, int x, int y);
+
+extern unsigned int place_walking_distance(struct place *place,
+                                           int x0, 
+                                           int y0, int x1, int y1);
+
+extern int place_flying_distance(struct place *place, int x0, int y0, int x1, int y1);
+
+void place_get_direction_vector(struct place *place, int x1, int y1, 
+                                int x2, int y2, int *dx, int *dy);
+
+extern class Party *place_get_Party(struct place *place,
+                                    int x, int y);
+
+extern class Vehicle *place_get_vehicle(struct place *place,
+                                        int x, int y);
+
+extern int place_eval_path(struct place *place,
+                           int x0, int y0, int x1, int y1);
+
+extern void place_move_object(struct place *place, 
+                              class Object *object, int newx, 
+                              int newy);
+extern int place_add_object(struct place *place, Object * object);
+
+extern void place_remove_object(struct place *place, Object * object);
+
+extern Object *place_get_object(struct place *place, int x, int y, enum layer layer);
+
+extern void place_add_moongate(struct place *place, 
+                               class Moongate * moongate);
+
+extern class Party *place_search_for_Party(struct place *place,
+                                           int x,
+                                           int y,
+                                           int radius,
+                                           int (*criteria) (class
+                                                            Party
+                                                            *
+                                                            Party));
+        
+        
+extern struct astar_node *place_find_path(struct place *place, 
+                                          struct astar_search_info *info,
+                                          class Object *requestor);
+
+extern struct astar_node *place_find_path_to_edge(struct place *place, int x0,
+                                                  int y0, int edgedir,
+                                                  int pflags,
+                                                  class Object *requestor);
+
+extern struct terrain_map *place_get_combat_terrain_map(struct place
+                                                        *place, int x,
+                                                        int y);
+        
+static inline int place_off_map(struct place *place, int x, int y) {
+        if (place->wraps)
+                return 0;
+        return (x < 0 || x >= place_w(place) || y < 0 || 
+                y >= place_h(place));
+}
+
+// returns direction location is off map (assumes it *is* off the map- check that first!)
+static inline int place_off_map_dir(struct place *place, int x, int y) 
+{
+    if (y<0) {
+        if (x<0) {
+            return NORTHWEST;
+        } else if (x >= place_w(place)) {
+            return NORTHEAST;
+        } else {
+            return NORTH;
+        }
+    } else if (y>=place_h(place)) {
+        if (x<0) {
+            return SOUTHWEST;
+        } else if (x >= place_w(place)) {
+            return SOUTHEAST;
+        } else {
+            return SOUTH;
+        }
+    } else if (x >= place_w(place)) {
+        return EAST;
+    } else {
+        assert(x<0);
+        return WEST;
+    }
+}
+
+extern void place_clip_to_map(struct place *place, int *x, int *y);
+
+static inline int place_wrap_x(struct place *place, int x) {
+        if (place->wraps)
+                return ((x +
+                         place->terrain_map->w) %
+                        place->terrain_map->w);
+        return x;
+}
+
+static inline int place_wrap_y(struct place *place, int y) {
+        if (place->wraps)
+                return ((y +
+                         place->terrain_map->h) %
+                        place->terrain_map->h);
+        return y;
+}
+
+extern void place_for_each_object(struct place *place, void (*fx) (class Object *, void *data), void *data);
+extern int place_get_light(struct place *place, int x, int y);
+extern void place_set_terrain(struct place *place, int x, int y, struct terrain *terrain);
+extern struct terrain *place_get_terrain(struct place *place, int x, int y);
+extern Uint32 place_get_color(struct place *place, int x, int y);
+extern int place_get_movement_cost(struct place *place,
+                                   int to_x, int to_y, 
+                                   class Object *obj, int flags);
+extern int place_get_diagonal_movement_cost(struct place *place, int from_x, 
+                                            int from_y,
+                                            int to_x, int to_y, 
+                                            class Object *obj, int flags);
+extern int place_adjust_turn_cost(struct place *place, int turns);
+extern int place_is_hazardous(struct place *place, int x, int y);
+extern class Party *place_random_encounter(struct place *);
+extern void place_paint_objects(struct place *place, int mx, int my, int sx, int sy);
+extern int place_los_blocked(struct place *place, int ax, int ay, int bx, int by);
+extern void place_exec(struct place *place);
+extern int place_contains_hostiles(struct place *place, Being *subject);
+extern void place_synchronize(struct place *place);
+extern void place_enter(struct place *place);
+extern void place_remove_and_destroy_all_objects(struct place *place);
+extern void place_save(struct save *, void *val);
+extern void place_start(void *val);
+extern int place_add_subplace(struct place *place, struct place *subplace, 
+                              int x, int y);
+extern struct place *place_get_subplace(struct place *place, int x, int y);
+extern void place_remove_subplace(struct place *place, struct place *subplace);
+extern void place_for_each_object_at(struct place *place, int x, int y, void (*fx)(class Object *, void *), void *);
+extern void place_exit(struct place *place);
+extern void place_unlock(struct place *place);
+extern void place_describe(struct place *place, int x, int y, int flags);
+extern void place_examine(struct place *place, int x, int y);
+extern int place_get_edge_entrance(struct place *place, int dir, int *x, int *y);
+extern int place_set_edge_entrance(struct place *place, int dir, int x, int y);
+extern class Object *place_get_filtered_object(struct place *place, int x, int y, int (*filter)(class Object*));
+extern struct place *place_get_neighbor(struct place *place, int dir);
+extern void place_set_neighbor(struct place *place, int dir, struct place *neighbor);
+extern int place_in_los(struct place *p1, int x1, int y1,
+                        struct place *p2, int x2, int y2);
+extern void place_add_on_entry_hook(struct place *place, closure_t *hook_fx);
+extern void place_set_terrain_map(struct place *place, struct terrain_map *map);
+int place_move_is_passable(struct place *place, int from_x, int from_y,
+                           int to_x, int to_y,
+                           class Object *subject, int flags);
+void place_apply_tile_effects(struct place *place, class Object *obj);
+
+END_DECL
+
+#endif
diff --git a/src/play.c b/src/play.c
new file mode 100644 (file)
index 0000000..41317ce
--- /dev/null
@@ -0,0 +1,374 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+/* 12/14/2002  Added HANDLE command by Sam Glasby.
+ */
+#include "config.h"
+#include "escape.h"
+#include "foogod.h"
+#include "play.h"
+#include "session.h"
+#include "place.h"
+#include "constants.h"
+#include "images.h"
+#include "sprite.h"
+#include "los.h"
+#include "astar.h"
+#include "common.h"
+#include "screen.h"
+#include "console.h"
+#include "status.h"
+#include "player.h"
+#include "sky.h"
+#include "map.h"
+#include "wq.h"
+#include "combat.h"
+#include "cursor.h"
+#include "Arms.h"
+#include "event.h"
+#include "wind.h"
+#include "Container.h"
+#include "dup_constants.h"
+#include "cmdwin.h"
+#include "vehicle.h"
+#include "terrain.h"
+#include "cmd.h"
+#include "debug.h"
+#include "log.h"
+#include "tick.h"
+#include "vmask.h"
+#include "menus.h"
+#include "kern_intvar.h"  // SAM
+#include "nazghul.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <ctype.h>
+// #include <sys/types.h>  // getpid()
+#include <unistd.h>     // getpid()
+#include <errno.h>
+
+#ifndef PROFILE_PLAY_LOOP
+#define PROFILE_PLAY_LOOP 0
+#endif
+
+#ifndef DETAILED_PROFILE
+#define DETAILED_PROFILE 0
+#endif
+
+bool Quit;
+
+static int play_load_session(char *fname);
+
+static bool tickHandler(struct TickHandler *th)
+{
+       Tick++;
+        wqRunToTick(&TickWorkQueue, Tick);
+        sprite_advance_ticks(1);
+        if (music_need_track())
+        {
+               session_run_hook(Session, music_change_hook, "p", Session->player);
+        }
+       return Quit;
+}
+
+static bool quitHandler(struct QuitHandler *kh)
+{
+       cmdQuit();
+        if (Quit) {
+                ExitProgram = 1;
+        }
+       return Quit;
+}
+
+static void play_print_end_of_game_prompt()
+{
+       log_msg("\n\n^c+r*** YOU HAVE DIED ***^c-\n\n");
+        log_msg("No one is left alive in your party!");
+       log_msg("Press any key to exit.\n");
+       getkey(NULL, anykey);
+}
+
+int G_exec_loops = 0;
+
+static void play_reload()
+{
+        char *fname = 0;
+
+        Reload = 0;
+
+        fname = load_game_menu();
+        if (!fname)
+                return;
+
+        tick_pause();
+        play_load_session(fname);
+        free(fname);
+        foogodSetMode(FOOGOD_DEFAULT);
+        session_run_hook(Session, new_game_start_hook, "p", Session->player);
+        place_synchronize(Place);
+        tick_run();
+        vmask_flush_all();
+}
+
+static void play_loop(void)
+{
+        int times[8];
+        int total_time = 0;
+        
+
+        Turn = 0;
+
+        // --------------------------------------------------------------------
+        // Enter the main game loop. Do not exit until the player is dead or
+        // wants to quit.
+        // --------------------------------------------------------------------
+
+        while (true) {
+
+                // ------------------------------------------------------------
+                // If the player party is camping then run the camping hook
+                // so the script can do things like ambushes, visions, etc.
+                // Since we don't know what the script might do check for party
+                // death and the Quit condition when it comes back.
+                // ------------------------------------------------------------
+
+                if (player_party->isCamping()) {
+                        session_run_hook(Session, camping_turn_start_hook, "pp",
+                                         player_party, Place);
+                        if (player_party->allDead()) {
+                                play_print_end_of_game_prompt();
+                                break;
+                        }
+                        if (Quit)
+                                break;
+                }
+
+                // ------------------------------------------------------------
+                // "Execute" the current place. This will loop through all
+                // objects in the current place and give them a chance to
+                // run. This includes player-controlled objects.
+                // ------------------------------------------------------------
+
+                times[0] = SDL_GetTicks();
+                place_exec(Place);
+
+                // ------------------------------------------------------------
+                // Check if the player requested to reload during that last
+                // turn.
+                // ------------------------------------------------------------
+
+                if (Reload) {
+                        play_reload();
+                }
+
+                // ------------------------------------------------------------
+                // Do a non-blocking check to see if any non-user events need
+                // to run (e.g., animation ticks). Normally these events get
+                // run in place_exec() when the game waits for player input,
+                // but if the player party is resting (for example) then that
+                // does not happen. To keep animation looking smooth I added
+                // this next call.
+                // ------------------------------------------------------------
+
+                times[2] = SDL_GetTicks();
+                eventHandlePending();
+
+                if (Reload) {
+                        play_reload();
+                }
+
+                // ------------------------------------------------------------
+                // Check for end-of-game conditions.
+                // ------------------------------------------------------------
+
+                times[3] = SDL_GetTicks();
+                if (player_party->allDead()) {
+                        play_print_end_of_game_prompt();
+                        break;
+                }
+
+                if (Quit)
+                        break;
+
+                // ------------------------------------------------------------
+                // Run all the non-object stuff in the game world.
+                //
+                // NOTE: you should keep the clock update first since most
+                //       things take their cue from the current time.
+                // ------------------------------------------------------------
+
+                times[4] = SDL_GetTicks();
+
+                dec_time_stop(session_ticks_per_turn());
+
+                if (! TimeStop) {
+                        
+                        dec_reveal(session_ticks_per_turn());
+                        dec_quicken(session_ticks_per_turn());
+                        dec_magic_negated(session_ticks_per_turn());
+                        dec_xray(session_ticks_per_turn());
+                        
+                        player_party->advanceTurns(session_ticks_per_turn());
+
+                        int oldHour = Session->clock.hour;
+                        clock_advance(session_ticks_per_turn());
+
+                        // On each change of the hour check characters with
+                        // multi-place schedules to see if they need to be
+                        // introduced to the current place.
+                        if (oldHour != Session->clock.hour) {
+                                session_intro_sched_chars(Session);
+                        }
+
+                        foogodAdvanceTurns();
+                        sky_advance(&Session->sky, 
+                                    NULL != Place && ! Place->underground);
+                        windAdvanceTurns();
+                        wqRunToTick(&TurnWorkQueue, Turn);
+
+                        /* Update the "Turn" counter. This drives the
+                         * TurnWorkQueue, which is still used for scheduled
+                         * things like torches burning out and doors closing.
+                         * Note: this is NOT the turn count shown in the foogod
+                         * window, that one is stored in the session struct and
+                         * is incremented above.
+                         */
+                        Turn += session_ticks_per_turn();
+                }
+
+                G_exec_loops++;
+                times[5] = SDL_GetTicks();
+
+                if (PROFILE_PLAY_LOOP) {
+                        total_time += (times[5]-times[0]);
+                        printf("Loop time=%d avg=%d\n", times[5] - times[0],
+                               total_time/G_exec_loops);
+                        if (DETAILED_PROFILE) {
+                          printf("      place_exec: %d\n", 
+                                 times[1] - times[0]);
+                          printf("     end-of-turn: %d\n", 
+                                 times[2] - times[1]);
+                          printf("  pending events: %d\n", 
+                                 times[3] - times[2]);
+                          printf("     end-of-game: %d\n", 
+                                 times[4] - times[3]);
+                          printf("    advance misc: %d\n", 
+                                 times[5] - times[4]);
+                        }
+                }
+                
+        }
+}
+
+static void updateAfterEvent(void)
+{
+       mapUpdate(REPAINT_IF_DIRTY|REPAINT_IF_OLD);
+}
+
+int playRun(char *fname)
+{
+       struct QuitHandler qh;
+       struct TickHandler th;
+
+        // -------------------------------------------------------------------
+        // Load a new session from a saved file.
+        // -------------------------------------------------------------------
+
+        if (play_load_session(fname)) {
+               return -1;
+        }
+
+        log_msg("'?' for help.");
+
+        foogodSetMode(FOOGOD_DEFAULT);
+
+        // Run the optional startup script.
+        session_run_hook(Session, new_game_start_hook, "p", Session->player);
+
+        /* bugfix: Place may not be set until after the startup script runs, so
+         * now is the first time we can be sure that the following will repaint
+         * the sun and moons. */
+        sky_advance(&Session->sky, 
+                    NULL != Place && ! Place->underground);
+
+        if (! Place) {
+                log_msg("Error: no starting place!");
+                return -1;
+        }
+
+        /* bugfix for [ 1475929 ]: sleeping npcs wake on reloads */
+        place_synchronize(Place);
+
+        mapUpdate(REPAINT_IF_DIRTY);
+        statusRepaint();
+
+       // Setup all the event handlers.
+       qh.fx = quitHandler;
+       th.fx = tickHandler;
+       eventPushQuitHandler(&qh);
+       eventPushTickHandler(&th);
+       eventAddHook(updateAfterEvent);
+        escape_start_handler();
+
+       Quit = false;
+        tick_run();
+
+       // Enter the main event loop. This won't exit until the player quits or
+       // dies.
+        play_loop();
+
+       // Cleanup the event handlers.
+        escape_stop_handler();
+       eventPopTickHandler();
+       eventPopQuitHandler();
+       //eventPopKeyHandler();
+
+        session_del(Session); /* here we go... */
+        Session = 0;
+
+       return 1;
+}
+
+static int play_load_session(char *fname)
+{
+        int error = 0;
+        log_begin("Loading from %s...", fname);
+        log_flush();
+        log_disable();
+       kern_intvar_init();  // SAM: Clear the kern_invar hash for the new session
+        error = session_load(fname);
+        log_enable();
+        if (error) {
+                log_end("^c+rerror^c-!");
+                if (session_get_last_error()) {
+                        log_msg(session_get_last_error());
+                }
+                return -1;
+        }
+        log_end("^c+gok^c-!");
+        assert(Session);
+        log_msg("Save file version is %u.%u.%u", Session->major, Session->minor, Session->release);
+        foogodSetMode(FOOGOD_DEFAULT);
+        session_run_hook(Session, new_game_start_hook, "p", Session->player);
+        return 0;
+}
diff --git a/src/play.h b/src/play.h
new file mode 100644 (file)
index 0000000..44947b1
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef play_h
+#define play_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+extern int playRun(char *game_fname);
+
+END_DECL
+
+#endif
diff --git a/src/player.cpp b/src/player.cpp
new file mode 100644 (file)
index 0000000..dfc89fa
--- /dev/null
@@ -0,0 +1,1896 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "player.h"
+#include "object.h"
+#include "status.h"
+#include "console.h"
+#include "place.h"
+#include "Party.h"
+#include "screen.h"
+#include "sound.h"
+#include "terrain.h"
+#include "map.h"
+#include "foogod.h"
+#include "combat.h"
+#include "wind.h"
+#include "dup_constants.h"
+#include "cmdwin.h"
+#include "vehicle.h"
+#include "sprite.h"
+#include "cmd.h"             // for ui_get_direction()
+#include "Field.h"
+#include "event.h"
+#include "formation.h"
+#include "ctrl.h"
+#include "session.h"
+#include "log.h"
+#include "factions.h"
+#include "gob.h"
+
+#include <unistd.h>
+#include <math.h>
+
+#define CAMPING_TIME_ACCELERATION (TURNS_PER_HOUR)
+
+
+#define DIRLOC(dir,place,coord) { \
+    if ((dir) < 0) \
+        (coord) = place_w((place)) - 1; \
+    else if (! (dir)) \
+        (coord) = place_w((place)) / 2; \
+    else \
+        (coord) = 0; \
+}
+
+extern void play_update_place_viewer(void);    /* hack */
+
+
+static bool apply_damage(class Character * pm, void *amount)
+{
+        pm->damage(*((int *)amount));
+       return false;
+}
+
+void PlayerParty::damage(int amount)
+{
+       /* First apply damage to the vehicle. If the vehicle is destroyed then
+           destroy the party, too. */
+       if (vehicle && vehicle->isVulnerable()) {
+
+                // Subtle: save a pointer to the vehicle. If vehicle->damage()
+                // actually destroys the vehicle, then in a roundabout way by
+                // the time that call returns we will have disembarked (meaning
+                // our usual vehicle pointrer will be NULL). But we still bear
+                // responsibility hear for destroying the vehicle. Messy, but
+                // there you go. It works and I don't care to fool with it.
+                class Vehicle *vehptr = vehicle;
+
+                obj_inc_ref(vehicle);
+               vehicle->damage(amount);
+               mapFlash(0);
+               foogodRepaint();
+
+                /* If the vehicle is destroyed then we are dead. */
+               if (vehptr->isDestroyed()) {
+                       vehicle = NULL;   
+               }
+
+                obj_dec_ref(vehptr);
+
+                return;
+       }
+
+       /* Apply damage to all party members. If they all die then the party is
+           destroyed, too. */
+        forEachMember(apply_damage, &amount);
+}
+
+static bool pc_get_first_living(class Character * pm, void *data)
+{
+        class Character **pc = (class Character**)data;
+       if (!pm->isDead()) {
+                *pc = pm;
+               return true;
+       }
+       return false;
+}
+
+static bool pc_check_if_alive(class Character * pm, void *data)
+{
+       int *count = (int *) data;
+       if (!pm->isDead()) {
+               (*count)++;
+               return false;
+       }
+       return false;
+}
+
+static bool pc_check_if_not_immobilized(class Character * pm, void *data)
+{
+       int *count = (int *) data;
+       if (!pm->isAsleep()) {
+               (*count)++;
+               return false;
+       }
+       return false;
+}
+
+static bool pc_eat_food(class Character * pm, void *data)
+{
+        if (pm->isDead()) {
+                return false;
+        }
+
+       if (player_party->food) {
+               player_party->food--;
+               return false;
+       }
+
+       log_msg("Starving!");
+
+        /* Partial fix for SF BUG [ 1526910 ] "starvation is lame". Instead of
+         * a fixed amount of damage, make damage proportional to existing
+         * health. The player can starve for a while before dying, but the loss
+         * of HP is a serious threat now even at high levels. */
+       int damage = max(pm->getHp()/2, 1);
+       apply_damage(pm, &damage);
+       return false;
+}
+
+void PlayerParty::changePlaceHook()
+{
+        mapSetPlace(place);
+        Place = place;
+        place_enter(place);
+        log_banner("Entering %s", Place->name);
+        
+        // --------------------------------------------------------------------
+        // If the party is relocating to a non-wilderness place then I have to
+        // break it out.
+        // --------------------------------------------------------------------
+        
+        if (! place_is_wilderness(place)) {
+                distributeMembers(place, x, y, dx, dy);
+                return;
+        } else {
+            foogod_set_title("Wilderness Travel");
+            foogodRepaint();
+        }
+}
+
+enum move_result PlayerParty::check_move_to(struct move_info *info)
+{
+       class Party *npc_party;
+
+       // null place?
+       if (!info->place)
+               return move_null_place;
+
+       info->x = place_wrap_x(info->place, info->x);
+       info->y = place_wrap_y(info->place, info->y);
+
+       // off-map?
+       if (place_off_map(info->place, info->x, info->y)) {
+               return move_off_map;
+       }
+       // occupied (this handles occupied vehicles, too)
+       if ((npc_party = place_get_Party(info->place, info->x, info->y))) {
+               if (are_hostile(this, npc_party)) {
+                       if (info->place->wilderness) {
+                               info->npc_party = npc_party;
+                       }
+                       return move_enter_combat;
+               }
+               return move_occupied;
+       }
+       // another vehicle?
+       if (vehicle && place_get_vehicle(info->place, info->x, info->y))
+               return move_occupied;
+
+        // pass subp vehi
+        // *    t    t    exit vehicle
+        // t    f    *    ok
+        // f    f    *    impassable
+
+        info->subplace = place_get_subplace(info->place, info->x, info->y);
+        if (info->subplace) {
+                if (vehicle)
+                        return move_not_in_vehicle;
+                return move_enter_subplace;
+        }
+
+       // passable? I moved this check to be before a test for portals. A
+       // portal is accessible iff the player can move across the terrain it
+       // is placed on. The "ladder in the lake to the ladder on land" test
+       // case just plain looks counterintuitive without it.
+       if (!place_move_is_passable(info->place, info->x - info->dx, info->y-info->dy, info->x, info->y, this, 
+                               PFLAG_MOVEATTEMPT))
+               return move_impassable;
+
+       return move_ok;
+}
+
+bool PlayerParty::turn_vehicle(void)
+{
+       int cost = 0;
+
+       // Three possible outcomes:
+       // 
+       // 1. We do NOT turn any vehicle, therefore we want to continue
+       // processing the move() command which calls us and we do NOT want to
+       // consume any turns (e.g., no vehicle, or horse turning north/south).
+       // 
+       // 2. We DO turn a vehicle, but it does not cost us anything (e.g.,
+       // horse turning east/west).
+       // 
+       // 3. We do turn a vehicle and it cost us a turn (e.g., ship).
+
+       if (!vehicle || !vehicle->turn(dx, dy, &cost) || !vehicle->mustTurn())
+               return false;
+
+       return true;
+}
+
+
+/* Note it is not safe to modify the member list within the block of the below
+ * 'iterator'  */
+#define FOR_EACH_MEMBER(e,c) \
+        for ((e) = node_next(&members), (c) = (class Character *)(e)->ptr; \
+           (e) != &members; \
+           (e) = node_next(e), (c) = (class Character *)(e)->ptr)
+
+#define FOR_EACH_REVERSE_MEMBER(e,c) \
+        for ((e) = node_prev(&members), (c) = (class Character *)(e)->ptr; \
+           (e) != &members; \
+           (e) = node_prev(e), (c) = (class Character *)(e)->ptr)
+
+
+void PlayerParty::distributeMembers(struct place *new_place, int new_x, 
+                                     int new_y, int new_dx, int new_dy)
+{
+        // --------------------------------------------------------------------
+        // Remove the player party from the current place and remove its view
+        // from the map viewer's consideration (instead we'll use the character
+        // views, which are added as each character is placed on the map
+        // below).
+        // --------------------------------------------------------------------
+
+        remove();
+
+        // --------------------------------------------------------------------
+        // Switch the current place to the portal destination place.
+        // --------------------------------------------------------------------
+
+        Place = new_place;
+
+        // --------------------------------------------------------------------
+        // Set the new destination place to be the subject of the map
+        // viewer. Center the camera on the portal destination.
+        // --------------------------------------------------------------------
+
+        mapSetPlace(new_place);
+        mapCenterCamera(new_x, new_y);
+        mapSetDirty();
+
+        // --------------------------------------------------------------------
+        // Distribute all the party members centered on the portal destination
+        // point. I assume this always succeeds, which means I'm relying on map
+        // editors to be nice and make nice, clear areas around their portal
+        // entrances.
+        //
+        // For now, I'll reuse the existing combat placement algorithm. Compare
+        // the code below with position_player_party() in combat.c:
+        // --------------------------------------------------------------------
+
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_REVERSE_MEMBER(entry, member) {
+                if (!member->isDead()) {
+
+                        int flags = 0;
+
+                        if (member->putOnMap(new_place, new_x, new_y, 
+                                             2 * size, 0))
+                                continue;
+
+                        // Try again, ignoring other objects.
+                        flags |= PFLAG_IGNOREMECHS;
+                        flags |= PFLAG_IGNOREBEINGS;
+                        if (member->putOnMap(new_place, new_x, new_y, 
+                                             2 * size, flags))
+                                continue;
+
+                        // Try again, ignoring hazards.
+                        flags |= PFLAG_IGNOREHAZARDS;
+                        flags |= PFLAG_IGNOREFIELDS;
+                        if (member->putOnMap(new_place, new_x, new_y, 
+                                             2 * size, flags))
+                                continue;
+
+                        // Try again, ignoring terrain.
+                        flags |= PFLAG_IGNORETERRAIN;
+                        if (member->putOnMap(new_place, new_x, new_y, 
+                                             2 * size, flags))
+                                continue;
+
+                        // Ok, now that should have worked!
+                        assert(0);
+                }
+       }
+
+// I've messed with this a bit. I think it's confusing (even to me!) to have
+// the party mode switched automatically. If it felt natural during play it
+// would be ok, but it's quite the opposite.
+#undef CONFIG_ENABLE_ROUND_ROBIN_ON_ENTRANCE_TO_HOSTILE_PLACE
+#ifdef CONFIG_ENABLE_ROUND_ROBIN_ON_ENTRANCE_TO_HOSTILE_PLACE
+        // --------------------------------------------------------------------
+        // Set the party mode to "follow" by default, but if hostiles are in
+        // this place then set to "character" mode.
+        // --------------------------------------------------------------------
+
+        if (place_contains_hostiles(new_place, this)) {
+                enableRoundRobinMode();
+                combat_set_state(COMBAT_STATE_FIGHTING);                
+        } else {
+                enableFollowMode();
+                combat_set_state(COMBAT_STATE_LOOTING);
+        }        
+#else
+        // --------------------------------------------------------------------
+        // Set the party mode to "follow" by default. If hostiles are present
+        // the user can opt to engage them manually. If hostiles are present
+        // but not visible it's confusing/annoying when the camera does not
+        // follow the party leader. This is especially true when there is only
+        // one party member. 
+        // --------------------------------------------------------------------
+        enableFollowMode();
+        if (place_contains_hostiles(new_place, this)) {
+                combat_set_state(COMBAT_STATE_FIGHTING);                
+        }
+#endif
+        endTurn();
+
+}
+
+enum MoveResult PlayerParty::try_to_enter_subplace_from_edge(
+        struct place *subplace, int dx, int dy)
+{
+        int new_x;
+        int new_y;
+        int dir;
+
+
+        // --------------------------------------------------------------------
+        // There should be no way to get here unless we are already in party
+        // mode, which means we are in the wilderness. And the destination
+        // should never be another wilderness.
+        // --------------------------------------------------------------------
+
+        assert(place_is_wilderness(getPlace()));
+        assert(!place_is_wilderness(subplace));
+
+        // --------------------------------------------------------------------
+        // Entering a subplace REQUIRES a direction so I know which edge of the
+        // subplace the party should enter from. If we don't have one then
+        // prompt the user to get one.
+        // --------------------------------------------------------------------
+
+       if (dx == 0 && dy == 0) {
+               cmdwin_spush("Enter");
+               dir = ui_get_direction();
+       } else {
+               dir = vector_to_8facing(dx, dy);
+       }
+
+        // --------------------------------------------------------------------
+        // Get the entry coordinates from the subplace.
+        // --------------------------------------------------------------------
+
+       switch (dir) {
+       case CANCEL:
+               return UserCanceled;
+       case HERE:
+               return NoDestination;
+       default:
+                if (place_get_edge_entrance(subplace, dir, &new_x, &new_y))
+                        return NoDestination;
+                break;
+       }
+
+        dx = directionToDx(dir);
+        dy = directionToDy(dir);
+
+        relocate(subplace, new_x, new_y);
+
+        return MovedOk;
+}
+
+enum MoveResult PlayerParty::try_to_move_off_map(struct move_info * info)
+{
+         
+        // Yes, I'm making the following unconditional with no further checks.
+        // The parent tile is _always_ and _unconditionally_ passable.
+        // Consider everything that could make that tile impassable:
+        //   --Terrain on parent map... don't care
+        //   --Autoportals leading elsewhere... ignore them
+        //   --Npc's... they aren't allowed on town tiles in the wilderness,
+        //     and if one sneaks through ignore it
+        //   --Fields... unlikely, and don't care
+        //   --Vehicles (when player is already in one)... ignore them (and
+        //     don't allow player to abandon a vehicle over a town, otherwise
+        //     we can leak vehicles since consecutive abandonments will 
+        //     clobber previous ones)
+        // See notes on the ship problem in discussion #1 of doc/GAME_RULES
+
+        if (! info->place->location.place) {
+                return OffMap;
+        }
+
+        relocate(info->place->location.place, 
+                 info->place->location.x, 
+                 info->place->location.y);
+
+        return MovedOk;
+}
+
+MoveResult PlayerParty::move(int newdx, int newdy)
+{
+       struct move_info info;
+       struct combat_info cinfo;
+        bool teleport = (abs(newdx) > 1 || abs(newdy) > 1);
+
+       mapSetDirty();
+       cmdwin_clear();
+
+       // Cache the requested direction. Can't remember what we use this for
+       // or if it's still necessary.
+       dx = newdx;
+       dy = newdy;
+
+       // Change vehicle facing. This might consume a turn in which case
+       // that's all we'll do.
+       if (!teleport && turn_vehicle())
+               return ChangedFacing;
+
+       // Check the consequences of moving to the target tile.
+       memset(&info, 0, sizeof(info));
+       info.place = getPlace();
+       info.x = x + dx;
+       info.y = y + dy;
+       info.dx = dx;
+       info.dy = dy;
+       switch (check_move_to(&info)) {
+
+       case move_ok:
+        {
+                int mv_cost = 0;
+
+                // No complications. Update the turn counter based on player
+                // speed and terrain difficulties then move the player.
+                mv_cost = place_get_diagonal_movement_cost(info.place, x, y, info.x, info.y, this,0);
+                                       relocate(info.place, info.x, info.y);          
+                if (vehicle)
+                        mv_cost *= vehicle->getMovementCostMultiplier();
+                decActionPoints(mv_cost);
+
+                extern int DeveloperMode;
+                if (DeveloperMode) {
+                    log_msg("mv_cost=%d\n", mv_cost);
+                }
+
+                // none of this is used atm
+                //
+                // // reload mv_cost because diagonal movement shouldnt affect 'very slow' etc
+                //mv_cost = place_get_movement_cost(info.place, info.x, info.y, this,0);
+                //if (vehicle)
+                //        mv_cost *= vehicle->getMovementCostMultiplier();                
+                //if (mv_cost < getSpeed()) {
+                //        progress = "";
+                //} else if (mv_cost < (getSpeed() * 2)) {
+                //        progress = "-slow";
+                //} else {
+                //        progress = "-very slow";
+                //}
+
+               //consolePrint("Move %s%s [%d AP]\n", 
+               //               directionToString(vector_to_8facing(dx, dy)),
+               //               progress, mv_cost);
+
+               return MovedOk;
+        }
+
+       case move_off_map:
+               return try_to_move_off_map(&info);
+               return OffMap;
+
+       case move_occupied:
+               // Occupied by a friendly npc party. If they were unfriendly
+               // we'd be going into combat.
+               return WasOccupied;
+
+       case move_impassable:
+               // Impassable terrain.
+               return WasImpassable;
+
+        case move_not_in_vehicle:
+                return NotInVehicle;
+
+       case move_enter_combat:
+               // Handle combat (possible multiple combats) until we're all
+               // done with them.
+               memset(&cinfo, 0, sizeof(cinfo));
+               cinfo.move = &info;
+
+                // ------------------------------------------------------------
+                // Enter combat on the current square, not the square we're
+                // trying to move onto.
+                // ------------------------------------------------------------
+
+                info.x = getX();
+                info.y = getY();
+                info.px = getX();
+                info.py = getY();
+
+               combat_enter(&cinfo);
+
+                endTurn();
+               return MovedOk;
+
+        case move_enter_subplace:
+
+#if OLD_PRE_ENTRY_INVOCATION
+                // Going to try and move this call to place_enter()... as I
+                // recall I put this here to allow an on-entry hook to prompt
+                // the player to see if he really wants to enter.
+
+                // run the place's pre-entry hook, if applicable
+                if (info.subplace->pre_entry_hook &&
+                    ! closure_exec(info.subplace->pre_entry_hook, "pp", 
+                                   info.subplace, this))
+                        return UserCanceled;
+#endif
+                return try_to_enter_subplace_from_edge(info.subplace, info.dx, 
+                                                       info.dy);
+
+       default:
+               // no other results expected
+               assert(false);
+               return NotApplicable;
+       }
+}
+
+struct sprite *PlayerParty::getSprite(void)
+{
+       if (vehicle)
+               return vehicle->getSprite();
+
+       return sprite;
+}
+
+char *PlayerParty::get_movement_description(void)
+{
+       if (!vehicle)
+               return mv_desc;
+       return vehicle->getMvDesc();
+}
+
+sound_t *PlayerParty::get_movement_sound(void)
+{
+       if (vehicle) {
+               return vehicle->get_movement_sound();
+       }
+       return mv_sound;
+}
+
+bool PlayerParty::add(class ObjectType * type, int quantity)
+{
+       if (!quantity)
+               return true;
+
+        log_begin("You get ");
+        type->describeType(quantity);
+        log_end(NULL);
+
+        return inventory->add(type, quantity);
+}
+
+bool PlayerParty::takeOut(ObjectType *type, int q)
+{
+        // Some types can be in more than one category, so remove from all.
+        log_begin("You lose ");
+        type->describeType(q);
+        log_end(NULL);
+        return inventory->takeOut(type, q);
+}
+
+static bool player_member_rest_one_hour(class Character * pm, void *data)
+{
+        if (pm->isAsleep())
+                pm->rest(1);
+        return false;
+}
+
+void PlayerParty::exec()
+{
+
+        if (allDead())
+                return;
+
+        // NOTE: by running startTurn() after this we are skipping the party
+        // members' start-of-party-turn hooks when resting. That's probably not
+        // desirable.
+
+        if (isResting()) {
+
+                /* After each hour of rest heal/restore party members */
+                if (clock_alarm_is_expired(&rest_alarm)) {
+                        forEachMember(player_member_rest_one_hour, NULL);
+                        clock_alarm_set(&rest_alarm, 60);
+                }
+
+                if (clock_alarm_is_expired(&wakeup_alarm)) {
+                        endResting();
+                }
+
+                return;
+        }
+
+        startTurn();      
+        
+        absorbMemberAPDebt();
+        
+        /* Loiter */
+        if (isLoitering())
+        {
+                               if (clock_alarm_is_expired(&wakeup_alarm))
+                               {
+                                       endLoitering();
+                               }
+                               endTurn();
+        }  
+
+        if (action_points > 0 && ! isDestroyed()) {        
+
+                /* In party mode increment the turn count whenever the player
+                 * moves. I'm assuming he'll move at most once per turn. */
+                session_inc_turn_count();
+                foogodRepaint();
+                
+                ctrl(this);
+
+                if (Session->reloaded)
+                        /* Hack: this object has been destroyed with the old
+                         * session. Leave now! */
+                        return;
+        }
+
+        endTurn();
+}
+
+bool PlayerParty::allDead(void)
+{
+       int count = 0;
+       forEachMember(pc_check_if_alive, &count);
+       return (count == 0);
+}
+
+bool PlayerParty::immobilized(void)
+{
+       int count = 0;
+       forEachMember(pc_check_if_not_immobilized, &count);
+       return (count == 0);        
+}
+
+struct VradInfo {
+       int vrad;
+       int light;
+};
+
+bool myGetBestVisionRadius(class Character * c, void *data)
+{
+       struct VradInfo *info = (struct VradInfo *) data;
+       info->vrad = max(info->vrad, c->getVisionRadius());
+       info->light = max(info->light, c->getLight());
+       return false;
+}
+
+int PlayerParty::getLight()
+{
+        struct node *entry;
+        class Character *member;
+
+        light = 0;
+
+        FOR_EACH_MEMBER(entry, member) {
+                light += member->getLight();
+        }
+
+        return light;
+}
+
+int PlayerParty::getVisionRadius()
+{
+       struct VradInfo info;
+
+       // Scan all party members to find the best light source and the best
+       // eyes. They needn't be from the same member since I assume they are
+       // traveling close enough to share their light sources with each other.
+       info.vrad = 0;
+       info.light = 0;
+       forEachMember(myGetBestVisionRadius, &info);
+
+       // hack -- should replace this with a routine for getting the ambient
+       // light from the local environment (place?)
+        assert(getPlace());
+       if (!getPlace()->underground)
+               info.light += sky_get_ambient_light(&Session->sky);
+
+       // Set the vision radius to the minimum of the best available light
+       // radius or the best available vision radius of all party members
+       light = max(info.light, MIN_PLAYER_LIGHT);
+
+
+        // left off here
+
+       return min(info.vrad, MAX_VISION_RADIUS);
+}
+
+PlayerParty::PlayerParty()
+{
+       dx                 = 0;
+       dy                 = -1;
+       sprite             = 0;
+       speed              = 0;
+       vehicle            = 0;
+       turns              = 0;
+       mv_desc            = NULL;
+       mv_sound           = NULL_SOUND;
+       leader             = NULL;
+       light              = 1;
+       food               = 0;
+       view               = 0;
+       onMap              = true;
+       gold               = 0;
+       formation          = 0;
+       campsite_map       = 0;
+       campsite_formation = 0;
+       camping            = false;
+        resting            = false;
+        loitering          = false;
+        leader             = NULL;
+        solo_member        = NULL;
+        control_mode       = PARTY_CONTROL_ROUND_ROBIN;
+        ctrl               = ctrl_party_ui;
+        inventory          = NULL;
+
+        setTurnsToNextMeal(TURNS_PER_FOOD);
+        setBaseFaction(PLAYER_PARTY_FACTION);
+        view = mapCreateView();
+}
+
+PlayerParty::PlayerParty(char *_tag,
+                           struct sprite *sprite,
+                           char *movement_desc, sound_t *movement_sound,
+                           int _food, int _gold,
+                           struct formation *_formation, 
+                           struct terrain_map *_camping_map,
+                           struct formation *_camping_formation)
+{
+        /* Do standard initialization first. */
+       dx                 = 0;
+       dy                 = -1;
+       speed              = 0;
+       vehicle            = 0;
+       turns              = 0;
+       leader             = NULL;
+       light              = 1;
+       food               = _food;
+       view               = 0;
+       gold               = _gold;
+       formation          = _formation;
+       campsite_map       = _camping_map;
+       campsite_formation = _camping_formation;
+       camping            = false;
+        resting            = false;
+        loitering          = false;
+        leader             = NULL;
+        solo_member        = NULL;
+        control_mode       = PARTY_CONTROL_ROUND_ROBIN;
+        ctrl               = ctrl_party_ui;
+        tag                = 0;
+        inventory          = NULL;
+
+        // --------------------------------------------------------------------
+        // Location (if any) will be set after construction by the loading
+        // code. Initially the party is off-map and on the orphan list.
+        // --------------------------------------------------------------------
+
+        setOnMap(false);
+
+        setTurnsToNextMeal(TURNS_PER_FOOD);
+        setBaseFaction(PLAYER_PARTY_FACTION);
+        view = mapCreateView();
+
+        /* Now use the arguments */
+
+        if (_tag) {
+                tag = strdup(_tag);
+                assert(tag);
+        }
+        
+        this->sprite = sprite;
+        if (movement_desc) {
+                this->mv_desc = strdup(movement_desc);
+                assert(this->mv_desc);
+        } else {
+                mv_desc = 0;
+        }
+
+        this->mv_sound = movement_sound;
+}
+
+PlayerParty::~PlayerParty()
+{
+        if (mv_desc)
+                free(mv_desc);
+
+        obj_dec_ref_safe(inventory);
+
+        // Bugfix: when quitting while on board a vehicle, force the vehicle to
+        // give up its reference to the player (otherwise this causes an
+        // assert in session_del()).
+        if (vehicle) {
+                vehicle->setOccupant(0);
+                vehicle->relocate(getPlace(), getX(), getY());
+                obj_dec_ref(vehicle);
+               vehicle = NULL;
+        }
+
+        /* fixme: need to somehow cancel those wq jobs setup by player_init? */
+}
+
+void PlayerParty::board_vehicle(void)
+{
+       cmdwin_clear();
+
+       // already in a vehicle so exit
+       if (vehicle) {
+                log_begin("You exit ");
+                vehicle->describe();
+                log_end(".");
+               vehicle->setOccupant(0);
+               vehicle->relocate(getPlace(), getX(), getY());
+                obj_dec_ref(vehicle);
+               vehicle = NULL;
+               mapSetDirty();
+
+                /* Erase vehicle hull stats. */
+                foogodRepaint();
+               return;
+       }
+
+       vehicle = place_get_vehicle(Place, x, y);
+       if (!vehicle) {
+               return;
+       }
+
+        obj_inc_ref(vehicle);
+
+        log_begin("You board ");
+        vehicle->describe();
+        log_end(".");
+
+       vehicle->setOccupant(this);
+       vehicle->remove();
+       mapSetDirty();
+
+        /* Show vehicle hull stats. */
+        foogodRepaint();
+
+        /* Prompt the player to name the vehicle so it isn't
+         * garbage-collected. */
+        if (! vehicle->isNamed()) {
+                ui_name_vehicle(vehicle);
+        }
+}
+
+class Character *PlayerParty::get_leader(void)
+{
+        if (leader == NULL) {
+                chooseNewLeader();
+        }
+        return leader;
+}
+
+void PlayerParty::removeMember(class Character *c)
+{
+        struct node *entry;
+        class Character *next_member;
+        int index;
+
+        assert(c->party == (class Party*)this);
+
+        // Remove all its readied arms from party inventory.
+               int armsIndex = 0;
+       for (class ArmsType * weapon = c->enumerateArms(&armsIndex); weapon != NULL; 
+             weapon = c->getNextArms(&armsIndex)) {
+
+               struct inv_entry *ie;
+
+               ie = inventory->search(weapon);
+               assert(ie);
+               ie->ref--;
+               takeOut(weapon, 1);
+       }
+
+        // Re-order the indices of the remaining party members
+        for (entry = node_next(c->plnode), index = c->getOrder(); 
+             entry != &members; 
+             entry = node_next(entry), index++) {
+                next_member = (class Character *)entry->ptr;
+                next_member->setOrder(index);
+        }
+
+        // Relinquish control.
+        c->setPlayerControlled(false);
+        c->setControlMode(CONTROL_MODE_AUTO);
+
+        // remove its view
+        c->rmView();
+        
+        // Unhook it from the party
+        Party::removeMember(c);
+}
+
+bool PlayerParty::addMember(class Character * c)
+{
+       // Note: this is called so early in startup that I can't touch the
+       // paint routines in here. Callers will have to update the map and
+       // status if necessary.
+
+       assert(!c->isPlayerControlled());
+
+        // Hook it to the party
+        Party::addMember(c);
+
+        // Make sure it's not going to try and run a schedule
+        c->setSchedule(NULL);
+
+        // Set special player-controlled flag
+       c->setPlayerControlled(true);
+
+        // gmcnutt: added this as a hack to support quickly determining if a
+        // character belongs to the player party.
+        c->party = (Party*)this;
+
+        // Can't think of any reason why a char should be on the orphan list
+        assert(! c->handle);
+
+        if (NULL == c->getView())
+                c->setView(mapCreateView());
+
+       // Loop over all readied weapons and add them to player inventory. Also
+       // must set the refcount once they are in inventory.
+
+       int armsIndex = 0;
+       for (class ArmsType * weapon = c->enumerateArms(&armsIndex);
+            weapon != NULL; weapon = c->getNextArms(&armsIndex)) {
+
+               struct inv_entry *ie;
+
+               add(weapon, 1);
+               ie = inventory->search(weapon);
+               assert(ie);
+               ie->ref++;
+
+       }
+
+       // Note: leave the readied arms as-is and character inventory as-is for
+       // now.
+
+        // --------------------------------------------------------------------
+        // Reevaluate leadership with the new member added to the group.
+        // --------------------------------------------------------------------
+        if (! c->engagedInTask()) {
+            switch (getPartyControlMode()) {
+            case PARTY_CONTROL_FOLLOW:
+                if (c != get_leader()) {
+                    c->setControlMode(CONTROL_MODE_FOLLOW);
+                }
+                break;
+                
+            case PARTY_CONTROL_SOLO:
+                c->setControlMode(CONTROL_MODE_IDLE);
+                break;
+                
+            case PARTY_CONTROL_ROUND_ROBIN:
+                c->setControlMode(CONTROL_MODE_PLAYER);
+                break;
+                
+            default:
+                assert(false);
+                break;
+            }
+        }
+
+        // Call statusSetMode() to force it to re-evaluate the necessary screen
+        // size for showing the party.
+        statusSetMode(ShowParty);
+
+        // Force a repaint on the status window.
+        statusRepaint();
+
+       return true;
+
+}
+
+void PlayerParty::paint(int sx, int sy)
+{
+       if (vehicle)
+               vehicle->paint(sx, sy);
+       else
+               Object::paint(sx, sy);
+}
+
+const char *PlayerParty::getName()
+{
+       return "player party";
+}
+
+bool PlayerParty::isVisible()
+{
+       return true;
+}
+
+void PlayerParty::describe()
+{
+       log_continue("the %s", getName());
+}
+
+struct formation *PlayerParty::get_formation()
+{
+       if (vehicle && vehicle->get_formation())
+               return vehicle->get_formation();
+       if (camping && campsite_formation)
+               return campsite_formation;
+       return formation;
+}
+
+int PlayerParty::get_num_living_members(void)
+{
+       int count = 0;
+       forEachMember(pc_check_if_alive, &count);
+        return count;
+}
+
+class Character *PlayerParty::get_first_living_member(void)
+{
+        class Character *pc = NULL;
+        forEachMember(pc_get_first_living, &pc);
+        return pc;
+}
+
+void PlayerParty::beginLoitering(int hours)
+{
+        struct node *entry = 0;
+        class Character *member = 0;
+
+        assert(hours > 0);
+
+        log_begin_group();
+        log_msg("Loitering...");
+        FOR_EACH_MEMBER(entry, member) {
+                member->beginLoitering(hours);
+        }
+        log_end_group();
+
+        clock_alarm_set(&wakeup_alarm, hours * 60);
+        loitering = true;
+
+        /* Bugfix for [ 1629974 ] "loitering in wilderness uses too much
+         * food". We want the acceleration to be one hour per turn at the
+         * current map scale. CAMPING_TIME_ACCELERATION is appropriate for a
+         * town-scale wilderness combat map (where camping typically occurs),
+         * but party loitering is done at wilderness scale. */
+        session_set_time_accel((float)CAMPING_TIME_ACCELERATION
+                               / (float)place_get_scale(getPlace()));
+}
+
+bool PlayerParty::isLoitering()
+{
+        return loitering;
+}
+
+void PlayerParty::endLoitering()
+{
+        struct node *entry;
+        class Character *member;
+
+        loitering  = false;
+        session_set_time_accel(1);
+        log_begin_group();
+        FOR_EACH_MEMBER(entry, member) {
+                member->endLoitering();
+        }
+        enableFollowMode();
+        log_end_group();
+}
+
+
+void PlayerParty::forceAbortLoitering()
+{
+       endLoitering();
+       
+       struct node *entry;
+       class Character *member;
+
+       log_begin_group();
+       FOR_EACH_MEMBER(entry, member) {
+               member->resetActionPoints();
+       }
+       log_end_group();
+}
+
+
+static bool member_begin_resting(class Character *member, void *data)
+{
+        member->beginResting(*((int*)data));
+        return false;
+}
+
+void PlayerParty::beginResting(int hours)
+{
+        assert(hours > 0);
+
+        log_begin_group();
+        log_msg("Begin resting...");
+        forEachMember(member_begin_resting, &hours);
+        log_end_group();
+
+        statusRepaint();
+
+        clock_alarm_set(&wakeup_alarm, hours * 60);
+        clock_alarm_set(&rest_alarm, 60);
+        resting   = true;
+
+        mapBlackout(1);
+        mapSetDirty();
+
+        // Accelerate time while resting.
+        session_set_time_accel(CAMPING_TIME_ACCELERATION);
+}
+
+bool PlayerParty::isResting()
+{
+        return (resting || camping);
+}
+
+void PlayerParty::throw_out_of_bed()
+{
+        assert(isResting());
+        endResting();
+}
+
+class Character *PlayerParty::getMemberAtIndex(int index)
+{
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (!index)
+                        return member;
+                index--;
+        }
+
+        return NULL;
+}
+
+static bool member_uncharm(class Character *member, void *data)
+{
+        member->unCharm();
+        return false;
+}
+
+void PlayerParty::unCharmMembers()
+{
+        forEachMember(member_uncharm, NULL);
+}
+
+bool PlayerParty::addToInventory(class Object *object)
+{
+        // ---------------------------------------------------------------------
+        // This is the overloaded generic Object method. For now it is just a
+        // wrapper for the pre-existing, historical add_to_inventory() method.
+        //
+        // Probably about the time I convert the player inventory to use
+        // objects instead of types I'll remove add_to_inventory() and roll the
+        // implementation into here.
+        // ---------------------------------------------------------------------
+
+        add(object->getObjectType(), object->getCount());
+        obj_dec_ref(object);
+        return true;
+}
+
+bool PlayerParty::isCamping()
+{
+        return camping;
+}
+
+void PlayerParty::beginCamping(class Character *guard, int hours)
+{
+        struct node *entry;
+        class Character *member;
+
+        camping    = true;
+        camp_guard = guard;        
+
+        if (camp_guard
+            && ! camp_guard->isDead()
+            && ! camp_guard->isAsleep())
+                camp_guard->beginGuarding(hours);
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (member != camp_guard)
+                        member->beginCamping(hours);
+       }
+
+        // Accelerate time while camping.
+        session_set_time_accel(CAMPING_TIME_ACCELERATION);
+}
+
+void PlayerParty::endCamping()
+{
+        struct node *entry;
+        class Character *member;
+
+        if (! isCamping())
+                return;
+
+        camping    = false;
+
+        // Un-accelerate time when done camping.
+        session_set_time_accel(1);
+
+        if (NULL != camp_guard) {
+                camp_guard->endGuarding();
+                camp_guard = NULL;
+        }
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (member != camp_guard)
+                        member->endCamping();
+        }
+
+}
+
+void PlayerParty::ambushWhileCamping()
+{
+        struct node *entry;
+        class Character *member;
+
+        camping = false;
+
+        // Un-accelerate time when done camping.
+        session_set_time_accel(1);
+
+        FOR_EACH_MEMBER(entry, member) {
+
+                // ------------------------------------------------------------
+                // If there's a guard then he/she/it will wake everybody else
+                // up.
+                // ------------------------------------------------------------
+                
+                if (camp_guard != NULL) {
+                        member->endResting();
+                }
+
+                // ------------------------------------------------------------
+                // Since there is no guard each member will roll to wake up.
+                // ------------------------------------------------------------
+
+                else {
+                        member->ambushWhileCamping();
+                }
+        }
+
+        if (camp_guard)
+                camp_guard->endGuarding();
+}
+
+void PlayerParty::endResting()
+{
+        struct node *entry;
+        class Character *member;
+
+        resting   = false;
+
+        // Un-accelerate time when done resting.
+        session_set_time_accel(1);
+
+        log_begin_group();
+        FOR_EACH_MEMBER(entry, member) {
+                member->endResting();
+        }
+        enableFollowMode();
+        log_end_group();
+
+        mapBlackout(0);
+        mapSetDirty();
+}
+
+// -----------------------------------------------------------------------------
+//
+//      Party control mode functions
+//
+// -----------------------------------------------------------------------------
+
+static bool member_set_control_mode(class Character *member, void *data)
+{
+    if (member->isPlayerControlled()
+        && ! member->engagedInTask()
+        ) {
+        member->setControlMode(*((enum control_mode*)data));
+    }
+    return false;
+}
+
+enum party_control PlayerParty::getPartyControlMode()
+{
+        return control_mode;
+}
+
+void PlayerParty::disableCurrentMode()
+{
+        if (solo_member) {
+                solo_member->setSolo(false);
+                solo_member = NULL;
+        }
+
+        if (leader) {
+                leader->setLeader(false);
+                leader = NULL;
+        }
+}
+
+void PlayerParty::enableFollowMode()
+{
+        enum control_mode mode = CONTROL_MODE_FOLLOW;
+
+        disableCurrentMode();
+        forEachMember(member_set_control_mode, &mode);
+        chooseNewLeader();
+        if (NULL == leader) {
+            enableRoundRobinMode();
+        } else {
+            control_mode = PARTY_CONTROL_FOLLOW;
+            foogod_set_title("Follow: %s", leader->getName());
+            foogodRepaint();
+        }
+
+}
+
+void PlayerParty::enableRoundRobinMode()
+{
+        enum control_mode mode = CONTROL_MODE_PLAYER;
+
+        disableCurrentMode();
+        forEachMember(member_set_control_mode, &mode);
+        control_mode = PARTY_CONTROL_ROUND_ROBIN;
+        foogod_set_title("Round Robin: <pending>");
+        foogodRepaint();
+}
+
+void PlayerParty::enableSoloMode(class Character *solo)
+{
+        enum control_mode mode = CONTROL_MODE_IDLE;
+
+        assert(solo->party == (class Party*)this);
+
+        disableCurrentMode();
+        forEachMember(member_set_control_mode, &mode);
+        solo->setSolo(true);
+        solo_member = solo;
+        control_mode = PARTY_CONTROL_SOLO;
+        foogod_set_title("Solo: %s", solo->getName());
+        foogodRepaint();
+}
+
+void PlayerParty::chooseNewLeader()
+{
+        if (NULL != leader) {
+                leader->setLeader(false);
+                leader = NULL;
+        }
+
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (member->canBeLeader()) {
+                        setLeader(member);
+                        break;
+                }
+        }
+
+        if (NULL != leader) {
+                leader->setLeader(true);
+                if (PARTY_CONTROL_FOLLOW == control_mode) {
+                    foogod_set_title("Follow: %s", leader->getName());
+                    foogodRepaint();
+                }
+        }
+}
+
+void PlayerParty::setLeader(class Character *character)
+{
+        leader = character;
+}
+
+bool PlayerParty::rendezvous(struct place *place, int rx, int ry)
+{
+        bool abort = false;
+        bool done;
+        int max_path_len;
+        struct node *entry;
+        class Character *member;
+
+        assert(NULL != leader);
+
+        // --------------------------------------------------------------------
+        // If any member cannot find a path at least this short than rendezvous
+        // fails
+        // --------------------------------------------------------------------
+
+        max_path_len = 10;
+
+        // --------------------------------------------------------------------
+        // Center the camera on the rendezvous point.
+        // --------------------------------------------------------------------
+
+        mapCenterCamera(rx, ry);
+        mapUpdate(0);
+
+        // --------------------------------------------------------------------
+        // Have each party member find and store a path to the rendezvous
+        // point.
+        // --------------------------------------------------------------------
+
+        FOR_EACH_MEMBER(entry, member) {
+
+                struct astar_search_info as_info;
+
+                // ------------------------------------------------------------
+                // If the member already has a cached path then clean it up.
+                // ------------------------------------------------------------
+                if (member->cachedPath) {
+                        astar_path_destroy(member->cachedPath);
+                        member->cachedPathPlace = NULL;
+                        member->cachedPath = NULL;
+                }
+
+                if (NULL == member 
+                    || member->isDead() 
+                    || !member->isOnMap() 
+                    || member == leader 
+                    || (member->getX() == rx 
+                        && member->getY() == ry))
+                        continue;
+
+                /* The following works for sleeping, but in general is not a
+                 * good solution. What about paralyzation, or other effects
+                 * unknown to the kernel? What will happen is these effects
+                 * will be ignored in the code below. Although technically not
+                 * correct behavior, it shouldn't crash or make the game
+                 * unplayable. */
+                if (member->isAsleep()
+                    || member->engagedInTask()
+                    || ! member->isPlayerControlled()
+                    ) {
+                        abort = true;
+                        continue;
+                }
+
+                memset(&as_info, 0, sizeof (as_info));
+                as_info.x0    = member->getX();
+                as_info.y0    = member->getY();
+                as_info.x1    = rx;
+                as_info.y1    = ry;
+                as_info.flags = PFLAG_IGNOREBEINGS;
+                member->cachedPath = place_find_path(place, &as_info, 
+                                               member);
+
+                if (!member->cachedPath) {
+                        log_msg("%s cannot make the rendezvous!", 
+                                     member->getName());
+                        abort = true;
+                }
+                else if (max_path_len > 0 && 
+                         member->cachedPath->len > max_path_len) {
+                        log_msg("%s is too far away!", 
+                                     member->getName());
+                        abort = true;
+                }
+        }
+
+        // --------------------------------------------------------------------
+        // If anyone could not find a path then abort.
+        // --------------------------------------------------------------------
+
+        if (abort) {
+                FOR_EACH_MEMBER(entry, member) {
+                        if (member->cachedPath) {
+                                astar_path_destroy(member->cachedPath);
+                                member->cachedPath = 0;
+                        }
+                }
+                return false;
+        }
+
+        // --------------------------------------------------------------------
+        // Otherwise everyone has a path, so have them each take turns
+        // following their own path to the rendezvous point.
+        // --------------------------------------------------------------------
+
+        done = false;
+        while (!done) {
+                done = true;
+                //consolePrint(".");
+                FOR_EACH_MEMBER(entry, member) {
+
+                        struct astar_node *tmp;
+
+                        // already arrived in an earlier iteration
+                        if (!member->cachedPath)
+                                continue;
+
+                        // should always be at least two nodes
+                        assert(member->cachedPath->next);
+
+                        // arrived
+                        if (member->cachedPath->next->x == rx && 
+                            member->cachedPath->next->y == ry) {
+                                astar_node_destroy(member->cachedPath);
+                                member->cachedPath = 0;
+                                //member->remove();   // try this... seems ok
+                                continue;
+                        }
+
+                        done = false;
+
+                        // move one step
+                        member->move(
+                                member->cachedPath->next->x - member->getX(), 
+                                member->cachedPath->next->y - member->getY());
+
+                        // clean up used path node
+                        tmp = member->cachedPath;
+                        member->cachedPath = member->cachedPath->next;
+                        astar_node_destroy(tmp);
+
+                        // Bugfix: after rendezvous party members sometimes
+                        // have a heavy action point debt, penalizing them in
+                        // the new place. Zero out the debt during rendezvous
+                        // to prevent that.
+                        member->resetActionPoints();
+
+                        mapUpdate(0);
+                }
+        }
+
+        //consolePrint("Ok!\n");
+
+        return true;
+
+}
+
+int PlayerParty::getContext(void)
+{
+        return (isOnMap() ? CONTEXT_WILDERNESS : CONTEXT_TOWN);
+}
+
+void PlayerParty::addView()
+{
+        attachCamera(true);
+        mapSetPlace(getPlace());
+        Object::addView();
+}
+
+struct place *PlayerParty::getPlaceFromMembers(void)
+{
+        struct node *elem;
+        class Character *member;
+
+        member = get_leader();
+
+        if (member)
+                return member->getPlace();
+
+        FOR_EACH_MEMBER(elem, member) {
+                if (member->isOnMap()) {
+                        return member->getPlace();
+                }
+        }
+
+        return 0;
+}
+
+void PlayerParty::startSession(void)
+{
+        struct node *elem;
+        class Character *member;
+
+
+        if (isOnMap())
+                return;
+
+        // --------------------------------------------------------------------
+        // Not on the map, so we must be in a small-scale place. At least one
+        // of the members needs to be on the map or I can't figure out where
+        // the starting place is. Once I know, I can setup the map viewer and
+        // add all the member views.
+        // --------------------------------------------------------------------
+       
+        Place = getPlaceFromMembers();
+
+        if (! Place)
+                return;
+
+        assert(Place);
+        mapSetPlace(Place);
+        mapSetDirty();
+        setPlace(Place);
+        
+        FOR_EACH_MEMBER(elem, member) {
+                if (member->isOnMap()) {
+                        member->addView();
+                }
+        }
+
+        // --------------------------------------------------------------------
+        // Set the party mode to "follow" by default, but if hostiles are in
+        // this place then set to "character" mode.
+        // --------------------------------------------------------------------
+
+        if (place_contains_hostiles(getPlace(), this)) {
+                enableRoundRobinMode();
+                combat_set_state(COMBAT_STATE_FIGHTING);
+        } else {
+                enableFollowMode();
+                combat_set_state(COMBAT_STATE_DONE);
+        }        
+
+}
+
+void PlayerParty::setOnMap(bool val)
+{
+        if (val == isOnMap())
+                return;
+
+        Object::setOnMap(val);
+
+        // --------------------------------------------------------------------
+        // If the party is going from off-map to on, then remove it from the
+        // orphan list. If the opposite then add it.
+        // --------------------------------------------------------------------
+
+        if (val) {
+                assert(handle);
+                session_rm_obj(Session, this);
+                handle = 0;
+        } else {
+                assert(! handle);
+                session_add_obj(Session, this, player_dtor, player_save, NULL);
+        }
+}
+
+void player_dtor(void *val)
+{
+        class PlayerParty *party = (class PlayerParty*)val;
+        obj_dec_ref(party);
+}
+
+void player_save(save_t *save, void *val)
+{
+        ((class PlayerParty*)val)->save(save);
+}
+
+void PlayerParty::save(save_t *save)
+{
+        save->enter(save, "(let ((kplayer ");
+
+        save->enter(save, "(kern-mk-player\n");
+        if (tag)
+                save->write(save, "'%s\n", tag);
+        else
+                save->write(save, "nil\n");
+        save->write(save, "%s\n", sprite_get_tag(this->sprite));
+        save->write(save, "\"%s\"\n", this->mv_desc);
+        if (NULL_SOUND != mv_sound)
+                save->write(save, "%s\n", sound_get_tag(this->mv_sound));
+        else
+                save->write(save, "nil\n");
+        save->write(save, "%d %d\n", food, gold);
+        save->write(save, "%d ;; turns to next meal\n", 
+                    turns_to_next_meal);
+        save->write(save, "%s\n", 
+                this->formation ? this->formation->tag : "nil");
+        save->write(save, "%s\n", 
+                this->campsite_map ? this->campsite_map->tag : "nil");
+        save->write(save, "%s\n", 
+                this->campsite_formation ? 
+                this->campsite_formation->tag : "nil");
+
+        if (vehicle)
+                vehicle->save(save);
+        else
+                save->write(save, "nil ; player's vehicle\n");
+
+        inventory->save(save);
+
+        if (list_empty(nodelst(&this->members))) {
+                save->write(save, "nil\n");
+        } else {
+                struct node *elem;
+                class Character *ch;
+
+                save->enter(save, "(list\n");
+                FOR_EACH_MEMBER(elem,ch) {
+                        char_save(save, ch);
+                }
+                save->exit(save, ")  ; list of party members\n");
+        }
+
+        save->exit(save, ")))\n"); // end ((kplayer (kern-mk-player ...)))
+
+        if (getGob()) {
+                save->enter(save, "(bind kplayer ");
+                gob_save(getGob(), save);
+                save->exit(save, ")\n");
+        }
+
+        save->exit(save, ")\n"); // end (let ...) block
+}
+
+bool PlayerParty::addFood(int amount)
+{
+        if (amount == 0)
+                return true;
+
+        if (amount > 0)
+                log_msg("You get %d food.", amount);
+        else
+                log_msg("You lose %d food.", -amount);
+
+        food += amount;
+        if (food < 0)
+                food = 0;
+        foogodRepaint();
+
+        return true;
+}
+
+bool PlayerParty::addGold(int amount)
+{
+        if (amount == 0)
+                return true;
+
+        if (amount > 0)
+                log_msg("You get %d gold.", amount);
+        else
+                log_msg("You lose %d gold.", -amount);
+
+        gold += amount;
+        if (gold < 0)
+                gold = 0;
+        foogodRepaint();
+
+        return true;
+}
+
+bool PlayerParty::isPlayerControlled()
+{
+        return true;
+}
+
+void PlayerParty::advanceTurns(int turns)
+{
+        // Check if its time to eat
+        turns_to_next_meal -= turns;
+        if (turns_to_next_meal <= 0) {
+                forEachMember(pc_eat_food, 0);
+                foogodRepaint();
+                turns_to_next_meal += TURNS_PER_FOOD;
+        }
+}
+
+void PlayerParty::setTurnsToNextMeal(int turns)
+{
+        turns_to_next_meal = turns;
+}
+
+bool PlayerParty::hasInInventory(class ObjectType *type)
+{
+        return inventory->search(type) != NULL;
+}
+
+void PlayerParty::unrefInventoryObject(ObjectType *type)
+{
+        struct inv_entry *ie = inventory->search(type);
+        assert(ie);
+        ie->ref--;
+}
+
+void PlayerParty::refInventoryObject(ObjectType *type)
+{
+        struct inv_entry *ie = inventory->search(type);
+        assert(ie);
+        ie->ref++;
+}
+
+void PlayerParty::setInventoryContainer(Container *val)
+{
+        assert(!inventory);
+        assert(val);
+
+        inventory = val;
+        obj_inc_ref(inventory);
+}
+
+void PlayerParty::addExperience(int val)
+{
+        struct node *entry;
+        class Character *member;
+
+        FOR_EACH_MEMBER(entry, member) {
+                if (!member->isDead()) {
+                        member->addExperience(val);
+                }
+        }
+}
+
+bool PlayerParty::canSeeLocation(struct place *place, int x, int y)
+{
+        // fixme -- ref naz.scm (any-player-party-member-visible?)
+        return false;
+}
+
+/* shifts currently wielded items to the top of the equipment list */
+void PlayerParty::sortReadiedItems(class Character * member)
+{
+       struct inv_entry *ie;
+       int armsIndex = 0;
+       for (class ArmsType * weapon = member->enumerateArms(&armsIndex); weapon != NULL; 
+             weapon = member->getNextArms(&armsIndex)) {
+
+               ie = inventory->search(weapon);
+               assert(ie);
+               inventory->moveToFront(ie);
+       }
+}
+
+class Container *PlayerParty::getInventory()
+{
+        // yes, I know it's public, but this is polymorphic with the Party base class
+        return inventory;
+}
diff --git a/src/player.h b/src/player.h
new file mode 100644 (file)
index 0000000..5a17209
--- /dev/null
@@ -0,0 +1,208 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef player_h
+#define player_h
+
+#include "Container.h"
+#include "object.h"
+#include "map.h"
+#include "character.h"
+#include "pinfo.h"
+#include "clock.h" /* for alarm clock */
+#include "place.h" // for struct location
+
+#include <string.h>
+
+enum party_control {
+        PARTY_CONTROL_ROUND_ROBIN = 0,
+        PARTY_CONTROL_FOLLOW,
+        PARTY_CONTROL_SOLO
+};
+
+enum move_result {
+        move_ok = 0,
+        move_off_map,
+        move_null_place,
+        move_occupied,
+        move_enter_combat,
+        move_enter_auto_portal,
+        move_impassable,
+        move_player_quit,
+        move_enter_subplace,
+        move_not_in_vehicle
+};
+
+struct move_info {
+        struct place *place;
+        int x;
+        int y;        
+        int dx;
+        int dy;
+        int px; // parent-x for wilderness combat
+        int py; // parent-y for wilderness combat
+        int turns; // consumed by movement
+        class Party *npc_party;
+        struct place *subplace;
+};
+
+class PlayerParty : public Party {
+      public:
+        PlayerParty(char *tag,
+                     struct sprite *sprite,
+                     char *mv_desc, sound_t *mv_sound,
+                     int food, int gold, 
+                     struct formation *formation, 
+                     struct terrain_map *camping_map,
+                     struct formation *camping_formation);
+       virtual ~ PlayerParty();
+
+        // overloaded Object methods:
+       virtual void addExperience(int delta);
+        virtual bool addToInventory(class Object *object);
+        virtual bool hasInInventory(class ObjectType *type);
+        virtual struct sprite *getSprite(void);
+        virtual const char *getName(void);
+        virtual bool isVisible();
+        virtual void describe();
+        virtual void exec();
+        virtual void damage(int amount);
+        virtual void beginResting(int hours);
+        virtual bool isResting();
+        virtual void beginCamping(class Character *guard, int hours);
+        virtual void endCamping();
+        virtual void ambushWhileCamping();
+        virtual void endResting();
+       virtual int getVisionRadius();
+        virtual void addView();
+        virtual int getLight();
+        virtual void changePlaceHook();
+        virtual bool isPlayerControlled();
+
+        void beginLoitering(int hours);
+        void endLoitering();
+        void forceAbortLoitering();
+        bool isLoitering();
+        void startSession(void);
+        void distributeMembers(struct place *new_place, int new_x, int new_y, 
+                               int new_dx, int new_dy);
+        MoveResult move(int dx, int dy);
+       enum MoveResult try_to_enter_subplace_from_edge(struct place *town,
+                                                        int dx, int dy);
+        void ready_arms(struct object *object);
+        bool allDead(void);
+        bool immobilized(void);
+       void for_each_member(bool(*fx) (class Character *, void *data),
+                            void *data);
+        void board_vehicle(void);
+        class Character *get_leader(void);
+       virtual void removeMember(class Character *);
+        virtual bool addMember(class Character *);
+        void add_spell(struct spell *spell, int quantity);
+        char *get_movement_description();
+        sound_t *get_movement_sound();
+        enum move_result check_move_to(struct move_info *info);
+        virtual void paint(int sx, int sy);
+        virtual struct formation *get_formation();
+        int get_num_living_members(void);
+        class Character *get_first_living_member(void);
+        void throw_out_of_bed();
+        class Character *getMemberAtIndex(int index);
+        void setCombatExitDestination(struct location *loc);
+        void getCombatExitDestination(struct location *loc);
+        void clearCombatExitDestination();
+        void unCharmMembers();
+        void setCamping(bool val);
+        bool isCamping();
+        enum party_control getPartyControlMode();
+        void enableFollowMode();
+        void enableRoundRobinMode();
+        void enableSoloMode(class Character *solo);
+        void setLeader(class Character *character);
+        bool rendezvous(struct place *place, int x, int y);
+        int getContext(void);
+        virtual void setOnMap(bool val);        
+        virtual void save(struct save *save);
+        virtual class Container *getInventory();
+
+        void chooseNewLeader();
+        void advanceTurns(int turns);
+        void setTurnsToNextMeal(int turns);
+        void setTurnsToNextRestCredit(int turns);
+
+        struct sprite *sprite;
+        int turns;
+        char *mv_desc;
+
+        /* Inventory management */
+        Container *inventory;
+        void setInventoryContainer(Container *val);
+        virtual bool addFood(int quantity);
+        virtual bool addGold(int quantity);
+        virtual bool add(ObjectType *type, int amount);
+        virtual bool takeOut(ObjectType *type, int amount);
+        void unrefInventoryObject(ObjectType *type);
+        void refInventoryObject(ObjectType *type);
+        bool canSeeLocation(struct place *place, int x, int y);
+
+        int food;
+        bool onMap;
+        int gold;
+        struct formation *formation;
+        struct terrain_map *campsite_map;
+        struct formation *campsite_formation;
+        void sortReadiedItems(class Character * member);
+
+ protected:
+        enum MoveResult try_to_move_off_map(struct move_info *info);
+        bool turn_vehicle(void);
+        void disableCurrentMode();
+        struct place *getPlaceFromMembers();
+
+        clock_alarm_t wakeup_alarm;
+        clock_alarm_t rest_alarm;
+        bool          resting;
+        int           speed;
+
+        bool camping;
+        class Character *camp_guard;
+
+        enum party_control control_mode;
+        class Character *leader;
+        class Character *solo_member;
+        class Character *active_member;
+        void (*ctrl)(class PlayerParty*);
+        int turns_to_next_rest_credit;
+        int turns_to_next_meal;
+        sound_t *mv_sound;
+        bool loitering;
+
+ private:
+        PlayerParty();
+
+};
+
+//extern class player_party *player_party;
+extern void player_dtor(void *val);
+extern void player_save(struct save *save, void *val);
+
+#endif                         // player_h
diff --git a/src/ptable.c b/src/ptable.c
new file mode 100644 (file)
index 0000000..08f63fd
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "ptable.h"
+
+#include "debug.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#define ptable_index(ptab,mmode,pclass) \
+    ((pclass) * (ptab)->n_mmode + (mmode))
+#define ptable_is_valid_mmode(ptable,mmode) \
+        ((mmode) >= 0 && (mmode) < (ptable)->n_mmode)
+#define ptable_is_valid_pclass(ptable,pclass) \
+        ((pclass) >= 0 && (pclass) < (ptable)->n_pclass)
+
+struct ptable *ptable_new(int n_mmodes, int n_pclass)
+{
+        struct ptable *ptable;
+
+        ptable = (struct ptable*)calloc(1, sizeof(*ptable));
+        assert(ptable);
+
+        ptable->n_mmode = n_mmodes;
+        ptable->n_pclass = n_pclass;
+        ptable->table = (int*)calloc(n_mmodes * n_pclass, sizeof(int));
+        assert(ptable->table);
+
+        return ptable;
+        
+}
+
+static int ptable_check(struct ptable *ptable, int mmode, int pclass)
+{
+        if (! ptable_is_valid_mmode(ptable, mmode)) {
+                warn("ptable_check: invalid mmode=%d\n", mmode);
+                return -1;
+        }
+
+        if (! ptable_is_valid_pclass(ptable, pclass)) {
+                warn("ptable_check: invalid pclass=%d\n", pclass);
+                return -1;
+        }
+
+        return 0;
+}
+
+void ptable_set(struct ptable *ptable, int mmode, int pclass, 
+                int cost)
+{
+        int index;
+
+        if (ptable_check(ptable, mmode, pclass))
+                return;
+
+        if (cost < 0 || cost > PTABLE_IMPASSABLE) {
+                warn("ptable_set: invalid cost=%d\n", cost);
+                return;
+        }
+
+        index = ptable_index(ptable, mmode, pclass);
+        ptable->table[index] = cost;
+}
+
+int ptable_get(struct ptable *ptable, int mmode, int pclass)
+{
+        int index;
+
+        if (ptable_check(ptable, mmode, pclass)) {
+                warn("ptable_get: defaulting to impassable\n");
+                return PTABLE_IMPASSABLE;
+        }
+
+        index = ptable_index(ptable, mmode, pclass);
+        return ptable->table[index];
+}
+
+void ptable_del(struct ptable *ptable)
+{
+        assert(ptable);
+
+        if (ptable->table)
+                free(ptable->table);
+        free(ptable);
+}
diff --git a/src/ptable.h b/src/ptable.h
new file mode 100644 (file)
index 0000000..1e87edf
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef ptable_h
+#define ptable_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+struct ptable {
+        int n_mmode;  /* number of movement modes */
+        int n_pclass; /* number of passability classes */
+        int *table;   /* 2d lookup indexed by mmode & pclass */
+};
+
+#define PTABLE_IMPASSABLE 255
+#define PCLASS_NONE 0
+#define PTABLE_NO_DROP         100             /* movement cost that disallows dropping objects */
+
+
+#define ptable_is_passable(ptable,mmode,pclass) \
+        (ptable_get((ptable),(mmode),(pclass)) != PTABLE_IMPASSABLE)
+
+extern struct ptable *ptable_new(int n_mmodes, int n_pclass);
+extern void ptable_set(struct ptable *ptable, int mmode, int pclass, 
+                       int cost);
+extern int ptable_get(struct ptable *ptable, int mmode, int pclass);
+extern void ptable_del(struct ptable *pass);
+
+END_DECL
+
+#endif
diff --git a/src/repstr.c b/src/repstr.c
new file mode 100644 (file)
index 0000000..a0812b9
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "repstr.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+void repstr(char **sptr, const char *val)
+{
+        if (*sptr == val)
+                return;
+
+        if (*sptr) {
+                free(*sptr);
+                *sptr = 0;
+        }
+        if (val) {
+                *sptr = strdup(val);
+                assert(*sptr);
+        }
+}
diff --git a/src/repstr.h b/src/repstr.h
new file mode 100644 (file)
index 0000000..13b9558
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef repstr_h
+#define repstr_h
+
+/* Replace a string value with a new value. If the string already has a value
+ * it is first freed with free(). The new value is created with
+ * strdup(). Checks for the special case where *sptr==val and does nothing. */
+void repstr(char **sptr, const char *val);
+
+#endif
diff --git a/src/result.h b/src/result.h
new file mode 100644 (file)
index 0000000..162a342
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef result_h
+#define result_h
+
+/* These need to match naz.scm */
+#define RESULT_OK          0
+#define RESULT_NO_TARGET   1
+#define RESULT_NO_EFFECT   2
+#define RESULT_NO_HOSTILES 3
+#define RESULT_LACKS_SKILL 4
+#define RESULT_FAILED      5
+#define RESULT_NOT_HERE    6
+#define RESULT_CRITICAL_FAIL 7
+#define RESULT_NOT_NOW     8
+
+#endif
diff --git a/src/sched.c b/src/sched.c
new file mode 100644 (file)
index 0000000..694021c
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "sched.h"
+#include "common.h"
+#include "scheme-private.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+const char *activity_names[NUM_ACTIVITIES] = {
+        "idle",
+        "working",
+        "sleeping",
+        "commuting",
+        "eating",
+        "drunk",
+        "fighting"
+};
+
+int sched_name_to_activity(char *activity_name)
+{
+        int i;
+        for (i = 0; i < NUM_ACTIVITIES; i++) {
+                if (! strcmp(activity_name, activity_names[i]))
+                        return i;
+        }
+        return -1;
+}
+
+const char *sched_activity_to_name(int activity)
+{
+        if (activity < NUM_ACTIVITIES &&
+            activity >= 0)
+                return activity_names[activity];
+        return NULL;
+}
+
+struct sched *sched_new(char *tag, int n_appts)
+{
+        struct sched *sched;
+        int i;
+
+        sched = (struct sched*)calloc(1, sizeof(*sched));
+        assert(sched);
+
+        sched->tag = strdup(tag);
+        assert(sched->tag);
+
+        sched->n_appts = n_appts;
+        sched->appts = (struct appt*)calloc(n_appts, sizeof(struct appt));
+        assert(sched->appts);
+
+        for (i = 0; i < n_appts; i++)
+                sched->appts[i].index = i;
+
+        return sched;
+}
+
+void sched_del(struct sched *sched)
+{
+       if (!sched)
+               return;
+       if (sched->tag)
+               free(sched->tag);
+       if (sched->appts)
+               free(sched->appts);
+        free(sched);
+}
+
+static struct place *sched_scheme_sym_to_place(scheme *sc, pointer sym)
+{
+        pointer pair;
+
+        assert(sym);
+        assert(sc);
+        assert(sc->vptr->is_symbol(sym));
+
+        pair = sc->vptr->find_slot_in_env(sc, sc->envir, sym, 1);
+        assert(sc->vptr->is_pair(pair));
+
+        return (struct place*)sc->vptr->pair_car(sc->vptr->pair_cdr(pair));
+}
+
+struct appt *sched_get_appointment(struct sched *sched, int hr, int min)
+{
+        int i = 0;
+        struct appt *appt = 0;
+
+        assert(hr >= 0);
+        assert(hr <= 23);
+
+        for (i = 0; i < sched->n_appts; i++) {
+                if (hr < sched->appts[i].hr)
+                        break;
+        }
+
+        assert(i);
+        assert(i <= sched->n_appts);
+
+        appt = &sched->appts[i-1];
+
+        /* resolve the place symbol to a place */
+        if (! appt->place) {
+                appt->place = sched_scheme_sym_to_place(sched->sc, 
+                                                        appt->place_sym);
+                assert(appt->place);
+        }
+
+        return appt;
+}
+
+struct place *sched_appt_get_place(struct sched *sched,
+                                         struct appt *appt)
+{
+        if (! appt->place) {
+                appt->place = sched_scheme_sym_to_place(sched->sc, 
+                                                        appt->place_sym);
+                assert(appt->place);
+        }
+        return appt->place;
+}
diff --git a/src/sched.h b/src/sched.h
new file mode 100644 (file)
index 0000000..01e4366
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef sched_h
+#define sched_h
+
+/* NPC schedules */
+
+#include "list.h"
+#include "scheme.h"           /* for pointer */
+#include "scheme-private.h"   /* for scheme */
+#include "place.h"
+
+/* Reserved activities (if you add one don't forget to update the
+ * activity_names[] array in sched.c) */
+#define NONE           0
+#define WORKING        1
+#define SLEEPING       2
+#define COMMUTING      3
+#define EATING         4
+#define DRUNK          5
+#define FIGHTING       6
+#define NUM_ACTIVITIES 7
+
+struct appt {
+        int hr, min, x, y, w, h, act;
+        int index;             /* into sched array */
+        pointer place_sym;     /* scheme var name for place */   
+        struct place *place;   /* appt place */
+};
+struct sched {
+        /* struct list list; */
+        char *tag;
+        int n_appts;
+        struct appt *appts;
+        scheme *sc;
+};
+
+extern struct sched *sched_new(char *tag, int n_appts);
+extern void sched_del(struct sched*);
+extern int sched_name_to_activity(char *activity_name);
+extern const char *sched_activity_to_name(int activity);
+extern struct appt *sched_get_appointment(struct sched *sched, 
+                                          int hr, int min);
+extern struct place *sched_appt_get_place(struct sched *sched, 
+                                          struct appt *appt);
+
+
+#endif
diff --git a/src/scheme-private.h b/src/scheme-private.h
new file mode 100644 (file)
index 0000000..c6ea26c
--- /dev/null
@@ -0,0 +1,255 @@
+/* scheme-private.h */
+
+#ifndef _SCHEME_PRIVATE_H
+#define _SCHEME_PRIVATE_H
+
+#include "scheme.h"
+/*------------------ Ugly internals -----------------------------------*/
+/*------------------ Of interest only to FFI users --------------------*/
+
+enum scheme_port_kind { 
+  port_free=0, 
+  port_file=1, 
+  port_string=2, 
+  port_input=16, 
+  port_output=32 
+};
+
+typedef struct port {
+  unsigned char kind;
+  union {
+    struct {            
+      FILE *file;
+      int closeit;
+#if USE_FILE_AND_LINE
+      char *name;
+      int line;
+#endif
+    } stdio;
+    struct {
+      char *start;
+      char *past_the_end;
+      char *curr;
+    } string;
+  } rep;
+} port;
+
+/* cell structure */
+struct cell {
+#if USE_PROTECT
+  struct list plist;
+  int pref;
+#endif
+  unsigned int _flag;
+  union {
+    struct {
+      char   *_svalue;
+      int   _length;
+    } _string;
+    num _number;
+    port *_port;
+    foreign_func _ff;
+    struct {
+      struct cell *_car;
+      struct cell *_cdr;
+    } _cons;
+  } _object;
+};
+
+struct scheme {
+/* arrays for segments */
+        func_alloc malloc;
+        func_dealloc free;
+        
+/* return code */
+        int retcode;
+        int tracing;
+        
+#define CELL_SEGSIZE    16*5000  /* # of cells in one segment */
+#define CELL_NSEGMENT   10    /* # of segments for cells */
+        char *alloc_seg[CELL_NSEGMENT];
+        pointer cell_seg[CELL_NSEGMENT];
+        int     last_cell_seg;
+        
+/* We use 4 registers. */
+        pointer args;            /* register for arguments of function */
+        pointer envir;           /* stack register for current environment */
+        pointer code;            /* register for current code */
+        pointer dump;            /* stack register for next evaluation */
+
+        int interactive_repl;    /* are we in an interactive REPL? */
+
+        struct cell _sink;
+        pointer sink;            /* when mem. alloc. fails */
+        struct cell _NIL;
+        pointer NIL;             /* special cell representing empty cell */
+        struct cell _HASHT;
+        pointer T;               /* special cell representing #t */
+        struct cell _HASHF;
+        pointer F;               /* special cell representing #f */
+        struct cell _EOF_OBJ;
+        pointer EOF_OBJ;         /* special cell representing end-of-file object */
+        pointer oblist;          /* pointer to symbol table */
+        pointer global_env;      /* pointer to global environment */
+
+/* global pointers to special symbols */
+        pointer LAMBDA;               /* pointer to syntax lambda */
+        pointer QUOTE;           /* pointer to syntax quote */
+
+        pointer QQUOTE;               /* pointer to symbol quasiquote */
+        pointer UNQUOTE;         /* pointer to symbol unquote */
+        pointer UNQUOTESP;       /* pointer to symbol unquote-splicing */
+        pointer FEED_TO;         /* => */
+        pointer COLON_HOOK;      /* *colon-hook* */
+        pointer ERROR_HOOK;      /* *error-hook* */
+        pointer SHARP_HOOK;  /* *sharp-hook* */
+
+        pointer free_cell;       /* pointer to top of free cells */
+        long    fcells;          /* # of free cells */
+
+        pointer inport;
+        pointer outport;
+        pointer save_inport;
+        pointer loadport;
+
+#define MAXFIL 64
+        port load_stack[MAXFIL];     /* Stack of open files for port -1 (LOADing) */
+        int nesting_stack[MAXFIL];
+        int file_i;
+        int nesting;
+
+        char    gc_verbose;      /* if gc_verbose is not zero, print gc status */
+        char    no_memory;       /* Whether mem. alloc. has failed */
+
+#define LINESIZE 1024
+        char    linebuff[LINESIZE];
+        char    strbuff[256];
+
+        FILE *tmpfp;
+        int tok;
+        int print_flag;
+        pointer value;
+        int op;
+
+        void *ext_data;     /* For the benefit of foreign functions */
+        long gensym_cnt;
+
+        struct scheme_interface *vptr;
+        void *dump_base;        /* pointer to base of allocated dump stack */
+        int dump_size;          /* number of frames allocated for dump stack */
+
+#if USE_PROTECT
+        struct list protect;
+        int ignore_protect;
+#endif
+        char inside; /* gmcnutt: flag to check recursive entry from C */
+
+#if USE_CUSTOM_FINALIZE
+        void (*custom_finalize)(scheme *sc, pointer pp);
+#endif
+};
+
+#define cons(sc,a,b) _cons(sc,a,b,0)
+#define immutable_cons(sc,a,b) _cons(sc,a,b,1)
+
+int is_string(pointer p);
+char *string_value(pointer p);
+int is_number(pointer p);
+num nvalue(pointer p);
+long ivalue(pointer p);
+double rvalue(pointer p);
+int is_integer(pointer p);
+int is_real(pointer p);
+int is_character(pointer p);
+long charvalue(pointer p);
+int is_vector(pointer p);
+
+int is_port(pointer p);
+
+int is_pair(pointer p);
+pointer pair_car(pointer p);
+pointer pair_cdr(pointer p);
+pointer set_car(pointer p, pointer q);
+pointer set_cdr(pointer p, pointer q);
+
+int is_symbol(pointer p);
+char *symname(pointer p);
+int hasprop(pointer p);
+
+int is_syntax(pointer p);
+int is_proc(pointer p);
+int is_foreign(pointer p);
+char *syntaxname(pointer p);
+int is_closure(pointer p);
+#ifdef USE_MACRO
+int is_macro(pointer p);
+#endif
+pointer closure_code(pointer p);
+pointer closure_env(pointer p);
+
+int is_continuation(pointer p);
+int is_promise(pointer p);
+int is_environment(pointer p);
+int is_immutable(pointer p);
+void setimmutable(pointer p);
+int scm_len(scheme *sc, pointer list);
+
+/* convenience macros for extrenal code that uses scheme internals */
+#define scm_protect(sc, cell) \
+        (sc)->vptr->protect((sc), (cell))
+
+#define scm_unprotect(sc, cell) \
+        (sc)->vptr->unprotect((sc), (cell))
+
+#define scm_mk_ptr(sc, val) \
+        (sc)->vptr->mk_foreign_func((sc), (foreign_func)(val))
+
+#define scm_mk_integer(sc, val) \
+        (sc)->vptr->mk_integer((sc), (val))
+
+#define scm_mk_symbol(sc, val) \
+        (sc)->vptr->mk_symbol((sc), (val))
+
+#define scm_mk_string(sc, val) \
+        (sc)->vptr->mk_string((sc), (val))
+
+#define scm_define(sc, sym, val) \
+        (sc)->vptr->scheme_define((sc),  \
+                                  (sc)->global_env,  \
+                                  (sc)->vptr->mk_symbol(sc, (sym)), \
+                                  (val))
+
+
+#define scm_define_int(sc, sym, val) \
+        scm_define(sc, sym, (sc)->vptr->mk_integer((sc), (val)))
+
+#define scm_define_bool(sc, sym, val) \
+        scm_define(sc, sym, (val) ? (sc)->T : (sc)->F)
+
+#define scm_define_ptr(sc, sym, val) \
+        scm_define(sc, sym, scm_mk_ptr(sc, val))
+
+#define scm_is_pair(sc,arg) ((sc)->vptr->is_pair(arg))
+#define scm_is_num(sc, arg) ((sc)->vptr->is_number(arg))
+#define scm_is_int(sc, arg) ((sc)->vptr->is_integer(arg))
+#define scm_is_real(sc, arg) ((sc)->vptr->is_real(arg))
+#define scm_is_str(sc, arg) ((sc)->vptr->is_string(arg))
+#define scm_is_sym(sc, arg) ((sc)->vptr->is_symbol(arg))
+#define scm_is_ptr(sc, arg) ((sc)->vptr->is_foreign(arg))
+#define scm_is_closure(sc, arg) ((sc)->vptr->is_closure(arg))
+
+#define scm_car(sc, arg) ((sc)->vptr->pair_car(arg))
+#define scm_cdr(sc, arg) ((sc)->vptr->pair_cdr(arg))
+
+#define scm_str_val(sc, arg) ((sc)->vptr->string_value(arg))
+#define scm_ptr_val(sc, arg) ((void*)(arg)->_object._ff)
+#define scm_int_val(sc, arg) ((sc)->vptr->ivalue(arg))
+#define scm_real_val(sc, arg) ((sc)->vptr->rvalue(arg))
+#define scm_sym_val(sc, arg) ((sc)->vptr->symname(arg))
+#define scm_closure_code(sc, arg) ((sc)->vptr->closure_code(arg))
+#define scm_closure_env(sc, arg) ((sc)->vptr->closure_env(arg))
+
+#define scm_set_cust_fin(sc, arg) ((sc)->vptr->setcustfin(arg))
+
+
+#endif
diff --git a/src/scheme.c b/src/scheme.c
new file mode 100644 (file)
index 0000000..ced9c24
--- /dev/null
@@ -0,0 +1,4944 @@
+/* T I N Y S C H E M E    1 . 3 3
+ *   Dimitrios Souflis (dsouflis@acm.org)
+ *   Based on MiniScheme (original credits follow)
+ * (MINISCM)               coded by Atsushi Moriwaki (11/5/1989)
+ * (MINISCM)           E-MAIL :  moriwaki@kurims.kurims.kyoto-u.ac.jp
+ * (MINISCM) This version has been modified by R.C. Secrist.
+ * (MINISCM)
+ * (MINISCM) Mini-Scheme is now maintained by Akira KIDA.
+ * (MINISCM)
+ * (MINISCM) This is a revised and modified version by Akira KIDA.
+ * (MINISCM)   current version is 0.85k4 (15 May 1994)
+ *
+ */
+
+#define _SCHEME_SOURCE
+#include "scheme-private.h"
+#if USE_DL
+# include "dynload.h"
+#endif
+#if USE_MATH
+#include <math.h>
+#endif
+#include <limits.h>
+#include <float.h>
+#include <ctype.h>
+
+#if USE_STRCASECMP
+#include <strings.h>
+#define stricmp strcasecmp
+#endif
+
+#if USE_PROTECT
+#include <assert.h>
+void dump_protect(scheme *sc);
+#endif
+#include "file.h"
+
+#if USE_CELLDUMP
+static void memleakcheck(scheme *sc);
+#endif
+
+/* Used for documentation purposes, to signal functions in 'interface' */
+#define INTERFACE
+
+#define TOK_EOF     (-1)
+#define TOK_LPAREN  0
+#define TOK_RPAREN  1
+#define TOK_DOT     2
+#define TOK_ATOM    3
+#define TOK_QUOTE   4
+#define TOK_COMMENT 5
+#define TOK_DQUOTE  6
+#define TOK_BQUOTE  7
+#define TOK_COMMA   8
+#define TOK_ATMARK  9
+#define TOK_SHARP   10
+#define TOK_SHARP_CONST 11
+#define TOK_VEC     12
+
+# define BACKQUOTE '`'
+
+/*
+ *  Basic memory allocation units
+ */
+
+#define banner "TinyScheme 1.33"
+
+#include <string.h>
+#include <stdlib.h>
+#ifndef __APPLE__
+# include <malloc.h>
+#endif /* __APPLE__ */
+
+#ifndef __AMIGA__
+
+#if USE_STRLWR
+#ifndef strlwr
+static const char *strlwr(char *s) {
+  const char *p=s;
+  while(*s) {
+    *s=tolower(*s);
+    s++;
+  }
+  return p;
+}
+#endif
+#endif
+
+#endif /* __AMIGA__ */
+
+#ifndef prompt
+# define prompt "> "
+#endif
+
+#ifndef InitFile
+# define InitFile "init.scm"
+#endif
+
+#ifndef FIRST_CELLSEGS
+# define FIRST_CELLSEGS 3
+#endif
+
+enum scheme_types {
+  T_STRING=1,
+  T_NUMBER=2,
+  T_SYMBOL=3,
+  T_PROC=4,
+  T_PAIR=5,
+  T_CLOSURE=6,
+  T_CONTINUATION=7,
+  T_FOREIGN=8,
+  T_CHARACTER=9,
+  T_PORT=10,
+  T_VECTOR=11,
+  T_MACRO=12,
+  T_PROMISE=13,
+  T_ENVIRONMENT=14,
+  T_LAST_SYSTEM_TYPE=14
+};
+
+/* ADJ is enough slack to align cells in a TYPE_BITS-bit boundary */
+#define ADJ 32
+#define TYPE_BITS 5
+#define T_MASKTYPE      31    /* 0000000000011111 */
+#if USE_CUSTOM_FINALIZE
+#define T_CUSTFIN     2048    /* 0000100000000000 */
+#endif
+#define T_SYNTAX      4096    /* 0001000000000000 */
+#define T_IMMUTABLE   8192    /* 0010000000000000 */
+#define T_ATOM       16384    /* 0100000000000000 */   /* only for gc */
+#define CLRATOM      49151    /* 1011111111111111 */   /* only for gc */
+#define MARK         32768    /* 1000000000000000 */
+#define UNMARK       32767    /* 0111111111111111 */
+
+/* operator code */
+enum scheme_opcodes { 
+#define _OP_DEF(A,B,C,D,E,OP) OP, 
+#include "opdefines.h" 
+  OP_MAXDEFINED 
+}; 
+
+
+static num num_add(num a, num b);
+static num num_mul(num a, num b);
+static num num_div(num a, num b);
+static num num_intdiv(num a, num b);
+static num num_sub(num a, num b);
+static num num_rem(num a, num b);
+static num num_mod(num a, num b);
+static int num_eq(num a, num b);
+static int num_gt(num a, num b);
+static int num_ge(num a, num b);
+static int num_lt(num a, num b);
+static int num_le(num a, num b);
+
+#if USE_MATH
+static double round_per_R5RS(double x);
+#endif
+static int is_zero_double(double x);
+
+static num num_zero;
+static num num_one;
+
+/* macros for cell operations */
+#define typeflag(p)      ((p)->_flag)
+#define type(p)          (typeflag(p)&T_MASKTYPE)
+
+INTERFACE INLINE int is_string(pointer p)     { return (type(p)==T_STRING); }
+#define strvalue(p)      ((p)->_object._string._svalue)
+#define strlength(p)        ((p)->_object._string._length)
+
+INTERFACE INLINE int is_vector(pointer p)    { return (type(p)==T_VECTOR); }
+INTERFACE static void fill_vector(pointer vec, pointer obj);
+INTERFACE static pointer vector_elem(pointer vec, int ielem);
+INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a);
+INTERFACE INLINE int is_number(pointer p)    { return (type(p)==T_NUMBER); }
+INTERFACE INLINE int is_integer(pointer p) { 
+  return ((p)->_object._number.is_fixnum); 
+}
+INTERFACE INLINE int is_real(pointer p) { 
+  return (!(p)->_object._number.is_fixnum); 
+}
+
+INTERFACE INLINE int is_character(pointer p) { return (type(p)==T_CHARACTER); }
+INTERFACE INLINE char *string_value(pointer p) { return strvalue(p); }
+INLINE num nvalue(pointer p)       { return ((p)->_object._number); }
+INTERFACE long ivalue(pointer p)      { return (is_integer(p)?(p)->_object._number.value.ivalue:(long)(p)->_object._number.value.rvalue); }
+INTERFACE double rvalue(pointer p)    { return (!is_integer(p)?(p)->_object._number.value.rvalue:(double)(p)->_object._number.value.ivalue); }
+#define ivalue_unchecked(p)       ((p)->_object._number.value.ivalue)
+#define rvalue_unchecked(p)       ((p)->_object._number.value.rvalue)
+#define set_integer(p)   (p)->_object._number.is_fixnum=1;
+#define set_real(p)      (p)->_object._number.is_fixnum=0;
+INTERFACE  long charvalue(pointer p)  { return ivalue_unchecked(p); }
+
+INTERFACE INLINE int is_port(pointer p)     { return (type(p)==T_PORT); }
+#define is_inport(p) (type(p)==T_PORT && p->_object._port->kind&port_input)
+#define is_outport(p) (type(p)==T_PORT && p->_object._port->kind&port_output)
+
+INTERFACE INLINE int is_pair(pointer p)     { return (type(p)==T_PAIR); }
+#define car(p)           ((p)->_object._cons._car)
+#define cdr(p)           ((p)->_object._cons._cdr)
+INTERFACE pointer pair_car(pointer p)   { return car(p); }
+INTERFACE pointer pair_cdr(pointer p)   { return cdr(p); }
+INTERFACE pointer set_car(pointer p, pointer q) { return car(p)=q; }
+INTERFACE pointer set_cdr(pointer p, pointer q) { return cdr(p)=q; }
+
+INTERFACE INLINE int is_symbol(pointer p)   { return (type(p)==T_SYMBOL); }
+INTERFACE INLINE char *symname(pointer p)   { return strvalue(car(p)); }
+#if USE_PLIST
+SCHEME_EXPORT INLINE int hasprop(pointer p)     { return (typeflag(p)&T_SYMBOL); }
+#define symprop(p)       cdr(p)
+#endif
+
+INTERFACE INLINE foreign_func ffvalue(pointer p) 
+{ return (!is_foreign(p) ? NULL : p->_object._ff); }
+
+INTERFACE INLINE int is_syntax(pointer p)   { return (typeflag(p)&T_SYNTAX); }
+INTERFACE INLINE int is_proc(pointer p)     { return (type(p)==T_PROC); }
+INTERFACE INLINE int is_foreign(pointer p)  { return (type(p)==T_FOREIGN); }
+INTERFACE INLINE char *syntaxname(pointer p) { return strvalue(car(p)); }
+#define procnum(p)       ivalue(p)
+static const char *procname(pointer x);
+
+INTERFACE INLINE int is_closure(pointer p)  { return (type(p)==T_CLOSURE); }
+INTERFACE INLINE int is_macro(pointer p)    { return (type(p)==T_MACRO); }
+INTERFACE INLINE pointer closure_code(pointer p)   { return car(p); }
+INTERFACE INLINE pointer closure_env(pointer p)    { return cdr(p); }
+
+INTERFACE INLINE int is_continuation(pointer p)    { return (type(p)==T_CONTINUATION); }
+#define cont_dump(p)     cdr(p)
+
+/* To do: promise should be forced ONCE only */
+INTERFACE INLINE int is_promise(pointer p)  { return (type(p)==T_PROMISE); }
+
+INTERFACE INLINE int is_environment(pointer p) { return (type(p)==T_ENVIRONMENT); }
+#define setenvironment(p)    typeflag(p) = T_ENVIRONMENT
+
+#define is_atom(p)       (typeflag(p)&T_ATOM)
+#define setatom(p)       typeflag(p) |= T_ATOM
+#define clratom(p)       typeflag(p) &= CLRATOM
+
+#define is_mark(p)       (typeflag(p)&MARK)
+#define setmark(p)       typeflag(p) |= MARK
+#define clrmark(p)       typeflag(p) &= UNMARK
+#define is_free(p)       (0==typeflag(p))
+
+#if USE_CUSTOM_FINALIZE
+#define is_custfin(p)    (typeflag(p)&T_CUSTFIN)
+#define setcustfin(p)    (typeflag(p)|=T_CUSTFIN)
+#define clrcustfin(p)    (typeflag(p)&=(~T_CUSTFIN))
+#endif
+
+#if USE_PROTECT
+INTERFACE INLINE pointer protect(scheme *sc, pointer p) 
+{ 
+        if (! p->pref)
+                list_add(&sc->protect, &p->plist);
+        p->pref++;
+        return p;
+}
+INTERFACE INLINE pointer unprotect(scheme *sc, pointer p) 
+{ 
+        assert(p->pref > 0);
+        p->pref--;
+        if (! p->pref)
+                list_remove(&p->plist); 
+        return p;
+}
+#define init_pref(p) ((p)->pref = 0)
+#else
+#define init_pref(p)
+#endif
+
+#if USE_CUSTOM_FINALIZE
+INTERFACE INLINE void ifc_setcustfin(pointer p)
+{
+        setcustfin(p);
+}
+#endif
+
+INTERFACE INLINE int is_immutable(pointer p) { return (typeflag(p)&T_IMMUTABLE); }
+/*#define setimmutable(p)  typeflag(p) |= T_IMMUTABLE*/
+INTERFACE INLINE void setimmutable(pointer p) { typeflag(p) |= T_IMMUTABLE; }
+
+#define caar(p)          car(car(p))
+#define cadr(p)          car(cdr(p))
+#define cdar(p)          cdr(car(p))
+#define cddr(p)          cdr(cdr(p))
+#define cadar(p)         car(cdr(car(p)))
+#define caddr(p)         car(cdr(cdr(p)))
+#define cadaar(p)        car(cdr(car(car(p))))
+#define cadddr(p)        car(cdr(cdr(cdr(p))))
+#define cddddr(p)        cdr(cdr(cdr(cdr(p))))
+
+#if USE_CHAR_CLASSIFIERS
+static INLINE int Cisalpha(int c) { return isascii(c) && isalpha(c); }
+static INLINE int Cisdigit(int c) { return isascii(c) && isdigit(c); }
+static INLINE int Cisspace(int c) { return isascii(c) && isspace(c); }
+static INLINE int Cisupper(int c) { return isascii(c) && isupper(c); }
+static INLINE int Cislower(int c) { return isascii(c) && islower(c); }
+#endif
+
+#if USE_ASCII_NAMES
+static const char *charnames[32]={
+ "nul",
+ "soh",
+ "stx",
+ "etx",
+ "eot",
+ "enq",
+ "ack",
+ "bel",
+ "bs",
+ "ht",
+ "lf",
+ "vt",
+ "ff",
+ "cr",
+ "so",
+ "si",
+ "dle",
+ "dc1",
+ "dc2",
+ "dc3",
+ "dc4",
+ "nak",
+ "syn",
+ "etb",
+ "can",
+ "em",
+ "sub",
+ "esc",
+ "fs",
+ "gs",
+ "rs",
+ "us"
+};
+
+static int is_ascii_name(const char *name, int *pc) {
+  int i;
+  for(i=0; i<32; i++) {
+     if(stricmp(name,charnames[i])==0) {
+          *pc=i;
+          return 1;
+     }
+  }
+  if(stricmp(name,"del")==0) {
+     *pc=127;
+     return 1;
+  }
+  return 0;
+}
+
+#endif
+
+static int file_push(scheme *sc, const char *fname);
+static void file_pop(scheme *sc);
+static int file_interactive(scheme *sc);
+static INLINE int is_one_of(const char *s, int c);
+static void nomem(scheme *sc);
+static int alloc_cellseg(scheme *sc, int n);
+static long binary_decode(const char *s);
+static INLINE pointer get_cell(scheme *sc, pointer a, pointer b);
+static pointer _get_cell(scheme *sc, pointer a, pointer b);
+static pointer get_consecutive_cells(scheme *sc, int n);
+static pointer find_consecutive_cells(scheme *sc, int n);
+static void finalize_cell(scheme *sc, pointer a);
+static int count_consecutive_cells(pointer x, int needed);
+static pointer find_slot_in_env(scheme *sc, pointer env, pointer sym, int all);
+static pointer mk_number(scheme *sc, num n);
+static pointer mk_empty_string(scheme *sc, int len, char fill);
+static char *store_string(scheme *sc, int len, const char *str, char fill);
+static pointer mk_vector(scheme *sc, int len);
+static pointer mk_atom(scheme *sc, char *q);
+static pointer mk_sharp_const(scheme *sc, char *name);
+static pointer mk_port(scheme *sc, port *p);
+static pointer port_from_filename(scheme *sc, const char *fn, int prop);
+static pointer port_from_file(scheme *sc, FILE *, int prop);
+static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop);
+static port *port_rep_from_filename(scheme *sc, const char *fn, int prop);
+static port *port_rep_from_file(scheme *sc, FILE *, int prop);
+static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop);
+static void port_close(scheme *sc, pointer p, int flag);
+static void mark(pointer a);
+static void gc(scheme *sc, pointer a, pointer b);
+static int basic_inchar(port *pt);
+static int inchar(scheme *sc);
+static void backchar(scheme *sc, int c);
+static char   *readstr_upto(scheme *sc, const char *delim);
+static pointer readstrexp(scheme *sc);
+static INLINE void skipspace(scheme *sc);
+static int token(scheme *sc);
+static void printslashstring(scheme *sc, char *s, int len);
+static void atom2str(scheme *sc, pointer l, int f, const char **pp, int *plen);
+static void printatom(scheme *sc, pointer l, int f);
+static pointer mk_proc(scheme *sc, enum scheme_opcodes op);
+static pointer mk_closure(scheme *sc, pointer c, pointer e);
+static pointer mk_continuation(scheme *sc, pointer d);
+static pointer reverse(scheme *sc, pointer a);
+static pointer reverse_in_place(scheme *sc, pointer term, pointer list);
+static pointer append(scheme *sc, pointer a, pointer b);
+static int list_length(scheme *sc, pointer a);
+static int eqv(pointer a, pointer b);
+static void dump_stack_mark(scheme *);
+static pointer opexe_0(scheme *sc, enum scheme_opcodes op);
+static pointer opexe_1(scheme *sc, enum scheme_opcodes op);
+static pointer opexe_2(scheme *sc, enum scheme_opcodes op);
+static pointer opexe_3(scheme *sc, enum scheme_opcodes op);
+static pointer opexe_4(scheme *sc, enum scheme_opcodes op);
+static pointer opexe_5(scheme *sc, enum scheme_opcodes op);
+static pointer opexe_6(scheme *sc, enum scheme_opcodes op);
+#ifdef USE_REENTER
+static pointer opexe_ghul(scheme *sc, enum scheme_opcodes op);
+#endif
+static void Eval_Cycle(scheme *sc, enum scheme_opcodes op);
+static void assign_syntax(scheme *sc, const char *name);
+static int syntaxnum(pointer p);
+static void assign_proc(scheme *sc, enum scheme_opcodes, const char *name);
+
+#define num_ivalue(n)       (n.is_fixnum?(n).value.ivalue:(long)(n).value.rvalue)
+#define num_rvalue(n)       (!n.is_fixnum?(n).value.rvalue:(double)(n).value.ivalue)
+
+static void nomem(scheme *sc)
+{
+        sc->no_memory = 1;
+}
+
+static num num_add(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+     ret.value.ivalue= a.value.ivalue+b.value.ivalue;
+ } else {
+     ret.value.rvalue=num_rvalue(a)+num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_mul(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+     ret.value.ivalue= a.value.ivalue*b.value.ivalue;
+ } else {
+     ret.value.rvalue=num_rvalue(a)*num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_div(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum && a.value.ivalue%b.value.ivalue==0;
+ if(ret.is_fixnum) {
+     ret.value.ivalue= a.value.ivalue/b.value.ivalue;
+ } else {
+     ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_intdiv(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+     ret.value.ivalue= a.value.ivalue/b.value.ivalue;
+ } else {
+     ret.value.rvalue=num_rvalue(a)/num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_sub(num a, num b) {
+ num ret;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(ret.is_fixnum) {
+     ret.value.ivalue= a.value.ivalue-b.value.ivalue;
+ } else {
+     ret.value.rvalue=num_rvalue(a)-num_rvalue(b);
+ }
+ return ret;
+}
+
+static num num_rem(num a, num b) {
+ num ret;
+ long e1, e2, res;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ e1=num_ivalue(a);
+ e2=num_ivalue(b);
+ res=e1%e2;
+ if(res*e1<0) {    /* remainder should have same sign as first operand */
+     e2=labs(e2);
+     if(res>0) {
+          res-=e2;
+     } else {
+          res+=e2;
+     }
+ }
+ ret.value.ivalue=res;
+ return ret;
+}
+
+static num num_mod(num a, num b) {
+ num ret;
+ long e1, e2, res;
+ ret.is_fixnum=a.is_fixnum && b.is_fixnum;
+ e1=num_ivalue(a);
+ e2=num_ivalue(b);
+ res=e1%e2;
+ if(res*e2<0) {    /* modulo should have same sign as second operand */
+     e2=labs(e2);
+     if(res>0) {
+          res-=e2;
+     } else {
+          res+=e2;
+     }
+ }
+ ret.value.ivalue=res;
+ return ret;
+}
+
+static int num_eq(num a, num b) {
+ int ret;
+ int is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(is_fixnum) {
+     ret= a.value.ivalue==b.value.ivalue;
+ } else {
+     ret=num_rvalue(a)==num_rvalue(b);
+ }
+ return ret;
+}
+
+
+static int num_gt(num a, num b) {
+ int ret;
+ int is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(is_fixnum) {
+     ret= a.value.ivalue>b.value.ivalue;
+ } else {
+     ret=num_rvalue(a)>num_rvalue(b);
+ }
+ return ret;
+}
+
+static int num_ge(num a, num b) {
+ return !num_lt(a,b);
+}
+
+static int num_lt(num a, num b) {
+ int ret;
+ int is_fixnum=a.is_fixnum && b.is_fixnum;
+ if(is_fixnum) {
+     ret= a.value.ivalue<b.value.ivalue;
+ } else {
+     ret=num_rvalue(a)<num_rvalue(b);
+ }
+ return ret;
+}
+
+static int num_le(num a, num b) {
+ return !num_gt(a,b);
+}
+
+#if USE_MATH
+/* Round to nearest. Round to even if midway */
+static double round_per_R5RS(double x) {
+ double fl=floor(x);
+ double ce=ceil(x);
+ double dfl=x-fl;
+ double dce=ce-x;
+ if(dfl>dce) {
+     return ce;
+ } else if(dfl<dce) {
+     return fl;
+ } else {
+     if(fmod(fl,2.0)==0.0) {       /* I imagine this holds */
+          return fl;
+     } else {
+          return ce;
+     }
+ }
+}
+#endif
+
+static int is_zero_double(double x) {
+ return x<DBL_MIN && x>-DBL_MIN;
+}
+
+static long binary_decode(const char *s) {
+ long x=0;
+
+ while(*s!=0 && (*s=='1' || *s=='0')) {
+     x<<=1;
+     x+=*s-'0';
+     s++;
+ }
+
+ return x;
+}
+
+/* allocate new cell segment */
+static int alloc_cellseg(scheme *sc, int n) {
+     pointer newp;
+     pointer last;
+     pointer p;
+     char *cp;
+     long i;
+     int k;
+     unsigned int adj=ADJ;
+
+     if(adj<sizeof(struct cell)) {
+       adj=sizeof(struct cell);
+     }
+
+     for (k = 0; k < n; k++) {
+          if (sc->last_cell_seg >= CELL_NSEGMENT - 1)
+               return k;
+          cp = (char*) sc->malloc(CELL_SEGSIZE * sizeof(struct cell)+adj);
+          if (cp == 0)
+               return k;
+         i = ++sc->last_cell_seg ;
+         sc->alloc_seg[i] = cp;
+         /* adjust in TYPE_BITS-bit boundary */
+         if(((long)cp)%adj!=0) {
+           cp=(char*)(adj*((long)cp/adj+1));
+         }
+        /* insert new segment in address order */
+         newp=(pointer)cp;
+        sc->cell_seg[i] = newp;
+        while (i > 0 && sc->cell_seg[i - 1] > sc->cell_seg[i]) {
+              p = sc->cell_seg[i];
+            sc->cell_seg[i] = sc->cell_seg[i - 1];
+            sc->cell_seg[--i] = p;
+        }
+          sc->fcells += CELL_SEGSIZE;
+        last = newp + CELL_SEGSIZE - 1;
+          for (p = newp; p <= last; p++) {
+               typeflag(p) = 0;
+               cdr(p) = p + 1;
+               car(p) = sc->NIL;
+          }
+        /* insert new cells in address order on free list */
+        if (sc->free_cell == sc->NIL || p < sc->free_cell) {
+             cdr(last) = sc->free_cell;
+             sc->free_cell = newp;
+        } else {
+              p = sc->free_cell;
+              while (cdr(p) != sc->NIL && newp > cdr(p))
+                   p = cdr(p);
+              cdr(last) = cdr(p);
+              cdr(p) = newp;
+        }
+     }
+     return n;
+}
+
+static INLINE pointer get_cell(scheme *sc, pointer a, pointer b) {
+  if (sc->free_cell != sc->NIL) {
+    pointer x = sc->free_cell;
+#ifdef USE_PROTECT
+    x->pref = 0;
+#endif
+    sc->free_cell = cdr(x);
+    --sc->fcells;
+    return (x);
+  } 
+  return _get_cell (sc, a, b);
+}
+
+
+/* get new cell.  parameter a, b is marked by gc. */
+static pointer _get_cell(scheme *sc, pointer a, pointer b) {
+  pointer x;
+
+  if(sc->no_memory) {
+    return sc->sink;
+  }
+  
+  if (sc->free_cell == sc->NIL) {
+    gc(sc,a, b);
+    if (sc->fcells < sc->last_cell_seg*8
+       || sc->free_cell == sc->NIL) {
+      /* if only a few recovered, get more to avoid fruitless gc's */
+      if (!alloc_cellseg(sc,1) && sc->free_cell == sc->NIL) {
+        nomem(sc);
+       return sc->sink;
+      }
+    }
+  }
+  x = sc->free_cell;
+#ifdef USE_PROTECT
+  x->pref = 0;
+#endif
+  sc->free_cell = cdr(x);
+  --sc->fcells;
+  return (x);
+}
+
+static pointer get_consecutive_cells(scheme *sc, int n) {
+  pointer x;
+
+  if(sc->no_memory) {
+    return sc->sink;
+  }
+  
+  /* Are there any cells available? */
+  x=find_consecutive_cells(sc,n);
+  if (x == sc->NIL) {
+    /* If not, try gc'ing some */
+    gc(sc, sc->NIL, sc->NIL);
+    x=find_consecutive_cells(sc,n);
+    if (x == sc->NIL) {
+      /* If there still aren't, try getting more heap */
+      if (!alloc_cellseg(sc,1)) {
+        nomem(sc);
+       return sc->sink;
+      }
+    }
+    x=find_consecutive_cells(sc,n);
+    if (x == sc->NIL) {
+      /* If all fail, report failure */
+      nomem(sc);
+      return sc->sink;
+    }
+  }
+  return (x);
+}
+
+static int count_consecutive_cells(pointer x, int needed) {
+ int n=1;
+ while(cdr(x)==x+1) {
+     x=cdr(x);
+     n++;
+     if(n>needed) return n;
+ }
+ return n;
+}
+
+static pointer find_consecutive_cells(scheme *sc, int n) {
+  pointer *pp;
+  int cnt;
+  
+  pp=&sc->free_cell;
+  while(*pp!=sc->NIL) {
+    cnt=count_consecutive_cells(*pp,n);
+    if(cnt>=n) {
+      pointer x=*pp;
+      *pp=cdr(*pp+n-1);
+      sc->fcells -= n;
+      return x;
+    }
+    pp=&cdr(*pp+cnt-1);
+  }
+  return sc->NIL;
+}
+
+/* get new cons cell */
+pointer _cons(scheme *sc, pointer a, pointer b, int immutable) {
+  pointer x = get_cell(sc,a, b);
+
+  typeflag(x) = T_PAIR;
+  if(immutable) {
+    setimmutable(x);
+  }
+  car(x) = a;
+  cdr(x) = b;
+  return (x);
+}
+
+/* ========== oblist implementation  ========== */ 
+
+#ifndef USE_OBJECT_LIST 
+
+static int hash_fn(const char *key, int table_size); 
+
+static pointer oblist_initial_value(scheme *sc) 
+{ 
+  return mk_vector(sc, 461); /* probably should be bigger */ 
+} 
+
+/* returns the new symbol */ 
+static pointer oblist_add_by_name(scheme *sc, const char *name) 
+{ 
+  pointer x; 
+  int location; 
+
+  x = immutable_cons(sc, mk_string(sc, name), sc->NIL); 
+  typeflag(x) = T_SYMBOL; 
+  setimmutable(car(x)); 
+
+  location = hash_fn(name, ivalue_unchecked(sc->oblist)); 
+  set_vector_elem(sc->oblist, location, 
+                  immutable_cons(sc, x, vector_elem(sc->oblist, location))); 
+  return x; 
+} 
+
+static INLINE pointer oblist_find_by_name(scheme *sc, const char *name) 
+{ 
+  int location; 
+  pointer x; 
+  char *s; 
+
+  location = hash_fn(name, ivalue_unchecked(sc->oblist)); 
+  for (x = vector_elem(sc->oblist, location); x != sc->NIL; x = cdr(x)) { 
+    s = symname(car(x)); 
+    /* case-insensitive, per R5RS section 2. */ 
+    if(stricmp(name, s) == 0) { 
+      return car(x); 
+    } 
+  } 
+  return sc->NIL; 
+} 
+
+static pointer oblist_all_symbols(scheme *sc) 
+{ 
+  int i; 
+  pointer x; 
+  pointer ob_list = sc->NIL; 
+
+  for (i = 0; i < ivalue_unchecked(sc->oblist); i++) { 
+    for (x  = vector_elem(sc->oblist, i); x != sc->NIL; x = cdr(x)) { 
+      ob_list = cons(sc, x, ob_list); 
+    } 
+  } 
+  return ob_list; 
+} 
+
+#else 
+
+static pointer oblist_initial_value(scheme *sc) 
+{ 
+  return sc->NIL; 
+} 
+
+static INLINE pointer oblist_find_by_name(scheme *sc, const char *name) 
+{ 
+     pointer x; 
+     char    *s; 
+
+     for (x = sc->oblist; x != sc->NIL; x = cdr(x)) { 
+        s = symname(car(x)); 
+        /* case-insensitive, per R5RS section 2. */ 
+        if(stricmp(name, s) == 0) { 
+          return car(x); 
+        } 
+     } 
+     return sc->NIL; 
+} 
+
+/* returns the new symbol */ 
+static pointer oblist_add_by_name(scheme *sc, const char *name) 
+{ 
+  pointer x; 
+
+  x = immutable_cons(sc, mk_string(sc, name), sc->NIL); 
+  typeflag(x) = T_SYMBOL; 
+  setimmutable(car(x)); 
+  sc->oblist = immutable_cons(sc, x, sc->oblist); 
+  return x; 
+} 
+static pointer oblist_all_symbols(scheme *sc) 
+{ 
+  return sc->oblist; 
+} 
+
+#endif 
+
+static pointer mk_port(scheme *sc, port *p) {
+  pointer x = get_cell(sc, sc->NIL, sc->NIL);
+  
+  typeflag(x) = T_PORT|T_ATOM;
+  x->_object._port=p;
+  return (x);
+}
+
+pointer mk_foreign_func(scheme *sc, foreign_func f) {
+  pointer x = get_cell(sc, sc->NIL, sc->NIL);
+  
+  typeflag(x) = (T_FOREIGN | T_ATOM);
+  x->_object._ff=f;
+  return (x);
+}
+
+INTERFACE pointer mk_character(scheme *sc, int c) {
+  pointer x = get_cell(sc,sc->NIL, sc->NIL);
+
+  typeflag(x) = (T_CHARACTER | T_ATOM);
+  ivalue_unchecked(x)= c;
+  set_integer(x);
+  return (x);
+}
+
+/* get number atom (integer) */
+INTERFACE pointer mk_integer(scheme *sc, long num) {
+  pointer x = get_cell(sc,sc->NIL, sc->NIL);
+
+  typeflag(x) = (T_NUMBER | T_ATOM);
+  ivalue_unchecked(x)= num;
+  set_integer(x);
+  return (x);
+}
+
+INTERFACE pointer mk_real(scheme *sc, double n) {
+  pointer x = get_cell(sc,sc->NIL, sc->NIL);
+
+  typeflag(x) = (T_NUMBER | T_ATOM);
+  rvalue_unchecked(x)= n;
+  set_real(x);
+  return (x);
+}
+
+static pointer mk_number(scheme *sc, num n) {
+ if(n.is_fixnum) {
+     return mk_integer(sc,n.value.ivalue);
+ } else {
+     return mk_real(sc,n.value.rvalue);
+ }
+}
+
+/* allocate name to string area */
+static char *store_string(scheme *sc, int len_str, const char *str, char fill) {
+     char *q;
+     
+     q=(char*)sc->malloc(len_str+1);
+     if(q==0) {
+          nomem(sc);
+          return sc->strbuff;
+     }
+     if(str!=0) {
+          strcpy(q, str);
+     } else {
+          memset(q, fill, len_str);
+          q[len_str]=0;
+     }
+     return (q);
+}
+
+/* get new string */
+INTERFACE pointer mk_string(scheme *sc, const char *str) {
+     return mk_counted_string(sc,str,strlen(str));
+}
+
+INTERFACE pointer mk_counted_string(scheme *sc, const char *str, int len) {
+     pointer x = get_cell(sc, sc->NIL, sc->NIL);
+
+     strvalue(x) = store_string(sc,len,str,0);
+     typeflag(x) = (T_STRING | T_ATOM);
+     strlength(x) = len;
+     return (x);
+}
+
+static pointer mk_empty_string(scheme *sc, int len, char fill) {
+     pointer x = get_cell(sc, sc->NIL, sc->NIL);
+
+     strvalue(x) = store_string(sc,len,0,fill);
+     typeflag(x) = (T_STRING | T_ATOM);
+     strlength(x) = len;
+     return (x);
+}
+
+INTERFACE static pointer mk_vector(scheme *sc, int len) {
+     pointer x=get_consecutive_cells(sc,len/2+len%2+1);
+     typeflag(x) = (T_VECTOR | T_ATOM);
+     ivalue_unchecked(x)=len;
+     set_integer(x);
+     fill_vector(x,sc->NIL);
+     return x;
+}
+
+INTERFACE static void fill_vector(pointer vec, pointer obj) {
+     int i;
+     int num=ivalue(vec)/2+ivalue(vec)%2;
+     for(i=0; i<num; i++) {
+          typeflag(vec+1+i) = T_PAIR;
+          setimmutable(vec+1+i);
+          car(vec+1+i)=obj;
+          cdr(vec+1+i)=obj;
+     }
+}
+
+INTERFACE static pointer vector_elem(pointer vec, int ielem) {
+     int n=ielem/2;
+     if(ielem%2==0) {
+          return car(vec+1+n);
+     } else {
+          return cdr(vec+1+n);
+     }
+}
+
+INTERFACE static pointer set_vector_elem(pointer vec, int ielem, pointer a) {
+     int n=ielem/2;
+     if(ielem%2==0) {
+          return car(vec+1+n)=a;
+     } else {
+          return cdr(vec+1+n)=a;
+     }
+}
+
+/* get new symbol */
+INTERFACE pointer mk_symbol(scheme *sc, const char *name) { 
+     pointer x; 
+
+     /* first check oblist */ 
+     x = oblist_find_by_name(sc, name); 
+     if (x != sc->NIL) { 
+          return (x); 
+     } else { 
+          x = oblist_add_by_name(sc, name); 
+          return (x); 
+     } 
+} 
+
+INTERFACE pointer gensym(scheme *sc) { 
+     pointer x; 
+     char name[40]; 
+
+     for(; sc->gensym_cnt<LONG_MAX; sc->gensym_cnt++) { 
+          sprintf(name,"gensym-%ld",sc->gensym_cnt); 
+
+          /* first check oblist */ 
+          x = oblist_find_by_name(sc, name); 
+
+          if (x != sc->NIL) { 
+               continue; 
+          } else { 
+               x = oblist_add_by_name(sc, name); 
+               return (x); 
+          } 
+     } 
+
+     return sc->NIL; 
+} 
+
+/* make symbol or number atom from string */
+static pointer mk_atom(scheme *sc, char *q) {
+     char    c, *p;
+     int has_dec_point=0;
+     int has_fp_exp = 0;
+
+#if USE_COLON_HOOK
+     if((p=strstr(q,"::"))!=0) {
+          *p=0;
+          return cons(sc, sc->COLON_HOOK,
+                          cons(sc,
+                              cons(sc,
+                                   sc->QUOTE,
+                                   cons(sc, mk_atom(sc,p+2), sc->NIL)),
+                              cons(sc, mk_symbol(sc,strlwr(q)), sc->NIL)));
+     }
+#endif
+
+     p = q;
+     c = *p++; 
+     if ((c == '+') || (c == '-')) { 
+       c = *p++; 
+       if (c == '.') { 
+         has_dec_point=1; 
+        c = *p++; 
+       } 
+       if (!isdigit(c)) { 
+        return (mk_symbol(sc, strlwr(q))); 
+       } 
+     } else if (c == '.') { 
+       has_dec_point=1; 
+       c = *p++; 
+       if (!isdigit(c)) { 
+        return (mk_symbol(sc, strlwr(q))); 
+       } 
+     } else if (!isdigit(c)) { 
+       return (mk_symbol(sc, strlwr(q))); 
+     }
+
+     for ( ; (c = *p) != 0; ++p) {
+          if (!isdigit(c)) {
+               if(c=='.') {
+                    if(!has_dec_point) {
+                         has_dec_point=1;
+                         continue;
+                    }
+               }
+               else if ((c == 'e') || (c == 'E')) {
+                       if(!has_fp_exp) {
+                          has_dec_point = 1; /* decimal point illegal
+                                                from now on */
+                          p++;
+                          if ((*p == '-') || (*p == '+') || isdigit(*p)) {
+                             continue;
+                          }
+                       }  
+               }    
+               return (mk_symbol(sc, strlwr(q)));
+          }
+     }
+     if(has_dec_point) {
+          return mk_real(sc,atof(q));
+     }
+     return (mk_integer(sc, atol(q)));
+}
+
+/* make constant */
+static pointer mk_sharp_const(scheme *sc, char *name) {
+     long    x;
+     char    tmp[256];
+
+     if (!strcmp(name, "t"))
+          return (sc->T);
+     else if (!strcmp(name, "f"))
+          return (sc->F);
+     else if (*name == 'o') {/* #o (octal) */
+          sprintf(tmp, "0%s", name+1);
+          sscanf(tmp, "%lo", &x);
+          return (mk_integer(sc, x));
+     } else if (*name == 'd') {    /* #d (decimal) */
+          sscanf(name+1, "%ld", &x);
+          return (mk_integer(sc, x));
+     } else if (*name == 'x') {    /* #x (hex) */
+          sprintf(tmp, "0x%s", name+1);
+          sscanf(tmp, "%lx", &x);
+          return (mk_integer(sc, x));
+     } else if (*name == 'b') {    /* #b (binary) */
+          x = binary_decode(name+1);
+          return (mk_integer(sc, x));
+     } else if (*name == '\\') { /* #\w (character) */
+          int c=0;
+          if(stricmp(name+1,"space")==0) {
+               c=' ';
+          } else if(stricmp(name+1,"newline")==0) {
+               c='\n';
+          } else if(stricmp(name+1,"return")==0) {
+               c='\r';
+          } else if(stricmp(name+1,"tab")==0) {
+               c='\t';
+     } else if(name[1]=='x' && name[2]!=0) {
+          int c1=0;
+          if(sscanf(name+2,"%x",&c1)==1 && c1<256) {
+               c=c1;
+          } else {
+               return sc->NIL;
+     }
+#if USE_ASCII_NAMES
+          } else if(is_ascii_name(name+1,&c)) {
+               /* nothing */
+#endif               
+          } else if(name[2]==0) {
+               c=name[1];
+          } else {
+               return sc->NIL;
+          }
+          return mk_character(sc,c);
+     } else
+          return (sc->NIL);
+}
+
+/* ========== garbage collector ========== */
+
+/*--
+ *  We use algorithm E (Knuth, The Art of Computer Programming Vol.1,
+ *  sec. 2.3.5), the Schorr-Deutsch-Waite link-inversion algorithm, 
+ *  for marking. 
+ */
+static void mark(pointer a) {
+     pointer t, q, p;
+
+     t = (pointer) 0;
+     p = a;
+E2:  setmark(p);
+     if(is_vector(p)) {
+          int i;
+          int num=ivalue_unchecked(p)/2+ivalue_unchecked(p)%2;
+          for(i=0; i<num; i++) {
+               /* Vector cells will be treated like ordinary cells */
+               mark(p+1+i);
+          }
+     }
+     if (is_atom(p))
+          goto E6;
+     /* E4: down car */
+     q = car(p);
+     if (q && !is_mark(q)) {
+          setatom(p);  /* a note that we have moved car */ 
+          car(p) = t;
+          t = p;
+          p = q;
+          goto E2;
+     }
+ E5:  q = cdr(p); /* down cdr */
+     if (q && !is_mark(q)) {
+          cdr(p) = t;
+          t = p;
+          p = q;
+          goto E2;
+     }
+E6:   /* up.  Undo the link switching from steps E4 and E5. */ 
+     if (!t)
+          return;
+     q = t;
+     if (is_atom(q)) {
+          clratom(q);
+          t = car(q);
+          car(q) = p;
+          p = q;
+          goto E5;
+     } else {
+          t = cdr(q);
+          cdr(q) = p;
+          p = q;
+          goto E6;
+     }
+}
+
+#if USE_PROTECT
+static void protected_mark(scheme *sc)
+{
+  struct list *elem;
+  pointer p;
+
+  list_for_each(&sc->protect, elem) {
+    p = list_entry(elem, struct cell, plist);
+    mark(p);
+  }
+}
+static void unprotect_all(scheme *sc)
+{
+#if 1
+        sc->ignore_protect = 1;
+#else
+  struct list *elem;
+  pointer p;
+
+  elem = sc->protect.next;
+  while (elem != &sc->protect) {
+          p = list_entry(elem, struct cell, plist);
+          elem = elem->next;
+          unprotect(sc, p);
+  }
+#endif /* ! 1 */
+}
+#endif
+
+/* garbage collection. parameter a, b is marked. */
+static void gc(scheme *sc, pointer a, pointer b) {
+  pointer p;
+  int i;
+  
+  if(sc->gc_verbose) {
+    putstr(sc, "gc...");
+  }
+
+  /* mark system globals */
+  mark(sc->oblist);
+  mark(sc->global_env);
+
+  /* mark current registers */
+  mark(sc->args);
+  mark(sc->envir);
+  mark(sc->code);
+  dump_stack_mark(sc); 
+  mark(sc->value);
+  mark(sc->inport);
+  mark(sc->save_inport);
+  mark(sc->outport);
+  mark(sc->loadport);
+
+  /* mark variables a, b */
+  mark(a);
+  mark(b);
+
+#if USE_PROTECT
+  /* mark protected */
+  if (!sc->ignore_protect) {
+          protected_mark(sc);
+  }
+#endif
+
+  /* garbage collect */
+  clrmark(sc->NIL);
+  sc->fcells = 0;
+  sc->free_cell = sc->NIL;
+  /* free-list is kept sorted by address so as to maintain consecutive
+     ranges, if possible, for use with vectors. Here we scan the cells
+     (which are also kept sorted by address) downwards to build the
+     free-list in sorted order.
+  */
+  for (i = sc->last_cell_seg; i >= 0; i--) {
+    p = sc->cell_seg[i] + CELL_SEGSIZE;
+    while (--p >= sc->cell_seg[i]) {
+      if (is_mark(p)) {
+        clrmark(p);
+      } else {
+        /* reclaim cell */
+        if (typeflag(p) != 0) { 
+          finalize_cell(sc, p); 
+          typeflag(p) = 0; 
+          ++sc->fcells; 
+          car(p) = sc->NIL; 
+        } 
+        cdr(p) = sc->free_cell; 
+        sc->free_cell = p; 
+      }
+    }
+  }
+  
+  if (sc->gc_verbose) {
+    char msg[80];
+    sprintf(msg,"done: %ld cells were recovered.\n", sc->fcells);
+    putstr(sc,msg);
+  }
+}
+
+static void finalize_cell(scheme *sc, pointer a) {
+        if(is_string(a)) {
+                sc->free(strvalue(a));
+        } else if(is_port(a)) {
+                if(a->_object._port->kind&port_file 
+                   && a->_object._port->rep.stdio.closeit) {
+                        port_close(sc,a,port_input|port_output);
+                }
+                sc->free(a->_object._port);
+        } else if(is_custfin(a) && sc->custom_finalize) {
+                sc->custom_finalize(sc, (pointer)ffvalue(a));
+        }        
+}
+
+/* ========== Routines for Reading ========== */
+
+static int file_push(scheme *sc, const char *fname) {
+  FILE *fin = file_open_in_include_dir(fname);
+  /*printf("load %s...\n", fname);*/
+  if(fin!=0) {
+    sc->file_i++;
+    sc->load_stack[sc->file_i].kind=port_file|port_input;
+    sc->load_stack[sc->file_i].rep.stdio.file=fin;
+    sc->load_stack[sc->file_i].rep.stdio.closeit=1;
+#if USE_FILE_AND_LINE
+    sc->load_stack[sc->file_i].rep.stdio.name = strdup(fname);
+    sc->load_stack[sc->file_i].rep.stdio.line = 0;
+#endif
+    sc->nesting_stack[sc->file_i]=0;
+    sc->loadport->_object._port=sc->load_stack+sc->file_i;
+  }
+  return fin!=0;
+}
+
+static void file_pop(scheme *sc) {
+ sc->nesting=sc->nesting_stack[sc->file_i];
+ if(sc->file_i!=0) {
+   port_close(sc,sc->loadport,port_input);
+   sc->file_i--;
+   sc->loadport->_object._port=sc->load_stack+sc->file_i;
+   if(file_interactive(sc)) {
+     putstr(sc,prompt);
+   }
+ }
+}
+
+static int file_interactive(scheme *sc) {
+ return sc->file_i==0 && sc->load_stack[0].rep.stdio.file==stdin
+     && sc->inport->_object._port->kind&port_file;
+}
+
+static port *port_rep_from_filename(scheme *sc, const char *fn, int prop) {
+  FILE *f;
+  const char *rw;
+  port *pt;
+  if(prop==(port_input|port_output)) {
+    rw="a+";
+  } else if(prop==port_output) {
+    rw="w";
+  } else {
+    rw="r";
+  }
+  f=fopen(fn,rw);
+  if(f==0) {
+    return 0;
+  }
+  pt=port_rep_from_file(sc,f,prop);
+  pt->rep.stdio.closeit=1;
+  return pt;
+}
+
+static pointer port_from_filename(scheme *sc, const char *fn, int prop) {
+  port *pt;
+  pt=port_rep_from_filename(sc,fn,prop);
+  if(pt==0) {
+    return sc->NIL;
+  }
+  return mk_port(sc,pt);
+}
+
+static port *port_rep_from_file(scheme *sc, FILE *f, int prop) {
+  const char *rw;
+  port *pt;
+  pt=(port*)sc->malloc(sizeof(port));
+  if(pt==0) {
+    return 0;
+  }
+  if(prop==(port_input|port_output)) {
+    rw="a+";
+  } else if(prop==port_output) {
+    rw="w";
+  } else {
+    rw="r";
+  }
+  pt->kind=port_file|prop;
+  pt->rep.stdio.file=f;
+  pt->rep.stdio.closeit=0;
+  return pt;
+}
+
+static pointer port_from_file(scheme *sc, FILE *f, int prop) {
+  port *pt;
+  pt=port_rep_from_file(sc,f,prop);
+  if(pt==0) {
+    return sc->NIL;
+  }
+  return mk_port(sc,pt);
+}
+
+static port *port_rep_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
+  port *pt;
+  pt=(port*)sc->malloc(sizeof(port));
+  if(pt==0) {
+    return 0;
+  }
+  pt->kind=port_string|prop;
+  pt->rep.string.start=start;
+  pt->rep.string.curr=start;
+  pt->rep.string.past_the_end=past_the_end;
+  return pt;
+}
+
+static pointer port_from_string(scheme *sc, char *start, char *past_the_end, int prop) {
+  port *pt;
+  pt=port_rep_from_string(sc,start,past_the_end,prop);
+  if(pt==0) {
+    return sc->NIL;
+  }
+  return mk_port(sc,pt);
+}
+
+static void port_close(scheme *sc, pointer p, int flag) {
+  port *pt=p->_object._port;
+  pt->kind&=~flag;
+  if((pt->kind & (port_input|port_output))==0) {
+    if(pt->kind&port_file) {
+      fclose(pt->rep.stdio.file);
+#if USE_FILE_AND_LINE
+      if (pt->rep.stdio.name) {
+              free(pt->rep.stdio.name);
+      }
+#endif
+    }
+    pt->kind=port_free;
+  }
+}
+
+/* get new character from input file */
+static int inchar(scheme *sc) {
+  int c;
+  port *pt;
+ again:
+  pt=sc->inport->_object._port;
+  c=basic_inchar(pt);
+  if(c==EOF && sc->inport==sc->loadport && sc->file_i!=0) {
+    file_pop(sc);
+    if(sc->nesting!=0 || sc->tok==TOK_COMMENT) {
+      return EOF;
+    }
+    goto again;
+  }
+#if USE_FILE_AND_LINE
+  if (c == '\n')
+          pt->rep.stdio.line++;
+#endif
+  return c;
+}
+
+static int basic_inchar(port *pt) {
+  if(pt->kind&port_file) {
+          int ch = fgetc(pt->rep.stdio.file);
+          return ch;
+  } else {
+    if(*pt->rep.string.curr==0
+       || pt->rep.string.curr==pt->rep.string.past_the_end) {
+      return EOF;
+    } else {
+      return *pt->rep.string.curr++;
+    }
+  }
+}
+
+/* back character to input buffer */
+static void backchar(scheme *sc, int c) {
+  port *pt;
+  if(c==EOF) return;
+  pt=sc->inport->_object._port;
+  if(pt->kind&port_file) {
+    ungetc(c,pt->rep.stdio.file);
+#if USE_FILE_AND_LINE
+    if (c == '\n')
+            pt->rep.stdio.line--;
+#endif
+  } else {
+    if(pt->rep.string.curr!=pt->rep.string.start) {
+      --pt->rep.string.curr;
+    }
+  }
+}
+
+INTERFACE void putstr(scheme *sc, const char *s) {
+  port *pt=sc->outport->_object._port;
+  if(pt->kind&port_file) {
+    fputs(s,pt->rep.stdio.file);
+  } else {
+    for(;*s;s++) {
+      if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
+       *pt->rep.string.curr++=*s;
+      }
+    }
+  }
+}
+
+static void putchars(scheme *sc, const char *s, int len) {
+  port *pt=sc->outport->_object._port;
+  if(pt->kind&port_file) {
+    fwrite(s,1,len,pt->rep.stdio.file);
+  } else {
+    for(;len;len--) {
+      if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
+       *pt->rep.string.curr++=*s++;
+      }
+    }
+  }
+}
+
+INTERFACE void putcharacter(scheme *sc, int c) {
+  port *pt=sc->outport->_object._port;
+  if(pt->kind&port_file) {
+    fputc(c,pt->rep.stdio.file);
+  } else {
+    if(pt->rep.string.curr!=pt->rep.string.past_the_end) {
+      *pt->rep.string.curr++=c;
+    }
+  }
+}
+
+/* read characters up to delimiter, but cater to character constants */
+static char   *readstr_upto(scheme *sc, const char *delim) {
+  char   *p = sc->strbuff;
+
+  while (!is_one_of(delim, (*p++ = inchar(sc))));
+  if(p==sc->strbuff+2 && p[-2]=='\\') {
+    *p=0;
+  } else {
+    backchar(sc,p[-1]);
+    *--p = '\0';
+  }
+  return sc->strbuff;
+}
+
+/* read string expression "xxx...xxx" */
+static pointer readstrexp(scheme *sc) {
+  char *p = sc->strbuff;
+  int c;
+  int c1=0;
+  enum { st_ok, st_bsl, st_x1, st_x2} state=st_ok;
+  
+  for (;;) {
+    c=inchar(sc);
+    if(c==EOF || (p-sc->strbuff)>(int)(sizeof(sc->strbuff)-1)) {
+      return sc->F;
+    }
+    switch(state) {
+    case st_ok:
+      switch(c) {
+      case '\\':
+       state=st_bsl;
+       break;
+      case '"':
+       *p=0;
+       return mk_counted_string(sc,sc->strbuff,p-sc->strbuff);
+      default:
+       *p++=c;
+       break;
+      }
+      break;
+    case st_bsl:
+      switch(c) {
+      case 'x':
+      case 'X':
+       state=st_x1;
+       c1=0;
+       break;
+      case 'n':
+       *p++='\n';
+       state=st_ok;
+       break;
+      case 't':
+       *p++='\t';
+       state=st_ok;
+       break;
+      case 'r':
+       *p++='\r';
+       state=st_ok;
+       break;
+      case '"':
+       *p++='"';
+       state=st_ok;
+       break;
+      default:
+       *p++=c;
+       state=st_ok;
+       break;
+      }
+      break;
+    case st_x1:
+    case st_x2:
+      c=toupper(c);
+      if(c>='0' && c<='F') {
+       if(c<='9') {
+         c1=(c1<<4)+c-'0';
+       } else {
+         c1=(c1<<4)+c-'A'+10;
+       }
+       if(state==st_x1) {
+         state=st_x2;
+       } else {
+         *p++=c1;
+         state=st_ok;
+       }
+      } else {
+       return sc->F;
+      }
+      break;
+    }
+  }
+}
+
+/* check c is in chars */
+static INLINE int is_one_of(const char *s, int c) {
+     if(c==EOF) return 1;
+     while (*s)
+          if (*s++ == c)
+               return (1);
+     return (0);
+}
+
+/* skip white characters */
+static INLINE void skipspace(scheme *sc) {
+     int c;
+     while (isspace(c=inchar(sc)))
+          ;
+     if(c!=EOF) {
+          backchar(sc,c);
+     }
+}
+
+/* get token */
+static int token(scheme *sc) {
+     int c;
+     skipspace(sc);
+     switch (c=inchar(sc)) {
+     case EOF:
+          return (TOK_EOF);
+     case '(':
+          return (TOK_LPAREN);
+     case ')':
+          return (TOK_RPAREN);
+     case '.':
+          c=inchar(sc);
+          if(is_one_of(" \n\t",c)) {
+               return (TOK_DOT);
+          } else {
+               backchar(sc,c);
+              backchar(sc,'.');
+               return TOK_ATOM;
+          }
+     case '\'':
+          return (TOK_QUOTE);
+     case ';':
+           while ((c=inchar(sc)) != '\n' && c!=EOF)
+             ;
+           return (token(sc));
+     case '"':
+          return (TOK_DQUOTE);
+     case BACKQUOTE:
+          return (TOK_BQUOTE);
+     case ',':
+          if ((c=inchar(sc)) == '@')
+               return (TOK_ATMARK);
+          else {
+               backchar(sc,c);
+               return (TOK_COMMA);
+          }
+     case '#':
+          c=inchar(sc);
+          if (c == '(') {
+               return (TOK_VEC);
+          } else if(c == '!') {
+               while ((c=inchar(sc)) != '\n' && c!=EOF)
+                   ;
+               return (token(sc));
+          } else {
+               backchar(sc,c);
+               if(is_one_of(" tfodxb\\",c)) {
+                    return TOK_SHARP_CONST;
+               } else {
+                    return (TOK_SHARP);
+               }
+          }
+     default:
+          backchar(sc,c);
+          return (TOK_ATOM);
+     }
+}
+
+/* ========== Routines for Printing ========== */
+#define   ok_abbrev(x)   (is_pair(x) && cdr(x) == sc->NIL)
+
+static void printslashstring(scheme *sc, char *p, int len) {
+  int i;
+  unsigned char *s=(unsigned char*)p;
+  putcharacter(sc,'"');
+  for ( i=0; i<len; i++) {
+    if(*s==0xff || *s=='"' || *s<' ' || *s=='\\') {
+      putcharacter(sc,'\\');
+      switch(*s) {
+      case '"':
+       putcharacter(sc,'"');
+       break;
+      case '\n':
+       putcharacter(sc,'n');
+       break;
+      case '\t':
+       putcharacter(sc,'t');
+       break;
+      case '\r':
+       putcharacter(sc,'r');
+       break;
+      case '\\':
+       putcharacter(sc,'\\');
+       break;
+      default: { 
+         int d=*s/16;
+         putcharacter(sc,'x');
+         if(d<10) {
+           putcharacter(sc,d+'0');
+         } else {
+           putcharacter(sc,d-10+'A');
+         }
+         d=*s%16;
+         if(d<10) {
+           putcharacter(sc,d+'0');
+         } else {
+           putcharacter(sc,d-10+'A');
+         }
+       }
+      }
+    } else {
+      putcharacter(sc,*s);
+    }
+    s++; 
+  }
+  putcharacter(sc,'"');
+}
+
+
+/* print atoms */
+static void printatom(scheme *sc, pointer l, int f) {
+  const char *p;
+  int len;
+  atom2str(sc,l,f,&p,&len);
+  putchars(sc,p,len);
+}
+
+
+/* Uses internal buffer unless string pointer is already available */
+static void atom2str(scheme *sc, pointer l, int f, const char **pp, int *plen) {
+     const char *p;
+
+     if (l == sc->NIL) {
+          p = "()";
+     } else if (l == sc->T) {
+          p = "#t";
+     } else if (l == sc->F) {
+          p = "#f";
+     } else if (l == sc->EOF_OBJ) {
+          p = "#<EOF>";
+     } else if (is_port(l)) {
+          strcpy(sc->strbuff, "#<PORT>");
+          p = sc->strbuff;
+     } else if (is_number(l)) {
+          if(is_integer(l)) {
+               sprintf(sc->strbuff, "%ld", ivalue_unchecked(l));
+          } else {
+               sprintf(sc->strbuff, "%.10g", rvalue_unchecked(l));
+          }
+          p = sc->strbuff;
+     } else if (is_string(l)) {
+          if (!f) {
+               p = strvalue(l);
+          } else { /* Hack, uses the fact that printing is needed */
+               *pp=sc->strbuff;
+              *plen=0;
+               printslashstring(sc, strvalue(l), strlength(l));
+              return;
+          }
+     } else if (is_character(l)) {
+          int c=charvalue(l);
+          if (!f) {
+               sc->strbuff[0]=c;
+               sc->strbuff[1]=0;
+          } else {
+               switch(c) {
+               case ' ':
+                    sprintf(sc->strbuff,"#\\space"); break;
+               case '\n':
+                    sprintf(sc->strbuff,"#\\newline"); break;
+               case '\r':
+                    sprintf(sc->strbuff,"#\\return"); break;
+               case '\t':
+                    sprintf(sc->strbuff,"#\\tab"); break;
+               default:
+#if USE_ASCII_NAMES
+                    if(c==127) {
+                         strcpy(sc->strbuff,"#\\del"); break;
+                    } else if(c<32) {
+                         strcpy(sc->strbuff,"#\\"); strcat(sc->strbuff,charnames[c]); break;
+                    }
+#else
+                   if(c<32) {
+                     sprintf(sc->strbuff,"#\\x%x",c); break;
+                   }
+#endif
+                    sprintf(sc->strbuff,"#\\%c",c); break;
+               }
+          }
+          p = sc->strbuff;
+     } else if (is_symbol(l)) {
+          p = symname(l);
+     } else if (is_proc(l)) {
+          sprintf(sc->strbuff, "#<%s PROCEDURE %ld>", procname(l),procnum(l));
+          p = sc->strbuff;
+     } else if (is_macro(l)) {
+          p = "#<MACRO>";
+     } else if (is_closure(l)) {
+          p = "#<CLOSURE>";
+     } else if (is_promise(l)) {
+          p = "#<PROMISE>";
+     } else if (is_foreign(l)) {
+          sprintf(sc->strbuff, "#<FOREIGN PROCEDURE %ld>", procnum(l));
+          p = sc->strbuff;
+     } else if (is_continuation(l)) {
+          p = "#<CONTINUATION>";
+     } else {
+          p = "#<ERROR>";
+     }
+     *pp=p;
+     *plen=strlen(p);
+}
+/* ========== Routines for Evaluation Cycle ========== */
+
+/* make closure. c is code. e is environment */
+static pointer mk_closure(scheme *sc, pointer c, pointer e) {
+     pointer x = get_cell(sc, c, e);
+
+     typeflag(x) = T_CLOSURE;
+     car(x) = c;
+     cdr(x) = e;
+     return (x);
+}
+
+/* make continuation. */
+static pointer mk_continuation(scheme *sc, pointer d) {
+     pointer x = get_cell(sc, sc->NIL, d);
+
+     typeflag(x) = T_CONTINUATION;
+     cont_dump(x) = d;
+     return (x);
+}
+
+static pointer list_star(scheme *sc, pointer d) {
+  pointer p, q;
+  if(cdr(d)==sc->NIL) {
+    return car(d);
+  }
+  p=cons(sc,car(d),cdr(d));
+  q=p;
+  while(cdr(cdr(p))!=sc->NIL) {
+    d=cons(sc,car(p),cdr(p));
+    if(cdr(cdr(p))!=sc->NIL) {
+      p=cdr(d);
+    }
+  }
+  cdr(p)=car(cdr(p));
+  return q;
+}
+
+/* reverse list -- produce new list */
+static pointer reverse(scheme *sc, pointer a) {
+/* a must be checked by gc */
+     pointer p = sc->NIL;
+
+     for ( ; is_pair(a); a = cdr(a)) {
+          p = cons(sc, car(a), p);
+     }
+     return (p);
+}
+
+/* reverse list --- in-place */
+static pointer reverse_in_place(scheme *sc, pointer term, pointer list) {
+     pointer p = list, result = term, q;
+
+     while (p != sc->NIL) {
+          q = cdr(p);
+          cdr(p) = result;
+          result = p;
+          p = q;
+     }
+     return (result);
+}
+
+/* append list -- produce new list */
+static pointer append(scheme *sc, pointer a, pointer b) {
+     pointer p = b, q;
+
+     if (a != sc->NIL) {
+          a = reverse(sc, a);
+          while (a != sc->NIL) {
+               q = cdr(a);
+               cdr(a) = p;
+               p = a;
+               a = q;
+          }
+     }
+     return (p);
+}
+
+/* equivalence of atoms */
+static int eqv(pointer a, pointer b) {
+     if (is_string(a)) {
+          if (is_string(b))
+               return (strvalue(a) == strvalue(b));
+          else
+               return (0);
+     } else if (is_number(a)) {
+          if (is_number(b))
+               return num_eq(nvalue(a),nvalue(b));
+          else
+               return (0);
+     } else if (is_character(a)) {
+          if (is_character(b))
+               return charvalue(a)==charvalue(b);
+          else
+               return (0);
+     } else if (is_port(a)) {
+          if (is_port(b))
+               return a==b;
+          else
+               return (0);
+     } else if (is_proc(a)) {
+          if (is_proc(b))
+               return procnum(a)==procnum(b);
+          else
+               return (0);
+     } else if (is_foreign(a)) {
+             if (is_foreign(b))
+                     return (a->_object._ff == b->_object._ff);
+             return (0);
+     } else {
+          return (a == b);
+     }
+}
+
+/* true or false value macro */
+/* () is #t in R5RS */
+#define is_true(p)       ((p) != sc->F)
+#define is_false(p)      ((p) == sc->F)
+
+/* ========== Environment implementation  ========== */ 
+
+#if !defined(USE_ALIST_ENV) || !defined(USE_OBJECT_LIST) 
+
+static int hash_fn(const char *key, int table_size) 
+{ 
+  unsigned int hashed = 0; 
+  const char *c; 
+  int bits_per_int = sizeof(unsigned int)*8; 
+
+  for (c = key; *c; c++) { 
+    /* letters have about 5 bits in them */ 
+    hashed = (hashed<<5) | (hashed>>(bits_per_int-5)); 
+    hashed ^= *c; 
+  } 
+  return hashed % table_size; 
+} 
+#endif 
+
+#ifndef USE_ALIST_ENV 
+
+/* 
+ * In this implementation, each frame of the environment may be 
+ * a hash table: a vector of alists hashed by variable name. 
+ * In practice, we use a vector only for the initial frame; 
+ * subsequent frames are too small and transient for the lookup 
+ * speed to out-weigh the cost of making a new vector. 
+ */ 
+
+static void new_frame_in_env(scheme *sc, pointer old_env) 
+{ 
+  pointer new_frame; 
+
+  /* The interaction-environment has about 300 variables in it. */ 
+  if (old_env == sc->NIL) { 
+    new_frame = mk_vector(sc, 461); 
+  } else { 
+    new_frame = sc->NIL; 
+  } 
+
+  sc->envir = immutable_cons(sc, new_frame, old_env); 
+  setenvironment(sc->envir); 
+} 
+
+static INLINE void new_slot_spec_in_env(scheme *sc, pointer env, 
+                                        pointer variable, pointer value) 
+{ 
+  pointer slot = immutable_cons(sc, variable, value); 
+
+  if (is_vector(car(env))) { 
+    int location = hash_fn(symname(variable), ivalue_unchecked(car(env))); 
+
+    set_vector_elem(car(env), location, 
+                    immutable_cons(sc, slot, vector_elem(car(env), location))); 
+  } else { 
+    car(env) = immutable_cons(sc, slot, car(env)); 
+  } 
+} 
+
+static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all) 
+{ 
+  pointer x,y=sc->NIL; 
+  int location; 
+
+  for (x = env; x != sc->NIL; x = cdr(x)) { 
+    if (is_vector(car(x))) { 
+      location = hash_fn(symname(hdl), ivalue_unchecked(car(x))); 
+      y = vector_elem(car(x), location); 
+    } else { 
+      y = car(x); 
+    } 
+    for ( ; y != sc->NIL; y = cdr(y)) { 
+            if (caar(y) == hdl) { 
+                    break; 
+            } 
+    } 
+    if (y != sc->NIL) { 
+            break; 
+    } 
+    if(!all) { 
+            return sc->NIL; 
+    } 
+  } 
+  if (x != sc->NIL) { 
+          return car(y); 
+  } 
+  return sc->NIL; 
+} 
+
+#else /* USE_ALIST_ENV */ 
+
+static INLINE void new_frame_in_env(scheme *sc, pointer old_env) 
+{ 
+  sc->envir = immutable_cons(sc, sc->NIL, old_env); 
+  setenvironment(sc->envir); 
+} 
+
+static INLINE void new_slot_spec_in_env(scheme *sc, pointer env, 
+                                        pointer variable, pointer value) 
+{ 
+  car(env) = immutable_cons(sc, immutable_cons(sc, variable, value), car(env)); 
+} 
+
+static pointer find_slot_in_env(scheme *sc, pointer env, pointer hdl, int all) 
+{ 
+    pointer x,y; 
+    for (x = env; x != sc->NIL; x = cdr(x)) { 
+         for (y = car(x); y != sc->NIL; y = cdr(y)) { 
+              if (caar(y) == hdl) { 
+                   break; 
+              } 
+         } 
+         if (y != sc->NIL) { 
+              break; 
+         } 
+         if(!all) { 
+           return sc->NIL; 
+         } 
+    } 
+    if (x != sc->NIL) { 
+          return car(y); 
+    } 
+    return sc->NIL; 
+} 
+
+#endif /* USE_ALIST_ENV else */ 
+
+static INLINE void new_slot_in_env(scheme *sc, pointer variable, pointer value) 
+{ 
+  new_slot_spec_in_env(sc, sc->envir, variable, value); 
+} 
+
+static INLINE void set_slot_in_env(scheme *sc, pointer slot, pointer value) 
+{ 
+  cdr(slot) = value; 
+} 
+
+static INLINE pointer slot_value_in_env(pointer slot) 
+{ 
+  return cdr(slot); 
+} 
+
+/* ========== Evaluation Cycle ========== */
+
+
+static pointer _Error_1(scheme *sc, const char *s, pointer a) {
+#if USE_ERROR_HOOK
+     pointer x;
+     pointer hdl=sc->ERROR_HOOK;
+
+     x=find_slot_in_env(sc,sc->envir,hdl,1);
+    if (x != sc->NIL) {
+         if(a!=0) {
+               sc->code = cons(sc, cons(sc, sc->QUOTE, cons(sc,(a), sc->NIL)), sc->NIL);
+         } else {
+               sc->code = sc->NIL;
+         }
+         sc->code = cons(sc, mk_string(sc, (s)), sc->code);
+         setimmutable(car(sc->code));
+         sc->code = cons(sc, slot_value_in_env(x), sc->code); 
+         sc->op = (int)OP_EVAL;
+         return sc->T;
+    }
+#endif
+
+    if(a!=0) {
+          sc->args = cons(sc, (a), sc->NIL);
+    } else {
+          sc->args = sc->NIL;
+    }
+    sc->args = cons(sc, mk_string(sc, (s)), sc->args);
+    setimmutable(car(sc->args));
+    sc->op = (int)OP_ERR0;
+    return sc->T;
+}
+#define Error_1(sc,s, a) return _Error_1(sc,s,a)
+#define Error_0(sc,s)    return _Error_1(sc,s,0)
+
+/* Too small to turn into function */
+# define  BEGIN     do {
+# define  END  } while (0)
+#define s_goto(sc,a) BEGIN                                  \
+    sc->op = (int)(a);                                      \
+    return sc->T; END
+
+#define s_return(sc,a) return _s_return(sc,a) 
+
+#ifndef USE_SCHEME_STACK 
+
+/* this structure holds all the interpreter's registers */ 
+struct dump_stack_frame { 
+  enum scheme_opcodes op; 
+  pointer args; 
+  pointer envir; 
+  pointer code; 
+}; 
+
+#define STACK_GROWTH 3 
+
+static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) 
+{ 
+  long nframes = (long)sc->dump; 
+  struct dump_stack_frame *next_frame; 
+
+  /* enough room for the next frame? */ 
+  if (nframes >= sc->dump_size) { 
+    sc->dump_size += STACK_GROWTH; 
+    /* alas there is no sc->realloc */ 
+    sc->dump_base = realloc(sc->dump_base, 
+                            sizeof(struct dump_stack_frame) * sc->dump_size); 
+  } 
+  next_frame = (struct dump_stack_frame *)sc->dump_base + nframes; 
+  next_frame->op = op; 
+  next_frame->args = args; 
+  next_frame->envir = sc->envir; 
+  next_frame->code = code; 
+  sc->dump = (pointer)(nframes+1); 
+} 
+
+static pointer _s_return(scheme *sc, pointer a) 
+{ 
+  long nframes = (long)sc->dump; 
+  struct dump_stack_frame *frame; 
+
+  sc->value = (a); 
+  if (nframes <= 0) { 
+    return sc->NIL; 
+  } 
+  nframes--; 
+  frame = (struct dump_stack_frame *)sc->dump_base + nframes; 
+  sc->op = frame->op; 
+  sc->args = frame->args; 
+  sc->envir = frame->envir; 
+  sc->code = frame->code; 
+  sc->dump = (pointer)nframes; 
+  return sc->T; 
+} 
+
+static INLINE void dump_stack_reset(scheme *sc) 
+{ 
+  /* in this implementation, sc->dump is the number of frames on the stack */ 
+  sc->dump = (pointer)0; 
+} 
+
+static INLINE void dump_stack_initialize(scheme *sc) 
+{ 
+  sc->dump_size = 0; 
+  sc->dump_base = NULL; 
+  dump_stack_reset(sc); 
+} 
+
+static void dump_stack_free(scheme *sc) 
+{ 
+  free(sc->dump_base); 
+  sc->dump_base = NULL; 
+  sc->dump = (pointer)0; 
+  sc->dump_size = 0; 
+} 
+
+static INLINE void dump_stack_mark(scheme *sc) 
+{ 
+  long nframes = (long)sc->dump;
+  int i;
+  for(i=0; i<nframes; i++) {
+    struct dump_stack_frame *frame;
+    frame = (struct dump_stack_frame *)sc->dump_base + i;
+    mark(frame->args);
+    mark(frame->envir);
+    mark(frame->code);
+  } 
+} 
+
+#else 
+
+static INLINE void dump_stack_reset(scheme *sc) 
+{ 
+  sc->dump = sc->NIL; 
+} 
+
+static INLINE void dump_stack_initialize(scheme *sc) 
+{ 
+  dump_stack_reset(sc); 
+} 
+
+static void dump_stack_free(scheme *sc) 
+{ 
+  sc->dump = sc->NIL; 
+} 
+
+static pointer _s_return(scheme *sc, pointer a) { 
+    sc->value = (a); 
+    if(sc->dump==sc->NIL) return sc->NIL; 
+    sc->op = ivalue(car(sc->dump)); 
+    sc->args = cadr(sc->dump); 
+    sc->envir = caddr(sc->dump); 
+    sc->code = cadddr(sc->dump); 
+    sc->dump = cddddr(sc->dump); 
+    return sc->T; 
+} 
+
+static void s_save(scheme *sc, enum scheme_opcodes op, pointer args, pointer code) { 
+    sc->dump = cons(sc, sc->envir, cons(sc, (code), sc->dump)); 
+    sc->dump = cons(sc, (args), sc->dump); 
+    sc->dump = cons(sc, mk_integer(sc, (long)(op)), sc->dump); 
+} 
+
+static INLINE void dump_stack_mark(scheme *sc) 
+{ 
+  mark(sc->dump); 
+} 
+#endif 
+
+#define s_retbool(tf)    s_return(sc,(tf) ? sc->T : sc->F)
+
+static pointer opexe_0(scheme *sc, enum scheme_opcodes op) {
+     pointer x, y;
+
+     switch (op) {
+     case OP_LOAD:       /* load */
+          if(file_interactive(sc)) {
+               fprintf(sc->outport->_object._port->rep.stdio.file, 
+                      "Loading %s\n", strvalue(car(sc->args)));
+          }
+          if (!file_push(sc,strvalue(car(sc->args)))) {
+               Error_1(sc,"unable to open", car(sc->args));
+          }
+          s_goto(sc,OP_T0LVL);
+
+     case OP_T0LVL: /* top level */
+          if(file_interactive(sc)) {
+               putstr(sc,"\n");
+          }
+          sc->nesting=0;
+          dump_stack_reset(sc); 
+          sc->envir = sc->global_env;
+         sc->save_inport=sc->inport;
+          sc->inport = sc->loadport;
+         s_save(sc,OP_T0LVL, sc->NIL, sc->NIL);
+          s_save(sc,OP_VALUEPRINT, sc->NIL, sc->NIL);
+          s_save(sc,OP_T1LVL, sc->NIL, sc->NIL);
+          if (file_interactive(sc)) {
+              putstr(sc,prompt);
+          }
+          s_goto(sc,OP_READ_INTERNAL);
+
+     case OP_T1LVL: /* top level */
+          sc->code = sc->value;
+          sc->inport=sc->save_inport;
+          s_goto(sc,OP_EVAL);
+
+     case OP_READ_INTERNAL:       /* internal read */
+          sc->tok = token(sc);
+          if(sc->tok==TOK_EOF) {
+               if(sc->inport==sc->loadport) {
+                    sc->args=sc->NIL;
+                    s_goto(sc,OP_QUIT);
+               } else {
+                    s_return(sc,sc->EOF_OBJ);
+               }
+          }
+          s_goto(sc,OP_RDSEXPR);
+
+     case OP_GENSYM:
+          s_return(sc, gensym(sc));
+
+     case OP_VALUEPRINT: /* print evaluation result */
+          /* OP_VALUEPRINT is always pushed, because when changing from
+             non-interactive to interactive mode, it needs to be
+             already on the stack */
+       if(sc->tracing) {
+        putstr(sc,"\nGives: ");
+       }
+       if(file_interactive(sc)) {
+        sc->print_flag = 1;
+        sc->args = sc->value;
+        s_goto(sc,OP_P0LIST);
+       } else {
+        s_return(sc,sc->value);
+       }
+
+     case OP_EVAL:       /* main part of evaluation */
+#if USE_TRACING
+       if(sc->tracing) {
+        /*s_save(sc,OP_VALUEPRINT,sc->NIL,sc->NIL);*/
+        s_save(sc,OP_REAL_EVAL,sc->args,sc->code);
+        sc->args=sc->code;
+        putstr(sc,"\nEval: ");
+        s_goto(sc,OP_P0LIST);
+       }
+       /* fall through */
+     case OP_REAL_EVAL:
+#endif
+          if (is_symbol(sc->code)) {    /* symbol */
+               x=find_slot_in_env(sc,sc->envir,sc->code,1);
+               if (x != sc->NIL) {
+                    s_return(sc,slot_value_in_env(x)); 
+               } else {
+                    Error_1(sc,"eval: unbound variable:", sc->code);
+               }
+          } else if (is_pair(sc->code)) {
+               if (is_syntax(x = car(sc->code))) {     /* SYNTAX */
+                    sc->code = cdr(sc->code);
+                    s_goto(sc,syntaxnum(x));
+               } else {/* first, eval top element and eval arguments */
+                    s_save(sc,OP_E0ARGS, sc->NIL, sc->code);
+                    /* If no macros => s_save(sc,OP_E1ARGS, sc->NIL, cdr(sc->code));*/
+                    sc->code = car(sc->code);
+                    s_goto(sc,OP_EVAL);
+               }
+          } else {
+               s_return(sc,sc->code);
+          }
+
+     case OP_E0ARGS:     /* eval arguments */
+          if (is_macro(sc->value)) {    /* macro expansion */
+               s_save(sc,OP_DOMACRO, sc->NIL, sc->NIL);
+               sc->args = cons(sc,sc->code, sc->NIL);
+               sc->code = sc->value;
+               s_goto(sc,OP_APPLY);
+          } else {
+               sc->code = cdr(sc->code);
+               s_goto(sc,OP_E1ARGS);
+          }
+
+     case OP_E1ARGS:     /* eval arguments */
+          sc->args = cons(sc, sc->value, sc->args);
+          if (is_pair(sc->code)) { /* continue */
+               s_save(sc,OP_E1ARGS, sc->args, cdr(sc->code));
+               sc->code = car(sc->code);
+               sc->args = sc->NIL;
+               s_goto(sc,OP_EVAL);
+          } else {  /* end */
+               sc->args = reverse_in_place(sc, sc->NIL, sc->args); 
+               sc->code = car(sc->args);
+               sc->args = cdr(sc->args);
+               s_goto(sc,OP_APPLY);
+          }
+
+#if USE_TRACING
+     case OP_TRACING: {
+       int tr=sc->tracing;
+       sc->tracing=ivalue(car(sc->args));
+       s_return(sc,mk_integer(sc,tr));
+     }
+#endif
+
+     case OP_APPLY:      /* apply 'code' to 'args' */
+#if USE_TRACING
+       if(sc->tracing) {
+        s_save(sc,OP_REAL_APPLY,sc->args,sc->code);
+        sc->print_flag = 1;
+        /*      sc->args=cons(sc,sc->code,sc->args);*/
+         putstr(sc,"\nApply to: ");
+        s_goto(sc,OP_P0LIST);
+       }
+       /* fall through */
+     case OP_REAL_APPLY:
+#endif
+          if (is_proc(sc->code)) {
+               s_goto(sc,procnum(sc->code));   /* PROCEDURE */
+          } else if (is_foreign(sc->code)) {
+               x=sc->code->_object._ff(sc,sc->args);
+               s_return(sc,x);
+          } else if (is_closure(sc->code) || is_macro(sc->code) 
+                    || is_promise(sc->code)) { /* CLOSURE */
+           /* Should not accept promise */
+               /* make environment */
+               new_frame_in_env(sc, closure_env(sc->code)); 
+               for (x = car(closure_code(sc->code)), y = sc->args;
+                    is_pair(x); x = cdr(x), y = cdr(y)) {
+                    if (y == sc->NIL) {
+                         Error_0(sc,"not enough arguments");
+                    } else {
+                         new_slot_in_env(sc, car(x), car(y)); 
+                    }
+               }
+               if (x == sc->NIL) {
+                    /*--
+                     * if (y != sc->NIL) {
+                     *   Error_0(sc,"too many arguments");
+                     * }
+                     */
+               } else if (is_symbol(x))
+                    new_slot_in_env(sc, x, y); 
+               else {
+                    Error_1(sc,"syntax error in closure: not a symbol:", x); 
+               }
+               sc->code = cdr(closure_code(sc->code));
+               sc->args = sc->NIL;
+               s_goto(sc,OP_BEGIN);
+          } else if (is_continuation(sc->code)) { /* CONTINUATION */
+               sc->dump = cont_dump(sc->code);
+               s_return(sc,sc->args != sc->NIL ? car(sc->args) : sc->NIL);
+          } else {
+               Error_0(sc,"illegal function");
+          }
+
+     case OP_DOMACRO:    /* do macro */
+          sc->code = sc->value;
+          s_goto(sc,OP_EVAL);
+
+     case OP_LAMBDA:     /* lambda */
+          s_return(sc,mk_closure(sc, sc->code, sc->envir));
+
+     case OP_MKCLOSURE: /* make-closure */
+       x=car(sc->args);
+       if(car(x)==sc->LAMBDA) {
+        x=cdr(x);
+       }
+       if(cdr(sc->args)==sc->NIL) {
+        y=sc->envir;
+       } else {
+        y=cadr(sc->args);
+       }
+       s_return(sc,mk_closure(sc, x, y));
+
+     case OP_QUOTE:      /* quote */
+          x=car(sc->code);
+          s_return(sc,car(sc->code));
+
+     case OP_DEF0:  /* define */
+          if (is_pair(car(sc->code))) {
+               x = caar(sc->code);
+               sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
+          } else {
+               x = car(sc->code);
+               sc->code = cadr(sc->code);
+          }
+          if (!is_symbol(x)) {
+               Error_0(sc,"variable is not a symbol");
+          }
+          s_save(sc,OP_DEF1, sc->NIL, x);
+          s_goto(sc,OP_EVAL);
+
+     case OP_DEF1:  /* define */
+       x=find_slot_in_env(sc,sc->envir,sc->code,0);
+          if (x != sc->NIL) {
+               set_slot_in_env(sc, x, sc->value); 
+          } else {
+               new_slot_in_env(sc, sc->code, sc->value); 
+          }
+          s_return(sc,sc->code);
+
+
+     case OP_DEFP:  /* defined? */
+          x=sc->envir;
+          if(cdr(sc->args)!=sc->NIL) {
+               x=cadr(sc->args);
+          }
+          s_retbool(find_slot_in_env(sc,x,car(sc->args),1)!=sc->NIL);
+
+     case OP_SET0:       /* set! */
+          s_save(sc,OP_SET1, sc->NIL, car(sc->code));
+          sc->code = cadr(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_SET1:       /* set! */
+       y=find_slot_in_env(sc,sc->envir,sc->code,1);
+          if (y != sc->NIL) {
+               set_slot_in_env(sc, y, sc->value); 
+               s_return(sc,sc->value);
+          } else {
+               Error_1(sc,"set!: unbound variable:", sc->code); 
+          }
+
+
+     case OP_BEGIN:      /* begin */
+          if (!is_pair(sc->code)) {
+               s_return(sc,sc->code);
+          }
+          if (cdr(sc->code) != sc->NIL) {
+               s_save(sc,OP_BEGIN, sc->NIL, cdr(sc->code));
+          }
+          sc->code = car(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_IF0:        /* if */
+          s_save(sc,OP_IF1, sc->NIL, cdr(sc->code));
+          sc->code = car(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_IF1:        /* if */
+          if (is_true(sc->value))
+               sc->code = car(sc->code);
+          else
+               sc->code = cadr(sc->code);  /* (if #f 1) ==> () because
+                               * car(sc->NIL) = sc->NIL */
+          s_goto(sc,OP_EVAL);
+
+     case OP_LET0:       /* let */
+          sc->args = sc->NIL;
+          sc->value = sc->code;
+          sc->code = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code);
+          s_goto(sc,OP_LET1);
+
+     case OP_LET1:       /* let (calculate parameters) */
+          sc->args = cons(sc, sc->value, sc->args);
+          if (is_pair(sc->code)) { /* continue */
+               s_save(sc,OP_LET1, sc->args, cdr(sc->code));
+               sc->code = cadar(sc->code);
+               sc->args = sc->NIL;
+               s_goto(sc,OP_EVAL);
+          } else {  /* end */
+               sc->args = reverse_in_place(sc, sc->NIL, sc->args);
+               sc->code = car(sc->args);
+               sc->args = cdr(sc->args);
+               s_goto(sc,OP_LET2);
+          }
+
+     case OP_LET2:       /* let */
+          new_frame_in_env(sc, sc->envir); 
+          for (x = is_symbol(car(sc->code)) ? cadr(sc->code) : car(sc->code), y = sc->args;
+               y != sc->NIL; x = cdr(x), y = cdr(y)) {
+               new_slot_in_env(sc, caar(x), car(y)); 
+          }
+          if (is_symbol(car(sc->code))) {    /* named let */
+               for (x = cadr(sc->code), sc->args = sc->NIL; x != sc->NIL; x = cdr(x)) {
+
+                    sc->args = cons(sc, caar(x), sc->args);
+               }
+               x = mk_closure(sc, cons(sc, reverse_in_place(sc, sc->NIL, sc->args), cddr(sc->code)), sc->envir); 
+               new_slot_in_env(sc, car(sc->code), x); 
+               sc->code = cddr(sc->code);
+               sc->args = sc->NIL;
+          } else {
+               sc->code = cdr(sc->code);
+               sc->args = sc->NIL;
+          }
+          s_goto(sc,OP_BEGIN);
+
+     case OP_LET0AST:    /* let* */
+          if (car(sc->code) == sc->NIL) {
+               new_frame_in_env(sc, sc->envir); 
+               sc->code = cdr(sc->code);
+               s_goto(sc,OP_BEGIN);
+          }
+          s_save(sc,OP_LET1AST, cdr(sc->code), car(sc->code));
+          sc->code = cadaar(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_LET1AST:    /* let* (make new frame) */
+          new_frame_in_env(sc, sc->envir); 
+          s_goto(sc,OP_LET2AST);
+
+     case OP_LET2AST:    /* let* (calculate parameters) */
+          new_slot_in_env(sc, caar(sc->code), sc->value); 
+          sc->code = cdr(sc->code);
+          if (is_pair(sc->code)) { /* continue */
+               s_save(sc,OP_LET2AST, sc->args, sc->code);
+               sc->code = cadar(sc->code);
+               sc->args = sc->NIL;
+               s_goto(sc,OP_EVAL);
+          } else {  /* end */
+               sc->code = sc->args;
+               sc->args = sc->NIL;
+               s_goto(sc,OP_BEGIN);
+          }
+     default:
+          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
+          Error_0(sc,sc->strbuff);
+     }
+     return sc->T;
+}
+
+static pointer opexe_1(scheme *sc, enum scheme_opcodes op) {
+     pointer x, y;
+
+     switch (op) {
+     case OP_LET0REC:    /* letrec */
+          new_frame_in_env(sc, sc->envir); 
+          sc->args = sc->NIL;
+          sc->value = sc->code;
+          sc->code = car(sc->code);
+          s_goto(sc,OP_LET1REC);
+
+     case OP_LET1REC:    /* letrec (calculate parameters) */
+          sc->args = cons(sc, sc->value, sc->args);
+          if (is_pair(sc->code)) { /* continue */
+               s_save(sc,OP_LET1REC, sc->args, cdr(sc->code));
+               sc->code = cadar(sc->code);
+               sc->args = sc->NIL;
+               s_goto(sc,OP_EVAL);
+          } else {  /* end */
+               sc->args = reverse_in_place(sc, sc->NIL, sc->args); 
+               sc->code = car(sc->args);
+               sc->args = cdr(sc->args);
+               s_goto(sc,OP_LET2REC);
+          }
+
+     case OP_LET2REC:    /* letrec */
+          for (x = car(sc->code), y = sc->args; y != sc->NIL; x = cdr(x), y = cdr(y)) {
+               new_slot_in_env(sc, caar(x), car(y)); 
+          }
+          sc->code = cdr(sc->code);
+          sc->args = sc->NIL;
+          s_goto(sc,OP_BEGIN);
+
+     case OP_COND0:      /* cond */
+          if (!is_pair(sc->code)) {
+               Error_0(sc,"syntax error in cond");
+          }
+          s_save(sc,OP_COND1, sc->NIL, sc->code);
+          sc->code = caar(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_COND1:      /* cond */
+          if (is_true(sc->value)) {
+               if ((sc->code = cdar(sc->code)) == sc->NIL) {
+                    s_return(sc,sc->value);
+               }
+               if(car(sc->code)==sc->FEED_TO) {
+                    if(!is_pair(cdr(sc->code))) {
+                         Error_0(sc,"syntax error in cond");
+                    }
+                    x=cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL));
+                    sc->code=cons(sc,cadr(sc->code),cons(sc,x,sc->NIL));
+                    s_goto(sc,OP_EVAL);
+               }
+               s_goto(sc,OP_BEGIN);
+          } else {
+               if ((sc->code = cdr(sc->code)) == sc->NIL) {
+                    s_return(sc,sc->NIL);
+               } else {
+                    s_save(sc,OP_COND1, sc->NIL, sc->code);
+                    sc->code = caar(sc->code);
+                    s_goto(sc,OP_EVAL);
+               }
+          }
+
+     case OP_DELAY:      /* delay */
+          x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
+          typeflag(x)=T_PROMISE;
+          s_return(sc,x);
+
+     case OP_AND0:       /* and */
+          if (sc->code == sc->NIL) {
+               s_return(sc,sc->T);
+          }
+          s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
+          sc->code = car(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_AND1:       /* and */
+          if (is_false(sc->value)) {
+               s_return(sc,sc->value);
+          } else if (sc->code == sc->NIL) {
+               s_return(sc,sc->value);
+          } else {
+               s_save(sc,OP_AND1, sc->NIL, cdr(sc->code));
+               sc->code = car(sc->code);
+               s_goto(sc,OP_EVAL);
+          }
+
+     case OP_OR0:        /* or */
+          if (sc->code == sc->NIL) {
+               s_return(sc,sc->F);
+          }
+          s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
+          sc->code = car(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_OR1:        /* or */
+          if (is_true(sc->value)) {
+               s_return(sc,sc->value);
+          } else if (sc->code == sc->NIL) {
+               s_return(sc,sc->value);
+          } else {
+               s_save(sc,OP_OR1, sc->NIL, cdr(sc->code));
+               sc->code = car(sc->code);
+               s_goto(sc,OP_EVAL);
+          }
+
+     case OP_C0STREAM:   /* cons-stream */
+          s_save(sc,OP_C1STREAM, sc->NIL, cdr(sc->code));
+          sc->code = car(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_C1STREAM:   /* cons-stream */
+          sc->args = sc->value;  /* save sc->value to register sc->args for gc */
+          x = mk_closure(sc, cons(sc, sc->NIL, sc->code), sc->envir);
+          typeflag(x)=T_PROMISE;
+          s_return(sc,cons(sc, sc->args, x));
+
+     case OP_MACRO0:     /* macro */
+          if (is_pair(car(sc->code))) {
+               x = caar(sc->code);
+               sc->code = cons(sc, sc->LAMBDA, cons(sc, cdar(sc->code), cdr(sc->code)));
+          } else {
+               x = car(sc->code);
+               sc->code = cadr(sc->code);
+          }
+          if (!is_symbol(x)) {
+               Error_0(sc,"variable is not a symbol");
+          }
+          s_save(sc,OP_MACRO1, sc->NIL, x);
+          s_goto(sc,OP_EVAL);
+
+     case OP_MACRO1:     /* macro */
+          typeflag(sc->value) = T_MACRO;
+          x = find_slot_in_env(sc, sc->envir, sc->code, 0); 
+          if (x != sc->NIL) {
+               set_slot_in_env(sc, x, sc->value); 
+          } else {
+               new_slot_in_env(sc, sc->code, sc->value); 
+          }
+          s_return(sc,sc->code);
+
+     case OP_CASE0:      /* case */
+          s_save(sc,OP_CASE1, sc->NIL, cdr(sc->code));
+          sc->code = car(sc->code);
+          s_goto(sc,OP_EVAL);
+
+     case OP_CASE1:      /* case */
+          for (x = sc->code; x != sc->NIL; x = cdr(x)) {
+               if (!is_pair(y = caar(x))) {
+                    break;
+               }
+               for ( ; y != sc->NIL; y = cdr(y)) {
+                    if (eqv(car(y), sc->value)) {
+                         break;
+                    }
+               }
+               if (y != sc->NIL) {
+                    break;
+               }
+          }
+          if (x != sc->NIL) {
+               if (is_pair(caar(x))) {
+                    sc->code = cdar(x);
+                    s_goto(sc,OP_BEGIN);
+               } else {/* else */
+                    s_save(sc,OP_CASE2, sc->NIL, cdar(x));
+                    sc->code = caar(x);
+                    s_goto(sc,OP_EVAL);
+               }
+          } else {
+               s_return(sc,sc->NIL);
+          }
+
+     case OP_CASE2:      /* case */
+          if (is_true(sc->value)) {
+               s_goto(sc,OP_BEGIN);
+          } else {
+               s_return(sc,sc->NIL);
+          }
+
+     case OP_PAPPLY:     /* apply */
+          sc->code = car(sc->args);
+         sc->args = list_star(sc,cdr(sc->args));
+          /*sc->args = cadr(sc->args);*/
+          s_goto(sc,OP_APPLY);
+
+     case OP_PEVAL: /* eval */
+          if(cdr(sc->args)!=sc->NIL) {
+               sc->envir=cadr(sc->args);
+          }
+          sc->code = car(sc->args);
+          s_goto(sc,OP_EVAL);
+
+     case OP_CONTINUATION:    /* call-with-current-continuation */
+          sc->code = car(sc->args);
+          sc->args = cons(sc, mk_continuation(sc, sc->dump), sc->NIL);
+          s_goto(sc,OP_APPLY);
+
+     default:
+          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
+          Error_0(sc,sc->strbuff);
+     }
+     return sc->T;
+}
+
+static pointer opexe_2(scheme *sc, enum scheme_opcodes op) {
+     pointer x;
+     num v;
+#if USE_MATH
+     double dd;
+#endif
+
+     switch (op) {
+#if USE_MATH
+     case OP_INEX2EX:    /* inexact->exact */
+          x=car(sc->args);
+          if(is_integer(x)) {
+               s_return(sc,x);
+          } else if(modf(rvalue_unchecked(x),&dd)==0.0) {
+               s_return(sc,mk_integer(sc,ivalue(x)));
+          } else {
+               Error_1(sc,"inexact->exact: not integral:",x);
+          }
+
+     case OP_EXP:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, exp(rvalue(x))));
+
+     case OP_LOG:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, log(rvalue(x))));
+
+     case OP_SIN:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, sin(rvalue(x))));
+
+     case OP_COS:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, cos(rvalue(x))));
+
+     case OP_TAN:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, tan(rvalue(x))));
+
+     case OP_ASIN:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, asin(rvalue(x))));
+
+     case OP_ACOS:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, acos(rvalue(x))));
+
+     case OP_ATAN:
+          x=car(sc->args);
+          if(cdr(sc->args)==sc->NIL) {
+               s_return(sc, mk_real(sc, atan(rvalue(x))));
+          } else {
+               pointer y=cadr(sc->args);
+               s_return(sc, mk_real(sc, atan2(rvalue(x),rvalue(y))));
+          }
+
+     case OP_SQRT:
+          x=car(sc->args);
+          s_return(sc, mk_real(sc, sqrt(rvalue(x))));
+
+     case OP_EXPT:
+          x=car(sc->args);
+          if(cdr(sc->args)==sc->NIL) {
+               Error_0(sc,"expt: needs two arguments");
+          } else {
+               pointer y=cadr(sc->args);
+               s_return(sc, mk_real(sc, pow(rvalue(x),
+                                            rvalue(y))));
+          }
+
+     case OP_FLOOR:
+          x=car(sc->args);
+         s_return(sc, mk_real(sc, floor(rvalue(x))));
+
+     case OP_CEILING:
+          x=car(sc->args);
+         s_return(sc, mk_real(sc, ceil(rvalue(x))));
+
+     case OP_TRUNCATE : {
+         double rvalue_of_x ;
+          x=car(sc->args);
+         rvalue_of_x = rvalue(x) ;
+         if (rvalue_of_x > 0) {
+           s_return(sc, mk_real(sc, floor(rvalue_of_x)));
+         } else {
+           s_return(sc, mk_real(sc, ceil(rvalue_of_x)));
+         }
+     }
+
+     case OP_ROUND:
+       x=car(sc->args);
+       s_return(sc, mk_real(sc, round_per_R5RS(rvalue(x))));
+#endif
+
+     case OP_ADD:        /* + */
+       v=num_zero;
+       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
+        v=num_add(v,nvalue(car(x)));
+       }
+       s_return(sc,mk_number(sc, v));
+
+     case OP_MUL:        /* * */
+       v=num_one;
+       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
+        v=num_mul(v,nvalue(car(x)));
+       }
+       s_return(sc,mk_number(sc, v));
+
+     case OP_SUB:        /* - */
+       if(cdr(sc->args)==sc->NIL) {
+        x=sc->args;
+        v=num_zero;
+       } else {
+        x = cdr(sc->args);
+        v = nvalue(car(sc->args));
+       }
+       for (; x != sc->NIL; x = cdr(x)) {
+        v=num_sub(v,nvalue(car(x)));
+       }
+       s_return(sc,mk_number(sc, v));
+
+     case OP_DIV:        /* / */
+       if(cdr(sc->args)==sc->NIL) {
+        x=sc->args;
+        v=num_one;
+       } else {
+        x = cdr(sc->args);
+        v = nvalue(car(sc->args));
+       }
+       for (; x != sc->NIL; x = cdr(x)) {
+        if (!is_zero_double(rvalue(car(x))))
+          v=num_div(v,nvalue(car(x)));
+        else {
+          Error_0(sc,"/: division by zero");
+        }
+       }
+       s_return(sc,mk_number(sc, v));
+
+     case OP_INTDIV:        /* quotient */
+          if(cdr(sc->args)==sc->NIL) {
+               x=sc->args;
+               v=num_one;
+          } else {
+               x = cdr(sc->args);
+               v = nvalue(car(sc->args));
+          }
+          for (; x != sc->NIL; x = cdr(x)) {
+               if (ivalue(car(x)) != 0)
+                    v=num_intdiv(v,nvalue(car(x)));
+               else {
+                    Error_0(sc,"quotient: division by zero");
+               }
+          }
+          s_return(sc,mk_number(sc, v));
+
+     case OP_REM:        /* remainder */
+          v = nvalue(car(sc->args));
+          if (ivalue(cadr(sc->args)) != 0)
+               v=num_rem(v,nvalue(cadr(sc->args)));
+          else {
+               Error_0(sc,"remainder: division by zero");
+          }
+          s_return(sc,mk_number(sc, v));
+
+     case OP_MOD:        /* modulo */
+          v = nvalue(car(sc->args));
+          if (ivalue(cadr(sc->args)) != 0)
+               v=num_mod(v,nvalue(cadr(sc->args)));
+          else {
+               Error_0(sc,"modulo: division by zero");
+          }
+          s_return(sc,mk_number(sc, v));
+
+     case OP_CAR:        /* car */
+       s_return(sc,caar(sc->args));
+
+     case OP_CDR:        /* cdr */
+       s_return(sc,cdar(sc->args));
+
+     case OP_CONS:       /* cons */
+          cdr(sc->args) = cadr(sc->args);
+          s_return(sc,sc->args);
+
+     case OP_SETCAR:     /* set-car! */
+       if(!is_immutable(car(sc->args))) {
+        caar(sc->args) = cadr(sc->args);
+        s_return(sc,car(sc->args));
+       } else {
+        Error_0(sc,"set-car!: unable to alter immutable pair");
+       }
+
+     case OP_SETCDR:     /* set-cdr! */
+       if(!is_immutable(car(sc->args))) {
+        cdar(sc->args) = cadr(sc->args);
+        s_return(sc,car(sc->args));
+       } else {
+        Error_0(sc,"set-cdr!: unable to alter immutable pair");
+       }
+
+     case OP_CHAR2INT: { /* char->integer */
+          char c;
+          c=(char)ivalue(car(sc->args));
+          s_return(sc,mk_integer(sc,(unsigned char)c));
+     }
+
+     case OP_INT2CHAR: { /* integer->char */
+          unsigned char c;
+          c=(unsigned char)ivalue(car(sc->args));
+          s_return(sc,mk_character(sc,(char)c));
+     }
+
+     case OP_CHARUPCASE: {
+          unsigned char c;
+          c=(unsigned char)ivalue(car(sc->args));
+          c=toupper(c);
+          s_return(sc,mk_character(sc,(char)c));
+     }
+
+     case OP_CHARDNCASE: {
+          unsigned char c;
+          c=(unsigned char)ivalue(car(sc->args));
+          c=tolower(c);
+          s_return(sc,mk_character(sc,(char)c));
+     }
+
+     case OP_STR2SYM:  /* string->symbol */
+          s_return(sc,mk_symbol(sc,strvalue(car(sc->args))));
+
+     case OP_STR2ATOM: /* string->atom */ {
+       char *s=strvalue(car(sc->args));
+       if(*s=='#') {
+        s_return(sc, mk_sharp_const(sc, s+1));
+       } else {
+        s_return(sc, mk_atom(sc, s));
+       }
+     }
+
+     case OP_SYM2STR: /* symbol->string */
+          x=mk_string(sc,symname(car(sc->args)));
+          setimmutable(x);
+          s_return(sc,x);
+     case OP_ATOM2STR: /* atom->string */
+       x=car(sc->args);
+       if(is_number(x) || is_character(x) || is_string(x) || is_symbol(x)) {
+        const char *p;
+        int len;
+        atom2str(sc,x,0,&p,&len);
+        s_return(sc,mk_counted_string(sc,p,len));
+       } else {
+        Error_1(sc, "atom->string: not an atom:", x);
+       }
+
+     case OP_MKSTRING: { /* make-string */
+          int fill=' ';
+          int len;
+
+          len=ivalue(car(sc->args));
+
+          if(cdr(sc->args)!=sc->NIL) {
+               fill=charvalue(cadr(sc->args));
+          }
+          s_return(sc,mk_empty_string(sc,len,(char)fill));
+     }
+
+     case OP_STRLEN:  /* string-length */
+          s_return(sc,mk_integer(sc,strlength(car(sc->args))));
+
+     case OP_STRREF: { /* string-ref */
+          char *str;
+          int index;
+
+          str=strvalue(car(sc->args));
+
+          index=ivalue(cadr(sc->args));
+
+          if(index>=strlength(car(sc->args))) {
+               Error_1(sc,"string-ref: out of bounds:",cadr(sc->args));
+          }
+
+          s_return(sc,mk_character(sc,((unsigned char*)str)[index]));
+     }
+
+     case OP_STRSET: { /* string-set! */
+          char *str;
+          int index;
+          int c;
+
+          if(is_immutable(car(sc->args))) {
+               Error_1(sc,"string-set!: unable to alter immutable string:",car(sc->args));
+          }
+          str=strvalue(car(sc->args));
+
+          index=ivalue(cadr(sc->args));
+          if(index>=strlength(car(sc->args))) {
+               Error_1(sc,"string-set!: out of bounds:",cadr(sc->args));
+          }
+
+          c=charvalue(caddr(sc->args));
+
+          str[index]=(char)c;
+          s_return(sc,car(sc->args));
+     }
+
+     case OP_STRAPPEND: { /* string-append */
+       /* in 1.29 string-append was in Scheme in init.scm but was too slow */
+       int len = 0;
+       pointer newstr;
+       char *pos;
+
+       /* compute needed length for new string */
+       for (x = sc->args; x != sc->NIL; x = cdr(x)) {
+          len += strlength(car(x));
+       }
+       newstr = mk_empty_string(sc, len, ' ');
+       /* store the contents of the argument strings into the new string */
+       for (pos = strvalue(newstr), x = sc->args; x != sc->NIL;
+           pos += strlength(car(x)), x = cdr(x)) {
+           memcpy(pos, strvalue(car(x)), strlength(car(x)));
+       }
+       s_return(sc, newstr);
+     }
+
+     case OP_SUBSTR: { /* substring */
+          char *str;
+          int index0;
+          int index1;
+          int len;
+
+          str=strvalue(car(sc->args));
+
+          index0=ivalue(cadr(sc->args));
+
+          if(index0>strlength(car(sc->args))) {
+               Error_1(sc,"substring: start out of bounds:",cadr(sc->args));
+          }
+
+          if(cddr(sc->args)!=sc->NIL) {
+               index1=ivalue(caddr(sc->args));
+               if(index1>strlength(car(sc->args)) || index1<index0) {
+                    Error_1(sc,"substring: end out of bounds:",caddr(sc->args));
+               }
+          } else {
+               index1=strlength(car(sc->args));
+          }
+
+          len=index1-index0;
+          x=mk_empty_string(sc,len,' ');
+          memcpy(strvalue(x),str+index0,len);
+          strvalue(x)[len]=0;
+
+          s_return(sc,x);
+     }
+
+     case OP_VECTOR: {   /* vector */
+          int i;
+          pointer vec;
+          int len=list_length(sc,sc->args);
+          if(len<0) {
+               Error_1(sc,"vector: not a proper list:",sc->args);
+          }
+          vec=mk_vector(sc,len);
+          for (x = sc->args, i = 0; is_pair(x); x = cdr(x), i++) {
+               set_vector_elem(vec,i,car(x));
+          }
+          s_return(sc,vec);
+     }
+
+     case OP_MKVECTOR: { /* make-vector */
+          pointer fill=sc->NIL;
+          int len;
+          pointer vec;
+
+          len=ivalue(car(sc->args));
+
+          if(cdr(sc->args)!=sc->NIL) {
+               fill=cadr(sc->args);
+          }
+          vec=mk_vector(sc,len);
+          if(fill!=sc->NIL) {
+               fill_vector(vec,fill);
+          }
+          s_return(sc,vec);
+     }
+
+     case OP_VECLEN:  /* vector-length */
+          s_return(sc,mk_integer(sc,ivalue(car(sc->args))));
+
+     case OP_VECREF: { /* vector-ref */
+          int index;
+
+          index=ivalue(cadr(sc->args));
+
+          if(index>=ivalue(car(sc->args))) {
+               Error_1(sc,"vector-ref: out of bounds:",cadr(sc->args));
+          }
+
+          s_return(sc,vector_elem(car(sc->args),index));
+     }
+
+     case OP_VECSET: {   /* vector-set! */
+          int index;
+
+          if(is_immutable(car(sc->args))) {
+               Error_1(sc,"vector-set!: unable to alter immutable vector:",car(sc->args));
+          }
+
+          index=ivalue(cadr(sc->args));
+          if(index>=ivalue(car(sc->args))) {
+               Error_1(sc,"vector-set!: out of bounds:",cadr(sc->args));
+          }
+
+          set_vector_elem(car(sc->args),index,caddr(sc->args));
+          s_return(sc,car(sc->args));
+     }
+
+     default:
+          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
+          Error_0(sc,sc->strbuff);
+     }
+     return sc->T;
+}
+
+static int list_length(scheme *sc, pointer a) {
+     int v=0;
+     pointer x;
+     for (x = a, v = 0; is_pair(x); x = cdr(x)) {
+          ++v;
+     }
+     if(x==sc->NIL) {
+          return v;
+     }
+     return -1;
+}
+
+static pointer opexe_3(scheme *sc, enum scheme_opcodes op) {
+     pointer x;
+     num v;
+     int (*comp_func)(num,num)=0;
+
+     switch (op) {
+     case OP_NOT:        /* not */
+          s_retbool(is_false(car(sc->args)));
+     case OP_BOOLP:       /* boolean? */
+          s_retbool(car(sc->args) == sc->F || car(sc->args) == sc->T);
+     case OP_EOFOBJP:       /* boolean? */
+          s_retbool(car(sc->args) == sc->EOF_OBJ);
+     case OP_NULLP:       /* null? */
+          s_retbool(car(sc->args) == sc->NIL);
+     case OP_NUMEQ:      /* = */
+     case OP_LESS:       /* < */
+     case OP_GRE:        /* > */
+     case OP_LEQ:        /* <= */
+     case OP_GEQ:        /* >= */
+          switch(op) {
+               case OP_NUMEQ: comp_func=num_eq; break;
+               case OP_LESS:  comp_func=num_lt; break;
+               case OP_GRE:   comp_func=num_gt; break;
+               case OP_LEQ:   comp_func=num_le; break;
+               case OP_GEQ:   comp_func=num_ge; break;
+          default: break;
+          }
+          x=sc->args;
+          v=nvalue(car(x));
+          x=cdr(x);
+
+          for (; x != sc->NIL; x = cdr(x)) {
+               if(!comp_func(v,nvalue(car(x)))) {
+                    s_retbool(0);
+               }
+              v=nvalue(car(x));
+          }
+          s_retbool(1);
+     case OP_SYMBOLP:     /* symbol? */
+          s_retbool(is_symbol(car(sc->args)));
+     case OP_NUMBERP:     /* number? */
+          s_retbool(is_number(car(sc->args)));
+     case OP_STRINGP:     /* string? */
+          s_retbool(is_string(car(sc->args)));
+     case OP_INTEGERP:     /* integer? */
+          s_retbool(is_integer(car(sc->args)));
+     case OP_REALP:     /* real? */
+          s_retbool(is_number(car(sc->args))); /* All numbers are real */
+     case OP_CHARP:     /* char? */
+          s_retbool(is_character(car(sc->args)));
+#if USE_CHAR_CLASSIFIERS
+     case OP_CHARAP:     /* char-alphabetic? */
+          s_retbool(Cisalpha(ivalue(car(sc->args))));
+     case OP_CHARNP:     /* char-numeric? */
+          s_retbool(Cisdigit(ivalue(car(sc->args))));
+     case OP_CHARWP:     /* char-whitespace? */
+          s_retbool(Cisspace(ivalue(car(sc->args))));
+     case OP_CHARUP:     /* char-upper-case? */
+          s_retbool(Cisupper(ivalue(car(sc->args))));
+     case OP_CHARLP:     /* char-lower-case? */
+          s_retbool(Cislower(ivalue(car(sc->args))));
+#endif
+     case OP_PORTP:     /* port? */
+          s_retbool(is_port(car(sc->args)));
+     case OP_INPORTP:     /* input-port? */
+          s_retbool(is_inport(car(sc->args)));
+     case OP_OUTPORTP:     /* output-port? */
+          s_retbool(is_outport(car(sc->args)));
+     case OP_PROCP:       /* procedure? */
+          /*--
+              * continuation should be procedure by the example
+              * (call-with-current-continuation procedure?) ==> #t
+                 * in R^3 report sec. 6.9
+              */
+          s_retbool(is_proc(car(sc->args)) || is_closure(car(sc->args))
+                 || is_continuation(car(sc->args)) || is_foreign(car(sc->args)));
+     case OP_PAIRP:       /* pair? */
+          s_retbool(is_pair(car(sc->args)));
+     case OP_LISTP: {     /* list? */
+          pointer slow, fast;
+          slow = fast = car(sc->args);
+          while (1) {
+             if (!is_pair(fast)) s_retbool(fast == sc->NIL);
+             fast = cdr(fast);
+             if (!is_pair(fast)) s_retbool(fast == sc->NIL);
+             fast = cdr(fast);
+             slow = cdr(slow);
+             if (fast == slow) {
+                  /* the fast pointer has looped back around and caught up
+                     with the slow pointer, hence the structure is circular,
+                     not of finite length, and therefore not a list */
+                  s_retbool(0);
+             }
+          }
+     }
+     case OP_ENVP:        /* environment? */
+          s_retbool(is_environment(car(sc->args)));
+     case OP_VECTORP:     /* vector? */
+          s_retbool(is_vector(car(sc->args)));
+     case OP_EQ:         /* eq? */
+          s_retbool(car(sc->args) == cadr(sc->args));
+     case OP_EQV:        /* eqv? */
+          s_retbool(eqv(car(sc->args), cadr(sc->args)));
+     default:
+          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
+          Error_0(sc,sc->strbuff);
+     }
+     return sc->T;
+}
+
+static pointer opexe_4(scheme *sc, enum scheme_opcodes op) {
+     pointer x, y;
+
+     switch (op) {
+     case OP_FORCE:      /* force */
+          sc->code = car(sc->args);
+          if (is_promise(sc->code)) {
+               /* Should change type to closure here */
+               s_save(sc, OP_SAVE_FORCED, sc->NIL, sc->code);
+               sc->args = sc->NIL;
+               s_goto(sc,OP_APPLY);
+          } else {
+               s_return(sc,sc->code);
+          }
+
+     case OP_SAVE_FORCED:     /* Save forced value replacing promise */
+          memcpy(sc->code,sc->value,sizeof(struct cell));
+          s_return(sc,sc->value);
+
+     case OP_WRITE:      /* write */
+     case OP_DISPLAY:    /* display */
+     case OP_WRITE_CHAR: /* write-char */
+          if(is_pair(cdr(sc->args))) {
+               if(cadr(sc->args)!=sc->outport) {
+                    x=cons(sc,sc->outport,sc->NIL);
+                    s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
+                    sc->outport=cadr(sc->args);
+               }
+          }
+          sc->args = car(sc->args);
+          if(op==OP_WRITE) {
+               sc->print_flag = 1;
+          } else {
+               sc->print_flag = 0;
+          }
+          s_goto(sc,OP_P0LIST);
+
+     case OP_NEWLINE:    /* newline */
+          if(is_pair(sc->args)) {
+               if(car(sc->args)!=sc->outport) {
+                    x=cons(sc,sc->outport,sc->NIL);
+                    s_save(sc,OP_SET_OUTPORT, x, sc->NIL);
+                    sc->outport=car(sc->args);
+               }
+          }
+          putstr(sc, "\n");
+          s_return(sc,sc->T);
+
+     case OP_ERR0:  /* error */
+          sc->retcode=-1;
+          if (!is_string(car(sc->args))) {
+               sc->args=cons(sc,mk_string(sc," -- "),sc->args);
+               setimmutable(car(sc->args));
+          }
+          putstr(sc, "Error: ");
+#if USE_FILE_AND_LINE
+          {
+                  port *pt;
+                  pt=sc->inport->_object._port;
+                  if(pt->kind&port_file &&
+                     pt->rep.stdio.name) {
+                          char linestr[16];
+                          putstr(sc, pt->rep.stdio.name);
+                          putstr(sc, " line ");
+                          snprintf(linestr, sizeof(linestr), "%d", pt->rep.stdio.line);
+                          putstr(sc, linestr);
+                          putstr(sc, ": ");
+                  }
+          }
+#endif
+          putstr(sc, strvalue(car(sc->args)));
+          sc->args = cdr(sc->args);
+          s_goto(sc,OP_ERR1);
+
+     case OP_ERR1:  /* error */
+          putstr(sc, " ");
+          if (sc->args != sc->NIL) {
+               s_save(sc,OP_ERR1, cdr(sc->args), sc->NIL);
+               sc->args = car(sc->args);
+               sc->print_flag = 1;
+               s_goto(sc,OP_P0LIST);
+          } else {
+               putstr(sc, "\n");
+               if(sc->interactive_repl) {
+                    s_goto(sc,OP_T0LVL);
+               } else {
+                    return sc->NIL;
+               }
+          }
+
+     case OP_REVERSE:    /* reverse */
+          s_return(sc,reverse(sc, car(sc->args)));
+
+     case OP_LIST_STAR: /* list* */
+       s_return(sc,list_star(sc,sc->args));
+
+     case OP_APPEND:     /* append */
+          if(sc->args==sc->NIL) {
+               s_return(sc,sc->NIL);
+          }
+          x=car(sc->args);
+          if(cdr(sc->args)==sc->NIL) {
+           s_return(sc,sc->args);
+         }
+          for (y = cdr(sc->args); y != sc->NIL; y = cdr(y)) {
+               x=append(sc,x,car(y));
+          }
+          s_return(sc,x);
+
+#if USE_PLIST
+     case OP_PUT:        /* put */
+          if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
+               Error_0(sc,"illegal use of put");
+          }
+          for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
+               if (caar(x) == y) {
+                    break;
+               }
+          }
+          if (x != sc->NIL)
+               cdar(x) = caddr(sc->args);
+          else
+               symprop(car(sc->args)) = cons(sc, cons(sc, y, caddr(sc->args)),
+                                symprop(car(sc->args)));
+          s_return(sc,sc->T);
+
+     case OP_GET:        /* get */
+          if (!hasprop(car(sc->args)) || !hasprop(cadr(sc->args))) {
+               Error_0(sc,"illegal use of get");
+          }
+          for (x = symprop(car(sc->args)), y = cadr(sc->args); x != sc->NIL; x = cdr(x)) {
+               if (caar(x) == y) {
+                    break;
+               }
+          }
+          if (x != sc->NIL) {
+               s_return(sc,cdar(x));
+          } else {
+               s_return(sc,sc->NIL);
+          }
+#endif /* USE_PLIST */
+     case OP_QUIT:       /* quit */
+          if(is_pair(sc->args)) {
+               sc->retcode=ivalue(car(sc->args));
+          }
+          return (sc->NIL);
+
+     case OP_GC:         /* gc */
+          gc(sc, sc->NIL, sc->NIL);
+          s_return(sc,sc->T);
+
+     case OP_GCVERB:          /* gc-verbose */
+     {    int  was = sc->gc_verbose;
+          
+          sc->gc_verbose = (car(sc->args) != sc->F);
+          s_retbool(was);
+     }
+
+     case OP_NEWSEGMENT: /* new-segment */
+          if (!is_pair(sc->args) || !is_number(car(sc->args))) {
+               Error_0(sc,"new-segment: argument must be a number");
+          }
+          alloc_cellseg(sc, (int) ivalue(car(sc->args)));
+          s_return(sc,sc->T);
+
+     case OP_OBLIST: /* oblist */
+          s_return(sc, oblist_all_symbols(sc)); 
+
+     case OP_CURR_INPORT: /* current-input-port */
+          s_return(sc,sc->inport);
+
+     case OP_CURR_OUTPORT: /* current-output-port */
+          s_return(sc,sc->outport);
+
+     case OP_OPEN_INFILE: /* open-input-file */
+     case OP_OPEN_OUTFILE: /* open-output-file */
+     case OP_OPEN_INOUTFILE: /* open-input-output-file */ {
+          int prop=0;
+          pointer p;
+          switch(op) {
+               case OP_OPEN_INFILE:     prop=port_input; break;
+               case OP_OPEN_OUTFILE:    prop=port_output; break;
+               case OP_OPEN_INOUTFILE: prop=port_input|port_output; break;
+          default: break;
+          }
+          p=port_from_filename(sc,strvalue(car(sc->args)),prop);
+          if(p==sc->NIL) {
+               s_return(sc,sc->F);
+          }
+          s_return(sc,p);
+     }
+     
+#if USE_STRING_PORTS
+     case OP_OPEN_INSTRING: /* open-input-string */
+     case OP_OPEN_OUTSTRING: /* open-output-string */
+     case OP_OPEN_INOUTSTRING: /* open-input-output-string */ {
+          int prop=0;
+          pointer p;
+          switch(op) {
+               case OP_OPEN_INSTRING:     prop=port_input; break;
+               case OP_OPEN_OUTSTRING:    prop=port_output; break;
+               case OP_OPEN_INOUTSTRING:  prop=port_input|port_output; break;
+          default: break;
+          }
+          p=port_from_string(sc, strvalue(car(sc->args)),
+                    strvalue(car(sc->args))+strlength(car(sc->args)), prop);
+          if(p==sc->NIL) {
+               s_return(sc,sc->F);
+          }
+          s_return(sc,p);
+     }
+#endif
+
+     case OP_CLOSE_INPORT: /* close-input-port */
+          port_close(sc,car(sc->args),port_input);
+          s_return(sc,sc->T);
+
+     case OP_CLOSE_OUTPORT: /* close-output-port */
+          port_close(sc,car(sc->args),port_output);
+          s_return(sc,sc->T);
+
+     case OP_INT_ENV: /* interaction-environment */
+          s_return(sc,sc->global_env);
+
+     case OP_CURR_ENV: /* current-environment */
+          s_return(sc,sc->envir);
+     default: break;
+
+     }
+     return sc->T;
+}
+
+static pointer opexe_5(scheme *sc, enum scheme_opcodes op) {
+     pointer x;
+
+     if(sc->nesting!=0) {
+          int n=sc->nesting;
+          sc->nesting=0;
+          sc->retcode=-1;
+          Error_1(sc,"unmatched parentheses:",mk_integer(sc,n));
+     }
+
+     switch (op) {
+     /* ========== reading part ========== */
+     case OP_READ:
+          if(!is_pair(sc->args)) {
+               s_goto(sc,OP_READ_INTERNAL);
+          }
+          if(!is_inport(car(sc->args))) {
+               Error_1(sc,"read: not an input port:",car(sc->args));
+          }
+          if(car(sc->args)==sc->inport) {
+               s_goto(sc,OP_READ_INTERNAL);
+          }
+          x=sc->inport;
+          sc->inport=car(sc->args);
+          x=cons(sc,x,sc->NIL);
+          s_save(sc,OP_SET_INPORT, x, sc->NIL);
+          s_goto(sc,OP_READ_INTERNAL);
+
+     case OP_READ_CHAR: /* read-char */
+     case OP_PEEK_CHAR: /* peek-char */ {
+          int c;
+          if(is_pair(sc->args)) {
+               if(car(sc->args)!=sc->inport) {
+                    x=sc->inport;
+                    x=cons(sc,x,sc->NIL);
+                    s_save(sc,OP_SET_INPORT, x, sc->NIL);
+                    sc->inport=car(sc->args);
+               }
+          }
+          c=inchar(sc);
+          if(c==EOF) {
+               s_return(sc,sc->EOF_OBJ);
+          }
+          if(sc->op==OP_PEEK_CHAR) {
+               backchar(sc,c);
+          }
+          s_return(sc,mk_character(sc,c));
+     }
+
+     case OP_CHAR_READY: /* char-ready? */ {
+          pointer p=sc->inport;
+          int res;
+          if(is_pair(sc->args)) {
+               p=car(sc->args);
+          }
+          res=p->_object._port->kind&port_string;
+          s_retbool(res);
+     }
+
+     case OP_SET_INPORT: /* set-input-port */
+          sc->inport=car(sc->args);
+          s_return(sc,sc->value);
+
+     case OP_SET_OUTPORT: /* set-output-port */
+          sc->outport=car(sc->args);
+          s_return(sc,sc->value);
+
+     case OP_RDSEXPR:
+          switch (sc->tok) {
+          case TOK_EOF:
+               if(sc->inport==sc->loadport) {
+                    sc->args=sc->NIL;
+                    s_goto(sc,OP_QUIT);
+               } else {
+                    s_return(sc,sc->EOF_OBJ);
+               }
+/*
+ * Commented out because we now skip comments in the scanner
+ * 
+          case TOK_COMMENT: {
+               int c;
+               while ((c=inchar(sc)) != '\n' && c!=EOF)
+                    ;
+               if (c!= EOF) {
+                       sc->tok = token(sc);
+               }
+               s_goto(sc,OP_RDSEXPR);
+          }
+*/
+          case TOK_VEC:
+               s_save(sc,OP_RDVEC,sc->NIL,sc->NIL);
+               /* fall through */
+          case TOK_LPAREN:
+               sc->tok = token(sc);
+               if (sc->tok == TOK_RPAREN) {
+                    s_return(sc,sc->NIL);
+               } else if (sc->tok == TOK_DOT) {
+                    Error_0(sc,"syntax error: illegal dot expression");
+               } else {
+                    sc->nesting_stack[sc->file_i]++;
+                    s_save(sc,OP_RDLIST, sc->NIL, sc->NIL);
+                    s_goto(sc,OP_RDSEXPR);
+               }
+          case TOK_QUOTE:
+               s_save(sc,OP_RDQUOTE, sc->NIL, sc->NIL);
+               sc->tok = token(sc);
+               s_goto(sc,OP_RDSEXPR);
+          case TOK_BQUOTE:
+               sc->tok = token(sc);
+              if(sc->tok==TOK_VEC) {
+                s_save(sc,OP_RDQQUOTEVEC, sc->NIL, sc->NIL);
+                sc->tok=TOK_LPAREN;
+                s_goto(sc,OP_RDSEXPR);
+              } else {
+                s_save(sc,OP_RDQQUOTE, sc->NIL, sc->NIL);
+              }
+               s_goto(sc,OP_RDSEXPR);
+          case TOK_COMMA:
+               s_save(sc,OP_RDUNQUOTE, sc->NIL, sc->NIL);
+               sc->tok = token(sc);
+               s_goto(sc,OP_RDSEXPR);
+          case TOK_ATMARK:
+               s_save(sc,OP_RDUQTSP, sc->NIL, sc->NIL);
+               sc->tok = token(sc);
+               s_goto(sc,OP_RDSEXPR);
+          case TOK_ATOM:
+               s_return(sc,mk_atom(sc, readstr_upto(sc, "();\t\n\r ")));
+          case TOK_DQUOTE:
+               x=readstrexp(sc);
+              if(x==sc->F) {
+                Error_0(sc,"Error reading string");
+              }
+               setimmutable(x);
+               s_return(sc,x);
+          case TOK_SHARP: {
+               pointer f=find_slot_in_env(sc,sc->envir,sc->SHARP_HOOK,1);
+               if(f==sc->NIL) {
+                    Error_0(sc,"undefined sharp expression");
+               } else {
+                    sc->code=cons(sc,slot_value_in_env(f),sc->NIL); 
+                    s_goto(sc,OP_EVAL);
+               }
+          }
+          case TOK_SHARP_CONST:
+               if ((x = mk_sharp_const(sc, readstr_upto(sc, "();\t\n\r "))) == sc->NIL) {
+                    Error_0(sc,"undefined sharp expression");
+               } else {
+                    s_return(sc,x);
+               }
+          default:
+               Error_0(sc,"syntax error: illegal token");
+          }
+          break;
+
+     case OP_RDLIST: {
+          sc->args = cons(sc, sc->value, sc->args);
+          sc->tok = token(sc);
+          if (sc->tok == TOK_COMMENT) {
+               int c;
+               while ((c=inchar(sc)) != '\n' && c!=EOF)
+                    ;
+               sc->tok = token(sc);
+          }
+          if (sc->tok == TOK_RPAREN) {
+               int c;
+               /* inchar() may pop the file, so decrement the nesting stack
+                * now. Otherwise if files end in RPAREN you'll get a mysterious
+                * "mismatched parentheseis: -1" error. */
+               sc->nesting_stack[sc->file_i]--;
+               c = inchar(sc);
+               if (c != '\n' && c != EOF) backchar(sc,c);
+               s_return(sc,reverse_in_place(sc, sc->NIL, sc->args));
+          } else if (sc->tok == TOK_DOT) {
+               s_save(sc,OP_RDDOT, sc->args, sc->NIL);
+               sc->tok = token(sc);
+               s_goto(sc,OP_RDSEXPR);
+          } else {
+               s_save(sc,OP_RDLIST, sc->args, sc->NIL);;
+               s_goto(sc,OP_RDSEXPR);
+          }
+     }
+
+     case OP_RDDOT:
+          if (token(sc) != TOK_RPAREN) {
+               Error_0(sc,"syntax error: illegal dot expression");
+          } else {
+               sc->nesting_stack[sc->file_i]--;
+               s_return(sc,reverse_in_place(sc, sc->value, sc->args));
+          }
+
+     case OP_RDQUOTE:
+          s_return(sc,cons(sc, sc->QUOTE, cons(sc, sc->value, sc->NIL)));
+
+     case OP_RDQQUOTE:
+          s_return(sc,cons(sc, sc->QQUOTE, cons(sc, sc->value, sc->NIL)));
+
+     case OP_RDQQUOTEVEC:
+       s_return(sc,cons(sc, mk_symbol(sc,"apply"),
+                       cons(sc, mk_symbol(sc,"vector"), 
+                            cons(sc,cons(sc, sc->QQUOTE, 
+                                 cons(sc,sc->value,sc->NIL)),
+                                 sc->NIL))));
+
+     case OP_RDUNQUOTE:
+          s_return(sc,cons(sc, sc->UNQUOTE, cons(sc, sc->value, sc->NIL)));
+
+     case OP_RDUQTSP:
+          s_return(sc,cons(sc, sc->UNQUOTESP, cons(sc, sc->value, sc->NIL)));
+
+     case OP_RDVEC:
+          /*sc->code=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
+          s_goto(sc,OP_EVAL); Cannot be quoted*/
+       /*x=cons(sc,mk_proc(sc,OP_VECTOR),sc->value);
+        s_return(sc,x); Cannot be part of pairs*/
+       /*sc->code=mk_proc(sc,OP_VECTOR);
+       sc->args=sc->value;
+       s_goto(sc,OP_APPLY);*/
+       sc->args=sc->value;
+       s_goto(sc,OP_VECTOR);
+
+     /* ========== printing part ========== */
+     case OP_P0LIST:
+          if(is_vector(sc->args)) {
+               putstr(sc,"#(");
+               sc->args=cons(sc,sc->args,mk_integer(sc,0));
+               s_goto(sc,OP_PVECFROM);
+          } else if(is_environment(sc->args)) {
+               putstr(sc,"#<ENVIRONMENT>");
+               s_return(sc,sc->T);
+          } else if (!is_pair(sc->args)) {
+               printatom(sc, sc->args, sc->print_flag);
+               s_return(sc,sc->T);
+          } else if (car(sc->args) == sc->QUOTE && ok_abbrev(cdr(sc->args))) {
+               putstr(sc, "'");
+               sc->args = cadr(sc->args);
+               s_goto(sc,OP_P0LIST);
+          } else if (car(sc->args) == sc->QQUOTE && ok_abbrev(cdr(sc->args))) {
+               putstr(sc, "`");
+               sc->args = cadr(sc->args);
+               s_goto(sc,OP_P0LIST);
+          } else if (car(sc->args) == sc->UNQUOTE && ok_abbrev(cdr(sc->args))) {
+               putstr(sc, ",");
+               sc->args = cadr(sc->args);
+               s_goto(sc,OP_P0LIST);
+          } else if (car(sc->args) == sc->UNQUOTESP && ok_abbrev(cdr(sc->args))) {
+               putstr(sc, ",@");
+               sc->args = cadr(sc->args);
+               s_goto(sc,OP_P0LIST);
+          } else {
+               putstr(sc, "(");
+               s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
+               sc->args = car(sc->args);
+               s_goto(sc,OP_P0LIST);
+          }
+
+     case OP_P1LIST:
+          if (is_pair(sc->args)) {
+           s_save(sc,OP_P1LIST, cdr(sc->args), sc->NIL);
+           putstr(sc, " ");
+           sc->args = car(sc->args);
+           s_goto(sc,OP_P0LIST);
+         } else if(is_vector(sc->args)) {
+           s_save(sc,OP_P1LIST,sc->NIL,sc->NIL);
+           putstr(sc, " . ");
+           s_goto(sc,OP_P0LIST);
+          } else {
+           if (sc->args != sc->NIL) {
+             putstr(sc, " . ");
+             printatom(sc, sc->args, sc->print_flag);
+           }
+           putstr(sc, ")");
+           s_return(sc,sc->T);
+          }
+     case OP_PVECFROM: {
+          int i=ivalue_unchecked(cdr(sc->args));
+          pointer vec=car(sc->args);
+          int len=ivalue_unchecked(vec);
+          if(i==len) {
+               putstr(sc,")");
+               s_return(sc,sc->T);
+          } else {
+               pointer elem=vector_elem(vec,i);
+               ivalue_unchecked(cdr(sc->args))=i+1;
+               s_save(sc,OP_PVECFROM, sc->args, sc->NIL);
+               sc->args=elem;
+               putstr(sc," ");
+               s_goto(sc,OP_P0LIST);
+          }
+     }
+
+     default:
+          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
+          Error_0(sc,sc->strbuff);
+
+     }
+     return sc->T;
+}
+
+static pointer opexe_6(scheme *sc, enum scheme_opcodes op) {
+     pointer x, y;
+     long v;
+
+     switch (op) {
+     case OP_LIST_LENGTH:     /* length */   /* a.k */
+          v=list_length(sc,car(sc->args));
+          if(v<0) {
+               Error_1(sc,"length: not a list:",car(sc->args));
+          }
+          s_return(sc,mk_integer(sc, v));
+
+     case OP_ASSQ:       /* assq */     /* a.k */
+          x = car(sc->args);
+          for (y = cadr(sc->args); is_pair(y); y = cdr(y)) {
+               if (!is_pair(car(y))) {
+                    Error_0(sc,"unable to handle non pair element");
+               }
+               if (x == caar(y))
+                    break;
+          }
+          if (is_pair(y)) {
+               s_return(sc,car(y));
+          } else {
+               s_return(sc,sc->F);
+          }
+          
+          
+     case OP_GET_CLOSURE:     /* get-closure-code */   /* a.k */
+          sc->args = car(sc->args);
+          if (sc->args == sc->NIL) {
+               s_return(sc,sc->F);
+          } else if (is_closure(sc->args)) {
+               s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
+          } else if (is_macro(sc->args)) {
+               s_return(sc,cons(sc, sc->LAMBDA, closure_code(sc->value)));
+          } else {
+               s_return(sc,sc->F);
+          }
+     case OP_CLOSUREP:        /* closure? */
+          /*
+           * Note, macro object is also a closure.
+           * Therefore, (closure? <#MACRO>) ==> #t
+           */
+          s_retbool(is_closure(car(sc->args)));
+     case OP_MACROP:          /* macro? */
+          s_retbool(is_macro(car(sc->args)));
+     default:
+          sprintf(sc->strbuff, "%d: illegal operator", sc->op);
+          Error_0(sc,sc->strbuff);
+     }
+     return sc->T; /* NOTREACHED */
+}
+
+#if USE_REENTER
+/* gmcnutt: added to fix the script->C->script recursion problem */
+static pointer opexe_ghul(scheme *sc, enum scheme_opcodes op) {
+        switch (op) {
+        case OP_EXIT_REENTER:
+                /* Returning sc->NIL will force Eval_Cycle to return without
+                 * consuming any more stack frames. We need to leave the stack
+                 * frames below this operation intact so that when C returns to
+                 * the script the script can continue processing. */
+                return sc->NIL;
+                break;
+        default: break;
+        }
+        return sc->T; /* NOTREACHED */
+}
+#endif
+
+typedef pointer (*dispatch_func)(scheme *, enum scheme_opcodes);
+
+typedef int (*test_predicate)(pointer);
+static int is_any(pointer p) { return 1;}
+static int is_num_integer(pointer p) { 
+  return is_number(p) && ((p)->_object._number.is_fixnum); 
+}
+static int is_nonneg(pointer p) {
+  return is_num_integer(p) && ivalue(p)>=0;
+}
+
+/* Correspond carefully with following defines! */
+static struct {
+  test_predicate fct;
+  const char *kind;
+} tests[]={
+  {0,0}, /* unused */
+  {is_any, 0},
+  {is_string, "string"},
+  {is_symbol, "symbol"},
+  {is_port, "port"},
+  {0,"input port"},
+  {0,"output_port"},
+  {is_environment, "environment"},
+  {is_pair, "pair"},
+  {0, "pair or '()"},
+  {is_character, "character"},
+  {is_vector, "vector"},
+  {is_number, "number"},
+  {is_num_integer, "integer"},
+  {is_nonneg, "non-negative integer"}
+};
+
+#define TST_NONE 0
+#define TST_ANY "\001"
+#define TST_STRING "\002"
+#define TST_SYMBOL "\003"
+#define TST_PORT "\004"
+#define TST_INPORT "\005"
+#define TST_OUTPORT "\006"
+#define TST_ENVIRONMENT "\007"
+#define TST_PAIR "\010"
+#define TST_LIST "\011"
+#define TST_CHAR "\012"
+#define TST_VECTOR "\013"
+#define TST_NUMBER "\014"
+#define TST_INTEGER "\015"
+#define TST_NATURAL "\016"
+
+typedef struct {
+  dispatch_func func;
+  const char *name;
+  int min_arity;
+  int max_arity;
+  const char *arg_tests_encoding;
+} op_code_info;
+
+#define INF_ARG 0xffff
+
+static op_code_info dispatch_table[]= { 
+#define _OP_DEF(A,B,C,D,E,OP) {A,B,C,D,E}, 
+#include "opdefines.h" 
+  { 0 } 
+}; 
+
+static const char *procname(pointer x) {
+ int n=procnum(x);
+ const char *name=dispatch_table[n].name;
+ if(name==0) {
+     name="ILLEGAL!";
+ }
+ return name;
+}
+
+/* kernel of this interpreter */
+static void Eval_Cycle(scheme *sc, enum scheme_opcodes op) {
+  int count=0;
+  int old_op;
+  
+  sc->inside++;
+
+  sc->op = op;
+  for (;;) {
+
+    /* special debug hack */
+    //assert((sc->oblist+1+(356/2))->_object._cons._cdr->_flag & T_IMMUTABLE);
+
+    op_code_info *pcd=dispatch_table+sc->op;
+    if (pcd->name!=0) { /* if built-in function, check arguments */
+      char msg[512];
+      int ok=1;
+      int n=list_length(sc,sc->args);
+      
+      /* Check number of arguments */
+      if(n<pcd->min_arity) {
+       ok=0;
+       sprintf(msg,"%s: needs%s %d argument(s)",
+               pcd->name,
+               pcd->min_arity==pcd->max_arity?"":" at least",
+               pcd->min_arity);
+      }
+      if(ok && n>pcd->max_arity) {
+       ok=0;
+       sprintf(msg,"%s: needs%s %d argument(s)",
+               pcd->name,
+               pcd->min_arity==pcd->max_arity?"":" at most",
+               pcd->max_arity);
+      }
+      if(ok) {
+       if(pcd->arg_tests_encoding!=0) {
+         int i=0;
+         int j;
+         const char *t=pcd->arg_tests_encoding;
+         pointer arglist=sc->args;
+         do {
+           pointer arg=car(arglist);
+           j=(int)t[0];
+           if(j==TST_INPORT[0]) {
+             if(!is_inport(arg)) break;
+           } else if(j==TST_OUTPORT[0]) {
+             if(!is_outport(arg)) break;
+            } else if(j==TST_LIST[0]) {
+              if(arg!=sc->NIL && !is_pair(arg)) break;               
+           } else {
+             if(!tests[j].fct(arg)) break;
+           }
+
+           if(t[1]!=0) {/* last test is replicated as necessary */
+             t++;
+           }
+           arglist=cdr(arglist);
+           i++;
+         } while(i<n);
+         if(i<n) {
+           ok=0;
+           sprintf(msg,"%s: argument %d must be: %s",
+                   pcd->name,
+                   i+1,
+                   tests[j].kind);
+         }
+       }
+      }
+      if(!ok) {
+       if(_Error_1(sc,msg,0)==sc->NIL) {
+                sc->inside--;
+         return;
+       }
+       pcd=dispatch_table+sc->op;
+      }
+    }
+    old_op=sc->op;
+    if (pcd->func(sc, (scheme_opcodes)sc->op) == sc->NIL) {
+            sc->inside--;
+      return;
+    }
+    if(sc->no_memory) {
+      fprintf(stderr,"No memory!\n");
+      sc->inside--;
+      return;
+    }
+    count++;
+  }
+  sc->inside--;
+}
+
+/* ========== Initialization of internal keywords ========== */
+
+static void assign_syntax(scheme *sc, const char *name) {
+     pointer x;
+
+     x = oblist_add_by_name(sc, name); 
+     typeflag(x) |= T_SYNTAX; 
+}
+
+static void assign_proc(scheme *sc, enum scheme_opcodes op, const char *name) {
+     pointer x, y;
+
+     x = mk_symbol(sc, name);
+     y = mk_proc(sc,op);
+     new_slot_in_env(sc, x, y); 
+}
+
+static pointer mk_proc(scheme *sc, enum scheme_opcodes op) {
+     pointer y;
+
+     y = get_cell(sc, sc->NIL, sc->NIL);
+     typeflag(y) = (T_PROC | T_ATOM);
+     ivalue_unchecked(y) = (long) op;
+     set_integer(y);
+     return y;
+}
+
+/* Hard-coded for the given keywords. Remember to rewrite if more are added! */
+static int syntaxnum(pointer p) {
+     const char *s=strvalue(car(p));
+     switch(strlength(car(p))) {
+     case 2:
+          if(s[0]=='i') return OP_IF0;        /* if */
+          else return OP_OR0;                 /* or */ 
+     case 3:
+          if(s[0]=='a') return OP_AND0;      /* and */
+          else return OP_LET0;               /* let */
+     case 4:
+          switch(s[3]) {
+          case 'e': return OP_CASE0;         /* case */
+          case 'd': return OP_COND0;         /* cond */
+          case '*': return OP_LET0AST;       /* let* */
+          default: return OP_SET0;           /* set! */          
+          }
+     case 5:
+          switch(s[2]) {
+          case 'g': return OP_BEGIN;         /* begin */
+          case 'l': return OP_DELAY;         /* delay */
+          case 'c': return OP_MACRO0;        /* macro */
+          default: return OP_QUOTE;          /* quote */
+          }
+     case 6:
+          switch(s[2]) {
+          case 'm': return OP_LAMBDA;        /* lambda */
+          case 'f': return OP_DEF0;          /* define */
+          default: return OP_LET0REC;        /* letrec */
+          }
+     default:
+          return OP_C0STREAM;                /* cons-stream */
+     }
+}
+
+/* initialization of TinyScheme */
+#if USE_INTERFACE
+INTERFACE static pointer s_cons(scheme *sc, pointer a, pointer b) {
+ return cons(sc,a,b);
+}
+INTERFACE static pointer s_immutable_cons(scheme *sc, pointer a, pointer b) {
+ return immutable_cons(sc,a,b);
+}
+
+static struct scheme_interface vtbl ={
+  scheme_define,
+  s_cons,
+  s_immutable_cons,
+  mk_integer,
+  mk_real,
+  mk_symbol,
+  gensym,
+  mk_string,
+  mk_counted_string,
+  mk_character,
+  mk_vector,
+  mk_foreign_func,
+  find_slot_in_env,
+  putstr,
+  putcharacter,
+
+  is_string,
+  string_value,
+  is_number,
+  nvalue,
+  ivalue,
+  rvalue,
+  is_integer,
+  is_real,
+  is_character,
+  charvalue,
+  is_vector,
+  ivalue,
+  fill_vector,
+  vector_elem,
+  set_vector_elem,
+  is_port,
+  is_pair,
+  pair_car,
+  pair_cdr,
+  set_car,
+  set_cdr,
+
+  is_symbol,
+  symname,
+
+  is_syntax,
+  is_proc,
+  is_foreign,
+  syntaxname,
+  is_closure,
+  is_macro,
+  closure_code,
+  closure_env,
+
+  is_continuation,
+  is_promise,
+  is_environment,
+  is_immutable,
+  setimmutable,
+
+  scheme_load_file,
+  scheme_load_string
+
+#if USE_PROTECT
+  , protect
+  , unprotect
+#endif
+#if USE_CUSTOM_FINALIZE
+  , ifc_setcustfin
+#endif
+  , ffvalue
+};
+#endif
+
+scheme *scheme_init_new() {
+  scheme *sc=(scheme*)malloc(sizeof(scheme));
+  if(!scheme_init(sc)) {
+    free(sc);
+    return 0;
+  } else {
+    return sc;
+  }
+}
+
+scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free) {
+  scheme *sc=(scheme*)malloc(sizeof(scheme));
+  if(!scheme_init_custom_alloc(sc,malloc,free)) {
+    free(sc);
+    return 0;
+  } else {
+    return sc;
+  }
+}
+
+
+int scheme_init(scheme *sc) {
+ return scheme_init_custom_alloc(sc,malloc,free);
+}
+
+int scheme_init_custom_alloc(scheme *sc, func_alloc malloc, func_dealloc free) {
+  int i, n=sizeof(dispatch_table)/sizeof(dispatch_table[0]);
+  pointer x;
+
+  num_zero.is_fixnum=1;
+  num_zero.value.ivalue=0;
+  num_one.is_fixnum=1;
+  num_one.value.ivalue=1;
+
+#if USE_INTERFACE
+  sc->vptr=&vtbl;
+#endif
+  sc->gensym_cnt=0;
+  sc->malloc=malloc;
+  sc->free=free;
+  sc->last_cell_seg = -1;
+  sc->sink = &sc->_sink;
+  sc->NIL = &sc->_NIL;
+  sc->T = &sc->_HASHT;
+  sc->F = &sc->_HASHF;
+  sc->EOF_OBJ=&sc->_EOF_OBJ;
+  sc->free_cell = &sc->_NIL;
+  sc->fcells = 0;
+  sc->no_memory=0;
+  sc->inport=sc->NIL;
+  sc->outport=sc->NIL;
+  sc->save_inport=sc->NIL;
+  sc->loadport=sc->NIL;
+  sc->nesting=0;
+  sc->interactive_repl=0;
+  
+  if (alloc_cellseg(sc,FIRST_CELLSEGS) != FIRST_CELLSEGS) {
+    nomem(sc);
+    return 0;
+  }
+  sc->gc_verbose = 0;
+  dump_stack_initialize(sc); 
+  sc->code = sc->NIL;
+  sc->tracing=0;
+  
+  /* init sc->NIL */
+  typeflag(sc->NIL) = (T_ATOM | MARK);
+  car(sc->NIL) = cdr(sc->NIL) = sc->NIL;
+  init_pref(sc->NIL);
+  /* init T */
+  typeflag(sc->T) = (T_ATOM | MARK);
+  car(sc->T) = cdr(sc->T) = sc->T;
+  init_pref(sc->T);
+  /* init F */
+  typeflag(sc->F) = (T_ATOM | MARK);
+  car(sc->F) = cdr(sc->F) = sc->F;
+  init_pref(sc->F);
+  sc->oblist = oblist_initial_value(sc); 
+  /* init global_env */
+  new_frame_in_env(sc, sc->NIL); 
+  sc->global_env = sc->envir; 
+  /* init else */
+  x = mk_symbol(sc,"else");
+  new_slot_in_env(sc, x, sc->T); 
+
+  assign_syntax(sc, "lambda");
+  assign_syntax(sc, "quote");
+  assign_syntax(sc, "define");
+  assign_syntax(sc, "if");
+  assign_syntax(sc, "begin");
+  assign_syntax(sc, "set!");
+  assign_syntax(sc, "let");
+  assign_syntax(sc, "let*");
+  assign_syntax(sc, "letrec");
+  assign_syntax(sc, "cond");
+  assign_syntax(sc, "delay");
+  assign_syntax(sc, "and");
+  assign_syntax(sc, "or");
+  assign_syntax(sc, "cons-stream");
+  assign_syntax(sc, "macro");
+  assign_syntax(sc, "case");
+  
+  for(i=0; i<n; i++) {
+    if(dispatch_table[i].name!=0) {
+      assign_proc(sc, (scheme_opcodes)i, dispatch_table[i].name);
+    }
+  }
+
+  /* initialization of global pointers to special symbols */
+  sc->LAMBDA = mk_symbol(sc, "lambda");
+  sc->QUOTE = mk_symbol(sc, "quote");
+  sc->QQUOTE = mk_symbol(sc, "quasiquote");
+  sc->UNQUOTE = mk_symbol(sc, "unquote");
+  sc->UNQUOTESP = mk_symbol(sc, "unquote-splicing");
+  sc->FEED_TO = mk_symbol(sc, "=>");
+  sc->COLON_HOOK = mk_symbol(sc,"*colon-hook*");
+  sc->ERROR_HOOK = mk_symbol(sc, "*error-hook*");
+  sc->SHARP_HOOK = mk_symbol(sc, "*sharp-hook*");
+
+#if USE_PROTECT
+  /* init protected list */
+  list_init(&sc->protect);
+  sc->ignore_protect = 0;
+#endif
+  sc->inside = 0;
+  return !sc->no_memory;
+}
+
+void scheme_set_input_port_file(scheme *sc, FILE *fin) {
+  sc->inport=port_from_file(sc,fin,port_input);
+}
+
+void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end) {
+  sc->inport=port_from_string(sc,start,past_the_end,port_input);
+}
+
+void scheme_set_output_port_file(scheme *sc, FILE *fout) {
+  sc->outport=port_from_file(sc,fout,port_output);
+}
+
+void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end) {
+  sc->outport=port_from_string(sc,start,past_the_end,port_output);
+}
+
+void scheme_set_external_data(scheme *sc, void *p) {
+ sc->ext_data=p;
+}
+
+#if 0
+static void scheme_finalize_all(scheme *sc)
+{
+        int i, j=0;
+        pointer p;
+
+        for (i = sc->last_cell_seg; i >= 0; i--) {
+                p = sc->cell_seg[i] + CELL_SEGSIZE;
+                while (--p >= sc->cell_seg[i]) {
+                        if (is_free(p)) {
+                                continue;
+                        }
+                        finalize_cell(sc, p);
+                        j++;
+                }
+        }
+        fprintf(stderr, "scheme_finalize_all: %d finalized\n", j);
+}
+#endif
+
+void scheme_deinit(scheme *sc) {
+  int i;
+
+#if USE_PROTECT
+  /* Check if the host program is still trying to protect some cells. */
+  if (!list_empty(&sc->protect)) {
+#if USE_CUSTOM_FINALIZE
+          /* Force all cells to be unprotected in order to break reference
+           * cycles between protected cells and host program objects that need
+           * to be dereferenced in the custom finalizer. If there are leaks in
+           * the host program, we can't detect them here. */
+          unprotect_all(sc);
+#else
+          /* This probably indicates a memory leak in the host program. */
+          fprintf(stderr, "warn: scheme protect list not empty!\n");
+          dump_protect(sc);
+#endif
+  }
+#endif
+
+  sc->oblist=sc->NIL;
+  sc->global_env=sc->NIL;
+  dump_stack_free(sc); 
+  sc->envir=sc->NIL;
+  sc->code=sc->NIL;
+  sc->args=sc->NIL;
+  sc->value=sc->NIL;
+  if(is_port(sc->inport)) {
+    typeflag(sc->inport) = T_ATOM;
+  }
+  sc->inport=sc->NIL;
+  sc->outport=sc->NIL;
+  if(is_port(sc->save_inport)) {
+    typeflag(sc->save_inport) = T_ATOM;
+  }
+  sc->save_inport=sc->NIL;
+  if(is_port(sc->loadport)) {
+    typeflag(sc->loadport) = T_ATOM;
+  }
+  sc->loadport=sc->NIL;
+  sc->gc_verbose=0;
+  gc(sc,sc->NIL,sc->NIL);
+
+#if USE_CELLDUMP
+  memleakcheck(sc);
+#endif
+
+  for(i=0; i<=sc->last_cell_seg; i++) {
+    sc->free(sc->alloc_seg[i]);
+  }
+
+}
+
+void scheme_load_file(scheme *sc, FILE *fin) {
+  dump_stack_reset(sc); 
+  sc->envir = sc->global_env;
+  sc->file_i=0;
+  sc->load_stack[0].kind=port_input|port_file;
+  sc->load_stack[0].rep.stdio.file=fin;
+  sc->loadport=mk_port(sc,sc->load_stack);
+  sc->retcode=0;
+  if(fin==stdin) {
+    sc->interactive_repl=1;
+  }
+  sc->inport=sc->loadport;
+  Eval_Cycle(sc, OP_T0LVL);
+  typeflag(sc->loadport)=T_ATOM;
+  if(sc->retcode==0) {
+    sc->retcode=sc->nesting!=0;
+  }
+}
+#if USE_FILE_AND_LINE
+void scheme_load_named_file(scheme *sc, FILE *fin, const char *fname) {
+  dump_stack_reset(sc); 
+  sc->envir = sc->global_env;
+  sc->file_i=0;
+  sc->load_stack[0].kind=port_input|port_file;
+  sc->load_stack[0].rep.stdio.file=fin;
+  sc->load_stack[0].rep.stdio.name = strdup(fname);
+  sc->load_stack[0].rep.stdio.line = 0;
+  sc->loadport=mk_port(sc,sc->load_stack);
+  sc->retcode=0;
+  if(fin==stdin) {
+    sc->interactive_repl=1;
+  }
+  sc->inport=sc->loadport;
+  Eval_Cycle(sc, OP_T0LVL);
+  typeflag(sc->loadport)=T_ATOM;
+  if(sc->retcode==0) {
+    sc->retcode=sc->nesting!=0;
+  }
+}
+#endif
+
+void scheme_load_string(scheme *sc, const char *cmd) {
+  dump_stack_reset(sc); 
+  sc->envir = sc->global_env;
+  sc->file_i=0;
+  sc->load_stack[0].kind=port_input|port_string;
+  sc->load_stack[0].rep.string.start=(char*)cmd; /* This func respects const */
+  sc->load_stack[0].rep.string.past_the_end=(char*)cmd+strlen(cmd);
+  sc->load_stack[0].rep.string.curr=(char*)cmd;
+  sc->loadport=mk_port(sc,sc->load_stack);
+  sc->retcode=0;
+  sc->interactive_repl=0;
+  sc->inport=sc->loadport;
+  Eval_Cycle(sc, OP_T0LVL);
+  typeflag(sc->loadport)=T_ATOM;
+  if(sc->retcode==0) {
+    sc->retcode=sc->nesting!=0;
+  }
+}
+
+void scheme_define(scheme *sc, pointer envir, pointer symbol, pointer value) {
+     pointer x;
+
+     x=find_slot_in_env(sc,envir,symbol,0);
+     if (x != sc->NIL) { 
+          set_slot_in_env(sc, x, value); 
+     } else { 
+          new_slot_spec_in_env(sc, envir, symbol, value); 
+     } 
+}
+
+#if !STANDALONE
+void scheme_apply0(scheme *sc, const char *procname) {
+     pointer carx=mk_symbol(sc,procname);
+     pointer cdrx=sc->NIL;
+
+     dump_stack_reset(sc); 
+     sc->envir = sc->global_env;
+     sc->code = cons(sc,carx,cdrx);
+     sc->interactive_repl=0;
+     sc->retcode=0;
+     Eval_Cycle(sc,OP_EVAL);
+     }
+
+//void scheme_call(scheme *sc, pointer func, pointer env, pointer args) { 
+pointer scheme_call(scheme *sc, pointer func, pointer args) { 
+#if USE_REENTER
+        if (sc->inside) {
+                /* We need to push a special operator on the stack to save all
+                 * stack frames below this one. */
+                s_save(sc, OP_EXIT_REENTER, args, func);
+        } else {
+                dump_stack_reset(sc);
+
+                /* gjm: file_push() pre-increments the load stack index, so
+                 * reset it so that the first call to load will use index
+                 * 0. (This fixes a crash when the code calls the load
+                 * procedure.) */
+                sc->file_i = -1;
+        }
+#else
+   dump_stack_reset(sc);
+#endif
+   sc->envir = sc->global_env; 
+   //sc->envir = env; 
+   sc->args = args; 
+   sc->code = func; 
+   sc->interactive_repl =0; 
+   sc->retcode = 0;
+   Eval_Cycle(sc, OP_APPLY); 
+
+   /* s_return puts the value in sc->value. I don't know how I got away with
+    * using sc->code for so long... maybe it depends upon the context? I hope
+    * not. */
+   /* return sc->code; */
+   return sc->value;
+} 
+
+#endif
+
+#if USE_SERIALIZE
+#include "session.h"
+#include <assert.h>
+#define SER_CAR 1
+static void serialize(scheme *sc, pointer p, struct save *save, int flags)
+{
+        if (is_atom(p)) {
+                if (p == sc->NIL) {
+                        if (flags & SER_CAR) {
+                                save->write(save, "'()\n");
+                        }
+                } else if (p == sc->T) {
+                        save->write(save, "#t\n");
+                } else if (p == sc->F) {
+                        save->write(save, "#f\n");
+                } else if (is_number(p)) {
+                        if (is_integer(p)) {
+                                save->write(save, "%d\n", ivalue(p));
+                        } else if (is_real(p)) {
+                                save->write(save, "%f\n", rvalue(p));
+                        } else {
+                                assert(0);
+                        }
+                } else if (is_foreign(p)) {
+                        save->write(save, "'()\n");
+                } else if (is_string(p)) {
+                        save->write(save, "\"%s\"\n", strvalue(p));
+                               } else if (is_vector(p)) {
+                                               save->enter(save, "(vector\n");
+                                               long vindex;
+                                               long vlength=ivalue(p);
+                                               for (vindex=0;vindex<vlength;vindex++)
+                                               {
+                                                       serialize(sc, vector_elem(p,vindex), save, SER_CAR);
+                                               }
+                                               save->exit(save, ")\n");
+                } else {
+                        assert(0);
+                }
+                return;
+        }
+
+        if (is_pair(p)) {
+                if (flags & SER_CAR) {
+                        save->enter(save, "(list\n");
+                }
+                serialize(sc, car(p), save, SER_CAR);
+                serialize(sc, cdr(p), save, 0);
+                if (flags & SER_CAR) {
+                        save->exit(save, ")\n");
+                }
+        } else if (is_symbol(p)) {
+                save->write(save, "'%s\n", symname(p));
+        } else if (is_closure(p)) {
+                fprintf(stderr, "can't serialize closures\n");
+                assert(0);
+        } else {
+                assert(0);
+        }
+}
+void scheme_serialize(scheme *sc, pointer p, struct save *save)
+{
+        serialize(sc, p, save, SER_CAR);
+}
+#endif
+
+#if USE_CELLDUMP
+#define MAX_DUMP_LEN 256
+void celldump(scheme *sc, pointer pp)
+{
+        static const char *typestr[T_LAST_SYSTEM_TYPE+1] = {
+                "---", "STR", "NUM", "SYM", "PRO",
+                "PAI", "CLO", "CON", "FOR",
+                "CHA", "POR", "VEC", "MAC",
+                "PRO", "ENV"
+        };
+        char strbuf[MAX_DUMP_LEN+1], *bptr;
+        unsigned int i;
+
+        memset(strbuf, ' ', sizeof(strbuf));
+
+        /* address */
+        bptr = strbuf;
+        bptr += sprintf(bptr, "%p ", pp);
+
+        /* allocated? */
+        if (0==typeflag(pp)) {
+                bptr += sprintf(bptr, "F %p", cdr(pp));
+        } else {
+
+                bptr += sprintf(bptr, "A ");
+
+                /* type */
+                for (i = 0; i < T_LAST_SYSTEM_TYPE && i != type(pp); i++)
+                        ;
+                bptr += sprintf(bptr, typestr[i]);
+                *bptr++ = ' ';
+                
+                /* flags */
+                if (is_syntax(pp))
+                        bptr += sprintf(bptr, "SYN|");
+                if (is_immutable(pp))
+                        bptr += sprintf(bptr, "IMM|");
+                if (is_atom(pp))
+                        bptr += sprintf(bptr, "ATM|");
+                if (is_mark(pp))
+                        bptr += sprintf(bptr, "MRK|");
+                if (*(bptr-1)=='|')
+                        *(bptr-1)=' ';
+
+                /* car/cdr */
+                if (is_pair(pp)) {
+                        bptr += sprintf(bptr, "%p %p", 
+                                        car(pp), cdr(pp));
+                } else {
+                        int len = 0;
+                        const char *str;
+                        atom2str(sc, pp, 0, &str, &len);
+                        bptr += sprintf(bptr, "%s", str);
+                }
+        }
+
+#if USE_CUSTOM_FINALIZE
+        if (is_custfin(pp)) {
+                bptr += sprintf(bptr, " ~");
+        }
+#endif
+
+#if USE_PROTECT
+        /* protected? */
+        if (!list_empty(&pp->plist)) {
+                bptr += sprintf(bptr, " P%d", pp->pref);
+        }
+#endif
+        bptr += sprintf(bptr, "\n");
+        strbuf[sizeof(strbuf)-1] = 0;
+
+        /*putstr(sc, strbuf);*/
+        fprintf(stderr,strbuf);
+        fflush(NULL);
+}
+
+#if 0
+static void memdump(scheme *sc)
+{
+        int i, j;
+        pointer p;
+        fprintf(stderr, ">>> MEMDUMP <<<\n");
+        for (i=0; i <= sc->last_cell_seg; i++) {
+                p = sc->cell_seg[i];
+                for (j = 0; j < CELL_SEGSIZE; j++, p++) {
+                        celldump(sc, p);
+                }
+        }
+}
+#endif 
+
+static void memleakcheck(scheme *sc)
+{
+        int i, j, leaks = 0;
+        pointer p;
+        fprintf(stderr, "Scheme leak check...\n");
+        for (i=0; i <= sc->last_cell_seg; i++) {
+                p = sc->cell_seg[i];
+                for (j = 0; j < CELL_SEGSIZE; j++, p++) {
+                        if (!is_free(p)) {
+                                celldump(sc, p);
+                                leaks++;
+                        }
+                }
+        }
+        fprintf(stderr, "%d leaked cells detected\n", leaks);
+}
+#endif /* USE_CELLDUMP */
+
+#if USE_PROTECT
+void dump_protect(scheme *sc)
+{
+        list *elem;
+        list_for_each(&sc->protect, elem) {
+                pointer pp = (pointer)elem;
+                celldump(sc,pp); /* assumes USE_CELLDUMP */
+        }
+
+}
+#endif /* USE_PROTECT */
+
+#if USE_CUSTOM_FINALIZE
+void scheme_set_custom_finalize(scheme *sc, void (*fin)(scheme *, pointer))
+{
+        sc->custom_finalize = fin;
+}
+#endif
+
+/* ========== Main ========== */
+#if STANDALONE
+
+#ifdef macintosh
+int main()
+{
+     extern MacTS_main(int argc, char **argv);
+     char**    argv;
+     int argc = ccommand(&argv);
+     MacTS_main(argc,argv);
+     return 0;
+}
+int MacTS_main(int argc, char **argv) {
+#else
+int main(int argc, char **argv) {
+#endif
+  scheme sc;
+  FILE *fin;
+  char *file_name=InitFile;
+  int retcode;
+  int isfile=1;
+  
+  if(argc==1) {
+    printf(banner);
+  }
+  if(argc==2 && strcmp(argv[1],"-?")==0) {
+    printf("Usage: %s [-? | <file1> <file2> ... | -1 <file> <arg1> <arg2> ...]\n\tUse - as filename for stdin.\n",argv[0]);
+    return 1;
+  }
+  if(!scheme_init(&sc)) {
+    fprintf(stderr,"Could not initialize!\n");
+    return 2;
+  }
+  scheme_set_input_port_file(&sc, stdin);
+  scheme_set_output_port_file(&sc, stdout);
+#if USE_DL
+  scheme_define(&sc,sc.global_env,mk_symbol(&sc,"load-extension"),mk_foreign_func(&sc, scm_load_ext));
+#endif
+  argv++;
+  if(access(file_name,0)!=0) {
+    char *p=getenv("TINYSCHEMEINIT");
+    if(p!=0) {
+      file_name=p;
+    }
+  }
+  do {
+    if(strcmp(file_name,"-")==0) {
+      fin=stdin;
+    } else if(strcmp(file_name,"-1")==0 || strcmp(file_name,"-c")==0) {
+      pointer args=sc.NIL;
+      isfile=file_name[1]=='1';
+      file_name=*argv++;
+      if(strcmp(file_name,"-")==0) {
+       fin=stdin;
+      } else if(isfile) {
+       fin=fopen(file_name,"r");
+      }
+      for(;*argv;argv++) {
+       pointer value=mk_string(&sc,*argv);
+       args=cons(&sc,value,args);
+      }
+      args=reverse_in_place(&sc,sc.NIL,args);
+      scheme_define(&sc,sc.global_env,mk_symbol(&sc,"*args*"),args);
+
+    } else {
+      fin=fopen(file_name,"r");
+    }
+    if(isfile && fin==0) {
+      fprintf(stderr,"Could not open file %s\n",file_name);
+    } else {
+      if(isfile) {
+       scheme_load_file(&sc,fin);
+      } else {
+       scheme_load_string(&sc,file_name);
+      }
+      if(!isfile || fin!=stdin) {
+       if(sc.retcode!=0) {
+         fprintf(stderr,"Errors encountered reading %s\n",file_name);
+       }
+       if(isfile) {
+         fclose(fin);
+       }
+      }
+    }
+    file_name=*argv++;
+  } while(file_name!=0);
+  if(argc==1) {
+    scheme_load_file(&sc,stdin);
+  }
+  retcode=sc.retcode;
+  scheme_deinit(&sc);
+  
+  return retcode;
+}
+
+#endif
+
+int scm_len(scheme *sc, pointer list)
+{
+        int len = 0;
+
+        while (scm_is_pair(sc, list)) {
+                len++;
+                list = scm_cdr(sc, list);
+        }
+
+        return len;
+}
diff --git a/src/scheme.h b/src/scheme.h
new file mode 100644 (file)
index 0000000..53774cb
--- /dev/null
@@ -0,0 +1,268 @@
+/* SCHEME.H */
+
+#ifndef _SCHEME_H
+#define _SCHEME_H
+
+#include <stdio.h>
+
+#define USE_INTERFACE 1
+
+/*
+ * Default values for #define'd symbols
+ */
+#ifndef STANDALONE       /* If used as standalone interpreter */
+# define STANDALONE 0
+#endif
+
+#ifndef _MSC_VER 
+# define USE_STRCASECMP 1 
+# ifndef WIN32 /* needed for Cygwin */
+#  define USE_STRLWR 1 
+# else
+#  define USE_STRLWR 0
+# endif
+# define SCHEME_EXPORT
+#else 
+# define USE_STRCASECMP 0 
+# define USE_STRLWR 0 
+# ifdef _SCHEME_SOURCE
+#  define SCHEME_EXPORT __declspec(dllexport)
+# else
+#  define SCHEME_EXPORT __declspec(dllimport)
+# endif
+#endif
+
+#if USE_NO_FEATURES
+# define USE_MATH 0
+# define USE_CHAR_CLASSIFIERS 0
+# define USE_ASCII_NAMES 0
+# define USE_STRING_PORTS 0
+# define USE_ERROR_HOOK 0
+# define USE_TRACING 0
+# define USE_COLON_HOOK 0
+# define USE_DL 0
+# define USE_PLIST 0
+# define USE_PROTECT 0
+# define USE_SERIALIZE 0
+# define USE_REENTER 0
+#endif
+
+#if USE_DL
+# define USE_INTERFACE 1
+#endif
+
+#ifndef USE_PROTECT
+# include "list.h"
+# define USE_PROTECT 1
+#endif
+
+#ifndef USE_REENTER
+# define USE_REENTER 1 /* works around script->C->script return issues */
+#endif
+
+#ifndef USE_FILE_AND_LINE
+# define USE_FILE_AND_LINE 1
+#endif
+
+#ifndef USE_SERIALIZE
+# define USE_SERIALIZE 1
+#endif
+
+#ifndef USE_MATH         /* If math support is needed */
+# define USE_MATH 1
+#endif
+
+#ifndef USE_CHAR_CLASSIFIERS  /* If char classifiers are needed */
+# define USE_CHAR_CLASSIFIERS 1
+#endif
+
+#ifndef USE_ASCII_NAMES  /* If extended escaped characters are needed */
+# define USE_ASCII_NAMES 1
+#endif
+
+#ifndef USE_STRING_PORTS      /* Enable string ports */
+# define USE_STRING_PORTS 1
+#endif
+
+#ifndef USE_TRACING
+# define USE_TRACING 0
+#endif
+
+#ifndef USE_PLIST
+# define USE_PLIST 0
+#endif
+
+/* To force system errors through user-defined error handling (see *error-hook*) */
+#ifndef USE_ERROR_HOOK
+# define USE_ERROR_HOOK 1
+#endif
+
+#ifndef USE_COLON_HOOK   /* Enable qualified qualifier */
+# define USE_COLON_HOOK 1
+#endif
+
+#ifndef USE_STRCASECMP   /* stricmp for Unix */
+# define USE_STRCASECMP 0
+#endif
+
+#ifndef USE_STRLWR
+# define USE_STRLWR 1
+#endif
+
+#ifndef STDIO_ADDS_CR    /* Define if DOS/Windows */
+# define STDIO_ADDS_CR 0
+#endif
+
+#ifndef INLINE
+# define INLINE
+#endif
+
+#ifndef USE_INTERFACE
+# define USE_INTERFACE 0
+#endif
+
+#ifndef USE_CELLDUMP
+# define USE_CELLDUMP 1
+#endif
+
+/* Allow cells to be marked with a flag that will run a custom finalizer on
+ * them. */
+#ifndef USE_CUSTOM_FINALIZE
+# define USE_CUSTOM_FINALIZE 1
+#endif
+
+typedef struct scheme scheme;
+typedef struct cell *pointer;
+
+typedef void * (*func_alloc)(size_t);
+typedef void (*func_dealloc)(void *);
+
+/* num, for generic arithmetic */
+typedef struct num {
+     char is_fixnum;
+     union {
+          long ivalue;
+          double rvalue;
+     } value;
+} num;
+
+SCHEME_EXPORT scheme *scheme_init_new();
+SCHEME_EXPORT scheme *scheme_init_new_custom_alloc(func_alloc malloc, func_dealloc free);
+SCHEME_EXPORT int scheme_init(scheme *sc);
+SCHEME_EXPORT int scheme_init_custom_alloc(scheme *sc, func_alloc, func_dealloc);
+SCHEME_EXPORT void scheme_deinit(scheme *sc);
+void scheme_set_input_port_file(scheme *sc, FILE *fin);
+void scheme_set_input_port_string(scheme *sc, char *start, char *past_the_end);
+SCHEME_EXPORT void scheme_set_output_port_file(scheme *sc, FILE *fin);
+void scheme_set_output_port_string(scheme *sc, char *start, char *past_the_end);
+#ifdef USE_FILE_AND_LINE
+SCHEME_EXPORT void scheme_load_named_file(scheme *sc, FILE *fin, const char *fname);
+#endif
+SCHEME_EXPORT void scheme_load_file(scheme *sc, FILE *fin);
+SCHEME_EXPORT void scheme_load_string(scheme *sc, const char *cmd);
+void scheme_apply0(scheme *sc, const char *procname);
+SCHEME_EXPORT pointer scheme_apply1(scheme *sc, const char *procname, pointer);
+void scheme_set_external_data(scheme *sc, void *p);
+SCHEME_EXPORT void scheme_define(scheme *sc, pointer env, pointer symbol, pointer value);
+//SCHEME_EXPORT void scheme_call(scheme *sc, pointer func, pointer env, pointer args);
+SCHEME_EXPORT pointer scheme_call(scheme *sc, pointer func, pointer args);
+
+#if USE_SERIALIZE
+SCHEME_EXPORT void scheme_serialize(scheme *sc, pointer p, struct save *save);
+#endif
+
+#if USE_CUSTOM_FINALIZE
+SCHEME_EXPORT void scheme_set_custom_finalize(scheme *, 
+                                              void (*fx)(scheme *, pointer));
+#endif
+
+typedef pointer (*foreign_func)(scheme *, pointer);
+
+pointer _cons(scheme *sc, pointer a, pointer b, int immutable);
+pointer mk_integer(scheme *sc, long num);
+pointer mk_real(scheme *sc, double num);
+pointer mk_symbol(scheme *sc, const char *name);
+pointer gensym(scheme *sc);
+pointer mk_string(scheme *sc, const char *str);
+pointer mk_counted_string(scheme *sc, const char *str, int len);
+pointer mk_character(scheme *sc, int c);
+pointer mk_foreign_func(scheme *sc, foreign_func f);
+void putstr(scheme *sc, const char *s);
+void celldump(scheme *sc, pointer p);
+
+#if USE_INTERFACE
+struct scheme_interface {
+  void (*scheme_define)(scheme *sc, pointer env, pointer symbol, pointer value);
+  pointer (*cons)(scheme *sc, pointer a, pointer b);
+  pointer (*immutable_cons)(scheme *sc, pointer a, pointer b);
+  pointer (*mk_integer)(scheme *sc, long num);
+  pointer (*mk_real)(scheme *sc, double num);
+  pointer (*mk_symbol)(scheme *sc, const char *name);
+  pointer (*gensym)(scheme *sc);
+  pointer (*mk_string)(scheme *sc, const char *str);
+  pointer (*mk_counted_string)(scheme *sc, const char *str, int len);
+  pointer (*mk_character)(scheme *sc, int c);
+  pointer (*mk_vector)(scheme *sc, int len);
+  pointer (*mk_foreign_func)(scheme *sc, foreign_func f);
+  pointer (*find_slot_in_env)(scheme *sc, pointer env, pointer sym, int all);
+  void (*putstr)(scheme *sc, const char *s);
+  void (*putcharacter)(scheme *sc, int c);
+  
+  int (*is_string)(pointer p);
+  char *(*string_value)(pointer p);
+  int (*is_number)(pointer p);
+  num (*nvalue)(pointer p);
+  long (*ivalue)(pointer p);
+  double (*rvalue)(pointer p);
+  int (*is_integer)(pointer p);
+  int (*is_real)(pointer p);
+  int (*is_character)(pointer p);
+  long (*charvalue)(pointer p);
+  int (*is_vector)(pointer p);
+  long (*vector_length)(pointer vec);
+  void (*fill_vector)(pointer vec, pointer elem);
+  pointer (*vector_elem)(pointer vec, int ielem);
+  pointer (*set_vector_elem)(pointer vec, int ielem, pointer newel);
+  int (*is_port)(pointer p);
+  
+  int (*is_pair)(pointer p);
+  pointer (*pair_car)(pointer p);
+  pointer (*pair_cdr)(pointer p);
+  pointer (*set_car)(pointer p, pointer q);
+  pointer (*set_cdr)(pointer p, pointer q);
+
+  int (*is_symbol)(pointer p);
+  char *(*symname)(pointer p);
+  
+  int (*is_syntax)(pointer p);
+  int (*is_proc)(pointer p);
+  int (*is_foreign)(pointer p);
+  char *(*syntaxname)(pointer p);
+  int (*is_closure)(pointer p);
+  int (*is_macro)(pointer p);
+  pointer (*closure_code)(pointer p);
+  pointer (*closure_env)(pointer p);
+
+  int (*is_continuation)(pointer p);
+  int (*is_promise)(pointer p);
+  int (*is_environment)(pointer p);
+  int (*is_immutable)(pointer p);
+  void (*setimmutable)(pointer p);
+  void (*load_file)(scheme *sc, FILE *fin);
+  void (*load_string)(scheme *sc, const char *input);
+
+#if USE_PROTECT
+  pointer (*protect)(scheme *sc, pointer p);
+  pointer (*unprotect)(scheme *sc, pointer p);
+#endif
+
+#if USE_CUSTOM_FINALIZE
+  void (*setcustfin)(pointer p);
+#endif
+
+  foreign_func (*ffvalue)(pointer arg); /* gmcnutt: new addition */
+};
+#endif
+
+#endif
+
diff --git a/src/screen.c b/src/screen.c
new file mode 100644 (file)
index 0000000..c45f0f8
--- /dev/null
@@ -0,0 +1,1036 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "screen.h"
+#include "common.h"
+#include "ascii.h"
+#include "sprite.h"
+#include "status.h"
+#include "foogod.h"
+#include "cfg.h"
+#include "images.h"
+#include "nazghul.h"   // for FullScreenMode
+
+#include <png.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#include <SDL_image.h>
+
+#define N_SHADERS 3
+#define MAX_SHADER (N_SHADERS - 1)
+#define SHADER_W STAT_W
+#define SHADER_H STAT_H_MAX
+#define HIGHLIGHT_THICKNESS 2
+
+/* Frame image indices */
+#define FRAME_ULC  0
+#define FRAME_TD   1
+#define FRAME_URC  2
+#define FRAME_ENDT 3
+#define FRAME_TR   4
+#define FRAME_TX   5
+#define FRAME_TL   6
+#define FRAME_VERT 7
+#define FRAME_LLC  8
+#define FRAME_TU   9
+#define FRAME_LRC  10
+#define FRAME_ENDD 11
+#define FRAME_ENDL 12
+#define FRAME_HORZ 13
+#define FRAME_ENDR 14
+#define FRAME_DOT  15
+#define FRAME_NUM_SPRITES 16
+
+/* Enable this to dump surfaces and video info */
+#ifndef SCREEN_DEBUG
+#define SCREEN_DEBUG 0
+#endif
+
+static SDL_Surface *Screen;
+static SDL_Surface *Shaders[N_SHADERS];
+static SDL_Surface *Highlight;
+static struct sprite *FrameSprites[FRAME_NUM_SPRITES];
+static int Zoom;
+static char screen_buf[128];
+
+Uint32 Black;
+Uint32 Blue;
+Uint32 White;
+Uint32 Green;
+Uint32 Red;
+Uint32 Yellow;
+Uint32 Cyan;
+Uint32 Magenta;
+Uint32 Gray;
+
+Uint32 TextRed;
+Uint32 TextGreen;
+Uint32 TextBlue;
+Uint32 TextYellow;
+Uint32 TextCyan;
+Uint32 TextMagenta;
+
+
+SDL_Color fontWhite = { 0xff, 0xff, 0xff, 0x00 };
+SDL_Color fontBlack = { 0, 0, 0, 0 };
+
+static void scaled_blit(SDL_Surface * source, SDL_Rect * from,
+                       SDL_Surface * dest, SDL_Rect * to);
+
+void screenInitColors(void)
+{
+
+       Black   = SDL_MapRGB(Screen->format, 0x00, 0x00, 0x00);
+       White   = SDL_MapRGB(Screen->format, 0xff, 0xff, 0xff);
+       Red     = SDL_MapRGB(Screen->format, 0xff, 0x00, 0x00);
+       TextRed = SDL_MapRGB(Screen->format, 0xff, 0x99, 0x99);
+       Green   = SDL_MapRGB(Screen->format, 0x00, 0xff, 0x00);
+       TextGreen = SDL_MapRGB(Screen->format, 0x99, 0xff, 0x99);
+       Blue    = SDL_MapRGB(Screen->format, 0x00, 0x00, 0xff);
+       TextBlue = SDL_MapRGB(Screen->format, 0x99, 0x99, 0xff);
+       Yellow  = SDL_MapRGB(Screen->format, 0xff, 0xff, 0x00);
+       TextYellow = SDL_MapRGB(Screen->format, 0xff, 0xff, 0x99);
+       Cyan    = SDL_MapRGB(Screen->format, 0x00, 0xff, 0xff);
+       TextCyan = SDL_MapRGB(Screen->format, 0x99, 0xff, 0xff);
+       Magenta = SDL_MapRGB(Screen->format, 0xff, 0xff, 0x00);
+       TextMagenta = SDL_MapRGB(Screen->format, 0xff, 0x99, 0xff);
+       Gray    = SDL_MapRGB(Screen->format, 0x80, 0x80, 0x80);
+}
+
+void dump_SDL_PixelFormat(SDL_PixelFormat *fmt)
+{
+        printf("Pixel Format:\n");
+        printf("     palette: %p\n", fmt->palette);
+        printf("BitsPerPixel: %d\n", fmt->BitsPerPixel);
+        printf("       Rmask: 0x%x\n", fmt->Rmask);
+        printf("       Gmask: 0x%x\n", fmt->Gmask);
+        printf("       Bmask: 0x%x\n", fmt->Bmask);
+        printf("       Amask: 0x%x\n", fmt->Amask);
+        printf("      Rshift: %d\n", fmt->Rshift);
+        printf("      Gshift: %d\n", fmt->Gshift);
+        printf("      Bshift: %d\n", fmt->Bshift);
+        printf("      Ashift: %d\n", fmt->Ashift);
+        printf("       Rloss: %d\n", fmt->Rloss);
+        printf("       Gloss: %d\n", fmt->Gloss);
+        printf("       Bloss: %d\n", fmt->Bloss);
+        printf("       Aloss: %d\n", fmt->Aloss);
+        printf("    colorkey: 0x%x\n", fmt->colorkey);
+        printf("       alpha: 0x%x\n", fmt->alpha);               
+}
+
+void dump_SDL_VideoInfo(const SDL_VideoInfo *fmt)
+{
+        printf("Video Info:\n");
+        printf(" hw_available: %c\n", fmt->hw_available ? 'y' : 'n');
+        printf(" wm_available: %c\n", fmt->wm_available ? 'y' : 'n');
+        printf("      blit_hw: %c\n", fmt->blit_hw ? 'y' : 'n');
+        printf("   blit_hw_CC: %c\n", fmt->blit_hw_CC ? 'y' : 'n');
+        printf("    blit_hw_A: %c\n", fmt->blit_hw_A ? 'y' : 'n');
+        printf("      blit_sw: %c\n", fmt->blit_sw ? 'y' : 'n');
+        printf("   blit_sw_CC: %c\n", fmt->blit_sw_CC ? 'y' : 'n');
+        printf("    blit_sw_A: %c\n", fmt->blit_sw_A ? 'y' : 'n');
+        printf("    blit_fill: %c\n", fmt->blit_fill ? 'y' : 'n');
+        printf("    video_mem: %d\n", fmt->video_mem);
+        dump_SDL_PixelFormat(fmt->vfmt);
+}
+
+void dump_SDL_Surface(SDL_Surface *surf)
+{
+        printf("Surface Info:\n");
+        printf("     flags:\n");
+        if (surf->flags & SDL_SWSURFACE)
+                printf("  SDL_SWSURFACE\n");
+        if (surf->flags & SDL_HWSURFACE)
+                printf("  SDL_HWSURFACE\n");
+        if (surf->flags & SDL_ASYNCBLIT)
+                printf("  SDL_ASYNCBLIT\n");
+        if (surf->flags & SDL_ANYFORMAT)
+                printf("  SDL_ANYFORMAT\n");
+        if (surf->flags & SDL_HWPALETTE)
+                printf("  SDL_HWPALETTE\n");
+        if (surf->flags & SDL_DOUBLEBUF)
+                printf("  SDL_DOUBLEBUF\n");
+        if (surf->flags & SDL_FULLSCREEN)
+                printf("  SDL_FULLSCREEN\n");
+        if (surf->flags & SDL_OPENGL)
+                printf("  SDL_OPENGL\n");
+        if (surf->flags & SDL_OPENGLBLIT)
+                printf("  SDL_OPENGLBLIT\n");
+        if (surf->flags & SDL_RESIZABLE)
+                printf("  SDL_RESIZABLE\n");
+        if (surf->flags & SDL_HWACCEL)
+                printf("  SDL_HWACCEL\n");
+        if (surf->flags & SDL_SRCCOLORKEY)
+                printf("  SDL_SRCCOLORKEY\n");
+        if (surf->flags & SDL_RLEACCEL)
+                printf("  SDL_RLEACCEL\n");
+        if (surf->flags & SDL_SRCALPHA)
+                printf("  SDL_SRCALPHA\n");
+        if (surf->flags & SDL_PREALLOC)
+                printf("  SDL_PREALLOC\n");
+        printf("         w: %d\n", surf->w);
+        printf("         h: %d\n", surf->h);
+        printf("     pitch: %d\n", surf->pitch);
+        printf("    pixels: %p\n", surf->pixels);
+        printf(" clip_rect: [%d %d %d %d]\n",
+               surf->clip_rect.x,
+               surf->clip_rect.y,
+               surf->clip_rect.w,
+               surf->clip_rect.h);
+        printf("  refcount: %d\n", surf->refcount);
+        dump_SDL_PixelFormat(surf->format);
+        
+}
+
+void screenInitScreen(void)
+{
+       Uint32 flags = SDL_ANYFORMAT;
+       const SDL_VideoInfo *fmt;
+
+        const int SCREEN_BPP = 0;      /* use display BPP */
+
+       if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+               perror_sdl("SDL_Init");
+               exit(-1);
+       }
+       atexit(SDL_Quit);
+
+       fmt = SDL_GetVideoInfo();
+       if (!fmt) {
+               perror_sdl("SDL_GetVideoInfo");
+               exit(-1);
+       }
+
+        if (SCREEN_DEBUG) {
+                dump_SDL_VideoInfo(fmt);
+        }
+
+       if (fmt->blit_hw_CC && fmt->blit_fill) {
+               flags |= SDL_HWSURFACE;
+               flags |= SDL_DOUBLEBUF;
+       }
+       if (FullScreenMode) {
+               flags |= SDL_FULLSCREEN;
+       }
+
+       Screen = SDL_SetVideoMode(SCREEN_W, SCREEN_H, SCREEN_BPP, flags);
+       if (!Screen) {
+               perror_sdl("SDL_SetVideoMode");
+               exit(-1);
+       }
+
+        if (SCREEN_DEBUG) {
+                printf("Video initialized to...\n");
+                dump_SDL_Surface(Screen);
+        }
+
+       SDL_WM_SetCaption(APPLICATION_NAME, APPLICATION_NAME);
+}
+
+void screen_fade_surface(SDL_Surface * surf, int fade_level)
+{
+       int x, y;
+       Uint8 *pix;
+       Uint8 trans;
+       int base;
+       int toggle;
+
+       assert(surf->format->BitsPerPixel == 8);
+
+       if (fade_level == 0)
+               return;
+
+       pix = (Uint8 *) surf->pixels;
+       trans = (Uint8) surf->format->colorkey;
+
+       for (y = 0; y < surf->h; y++) {
+               base = y * surf->pitch;
+               toggle = y % 2;
+               for (x = 0; x < surf->w; x++) {
+                       int i = base + x;
+                       if (toggle) {
+                               if (pix[i] != trans) {
+                                       toggle = 0;
+                                       pix[i] = trans;
+                               }
+                       } else if (pix[i] != trans) {
+                               toggle = 1;
+                       }
+               }               // for (x)
+       }                       // for (y)
+
+       assert(surf->format->BitsPerPixel == 8);
+
+       screen_fade_surface(surf, fade_level - 1);
+}
+
+static SDL_Surface *create_shader(int fade_level)
+{
+       SDL_Surface *shader;
+
+       shader = screenCreateSurface(SHADER_W, SHADER_H);
+       if (shader == NULL)
+               return NULL;
+
+       SDL_FillRect(shader, NULL, SDL_MapRGBA(shader->format, 0, 0, 0, 0));
+
+       if (shader->format->palette != NULL) {
+               SDL_LockSurface(shader);
+               screen_fade_surface(shader, fade_level);
+               SDL_UnlockSurface(shader);
+       }
+
+       return shader;
+}
+
+void screenInitShader(void)
+{
+       int n, i;
+
+       n = (Screen->format->BitsPerPixel == 8) ? N_SHADERS : 1;
+
+       for (i = 0; i < n; i++) {
+               Shaders[i] = create_shader(i);
+       }
+}
+
+void screenInitHighlight(void)
+{
+       Highlight = screenCreateSurface(SHADER_W, SHADER_H);
+        assert(Highlight != NULL);
+
+       SDL_FillRect(Highlight, NULL, SDL_MapRGBA(Highlight->format, 255, 255, 255, 0));
+
+       if (Highlight->format->palette != NULL) {
+               SDL_LockSurface(Highlight);
+               screen_fade_surface(Highlight, 4);
+               SDL_UnlockSurface(Highlight);
+       }
+}
+
+static void screenInitFrame(void)
+{
+        int i;
+        char *fname = cfg_get("frame-image-filename");
+        struct images *ss_frame = 0;
+
+        if (!fname) {
+                warn("No frame image filename!");
+                return;
+        }
+
+        memset(FrameSprites, 0, sizeof(FrameSprites));
+
+        ss_frame = images_new(0, 16, 16, 4, 4, 0, 0, fname);
+        assert(ss_frame);
+
+        for (i = 0; i < FRAME_NUM_SPRITES; i++) {
+                FrameSprites[i] = sprite_new(0, 1, i, 0, 0, ss_frame);
+                assert(FrameSprites[i]);
+        }
+}
+
+int screenInit(void)
+{
+       screenInitScreen();
+       screenInitColors();
+       screenInitShader();
+        screenInitHighlight();
+        screenInitFrame();
+       Zoom = 1;
+
+       SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY,
+                           SDL_DEFAULT_REPEAT_INTERVAL);
+
+        return 0;
+}
+
+void screenErase(SDL_Rect * rect)
+{
+       SDL_FillRect(Screen, rect, Black);
+}
+
+void screenFill(SDL_Rect * rect, Uint32 color)
+{
+       SDL_Rect tmp = *rect;
+       rect->w /= Zoom;
+       rect->h /= Zoom;
+       SDL_FillRect(Screen, rect, color);
+}
+
+void screenUpdate(SDL_Rect * rect)
+{
+       if (rect) {
+               SDL_UpdateRect(Screen, rect->x, rect->y, rect->w, rect->h);
+       } else {
+               SDL_Flip(Screen);
+       }
+}
+
+/* bpp-independent macro to test if a pixel is magenta */
+#define isTransparent(ff,pp) \
+        (((ff)->Rmask&(pp))==(ff)->Rmask \
+          && ((ff)->Gmask&(pp))==0 \
+          && ((ff)->Bmask&(pp))==(ff)->Bmask)
+
+static void scaled_blit_32bpp(SDL_Surface * source, SDL_Rect * from,
+                             SDL_Surface * dest, SDL_Rect * to,
+                             int spitch, int dpitch)
+{
+       int dx, dy, di, sx, sy, si;
+       Uint32 *d, *s;
+
+       d = (Uint32 *) dest->pixels;
+       s = (Uint32 *) source->pixels;
+
+       for (dy = 0; dy < to->h; dy++) {
+               sy = dy * Zoom;
+               for (dx = 0; dx < to->w; dx++) {
+                       sx = dx * Zoom;
+                       di = (dy + to->y) * dpitch + (dx + to->x);
+                       si = (sy + from->y) * spitch + (sx + from->x);
+                        if (!isTransparent(dest->format, s[si]))
+                                d[di] = s[si];
+               }               // for (dx)
+       }                       // for (dy)
+}
+
+static void scaled_blit_16bpp(SDL_Surface * source, SDL_Rect * from,
+                             SDL_Surface * dest, SDL_Rect * to,
+                             int spitch, int dpitch)
+{
+       int dx, dy, di, sx, sy, si;
+       Uint16 *d, *s;
+
+       d = (Uint16 *) dest->pixels;
+       s = (Uint16 *) source->pixels;
+
+       for (dy = 0; dy < to->h; dy++) {
+               sy = dy * Zoom;
+               for (dx = 0; dx < to->w; dx++) {
+                       sx = dx * Zoom;
+                       di = (dy + to->y) * dpitch + (dx + to->x);
+                       si = (sy + from->y) * spitch + (sx + from->x);
+                        if (! isTransparent(dest->format, s[si]))
+                                d[di] = s[si];
+               }               // for (dx)
+       }                       // for (dy)
+}
+
+static void scaled_blit_8bpp(SDL_Surface * source, SDL_Rect * from,
+                            SDL_Surface * dest, SDL_Rect * to,
+                            int spitch, int dpitch)
+{
+       int dx, dy, di, sx, sy, si;
+       Uint8 *d, *s;
+
+       d = (Uint8 *) dest->pixels;
+       s = (Uint8 *) source->pixels;
+
+       for (dy = 0; dy < to->h; dy++) {
+               sy = dy * Zoom;
+               for (dx = 0; dx < to->w; dx++) {
+                       sx = dx * Zoom;
+                       di = (dy + to->y) * dpitch + (dx + to->x);
+                       si = (sy + from->y) * spitch + (sx + from->x);
+                       d[di] = s[si];
+               }               // for (dx)
+       }                       // for (dy)
+}
+
+/* scale_then_blit_normal -- cheesy hack to support scaled blitting of
+ * incompatible surface types. This blits the source to a temporary compatible
+ * surface using the scaled_blit function, then blits the tmp surface to the
+ * screen with Zoom=1. Inefficient but functional. */
+static void scale_then_blit_normal(SDL_Surface * source, SDL_Rect * from,
+                                   SDL_Surface * dest, SDL_Rect * to)
+{
+        SDL_Surface *tmp = 0;
+        SDL_Rect rect;
+        int o_zoom = Zoom;
+
+        /* Create a temporary surface for the scaled blit which has the same
+         * format as the source. */
+       tmp = SDL_CreateRGBSurface(source->flags,
+                                  from->w / Zoom, from->h / Zoom,
+                                  source->format->BitsPerPixel,
+                                  source->format->Rmask,
+                                  source->format->Gmask,
+                                  source->format->Bmask,
+                                  source->format->Amask);
+        if (!tmp) {
+               perror_sdl("SDL_CreateRGBSurface");
+               return;
+        }
+
+        /* Setup a rect for the tmp surface. */
+        rect.x = 0;
+        rect.y = 0;
+        rect.w = to->w;
+        rect.h = to->h;
+
+        /* Do a scaled_blit from the source to the temporary surface. */
+        scaled_blit(source, from, tmp, &rect);
+
+        /* Do a normal blit from the tmp surface to the final dest, temporarily
+         * setting Zoom factor to 1 to prevent another call into
+         * scaled_blit(). */
+        o_zoom = Zoom;
+        Zoom = 1;
+        screenBlit(tmp, &rect, to);
+        Zoom = o_zoom;
+
+        /* Free the tmp surface. */
+       SDL_FreeSurface(tmp);        
+}
+
+static void scaled_blit(SDL_Surface * source, SDL_Rect * from,
+                       SDL_Surface * dest, SDL_Rect * to)
+{
+       int dpitch, spitch;
+
+       assert(Zoom > 0);
+
+       /* This is not a general-purpose blitting routine. If the source and
+         * destination surfaces don't have the same format then use a hack to
+         * workaround it. */
+       if (source->format->BitsPerPixel != dest->format->BitsPerPixel
+            || source->format->Amask != dest->format->Amask
+                ) {
+                scale_then_blit_normal(source, from, dest, to);
+                return;
+        }
+        
+       to->w /= Zoom;
+       to->h /= Zoom;
+
+       dpitch = dest->pitch / dest->format->BytesPerPixel;
+       spitch = source->pitch / source->format->BytesPerPixel;
+
+       if (SDL_LockSurface(dest) < 0)
+               return;
+
+       switch (dest->format->BitsPerPixel) {
+       case 32:
+               scaled_blit_32bpp(source, from, dest, to, spitch, dpitch);
+               break;
+       case 16:
+               scaled_blit_16bpp(source, from, dest, to, spitch, dpitch);
+               break;
+       case 8:
+               scaled_blit_8bpp(source, from, dest, to, spitch, dpitch);
+               break;
+       default:
+               assert(0);
+               break;
+       }
+
+       SDL_UnlockSurface(dest);
+}
+
+void screenBlit(SDL_Surface * source, SDL_Rect * from, SDL_Rect * to)
+{
+       /* Clipping is really only needed for wave sprites right now. If the
+        * following proves to be too expensive on slow machines... */
+       if (to) {
+               SDL_Rect _to = *to;
+               SDL_SetClipRect(Screen, &_to);
+               if (Zoom > 1) {
+
+                        // Clients are allowed to pass a NULL from rect,
+                        // indicating they want to blit the whole source
+                        // area. But the scaled blits require a non-NULL
+                        // from rect.
+                        SDL_Rect _from;
+                        if (from == NULL) {
+                                _from.x = 0;
+                                _from.y = 0;
+                                _from.w = source->w;
+                                _from.h = source->h;
+                                from = &_from;
+                        }
+
+                       scaled_blit(source, from, Screen, &_to);
+                } else {
+                       if (SDL_BlitSurface(source, from, Screen, &_to) < 0)
+                               perror_sdl("SDL_BlitSurface");
+               }
+               SDL_SetClipRect(Screen, 0);
+       } else {
+               SDL_SetClipRect(Screen, to);
+               if (SDL_BlitSurface(source, from, Screen, NULL) < 0)
+                       perror_sdl("SDL_BlitSurface");
+               SDL_SetClipRect(Screen, 0);
+       }
+}
+
+int screenWidth(void)
+{
+       return Screen->w;
+}
+
+int screenHeight(void)
+{
+       return Screen->h;
+}
+
+SDL_PixelFormat *screenFormat(void)
+{
+       return Screen->format;
+}
+
+void screenFlash(SDL_Rect * rect, int mdelay, Uint32 color)
+{
+       screenFill(rect, color);
+       screenUpdate(rect);
+       //usleep(mdelay * 1000);
+        SDL_Delay(mdelay);
+}
+
+void screenPrint(SDL_Rect * rect, int flags, const char *fmt, ...)
+{
+       va_list args;
+       int i;
+       int x = rect->x;
+       int y = rect->y;
+       int alen, slen, stop;
+
+        /* Print the string to a buffer. */
+       va_start(args, fmt);
+       vsnprintf(screen_buf, sizeof(screen_buf), fmt, args);
+       va_end(args);
+
+       slen = strlen(screen_buf);
+        alen = asciiStrlen(screen_buf);
+        stop = rect->x + (rect->w * ASCII_W);
+
+       /* If painting on the border then first fill the line with the border
+         * image. */
+       if (flags & SP_ONBORDER) {
+               for (x = rect->x; x < rect->x + rect->w; x += BORDER_W)
+                       sprite_paint(FrameSprites[FRAME_HORZ], 0, x, rect->y);
+       }
+
+        /* Calculate offset for center and right-justified cases */
+       if (flags & SP_CENTERED) {
+               int w = alen * ASCII_W;
+               if (w > rect->w) {
+                       w = rect->w;
+               }
+               x = (rect->w - w) / 2 + rect->x;
+       } else if (flags & SP_RIGHTJUSTIFIED) {
+               int w = alen * ASCII_W;
+               if (w > rect->w) {
+                       w = rect->w;
+               }
+               x = (rect->w - w) + rect->x;
+       }
+
+       /* If painting on the border, then paint the right stub 
+         * to the left of the text. */
+       if (flags & SP_ONBORDER) {
+               sprite_paint(FrameSprites[FRAME_ENDR], 0, x - BORDER_W, rect->y);
+        }
+
+        /* Paint the characters until we run out or hit the end of the
+         * region. */
+       for (i = 0; i < slen && x < stop; i++) {
+
+                if (asciiPaint(screen_buf[i], x, y, Screen)) {
+
+                        /* Move right. */
+                        x += ASCII_W;
+                }
+       }
+
+       /* If painting on the border, then paint the left stub 
+         * to the right of the text. */
+       if (flags & SP_ONBORDER) {
+               sprite_paint(FrameSprites[FRAME_ENDL], 0, x, rect->y);
+        }
+}
+
+void screen_repaint_frame(void)
+{
+       int i;
+
+       // First draw the top and bottom horizontal bars. Leave gaps for the
+       // sky and wind windows. Originally I went ahead and painted over them
+       // here, relying on their update routines to black out their
+       // backgrounds. But when I started using the tall/short mode for the
+       // status window I found that this was no longer good enough. The
+       // backgrounds of these windows tended to flash when switching mode.
+
+       // Draw the top bar from the top left corner to the sky window.
+       for (i = 0; i < SKY_X - BORDER_W; i += BORDER_W)
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i, 0);
+
+       // Draw the top bar from the sky window to the left edge of the status
+       // window's title.
+       for (i = SKY_X + SKY_W + BORDER_W; i < STAT_X; i += BORDER_W)
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i, 0);
+
+       // Draw the bottom of the map from the left edge to the wind window.
+       for (i = 0; i < (int) (WIND_X - BORDER_W); i += BORDER_W)
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i, MAP_X + MAP_H);
+
+       // Draw the bottom of the map from the wind window to the left edge of
+       // the console window.
+       for (i = WIND_X + WIND_W + BORDER_W; i < CONS_X - BORDER_W;
+            i += BORDER_W)
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i, MAP_X + MAP_H);
+
+       // Draw the bar across the bottom of the screen.
+       for (i = 0; i < SCREEN_W; i += BORDER_W)
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i, SCREEN_H - BORDER_H);
+
+       // Next draw the bottom of the status and food/gold window.
+       for (i = (MAP_X + MAP_W); i < SCREEN_W; i += BORDER_W) {
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i, STAT_Y + status_get_h());
+               sprite_paint(FrameSprites[FRAME_HORZ], 0, i,
+                           foogod_get_y() + FOOGOD_H);
+       }
+
+       // Next rough in all the vertical lines.
+       for (i = 0; i < SCREEN_H; i += BORDER_H) {
+               sprite_paint(FrameSprites[FRAME_VERT], 0, 0, i);
+               sprite_paint(FrameSprites[FRAME_VERT], 0, MAP_X + MAP_W, i);
+               sprite_paint(FrameSprites[FRAME_VERT], 0, SCREEN_W - BORDER_W, i);
+       }
+
+       // Now paint the four corner pieces
+       sprite_paint(FrameSprites[FRAME_ULC], 0, 0, 0);
+       sprite_paint(FrameSprites[FRAME_URC], 0, SCREEN_W - BORDER_W, 0);
+       sprite_paint(FrameSprites[FRAME_LLC], 0, 0, SCREEN_H - BORDER_H);
+       sprite_paint(FrameSprites[FRAME_LRC], 0, SCREEN_W - BORDER_W,
+                   SCREEN_H - BORDER_H);
+
+       // Then all the right-facing tee-joints
+       sprite_paint(FrameSprites[FRAME_TR], 0, 0, MAP_Y + MAP_H);
+       sprite_paint(FrameSprites[FRAME_TR], 0, MAP_X + MAP_W,
+                   STAT_Y + status_get_h());
+       sprite_paint(FrameSprites[FRAME_TR], 0, MAP_X + MAP_W,
+                   foogod_get_y() + FOOGOD_H);
+
+       // Then all the left-facing tee-joints
+       sprite_paint(FrameSprites[FRAME_TL], 0, MAP_X + MAP_W, MAP_Y + MAP_H);
+       sprite_paint(FrameSprites[FRAME_TL], 0, SCREEN_W - BORDER_W,
+                   STAT_Y + status_get_h());
+       sprite_paint(FrameSprites[FRAME_TL], 0, SCREEN_W - BORDER_W,
+                   foogod_get_y() + FOOGOD_H);
+
+       // Then the downward and upward-facing tee-joints
+       sprite_paint(FrameSprites[FRAME_TD], 0, MAP_X + MAP_W, 0);
+       sprite_paint(FrameSprites[FRAME_TU], 0, MAP_X + MAP_W, SCREEN_H - BORDER_H);
+
+       // And then the stubs around the sky section
+       sprite_paint(FrameSprites[FRAME_ENDR], 0, SKY_X - BORDER_W, 0);
+       sprite_paint(FrameSprites[FRAME_ENDL], 0, SKY_X + SKY_W, 0);
+
+       // And finally stubs around the wind section
+       sprite_paint(FrameSprites[FRAME_ENDR], 0, WIND_X - BORDER_W, MAP_X + MAP_H);
+       sprite_paint(FrameSprites[FRAME_ENDL], 0, WIND_X + WIND_W, MAP_X + MAP_H);
+
+        // And some stubs around the status title section
+       sprite_paint(FrameSprites[FRAME_ENDR], 0, STAT_X, 0);
+       sprite_paint(FrameSprites[FRAME_ENDL], 0, STAT_X + STAT_W - BORDER_W,   0);
+
+       screenUpdate(0);
+
+}
+
+SDL_Surface *screenCreateSurface(int w, int h)
+{
+       SDL_Surface *surf = NULL, *tmp;
+
+       tmp = SDL_CreateRGBSurface(Screen->flags,
+                                  w, h,
+                                  Screen->format->BitsPerPixel,
+                                  Screen->format->Rmask,
+                                  Screen->format->Gmask,
+                                  Screen->format->Bmask,
+                                  Screen->format->Amask);
+
+       // surf->format->palette = Screen->format->palette;
+
+       if (tmp == NULL) {
+               perror_sdl("SDL_CreateRGBSurface");
+               return NULL;
+       }
+
+       surf = SDL_DisplayFormat(tmp);
+       SDL_FreeSurface(tmp);
+
+       if (surf == NULL) {
+               perror_sdl("SDL_DisplayFormat");
+               return NULL;
+       }
+
+       if (surf->format->palette) {
+               SDL_SetColorKey(surf, SDL_SRCCOLORKEY,
+                               SDL_MapRGB(surf->format, 0xFF, 0x00, 0xFF));
+       }
+
+       return surf;
+}
+
+void screenCopy(SDL_Rect * from, SDL_Rect * to, SDL_Surface * dest)
+{
+       if (SDL_BlitSurface(Screen, from, dest, to) < 0)
+               perror_sdl("SDL_BlitSurface");
+
+        assert(from);
+        assert(dest);
+
+        SDL_Rect _from = *from;
+
+        if (Zoom > 1) {
+                // Clients are allowed to pass a NULL 'to' rect,
+                // indicating they want to blit the whole dest
+                // area. But the scaled blits require a non-NULL
+                // 'to' rect.
+                SDL_Rect _to;
+                if (to == NULL) {
+                        _to.x = 0;
+                        _to.y = 0;
+                        _to.w = dest->w;
+                        _to.h = dest->h;
+                        to = &_to;
+                }
+                scaled_blit(Screen, &_from, dest, to);
+        } else {
+                if (SDL_BlitSurface(Screen, &_from, dest, to) < 0)
+                        perror_sdl("SDL_BlitSurface");
+        }
+}
+
+void screenShade(SDL_Rect * area, unsigned char amount)
+{
+       SDL_Surface *shade;
+
+       assert(area->w <= SHADER_W);
+       assert(area->h <= SHADER_H);
+
+       if (amount == 0)
+               return;
+
+       if (Screen->format->BitsPerPixel == 8) {
+               shade = Shaders[MAX_SHADER - (amount * MAX_SHADER) / 255];
+       } else {
+               shade = Shaders[0];
+               SDL_SetAlpha(shade, SDL_SRCALPHA, amount);
+       }
+       screenBlit(shade, NULL, area);
+}
+
+void screenHighlightColored(SDL_Rect * area, Uint32 color)
+{
+        SDL_Rect edge;
+
+        // ---------------------------------------------------------------------
+        // Top edge
+        // ---------------------------------------------------------------------
+
+        edge.x = area->x;
+        edge.y = area->y;
+        edge.w = area->w;
+        edge.h = HIGHLIGHT_THICKNESS;
+
+        screenFill(&edge, color);
+
+        // ---------------------------------------------------------------------
+        // Bottom edge
+        // ---------------------------------------------------------------------
+
+        edge.x = area->x;
+        edge.y = area->y + (area->h/Zoom) - HIGHLIGHT_THICKNESS;
+        edge.w = area->w;
+        edge.h = HIGHLIGHT_THICKNESS;
+
+        screenFill(&edge, color);
+
+        // ---------------------------------------------------------------------
+        // Left edge
+        // ---------------------------------------------------------------------
+
+        edge.x = area->x;
+        edge.y = area->y;
+        edge.w = HIGHLIGHT_THICKNESS;
+        edge.h = area->h;
+
+        screenFill(&edge, color);
+
+        // ---------------------------------------------------------------------
+        // Right edge
+        // ---------------------------------------------------------------------
+
+        edge.x = area->x + (area->w/Zoom) - HIGHLIGHT_THICKNESS;
+        edge.y = area->y;
+        edge.w = HIGHLIGHT_THICKNESS;
+        edge.h = area->h;
+
+        screenFill(&edge, color);
+}
+
+void screenHighlight(SDL_Rect *area)
+{
+        screenHighlightColored(area, White);
+}
+
+int screenLock(void)
+{
+       return SDL_LockSurface(Screen);
+}
+
+void screenUnlock(void)
+{
+       SDL_UnlockSurface(Screen);
+}
+
+/* assumes the pixel value is gotten from screenMapRGB() i.e. safe! */
+void screenSetPixel(int x, int y, Uint32 color)
+{
+       Uint8 *pix = (Uint8*)(Screen->pixels);
+       pix += y * Screen->pitch + x * Screen->format->BytesPerPixel;
+
+       switch (Screen->format->BytesPerPixel) {
+       case 4: *(Uint32*)pix = (Uint32)color; break;
+       case 2: *(Uint16*)pix = (Uint16)color; break;
+       case 1: *(Uint8 *)pix = (Uint8)color;  break;
+       default: assert(0); break;
+       }
+}
+
+Uint32 screenMapRGB(Uint8 red, Uint8 grn, Uint8 blu)
+{
+       return SDL_MapRGB(Screen->format, red, grn, blu);
+}
+
+void screenZoomOut(int factor)
+{
+       if (factor)
+               Zoom *= factor;
+}
+
+void screenZoomIn(int factor)
+{
+       if (factor)
+               Zoom /= factor;
+}
+
+void screenCapture(char *fname, SDL_Rect *rect)
+{
+        png_structp png_ptr = 0;
+        png_infop info_ptr = 0;
+        Uint32 *spix = 0;
+        Uint8 *row_pointer = 0;
+        int si, spitch;
+
+        /* Open the destination file. */
+        FILE *fp = fopen(fname, "wb");
+        if (!fp) {
+                return;
+        }
+
+        /* Setup PNG for writing. */
+        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 
+                                          (png_voidp)0,
+                                          0, 
+                                          0);
+        if (!png_ptr) {
+                goto done;
+                return;
+        }
+
+        info_ptr = png_create_info_struct(png_ptr);
+        if (!info_ptr) {
+                goto done;
+        }
+        
+        if (setjmp(png_jmpbuf(png_ptr))) {
+                warn("screenCapture: PNG error!\n");
+                goto done;
+        }
+
+        png_init_io(png_ptr, fp);
+
+        /* Setup the image header. */
+        png_set_IHDR(png_ptr, info_ptr,
+                     MAP_W,
+                     MAP_H,
+                     8,
+                     PNG_COLOR_TYPE_RGB,
+                     PNG_INTERLACE_NONE,
+                     PNG_COMPRESSION_TYPE_DEFAULT,
+                     PNG_FILTER_TYPE_DEFAULT);
+
+        /* Write the header. */
+        png_write_info(png_ptr, info_ptr);
+
+       /* TODO: if Screen is not in correct format, convert it to
+        *       a suitable temp surface (maybe a row at the time?).
+        */
+        assert(Screen->format->BytesPerPixel==4);
+        /* Grab the screen pixels. */
+        spix = (Uint32*)Screen->pixels;
+        spitch = Screen->pitch / Screen->format->BytesPerPixel;
+
+        /* Allocate the row buffer. I copy pixels to an intermediate row buffer
+         * so that I can handle different pixel formats (eg, RGBA vs ARGB,
+         * etc). */
+        row_pointer = (Uint8*)malloc(rect->w * 3);
+        assert(row_pointer);
+
+        for (int y = 0; y < rect->h; y++) {
+
+                /* Copy the SDL pixels into the intermediate buffer. PNG
+                 * expects pixels in RGB order. */
+                Uint8 *dpix = row_pointer;
+                for (int x = 0; x < rect->w; x++) {
+                        si = (y + rect->y) * spitch + (x + rect->x);
+                        *dpix++ = ((spix[si] & Screen->format->Rmask) 
+                                   >> Screen->format->Rshift);
+                        *dpix++ = ((spix[si] & Screen->format->Gmask) 
+                                   >> Screen->format->Gshift);
+                        *dpix++ = ((spix[si] & Screen->format->Bmask) 
+                                   >> Screen->format->Bshift);
+                }
+
+                /* Write the row to PNG. */
+                png_write_row(png_ptr, row_pointer);
+        }
+
+        png_write_end(png_ptr, 0);
+
+ done:
+        if (row_pointer) {
+                free(row_pointer);
+        }
+
+        if (png_ptr) {
+                png_destroy_write_struct(&png_ptr, &info_ptr);
+        }
+        
+        fclose(fp);
+
+}
diff --git a/src/screen.h b/src/screen.h
new file mode 100644 (file)
index 0000000..b71ea79
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef screen_h
+#define screen_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include <SDL.h>
+
+#define MAX_SHADE 0
+#define MIN_SHADE 255
+
+extern Uint32 Blue;
+extern Uint32 Black;
+extern Uint32 White;
+extern Uint32 Green;
+extern Uint32 Red;
+extern Uint32 Yellow;
+extern Uint32 Cyan;
+extern Uint32 Magenta;
+extern Uint32 Gray;
+
+extern Uint32 TextRed;
+extern Uint32 TextGreen;
+extern Uint32 TextBlue;
+extern Uint32 TextYellow;
+extern Uint32 TextCyan;
+extern Uint32 TextMagenta;
+
+extern SDL_Color fontWhite;
+extern SDL_Color fontBlack;
+
+#define SP_CENTERED (1 << 0)
+#define SP_INVERTED (1 << 1)
+#define SP_RIGHTJUSTIFIED (1 << 2)
+#define SP_ONBORDER (1 << 4)
+
+#define SP_ESC '^'
+#define SP_CLR 'c'
+
+extern int screenInit(void);
+extern void screenErase(SDL_Rect * rect);
+extern void screenUpdate(SDL_Rect * rect);
+extern void screenFill(SDL_Rect * rect, Uint32 color);
+extern void screenBlit(SDL_Surface * source, SDL_Rect * from,
+                       SDL_Rect * to);
+extern int screenWidth(void);
+extern int screenHeight(void);
+extern SDL_PixelFormat *screenFormat(void);
+extern void screenFlash(SDL_Rect * rect, int mdelay, Uint32 color);
+extern void screenPrint(SDL_Rect * rect, int flags, const char *fmt, ...);
+
+// Added for missile animations
+extern SDL_Surface *screenCreateSurface(int w, int h);
+extern void screenCopy(SDL_Rect * from, SDL_Rect * to,
+                       SDL_Surface * dest);
+extern void screenShade(SDL_Rect * area, unsigned char amount);
+extern void screenHighlight(SDL_Rect * area);
+extern void screenHighlightColored(SDL_Rect * area, Uint32 color);
+
+// Added for peer effect
+extern int screenLock(void);
+extern void screenUnlock(void);
+extern void screenSetPixel(int x, int y, Uint32 color);
+extern Uint32 screenMapRGB(Uint8 red, Uint8 grn, Uint8 blu);
+extern void screenZoomOut(int factor);
+extern void screenZoomIn(int factor);
+
+extern void screen_fade_surface(SDL_Surface * surf, int transparency);
+extern void screen_repaint_frame(void);
+extern void screenCapture(char *fname, SDL_Rect *rect);
+
+END_DECL
+
+#endif
diff --git a/src/screen_dims.h b/src/screen_dims.h
new file mode 100644 (file)
index 0000000..47667b9
--- /dev/null
@@ -0,0 +1,25 @@
+/* $Id: screen_dims.h,v 1.2 2007/12/05 01:53:23 gmcnutt Exp $
+ *
+ * Copyright (C) 2006 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* Enumerate the supported screen dimensions and map them to the map viewer
+ * width (in tiles). Note that the usual #ifndef include guards are not
+ * desirable for this file, nor are C++-style '//' comments. */
+ADD_SCREEN_DIM("640x480", 11)
+ADD_SCREEN_DIM("800x480", 12)
+ADD_SCREEN_DIM("1280x960", MAX_MAP_SIZE)
diff --git a/src/session.c b/src/session.c
new file mode 100644 (file)
index 0000000..82d785b
--- /dev/null
@@ -0,0 +1,912 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "session.h"
+
+#include "../config.h"
+#include "character.h"
+#include "object.h"
+#include "sprite.h"
+#include "terrain.h"
+#include "place.h"
+#include "images.h"
+#include "Party.h"
+#include "ptable.h"
+#include "file.h"
+#include "player.h"
+#include "sky.h"
+#include "map.h"
+#include "cursor.h"
+#include "Arms.h"
+#include "Field.h"
+#include "occ.h"
+#include "species.h"
+#include "sched.h"
+#include "Reagent.h"
+#include "screen.h"
+#include "vehicle.h"
+#include "formation.h"
+#include "combat.h"
+#include "Container.h"
+#include "clock.h"
+#include "wind.h"
+#include "foogod.h"
+#include "terrain_map.h" // dbg
+#include "dtable.h"
+#include "wq.h"
+#include "cfg.h"
+#include "skill.h"
+#include "skill_set.h"
+
+#include <assert.h>
+#include <ctype.h>              // isspace()
+#include <errno.h>
+#include <kern.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <SDL_image.h>
+#include <unistd.h>
+#include <sys/stat.h>
+//#include <sys/mman.h>
+#include <stdarg.h>
+#include <SDL.h>            // for SDL_GetTicks()
+
+//#include "scheme.h"
+#include "scheme-private.h"
+
+struct data_obj_entry {
+        struct list list;
+        void *obj;
+        int refcount;
+        void (*dtor)(void*);
+        void (*save)(save_t *save, void *obj);
+        void (*start)(void *obj);
+};
+
+struct session_hook_entry {
+        struct list list;
+        struct closure *proc;
+        pointer args;
+};
+
+struct session *Session = 0;
+int load_errs = 0;
+int save_errs = 0;
+
+static void session_init_hooks(struct session *session);
+static void session_cleanup_hooks(struct session *session);
+static void session_cleanup_queries(struct session *session);
+
+/* Redefine the session hook macro to turn its arg into a string, then #include
+ * the list of hooks directly into an array of string pointers. */
+#undef SESSION_DECL_HOOK
+#define SESSION_DECL_HOOK(id) #id
+static const char * session_hook_str[] = {
+#       include "session_hooks.h"
+};
+
+static char session_last_error[128] = { 0 };
+
+void load_err(const char *fmt, ...)
+{
+        load_err_inc();
+        warn("load_err: ");
+        va_list args;
+        va_start(args, fmt);
+        vwarn(fmt, args);
+        va_end(args);
+        warn("\n");
+
+        /* duplicate it to the global string error */
+        va_start(args, fmt);
+        vsnprintf(session_last_error, sizeof(session_last_error),
+                  fmt, args);
+        va_end(args);
+        
+}
+
+void rt_err(const char *fmt, ...)
+{
+        load_err_inc();
+        warn("runtime error: ");
+        va_list args;
+        va_start(args, fmt);
+        vwarn(fmt, args);
+        va_end(args);
+        warn("\n");
+
+        consolePrint("\n*** script error! ***\n");
+}
+
+
+
+void save_err(const char *fmt, ...)
+{
+        save_err_inc();
+        warn("save_err: ");
+        va_list args;
+        va_start(args, fmt);
+        vwarn(fmt, args);
+        va_end(args);
+        warn("\n");
+}
+
+static void data_obj_entry_unref(struct data_obj_entry *entry)
+{
+        assert(entry->refcount >= 1);
+        entry->refcount--;
+        if (! entry->refcount) {
+                free(entry);
+        }
+}
+
+void *session_add(struct session *session, void *obj, 
+                  void (*dtor)(void *),
+                  void (*save)(save_t *, void *),
+                  void (*start)(void *)
+        )
+{
+        struct data_obj_entry *entry;
+
+        entry = (struct data_obj_entry *)malloc(sizeof(*entry));
+        assert(entry);
+        list_init(&entry->list);
+        entry->obj = obj;
+        entry->refcount = 1;
+        entry->dtor = dtor;
+        entry->save = save;
+        entry->start = start;
+
+        /* Note: it's important to always add to the tail of the list. This
+         * ensures that the objects in a session will be saved in the same
+         * order they are loaded. The order can matter in certain cases (e.g.,
+         * include files loaded at the front of the session). */
+        list_add_tail(&session->data_objects, &entry->list);
+        return entry;
+}
+
+void session_rm(struct session *session, void *handle)
+{
+        struct data_obj_entry *entry;
+        entry = (struct data_obj_entry *)handle;
+        list_remove(&entry->list);
+        data_obj_entry_unref(entry);
+}
+
+static void session_save_crosshair(save_t *save, struct session *session)
+{
+        save->write(save, "(kern-set-crosshair %s)\n", 
+                session->crosshair_type->getTag());
+}
+
+static void session_save_damage_sprite(save_t *save, struct session *session)
+{
+        save->write(save, "(kern-set-damage-sprite %s)\n", 
+                    sprite_get_tag(session->damage_sprite));
+}
+
+static void session_save_clock(save_t *save, struct session *session)
+{
+        save->write(save, "(kern-set-clock %d %d %d %d %d %d)\n",
+                session->clock.year,
+                session->clock.month,
+                session->clock.week,
+                session->clock.day,
+                session->clock.hour,
+                session->clock.min);
+}
+
+static void session_save_time_accel(save_t *save, struct session *session)
+{
+        save->write(save, "(kern-set-time-accel %f)\n",
+                    session->time_accel);
+}
+
+static void session_save_turn_count(save_t *save, struct session *session)
+{
+        save->write(save, "(kern-set-turn-count %d)\n", 
+                    session->turn_count);
+}
+
+struct session *session_new(void *interp)
+{
+        struct session *session = (struct session*)calloc(1, sizeof(*session));
+        assert(session);
+        list_init(&session->data_objects);        
+        list_init(&session->terrains);
+        session->interp = interp;
+        session->status_mode = ShowParty;
+        session->los = "angband";
+        sky_init(&session->sky);
+        magic_init(&session->magic);
+        list_init(&session->tickq);
+        list_init(&session->turnq);
+        node_init(&session->sched_chars);
+        list_init(&session->blenders);
+        list_init(&session->skills);
+        list_init(&session->skill_sets);
+        session->time_accel = 1;
+        session_init_hooks(session);
+        return session;
+}
+
+void session_del(struct session *session)
+{
+        struct list *elem;
+        struct data_obj_entry *entry;
+
+        /* ref the player party so we can control when it gets destroyed, so we
+         * know when to zero out the global */
+        if (session->player) {
+                obj_inc_ref(session->player);
+        }
+
+        freezer_del();
+
+        /* stop sound so sound entries will be purged */
+        sound_haltall();
+        
+        /* Cleanup the data objects */
+        elem = session->data_objects.next;
+        int count = 0;
+        while (elem != &session->data_objects) {
+                entry = list_entry(elem, struct data_obj_entry, list);
+                elem = elem->next;
+                entry->refcount++; /* keep a ref while dtor runs */
+                entry->dtor(entry->obj);
+                data_obj_entry_unref(entry); /* now release ref */
+                count++;
+        }
+
+        /* Cleanup the terrains */
+        elem = session->terrains.next;
+        while (elem != &session->terrains) {
+                struct terrain *terrain = list_entry(elem, struct terrain, 
+                                                     session_list);
+                elem = elem->next;
+                list_remove(&terrain->session_list);
+                terrain_del(terrain);
+        }
+
+        if (session->crosshair)
+                obj_dec_ref(session->crosshair);
+        sky_end_session(&session->sky);
+        magic_end_session(&session->magic);
+        if (session->ptable)
+                ptable_del(session->ptable);
+        if (session->dtable)
+                dtable_del(session->dtable);
+
+        /* Clean up the turn work queue */
+        elem = session->turnq.next;
+        while (elem != &session->turnq) {
+                struct wq_job *job = list_entry(elem, struct wq_job, list);
+                elem = elem->next;
+                wq_job_del(job);
+        }
+
+        /* Clean up the tick work queue */
+        elem = session->tickq.next;
+        while (elem != &session->tickq) {
+                struct wq_job *job = list_entry(elem, struct wq_job, list);
+                elem = elem->next;
+                wq_job_del(job);
+        }
+
+        session_cleanup_hooks(session);
+        session_cleanup_queries(session);
+
+        /* Ensure that nothing is referencing the player party (except perhaps
+         * its vehicle, which will be cleaned up with the party). Note: if
+         * we're aborting a failed load then the player may not exist. */
+        if (session->player) {
+                assert((1==session->player->refcount)
+                       || ((2==session->player->refcount)
+                           && session->player->getVehicle()));
+
+                /* Now zilch the global player party */
+                obj_dec_ref(session->player);
+                session->player = 0;
+        }
+
+        /* clean up the list of skills */
+        elem = session->skills.next;
+        while (elem != &session->skills) {
+                struct skill *skill = list_entry(elem, struct skill, list);
+                elem = elem->next;
+                list_remove(&skill->list);
+                skill_unref(skill);
+        }
+
+        /* clean up the list of skill sets */
+        elem = session->skill_sets.next;
+        while (elem != &session->skill_sets) {
+                struct skill_set *skset 
+                        = list_entry(elem, struct skill_set, list);
+                elem = elem->next;
+                list_remove(&skset->list);
+                skill_set_unref(skset);
+        }
+
+        /* cleanup the interpreter */
+        if (session->interp) {
+                scheme_deinit((scheme*)session->interp);
+                free(session->interp);
+        }
+
+        /* Check for memory leaks. Character dtors should have removed
+         * themselves from the sched_chars list if they were on it. */
+        if (! node_list_empty(&session->sched_chars)) {
+                fprintf(stderr, 
+                        "warn: session sched_chars list non-empty\n");
+        }
+
+        free(session);
+}
+
+int session_load(char *filename)
+{
+        scheme *sc;
+        FILE *file = NULL;
+        struct session *old_session;
+        int t1, t2;
+        struct list *elem;
+
+        /* Remember the old session in case we have to bail out. */
+        old_session = Session;
+
+        /* Clear any leftover load errors. */
+        load_err_clear();
+
+        /* Open the load file (this might come from the include dir or the save
+         * dir, so the caller must pass in the complete pathname). */
+        file = file_open(filename, "r");
+        if (! file) {
+                load_err("could not open script file '%s' for reading: %s",
+                           filename, strerror(errno));
+                return -1;
+        }
+
+        /* Create a new interpreter. */
+        if (! (sc = kern_init())) {
+                load_err("could not create interpreter");
+                fclose(file);
+                return -1;
+        }
+
+        /* Create a new current sesssion. */
+        Session = session_new(sc);
+        assert(Session);
+
+        /* Load the file and close it. */
+        t1 = SDL_GetTicks();
+        scheme_load_named_file(sc, file, filename);
+        t2 = SDL_GetTicks();
+        info("%d ms to load\n", (t2 - t1));
+
+        fclose(file);
+
+        /* Check for any errors during loading. */
+        if (load_err_any()) {
+
+                /* Check if the problem is version obsolescence. */
+                if (Session->major < MIN_SCRIPT_MAJOR
+                    || Session->minor < MIN_SCRIPT_MINOR
+                    || Session->release < MIN_SCRIPT_RELEASE) {
+                        snprintf(session_last_error,
+                                 sizeof(session_last_error),
+                                 "The save file format is version %u.%u.%u, "
+                                 "but this release of the engine requires "
+                                 "version %u.%u.%u or better. You might try "
+                                 "an older version of the engine with this "
+                                 "file.",
+                                 Session->major, Session->minor, 
+                                 Session->release, MIN_SCRIPT_MAJOR, 
+                                 MIN_SCRIPT_MINOR, MIN_SCRIPT_RELEASE);
+                }
+
+                session_del(Session);
+                Session = old_session;
+                return -1;
+        }
+
+        /* Check for stuff that needs to be there for the new session to
+         * work. Start with some globals. */
+        if (! Session->crosshair_type) {
+                load_err("no crosshair object (use kern-set-crosshair)");
+        } else {
+                Session->crosshair = new Cursor();
+                Session->crosshair->init(Session->crosshair_type);
+                obj_inc_ref(Session->crosshair);
+        }
+        if (! Session->damage_sprite) {
+                load_err("no damage sprite (use kern-set-cursor)");
+        }
+        if (! Session->clock.set) {
+                load_err("clock not set (use kern-set-clock)");
+        }
+        if (! Session->ptable) {
+                load_err("passability table not set (use kern-set-ptable)");
+        }
+        if (! Session->dtable) {
+                load_err("diplomacy table not set (use kern-set-dtable)");
+        }
+
+        if (! Session->player) {
+                load_err("no player party");
+        }
+        if (Session->player->getSize() == 0) {
+                load_err("player party empty");
+        }
+
+
+        /* Check for any errors. If there are any then destroy the new session
+         * and return the old one. Otherwise destroy the old session and return
+         * the new one. */
+        if (load_err_any()) {
+                session_del(Session);
+                scheme_deinit(sc);
+                free(sc);
+                Session = old_session;
+                return -1;
+        }
+
+        /* No errors, so it's safe to delete the old session. */
+        if (old_session) {
+                session_del(old_session);
+        }
+
+        combat_reset_state();
+        
+        Session->player->startSession();
+
+        /* Now setup stuff that with known defaults. */
+        statusSetMode(Session->status_mode);
+        mapSetLosStyle(Session->los);
+
+        /* Run through all the objects in the world, initializing their
+         * effects */
+        list_for_each(&Session->data_objects, elem) {
+                struct data_obj_entry *entry;
+                entry = list_entry(elem, struct data_obj_entry, list);
+                if (entry->start) {
+                        entry->start(entry->obj);
+                }
+        }     
+               /* need to start all the objects in the freezer too */
+               freezer_start_contents();
+
+        sky_start_session(&Session->sky, 
+                          NULL != Place && ! Place->underground);
+
+
+        // This is also called from place_enter(), which is called when the
+        // game first starts up but apparently not necessarily on a
+        // reload. Should be safe to call more than once, I think.
+        //session_synch_sched_chars(Session);
+        /* Paint all the windows for the first time in the new session. */
+        screenErase(0);
+       screen_repaint_frame();
+       foogodRepaint();
+       consoleRepaint();
+       statusRepaint();
+
+        /* show the sun, moon and wind status */
+        sky_advance(&Session->sky, 
+                    NULL != Place && ! Place->underground);
+
+        windRepaint();
+
+        session_run_hook(Session, session_start_hook, "p", Session->player);
+        
+        return 0;
+}
+
+#define SAVE_INDENT_WIDTH 2
+static void save_vwrite(struct save *save, const char *fmt, va_list args)
+{
+        if (save->indent)
+                fprintf(save->file, "%*c", save->indent, ' ');
+        vfprintf(save->file, fmt, args);
+}
+
+static void save_write(save_t *save, const char *fmt, ...)
+{
+        va_list args;
+        va_start(args, fmt);
+        save_vwrite(save, fmt, args);
+        va_end(args);        
+}
+
+static void save_append(save_t *save, const char *fmt, ...)
+{
+        va_list args;
+        va_start(args, fmt);
+        vfprintf(save->file, fmt, args);
+        va_end(args);    
+}
+
+static void save_enter(save_t *save, const char *fmt, ...)
+{
+        va_list args;
+        va_start(args, fmt);
+        save_vwrite(save, fmt, args);
+        va_end(args);
+        save->indent += SAVE_INDENT_WIDTH;
+}
+
+static void save_exit(save_t *save, const char *fmt, ...)
+{
+        va_list args;
+        va_start(args, fmt);
+        save->indent -= SAVE_INDENT_WIDTH;
+        assert(save->indent >= 0);
+        save_vwrite(save, fmt, args);
+        va_end(args);        
+}
+
+save_t *save_new(FILE *file)
+{
+        save_t *save;
+
+        save = (save_t*)calloc(1, sizeof(*save));
+        assert(save);
+
+        save->file = file;
+       // SAM: Where is indent ever initialized???
+        save->write = save_write;
+        save->enter = save_enter;
+        save->exit = save_exit;
+        save->append = save_append;
+
+        return save;
+}
+
+void save_del(save_t *save)
+{
+        if (save->indent) {
+                warn("save file indentation left at %d; possible "\
+                     "unterminated block in save file", save->indent);
+        }
+        fflush(save->file);
+        free(save);
+}
+
+int session_save(char *fname)
+{
+        FILE *file = 0;
+        struct list *elem;
+        save_t *save;
+        int object_saves = 0;
+
+        file = file_open_in_save_dir(fname, "w");
+        if (! file) {
+                warn("session_save: could not open %s: %s\n", fname,
+                     file_get_error());
+                return -1;
+        }
+
+        save = save_new(file);
+
+        /* Advance the session ID each time we save so that objects can know
+         * that they need to save themselves. */
+        Session->session_id++;
+        save->session_id = Session->session_id;
+
+        /* Save the header. */
+        save->write(save, ";; %s -- a nazghul session file\n", fname);
+        /* Note: below does not work, and causes false negs with regression
+         * tests: */
+        /* save->write(save, ";; Created %s\n", ctime(&timep)); */
+
+        /* Save the standard file. */
+        save->write(save, ";; Load the standard definitions file\n");
+        save->write(save, "(load \"naz.scm\")\n");
+        save->write(save, "\n");
+
+        /* Write the (new) version */
+        save->write(save, "(kern-script-version \"%s\")\n", PACKAGE_VERSION);
+
+        /* Generate the first part of the progress bar code. Use the number of
+         * data objects which will save themselves, plus the number of load
+         * files, as the limit. */
+        list_for_each(&Session->data_objects, elem) {
+                struct data_obj_entry *entry;
+                entry = list_entry(elem, struct data_obj_entry, list);
+                if (entry->save) {
+                        object_saves++;
+                }
+        }
+
+        save->write(save, ";; Progress bar\n");
+        save->write(save, "(kern-progress-bar-start \"Loading\" %d)\n", 
+                    Session->num_kern_includes + object_saves);
+        
+        /* Generate code to advance the progress bar as each file is loaded. */
+        save->write(save, "(define original-load load)  "
+                    "(define (load file) "
+                    "(kern-progress-bar-advance 1) "
+                    "(original-load file))\n");
+
+        /* Save all the saveable objects. */
+        list_for_each(&Session->data_objects, elem) {
+                struct data_obj_entry *entry;
+                entry = list_entry(elem, struct data_obj_entry, list);
+                if (entry->save) {
+                        entry->save(save, entry->obj);
+                        if (save_err_any()) {
+                                warn("Aborting save to %s due to errors\n", 
+                                     fname);
+                                break;
+                        }
+
+                        /* Generate code to advance the progress bar as each
+                         * object finishes loading. */
+                        save->write(save, "(kern-progress-bar-advance 1)\n");
+                }
+
+        }
+        /* Object freezer */
+        save->write(save, ";;--------------\n");
+        save->write(save, ";; ObjectFreezer\n");
+        save->write(save, ";;--------------\n");
+        freezer_save(save);
+
+        /* Save all the special-case stuff... */
+        save->write(save, ";;--------------\n");
+        save->write(save, ";; Miscellaneous\n");
+        save->write(save, ";;--------------\n");
+        session_save_damage_sprite(save, Session);
+        session_save_crosshair(save, Session);
+        session_save_clock(save, Session);
+        session_save_time_accel(save, Session);
+        session_save_turn_count(save, Session);
+        dtable_save(Session->dtable, save);
+        sky_save(&Session->sky, save);
+        windSave(save);
+
+        /* Save the flags */
+        save->write(save, "(kern-add-reveal %d)\n", Session->reveal.duration);
+        save->write(save, "(kern-add-quicken %d)\n", 
+                    Session->quicken.duration);
+        save->write(save, "(kern-add-time-stop %d)\n", 
+                    Session->time_stop.duration);
+        save->write(save, "(kern-add-magic-negated %d)\n", 
+                    Session->magic_negated.duration);
+        save->write(save, "(kern-add-xray-vision %d)\n", 
+                    Session->xray.duration);
+
+        /* save the work queues */
+        /* NOTE: don't see how we can, since work queue jobs use a void
+         * pointer. We could also require a save callback pointer in the job,
+         * but usually the data is a C pointer which won't be valid on reload,
+         * so I don't know what the save callback can do to help. */
+        /*         session_save_wq(&session->turnq); */
+        /*         session_save_wq(&session->tickq); */
+
+        /* Finish progress bar code */
+        save->write(save, "(kern-progress-bar-finish)\n");
+
+        save_del(save);
+        fclose(file);                
+        return 0;
+}
+
+struct node *session_add_sched_char(struct session *session,
+                                    class Character *npc)
+{
+        struct node *node = node_new(npc);
+        node_add(&session->sched_chars, node);
+        return node;
+}
+
+void session_rm_sched_char(struct node *node)
+{
+        /* beware of doing this while iterationg over the sched_chars list */
+        node_remove(node);
+        node_unref(node);
+}
+
+void session_synch_sched_chars(struct session *session)
+{
+        struct node *node = node_next(&session->sched_chars);
+        while (node != &session->sched_chars) {
+                class Character *npc = (class Character*)node->ptr;
+                node = node_next(node);
+                npc->synchronize();
+                if (npc->isCharmed())
+                        npc->unCharm();
+        }
+}
+
+void session_intro_sched_chars(struct session *session)
+{
+        struct node *node = node_next(&session->sched_chars);
+        while (node != &session->sched_chars) {
+                class Character *npc = (class Character*)node->ptr;
+                npc->introduce();
+                node = node_next(node);
+        }        
+}
+
+static void session_init_hooks(struct session *session)
+{
+        int id;
+
+        for (id = 0; id < NUM_HOOKS; id++) {
+                list_init(&session->hook_table[id]);
+        }
+}
+
+void session_run_hook(struct session *session, session_hook_id_t id, const char *fmt, ...)
+{
+        struct list *lptr, *head;
+
+        assert(id < NUM_HOOKS);
+        head = &session->hook_table[id];
+
+        list_for_each(head, lptr) {
+                struct session_hook_entry *entry = list_entry(lptr, struct session_hook_entry, list);
+                va_list args;
+                va_start(args, fmt);
+                closure_execvl(entry->proc, fmt, args, entry->args);
+                va_end(args);
+        }
+        
+        
+}
+
+void *session_add_hook(struct session *session, session_hook_id_t id, struct closure *proc, pointer args)
+{
+        struct list *head;
+        struct session_hook_entry *entry;
+
+        assert(id < NUM_HOOKS);
+        head = &session->hook_table[id];
+
+        if (!(entry = (struct session_hook_entry*)calloc(1, sizeof(*entry)))) {
+                return 0;
+        }
+
+        entry->proc = proc;
+        closure_ref(proc);
+        entry->args = args;
+        proc->sc->vptr->protect(proc->sc, args);
+
+        list_add_tail(&session->hook_table[id], &entry->list);
+        return entry;
+}
+
+void session_rm_hook(struct session *session, session_hook_id_t id, pointer code)
+{
+        struct list *head, *lptr;
+        struct session_hook_entry *entry;
+
+        assert(id < NUM_HOOKS);
+        head = &session->hook_table[id];
+        lptr = head->next;
+        while (lptr != head) {
+            entry = list_entry(lptr, struct session_hook_entry, list);
+            struct closure *proc = entry->proc;
+            if (proc->code == code) {
+                list_remove(lptr);
+                scheme *sc = proc->sc;
+                sc->vptr->unprotect(sc, entry->args);
+                closure_unref(proc);
+                free(entry);
+                return;
+            }
+            lptr = lptr->next;
+        }
+}
+
+static void session_cleanup_hooks(struct session *session)
+{
+        int i;
+        for (i = 0; i < NUM_HOOKS; i++) {
+                struct list *head = &session->hook_table[i];
+                struct list *lptr = head->next;
+                while (lptr != head) {
+                        struct session_hook_entry *entry = list_entry(lptr, struct session_hook_entry, list);
+                        lptr = lptr->next;
+                        list_remove(&entry->list);
+                        entry->proc->sc->vptr->unprotect(entry->proc->sc, entry->args);
+                        closure_unref(entry->proc);
+                        free(entry);
+                }
+        }
+}
+
+int session_run_query(struct session *session, session_query_id_t id, const char *fmt, ...)
+{
+        assert(id < NUM_QUERIES);
+        struct closure *proc = session->query_table[id];
+        va_list args;
+
+        if (proc) {
+                pointer result;
+                va_start(args, fmt);
+                result = closure_execv(proc, fmt, args);
+                va_end(args);
+                return closure_translate_result(proc->sc, result);
+        }
+        
+        return 0;
+}
+
+void session_add_query(struct session *session, session_query_id_t id, struct closure *proc)
+{
+        assert(id < NUM_QUERIES);
+
+        /* out with the old */
+        if (session->query_table[id]) {
+                closure_unref(session->query_table[id]);
+                session->query_table[id] = NULL;
+        }
+        
+        /* in with the new */
+        if (proc) {
+                closure_ref(proc);
+                session->query_table[id] = proc;
+        }
+}
+
+static void session_cleanup_queries(struct session *session)
+{
+        int i;
+        for (i = 0; i < NUM_QUERIES; i++) {
+                if (session->query_table[i]) {
+                        closure_unref(session->query_table[i]);
+                        session->query_table[i] = NULL;
+                }
+        }
+}
+
+const char *session_hook_id_to_str(session_hook_id_t id)
+{
+        assert(id < NUM_HOOKS);
+        return session_hook_str[id];
+}
+
+session_hook_id_t session_str_to_hook_id(char *str)
+{
+        int id;
+        for (id = 0; id < NUM_HOOKS; id++) {
+                if (! strcmp(session_hook_str[id], str)) {
+                        break;
+                }
+        }
+        return (session_hook_id_t)id;
+}
+
+char *session_get_last_error(void)
+{
+        return session_last_error;
+}
+
+void session_eval(struct session *session, char *buf)
+{
+        scheme_load_string((scheme *)(session->interp), (const char*)buf);
+}
diff --git a/src/session.h b/src/session.h
new file mode 100644 (file)
index 0000000..3c92e47
--- /dev/null
@@ -0,0 +1,338 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef session_h
+#define session_h
+
+#include "ascii.h"
+#include "clock.h"
+#include "list.h"
+#include "magic.h"
+#include "scheme.h"
+#include "screen.h"
+#include "sky.h"
+#include "status.h"
+#include "node.h"
+#include "Being.h"
+
+/* File for quick save/reload with CTRL-q and CTRL-r */
+#define QUICKSAVE_FNAME "save.scm"
+
+/* Shared between session.c and kern.c */
+#define load_err_any() (load_errs != 0)
+#define load_err_clear() (load_errs = 0)
+#define load_err_inc() (load_errs++)
+
+/* Shared between session.c and kern.c */
+#define save_err_any() (save_errs != 0)
+#define save_err_clear() (save_errs = 0)
+#define save_err_inc() (save_errs++)
+
+/* Shared between session.c and kern.c */
+extern void load_err(const char *fmt, ...);
+extern void rt_err(const char *fmt, ...);
+extern void save_err(const char *fmt, ...);
+
+/* Shared between session.c and kern.c */
+extern int load_errs;
+extern int save_errs;
+
+typedef struct {
+        int duration;
+        struct sprite *sprite;
+} global_effect_t;
+
+/* Indices into the hook table */
+#define SESSION_DECL_HOOK(id) id
+typedef enum {
+#       include "session_hooks.h"
+        NUM_HOOKS
+} session_hook_id_t;
+
+/* Indices into the query table */
+#define SESSION_DECL_QUERY(id) id
+typedef enum {
+#       include "session_queries.h"
+        NUM_QUERIES
+} session_query_id_t;
+
+/* Backwards-compatible replacements for the old global flags: */
+#define Reload (Session->reload)
+#define Reveal (Session->reveal.duration)
+#define Quicken (Session->quicken.duration)
+#define TimeStop (Session->time_stop.duration)
+#define MagicNegated (Session->magic_negated.duration)
+#define XrayVision (Session->xray.duration)
+
+#define add_reveal(val) ((Reveal) += val)
+#define add_quicken(val) ((Quicken) += val)
+#define add_time_stop(val) ((TimeStop) += val)
+#define add_magic_negated(val) ((MagicNegated) += val)
+#define add_xray(val) ((XrayVision) += val)
+
+#define dec_reveal(val) ((Reveal) -= min((Reveal), (val)))
+#define dec_quicken(val) ((Quicken) -= min((Quicken), (val)))
+#define dec_time_stop(val) ((TimeStop) -= min((TimeStop), (val)))
+#define dec_magic_negated(val) ((MagicNegated) -= min((MagicNegated), (val)))
+#define dec_xray(val) ((XrayVision) -= min((XrayVision), (val)))
+
+#define reveal_effect_sprite() (Session->reveal.sprite)
+#define quicken_effect_sprite() (Session->quicken.sprite)
+#define time_stop_effect_sprite() (Session->time_stop.sprite)
+#define magic_negated_effect_sprite() (Session->magic_negated.sprite)
+#define xray_vision_effect_sprite() (Session->xray.sprite)
+
+/* Access to global session passability table: */
+#define session_ptable() (Session->ptable)
+
+/* Access to global session diplomacy table: */
+#define session_dtable() (Session->dtable)
+
+#define session_ticks_per_turn() (int)(place_get_scale(Place) * Session->time_accel)
+#define session_set_time_accel(val) (Session->time_accel = (val))
+#define session_get_time_accel(val) (Session->time_accel)
+
+/* Backwards-compatible replacements for the old global work queues: */
+#define TickWorkQueue (Session->tickq)
+#define TurnWorkQueue (Session->turnq)
+
+/* Access to the turn counter: */
+#define session_inc_turn_count() (Session->turn_count++)
+#define session_set_turn_count(val) (Session->turn_count=(val))
+#define session_get_turn_count() (Session->turn_count)
+
+/* Backwards-compatible replacement for the old global player_party */
+#define player_party (Session->player)
+
+struct skill;
+struct skill_set;
+
+struct session {
+
+        // This list keeps track of all loaded object types. It's private to
+        // the session management code which uses it to save and delete objects
+        // when tearing down a session. (aka the "orphan list").
+        struct list data_objects;
+
+        struct list terrains; /* list of all terrains */
+
+        // The global crosshair type is per-session and several many places
+        class ObjectType *crosshair_type;
+        class Cursor *crosshair;
+
+        // The damage sprite is used in mapPaintDamage
+        struct sprite *damage_sprite;
+
+        // Global clock settings
+        struct clock clock;
+
+        // Saved status window state.
+        enum StatusMode status_mode;
+
+        // Saved LOS style.
+        const char *los;
+
+        // Only one palette per session will be allowed, and it will be
+        // globally accessible here. This is to accomodate the creation of
+        // temporary combat maps in the wilderness.
+        struct terrain_palette *palette;
+
+        // The sky is used by sky.c
+        struct sky sky;
+
+        // Magic is used in cmd.c
+        struct magic magic;
+
+        // The interpreter is private
+        void *interp;
+
+        // This starts at zero when the session is loaded and is incremented
+        // each time the session is saved. A copy of its value is kept in the
+        // saved struct below.
+        int session_id;
+
+        // Temporary wilderness combat place requires special handling so that
+        // it is saved in the proper order.
+        struct place *combat_place;
+        char saved_combat_place : 1;
+
+        int reloaded : 1; /* Old session destroyed, this one is new */
+
+        /* Flag to signal a reload has been requested and is pending */
+        int reload;
+
+        /* The number of turns until the "reveal hidden" effect expires: */
+        global_effect_t reveal;
+
+        /* The number of turns until the "quicken" effect expires: */
+        global_effect_t quicken;
+
+        /* The number of turns until the "time stop" effect expires: */
+        global_effect_t time_stop;
+
+        /* During time stop, sprites for player-controlled objects should be
+         * the only ones that animate. Instead of advancing the general
+         * animation tick counter in sprites.c, advance a special tick counter
+         * here. In object.c it will use this special tick counter for
+         * advancing only player-controlled object sprites. */
+        int time_stop_ticks;
+
+        /* The number of turns until the "magic negated" effect expires: */
+        global_effect_t magic_negated;
+
+        /* The number of turns until the "xray vision" effect expires: */
+        global_effect_t xray;
+
+        /* The passability table */
+        struct ptable *ptable;
+
+        /* The diplomacy table */
+        struct dtable *dtable;
+
+        /* The turn/tick work queues */
+        struct list turnq;
+        struct list tickq;
+
+        /* Startup script */
+        struct closure *start_proc;
+
+        /* A multiplier for temporarily speeding up time (used when the player
+         * is camping or resting) */
+        float time_accel;
+
+        struct list hook_table[NUM_HOOKS];
+        struct closure *query_table[NUM_QUERIES];
+
+        struct node sched_chars;   /* characters with multi-place schedules */
+
+        /* This is a flat-out hack. I decided to add some things like
+         * describing if beings are hostile for the xamine command and showing
+         * red or green squares around NPCs for the attack command, and these
+         * require knowledge of a "who wants to know?" nature deep in the guts
+         * of some call stacks. So, I added this global variable. It's
+         * wrong, I know. Be careful with it. */
+        Being *subject;
+
+        struct list skills;     /* list of all skills in the game     */
+        struct list skill_sets; /* list of all skill sets in the game */
+        struct list blenders;   /* obsolete?                          */
+
+        /* The turn count shown in the foogod window; incremented once per game
+         * loop in play.c */
+        int turn_count;
+
+        /* The player party object for this session */
+        class PlayerParty *player;
+
+        char show_boxes : 1;  /* draw red/green/yellow boxes around npcs */
+       char is_demo : 1; /* demo mode session */
+       
+        struct tree *freezer;
+
+        int num_kern_includes; /* Number of times kern-include was used when
+                                * loading the session. Needed for generating
+                                * progress bar code in the save file. */
+
+        unsigned int major, minor, release; /* script version */
+};
+
+// Callback table for saving objects
+typedef struct save {
+
+        FILE *file;
+        int indent;
+
+        // This is so objects can tell if they've saved themselves already for
+        // the current session.
+        int session_id;
+
+        // printf with tabs
+        void (*write)(struct save *save, const char *fmt, ...);
+
+        // printf without tabs
+        void (*append)(struct save *save, const char *fmt, ...);
+
+        // printf with tabs & incr tabs
+        void (*enter)(struct save *save, const char *fmt, ...);
+
+        // printf with tabs & decr tabs
+        void (*exit)(struct save *save, const char *fmt, ...);
+
+        
+
+} save_t;
+
+save_t * save_new(FILE *   file);
+void     save_del(save_t * save);
+
+extern int session_load(char *filename);
+extern int session_save(char *fname);
+struct session *session_new(void *interp);
+void session_del(struct session *session);
+
+// ----------------------------------------------------------------------------
+// Add a persistent object to the session. If you want an object to get saved
+// and destroyed when the session exits then you should do this. Objects which
+// are loaded from a script at the start of a session are automatically added,
+// and most objects created at runtime will be saved as part of the place or
+// inventory which contains them. I specifically made this call externally
+// accessible so I could manage the temporary combat place, which is very much
+// a special case.
+//
+// This call returns a 'handle' which can be passed to session_rm() to remove
+// the object if you want to remove it from the session (NOTE: calling
+// session_rm() will NOT invoke the dtor provided to session_add()).
+// ----------------------------------------------------------------------------
+extern void * session_add(struct session *session, void *obj, 
+                          void (*dtor)(void *),
+                          void (*save)(save_t *save, void *obj),
+                          void (*start)(void *obj)
+        );
+extern void * session_add_connection(struct session *session, void *obj, 
+                                     void (*dtor)(void *),
+                                     void (*save)(save_t *save, void *obj)
+        );
+extern void session_rm(struct session *session, void *handle);
+
+extern void session_run_hook(struct session *session, session_hook_id_t id, const char *fmt, ...);
+extern void *session_add_hook(struct session *session, session_hook_id_t id, struct closure *proc, pointer args);
+extern void session_rm_hook(struct session *session, session_hook_id_t id, pointer code);
+extern int session_run_query(struct session *session, session_query_id_t id, const char *fmt, ...);
+extern void session_add_query(struct session *session, session_query_id_t id, struct closure *proc);
+extern const char *session_hook_id_to_str(session_hook_id_t id);
+extern session_hook_id_t session_str_to_hook_id(char *str);
+
+extern void save_err(const char *fmt, ...);
+extern struct node *session_add_sched_char(struct session *session,
+                                           class Character *npc);
+extern void session_rm_sched_char(struct node *node);
+extern void session_synch_sched_chars(struct session *session);
+extern void session_intro_sched_chars(struct session *session);
+extern char *session_get_last_error(void);
+extern void session_eval(struct session *session, char *buf);
+
+// Global session object.
+extern struct session *Session;
+
+#include "objectfreezer.h"
+
+#endif
diff --git a/src/session_hooks.h b/src/session_hooks.h
new file mode 100644 (file)
index 0000000..46e52a6
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+/**
+ * This is where you add a new hook to the kernel. session.h #includes this to
+ * create the id's for its hook array. kern.c uses this to map scheme strings
+ * to hook id's via a table. The only other thing you need to do for a hook is
+ * add a call to run it from the appropriate place in the kernel source.
+ *
+ * Note: by convention the comments following each line show the args the hook
+ * proc expects.
+ *
+ * Note: do NOT use #define guards for this header, since kern.c includes it
+ * twice via session.h.
+ */
+
+SESSION_DECL_HOOK(session_start_hook), /* player party */
+SESSION_DECL_HOOK(new_game_start_hook), /* player party */
+SESSION_DECL_HOOK(camping_turn_start_hook), /* player party */
+SESSION_DECL_HOOK(conv_start_hook), /* pc, npc */
+SESSION_DECL_HOOK(conv_end_hook), /* pc, npc */
+SESSION_DECL_HOOK(music_change_hook), /* player party */
+SESSION_DECL_HOOK(combat_change_hook), /* player party */
diff --git a/src/session_queries.h b/src/session_queries.h
new file mode 100644 (file)
index 0000000..be9f80f
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+/**
+ * This is where you add a new query to the kernel. session.h #includes this to
+ * create the id's for its query array. kern.c uses this to map scheme strings
+ * to query id's via a table. The only other thing you need to do for a query is
+ * add a call to run it from the appropriate place in the kernel source.
+ *
+ * Note: by convention the comments following each line show the args the query
+ * proc expects.
+ *
+ * Note: do NOT use #define guards for this header, since kern.c includes it
+ * twice via session.h.
+ */
+
+SESSION_DECL_QUERY(str_based_attack_query), /* character */
+SESSION_DECL_QUERY(dex_based_attack_query), /* character */
+SESSION_DECL_QUERY(damage_bonus_query), /* character */
+SESSION_DECL_QUERY(defense_bonus_query), /* character */
diff --git a/src/skill.c b/src/skill.c
new file mode 100644 (file)
index 0000000..610ebc2
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "skill.h"
+#include "closure.h"
+
+#include <assert.h>
+#include <config.h>
+//#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+//#endif
+#include <string.h>
+
+static void skill_del(struct skill *skill)
+{
+        struct list *elem;
+
+        assert(!skill->refcount);
+        if (skill->name) {
+                free(skill->name);
+        }
+        if (skill->desc) {
+                free(skill->desc);
+        }
+        if (skill->yuse) {
+                closure_unref(skill->yuse);
+        }
+        if (skill->can_yuse) {
+                closure_unref(skill->can_yuse);
+        }
+
+        /* delete the list of tools */
+        node_list_unlink_and_unref(&skill->tools);
+
+        /* delete the list of materials */
+        elem = skill->materials.next;
+        while (elem != &skill->materials) {
+                struct list *tmp = elem->next;
+                free(elem);
+                elem = tmp;
+        }
+
+        free(skill);
+}
+
+struct skill *skill_new(void)
+{
+        struct skill *skill = (struct skill*)calloc(1, sizeof(*skill));
+        assert(skill);
+        list_init(&skill->list);
+        node_init(&skill->tools);
+        list_init(&skill->materials);
+        skill->refcount = 1;
+        return skill;
+}
+
+void skill_set_name(struct skill *skill, char *val)
+{
+        assert(val);
+        if (skill->name) {
+                free(skill->name);
+        }
+        skill->name = strdup(val);
+        assert(skill->name);
+}
+
+void skill_set_desc(struct skill *skill, char *val)
+{
+        assert(val);
+        if (skill->desc) {
+                free(skill->desc);
+        }
+        skill->desc = strdup(val);
+        assert(skill->name);
+}
+
+void skill_ref(struct skill *skill)
+{
+        skill->refcount++;
+}
+
+void skill_unref(struct skill *skill)
+{
+        assert(skill->refcount > 0);
+        skill->refcount--;
+        if (!skill->refcount) {
+                skill_del(skill);
+        }
+}
+
+void skill_add_tool(struct skill *skill, void *objtype)
+{
+        struct node *node = node_new(objtype);
+        node_add(&skill->tools, node);
+}
+
+void skill_add_material(struct skill *skill, void *objtype, int quan)
+{
+        struct skill_material *mat;
+        mat = (struct skill_material*)calloc(1, sizeof(*mat));
+        assert(mat);
+        mat->objtype = objtype;
+        mat->quantity = quan;
+        list_add(&skill->materials, &mat->list);
+}
diff --git a/src/skill.h b/src/skill.h
new file mode 100644 (file)
index 0000000..354aa1a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef skill_h
+#define skill_h
+
+#include "list.h"
+#include "node.h"
+
+/* Description of a material item needed by a skill */
+struct skill_material {
+        struct list list;  /* list of materials in skill */
+        void *objtype;     /* ObjectType consumed */
+        int quantity;      /* quantity consumed */
+};
+
+/* Description of a skill */
+struct skill {
+        struct list list;         /* list of all skills in the session */
+        char *name;               /* name shown in UI */
+        char *desc;               /* flavor text for UI; should also describe
+                                   * special requirements checked for in the
+                                   * can_yuse closure. */
+        int ap;                   /* action points consumed */
+        int mp;                   /* mana points consumed */
+        struct node tools;        /* ObjectTypes needed to y)use */
+        struct list materials;    /* skill_materials consumed with y)use */
+        struct closure *yuse;     /* proc that executes the y)use */
+        struct closure *can_yuse; /* check special requirements to y)use */
+        int refcount;             /* memory management */
+        char wilderness_ok : 1;   /* can y)use in wilderness */
+        char passive : 1;         /* y)use is n/a */
+};
+
+extern struct skill *skill_new();
+extern void skill_ref(struct skill *);
+extern void skill_unref(struct skill *);
+extern void skill_set_name(struct skill *skill, char *name);
+extern void skill_set_desc(struct skill *skill, char *name);
+extern void skill_add_tool(struct skill *skill, void *objtype);
+extern void skill_add_material(struct skill *skill, void *objtype, int quan);
+
+#endif
diff --git a/src/skill_set.c b/src/skill_set.c
new file mode 100644 (file)
index 0000000..7565f6e
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "skill_set.h"
+#include "skill_set_entry.h"
+
+#include <assert.h>
+#include <config.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+
+
+static void skill_set_del(struct skill_set *skset)
+{
+        struct list *list;
+
+        assert(!skset->refcount);
+
+        if (skset->name) {
+                free(skset->name);
+        }
+        
+        list = skset->skills.next;
+        while (list != &skset->skills) {
+                struct skill_set_entry *ssent;
+
+                ssent = list_entry(list, struct skill_set_entry, list);
+                list = list->next;
+                list_remove(&ssent->list);
+                skill_set_entry_unref(ssent);
+        }
+
+        free(skset);
+}
+
+struct skill_set *skill_set_new(void)
+{
+        struct skill_set *skset = (struct skill_set*)calloc(1, sizeof(*skset));
+        assert(skset);
+        list_init(&skset->list);
+        list_init(&skset->skills);
+        skset->refcount = 1;
+        return skset;
+}
+
+void skill_set_set_name(struct skill_set *skset, char *val)
+{
+        assert(val);
+        if (skset->name) {
+                free(skset->name);
+        }
+        skset->name = strdup(val);
+        assert(skset->name);
+}
+
+void skill_set_ref(struct skill_set *skset)
+{
+        skset->refcount++;
+}
+
+void skill_set_unref(struct skill_set *skset)
+{
+        assert(skset->refcount > 0);
+        skset->refcount--;
+        if (!skset->refcount) {
+                skill_set_del(skset);
+        }
+}
+
+void skill_set_add_skill(struct skill_set *skset, struct skill *skill,
+                         int level)
+{
+        struct skill_set_entry *ssent = skill_set_entry_new(skill, level);
+        assert(ssent);
+        list_add_tail(&skset->skills, &ssent->list);
+}
diff --git a/src/skill_set.h b/src/skill_set.h
new file mode 100644 (file)
index 0000000..b51e36e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef skill_set_h
+#define skill_set_h
+
+#include "list.h"
+
+/**
+ * Skills are grouped into skill sets. Within a skill set, each skill has a
+ * minimum level at which it may be used. Multiple skill sets may reference the
+ * same skill, and each may have its own min level. So whereas skill structs
+ * are shared across skill sets, skill_set_entry structs are unique to a skill
+ * set. For example, a detect trap skill may be part of both a rogue skill set
+ * and a ranger skill set, but the rogue can use the skill at level 2 whereas
+ * the ranger must be level 4.
+ */
+struct skill_set {
+        struct list list;         /* list of all skill_sets in the session */
+        char *name;               /* name of the skill set, eg "Ranger" */
+        struct list skills;       /* list of skill_set_entry structs */
+        int refcount;             /* memory management */
+};
+
+extern struct skill_set *skill_set_new();
+extern void skill_set_ref(struct skill_set *skset);
+extern void skill_set_unref(struct skill_set *skset);
+extern void skill_set_set_name(struct skill_set *skset, char *name);
+extern void skill_set_add_skill(struct skill_set *skset, struct skill *skill,
+                                int level);
+
+
+#endif
diff --git a/src/skill_set_entry.c b/src/skill_set_entry.c
new file mode 100644 (file)
index 0000000..5c52691
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "skill_set_entry.h"
+#include "skill.h"
+
+#include <assert.h>
+#include <config.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+
+static void skill_set_entry_del(struct skill_set_entry *ssent)
+{
+        assert(!ssent->refcount);
+        if (ssent->skill) {
+                skill_unref(ssent->skill);
+        }
+        free(ssent);
+}
+
+struct skill_set_entry *skill_set_entry_new(struct skill *skill, int lvl)
+{
+        struct skill_set_entry *ssent;
+        ssent = (struct skill_set_entry*)calloc(1, sizeof(*ssent));
+        assert(ssent);
+        list_init(&ssent->list);
+        ssent->refcount = 1;
+        ssent->skill = skill;
+        skill_ref(skill);
+        ssent->level = lvl;
+        return ssent;
+}
+
+void skill_set_entry_ref(struct skill_set_entry *ssent)
+{
+        ssent->refcount++;
+}
+
+void skill_set_entry_unref(struct skill_set_entry *ssent)
+{
+        assert(ssent->refcount > 0);
+        ssent->refcount--;
+        if (!ssent->refcount) {
+                skill_set_entry_del(ssent);
+        }
+}
diff --git a/src/skill_set_entry.h b/src/skill_set_entry.h
new file mode 100644 (file)
index 0000000..5c1c3e3
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef skill_set_entry_h
+#define skill_set_entry_h
+
+#include "list.h"
+
+/* These are used to list the skills in a skill set, and to associate a minimum
+ * required level to use each skill. */
+struct skill_set_entry {
+        struct list list;         /* list of other skills in the skill set */
+        struct skill *skill;      /* the skill                             */
+        int level;                /* min skill level to use this skill     */
+        int refcount;             /* memory management                     */
+};
+
+extern struct skill_set_entry *skill_set_entry_new(struct skill *skill, int level);
+extern void skill_set_entry_ref(struct skill_set_entry *ssent);
+extern void skill_set_entry_unref(struct skill_set_entry *ssent);
+
+#endif
diff --git a/src/sky.c b/src/sky.c
new file mode 100644 (file)
index 0000000..78804cb
--- /dev/null
+++ b/src/sky.c
@@ -0,0 +1,697 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// Thi program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "sky.h"
+#include "screen.h"
+#include "common.h"
+#include "sprite.h"
+#include "place.h"
+#include "map.h"
+#include "player.h"
+#include "wq.h"
+#include "clock.h"
+#include "session.h"
+#include "gob.h"
+
+#include <assert.h>
+#include <math.h>
+
+// Amount by which we horizontally shift the light function to make noon
+// produce maximum light
+#define SKY_HORZ_SHIFT (NOON_DEGREE - 90)
+
+// Amount by which we vertically shift the light function to make sunrise and
+// sunset occur at the specified times. Since this involces taking the sin
+// of a value we must do this at runtime.
+static double SKY_VERT_SHIFT = 0.0;
+
+// Amount by which we multiple the sine factor of the light function to make it
+// ramp up faster. Again, must do this at runtime.
+static double SKY_AMPLITUDE = 0.0;
+
+// Conversion factors for deciding where in the sky window an astral body is
+//
+// W = width of sky window
+// t = width of astral body sprite
+// R = sunrise
+// S = sunset
+// P(x) = position in window of arc x
+//
+//                                     0
+// +---+-------------------------------+---+
+// | t |<------------ W -------------->| t |
+// +---+-------------------------------+---+
+// S                                   R
+//
+// P(R) = 0
+// P(S) = W + t
+// P(x) = mx + b
+//
+// And solving we get:
+// m = (W + t)/(S - R)
+// b = -R * m
+//
+
+// 1.06667
+static double SKY_WIN_SLOPE;
+static double SKY_WIN_OFFSET;
+
+#define SKY_ARC_TO_PIXEL_OFFSET(arc) (int)(SKY_WIN_SLOPE * (double)(arc) + \
+                                           (SKY_WIN_OFFSET))
+
+#define DEGREES_TO_RADIANS(deg) (double)((deg) * 0.0174603)
+
+#define ASTRAL_BODY_ARC_WIDTH   ((double)SKY_SPRITE_W/(double)SKY_WIN_SLOPE)
+#define ECLIPSE_FACTOR 0.75
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Internal helper functions
+//
+//////////////////////////////////////////////////////////////////////////////
+
+static int sky_get_light_from_astral_body(int arc, int maxlight)
+{
+        //  light
+        // M |        ...................
+        //   |       .                   .
+        //   |      .                     .
+        // 0 |--------|--------|--------|--------| arc
+        //   0       90       180      270       0
+        //
+        // Start ramping up at sunrise, ramp down and hit zero at sunset. I
+        // think a simple way to simulate this is to take a horizontal slice
+        // out of a sine wave.
+        //
+        // Here's sin(arc):
+        //
+        //  |   . .
+        //  | .     .
+        //  |._______._______.
+        //  |         .     .
+        //  |           . .
+        //  r        s
+        //
+        // Point 'r' is sunrise, 's' is sunset. In our system the day and night
+        // are not equal, so to simulate this we modify the basic sine function
+        // like this:
+        //
+        // Here's sin(arc) + C
+        //
+        //  |   . .
+        //  | .     .
+        //  |.       .       .
+        //  |_________._____._
+        //  |           . .
+        //  r         s     r
+        //
+        // But in our system sunrise is not at zero degrees, so we need to
+        // shift the function:
+        //
+        // sin(arc - theta) + C:
+        //
+        //  |      . .
+        //  |    .     .
+        //  |   .       .         
+        //  |__._________.____.
+        //  |.             . .
+        //     r         s    r
+        //
+        // Since we don't want our function to produce a value greater than
+        // 1.0, we cap it, producing a flat top which represents max light.  If
+        // we stop here then it takes about four hours for the sun to go from
+        // zero to max output. I'd prefer it if this were more like an hour. So
+        // for this we need to multiply the result of the sin function to
+        // increase the amplitude.
+        //
+        // A * (sin(arc - theta) + C)
+        //
+        //  |            
+        //  |   .........
+        //  |  .         .        
+        //  |__._________.____.
+        //  |..           ....
+        //     r         s    r
+        // 
+        // 
+
+        int degrees = (arc - SKY_HORZ_SHIFT);
+        double radians = DEGREES_TO_RADIANS(degrees);
+        double factor = SKY_AMPLITUDE * (sin(radians) + SKY_VERT_SHIFT);
+        clamp(factor, 0.0, 1.0);
+        int light = (int)(factor * maxlight);
+        light = (light < 0) ? 0 : light;
+        return light;
+}
+
+static void sky_compute_factors(void)
+{
+        // Called once at load time. The light function is derived above as:
+        //
+        // light = A * (sin(x - theta) + C)
+        //
+        // Here we solve for C by using the sunrise time 'R', where the
+        // function passes through 0. Since the amplitude does not
+        //
+        // A * (sin(R - theta) + C) = 0
+        // C = -sin(R - theta)
+        // 
+        SKY_VERT_SHIFT = -sin(DEGREES_TO_RADIANS(SUNRISE_DEGREE - 
+                                                 SKY_HORZ_SHIFT));
+
+        // Now solve for A, which is the amplitude, using the first value after
+        // sunrise for which the function produces 1.0. This value should be
+        // one hour after sunrise.
+        //
+        // A  * (sin(V - theta) + C) = 1
+        // A = 1 / (sin(V - theta) + C)
+
+        double inverse = sin(DEGREES_TO_RADIANS(SUNRISE_DEGREE + 
+                                                DEGREES_PER_HOUR -  
+                                                SKY_HORZ_SHIFT) +
+                             SKY_VERT_SHIFT);
+        assert(inverse != 0.0);
+        SKY_AMPLITUDE = 1 / inverse;
+}
+
+static void sky_paint_astral_body(struct sky *sky, int arc, 
+                                  struct sprite *sprite)
+{
+       int x;
+       int pixels;
+
+        pixels = SKY_ARC_TO_PIXEL_OFFSET(arc);
+        if (pixels < 0 || pixels > SKY_W + SKY_SPRITE_W)
+                return;
+       x = sky->screenRect.x + sky->screenRect.w - pixels;
+
+       sprite_paint(sprite, 0, x, sky->screenRect.y);
+}
+
+int astral_body_is_visible(int arc)
+{
+       // SAM:
+       // I tested somewhat before, during, after sunset,
+       // and found that the sprite for the moon "left of the sun"
+       // became not visible (out of the drawing area?) before
+       // the AT command (which calls sky_astral_body_is_visible() )
+       // reported that a moon had set.
+       // 
+       // Why the difference in apparent "set" time?
+       if (arc < SUNRISE_DEGREE || arc > (SUNSET_DEGREE + SKY_SPRITE_W))
+               return 0;
+       return 1;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Astral body api
+//
+//////////////////////////////////////////////////////////////////////////////
+
+struct astral_body *astral_body_new(char *tag, char *name, int n_phases)
+{
+        struct astral_body *body;
+
+        assert(n_phases);
+        assert(name);
+
+        body = (struct astral_body*)calloc(1, sizeof(*body));        
+        assert(body);
+
+        list_init(&body->list);
+        body->eclipse = 0;
+        body->n_phases = n_phases;
+        body->phases = (struct phase*)calloc(body->n_phases, 
+                                             sizeof(struct phase));
+        assert(body->phases);
+
+        body->tag = strdup(tag);
+        assert(body->tag);
+
+        body->name = strdup(name);
+        assert(body->name);
+
+        return body;
+}
+
+void astral_body_del(struct astral_body *body)
+{
+        int i;
+
+        assert(body);
+        assert(body->tag);
+        assert(body->name);
+        assert(body->phases);
+
+        closure_unref_safe(body->gifc);
+        if (body->gob)
+                gob_del(body->gob);
+        free(body->tag);
+        free(body->name);
+        for (i = 0; i < body->n_phases; i++)
+                if (body->phases[i].name)
+                        free(body->phases[i].name);
+        free(body->phases);
+        free(body);
+}
+
+void astral_body_save(struct astral_body *body, struct save *save)
+{
+        int i;
+
+        if (body->gob)
+                save->enter(save, "(bind-astral-body\n");
+
+        save->enter(save, "(kern-mk-astral-body\n");        
+        save->write(save, "'%s\t; tag\n", body->tag);
+        save->write(save, "\"%s\"\t; name\n", body->name);
+        save->write(save, "%d\t; distance\n", body->distance);
+        save->write(save, "%d\t; minutes_per_phase\n", 
+                    body->minutes_per_phase);
+        save->write(save, "%d\t; minutes_per_degress\n", 
+                    body->minutes_per_degree);
+        save->write(save, "%d\t; initial_arc\n", body->initial_arc);
+        save->write(save, "%d\t; initial_phase\n", body->initial_phase);
+        //save->write(save, "%d\t; n_phases\n", body->n_phases);
+        if (body->gifc)
+                closure_save(body->gifc, save);
+        else
+                save->write(save, "nil\t; gifc\n");
+        assert(body->n_phases);
+        save->enter(save, "(list\n");
+        for (i = 0; i < body->n_phases; i++) {
+                save->write(save, "(list %s %d \"%s\")\n", 
+                            sprite_get_tag(body->phases[i].sprite),
+                            body->phases[i].maxlight,
+                            body->phases[i].name);
+        }
+        save->exit(save, ")\n");
+        save->exit(save, ")\n");
+
+        if (body->gob) {
+                gob_save(body->gob, save);
+                save->exit(save, ") ;; bind-astral-body\n");
+        }
+}
+
+static void astral_body_advance_phase(struct astral_body *body)
+{
+        int new_phase;
+
+        assert(body->n_phases);
+
+        // Calculate the new phase
+        new_phase = 0;
+        if (body->minutes_per_phase) {
+                new_phase = clock_time() / body->minutes_per_phase;
+        }
+        new_phase += body->initial_phase;
+        new_phase %= body->n_phases;
+        
+        if (new_phase == body->phase)
+                return;
+                
+        // Run the phase-change handler in the script
+        if (body->gifc)
+                closure_exec(body->gifc, "ypdd", "phase-change", 
+                             body, body->phase, new_phase);
+                
+        body->phase = new_phase;
+}
+
+static void astral_body_advance_arc(struct astral_body *body)
+{
+        int new_arc;
+        int original_light;
+
+        // Calculate the new arc
+        new_arc = (clock_time() / body->minutes_per_degree);
+        new_arc += body->initial_arc;
+        new_arc %= 360;
+
+        if (new_arc == body->arc)
+                return;
+
+        body->arc = new_arc;
+                
+        if (body->n_phases > 0) {
+                astral_body_advance_phase(body);
+        }
+
+        // Change the body's light
+        original_light = body->light;
+        body->light = sky_get_light_from_astral_body(
+                body->arc, 
+                body->phases[body->phase].maxlight);
+        if (original_light != body->light)
+                mapSetDirty();
+}
+
+typedef struct {
+        struct list list;
+        int x, w, ref;
+} range_t;
+
+static void range_init(range_t *range)
+{
+        list_init(&range->list);
+        range->x=0;
+        range->w=0;
+        range->ref=0;
+}
+
+static range_t *range_new()
+{
+        range_t *range = (range_t*)malloc(sizeof(*range));
+        range_init(range);
+        range->ref++;
+        return range;
+}
+
+static void range_unref(range_t *range)
+{
+        assert(range->ref);
+        range->ref--;
+        if (!range->ref)
+                free(range);
+}
+
+static void range_set_value(range_t *range, int x, int w)
+{
+        range->x = x;
+        range->w = w;
+}
+
+static range_t * range_intersect(range_t *r1, range_t *r2)
+{
+        // Note: this assumes positive values all around, no modulo
+        range_t *out = NULL;
+        int edge, overlap;
+
+        if (r1->x >= r2->x) {
+                edge = r1->x - r1->w;
+                if (edge > r2->x) {
+                        // no overlap:
+                        //   r1---->
+                        // --|-----|-----|-----|
+                        //              r2---->
+                        return NULL;
+                }
+                // r1 overlaps onto r2:
+                //   r1---->
+                // --|--|##|-----|
+                //     r2------->
+                out = range_new();
+                overlap = r2->x - edge;
+                range_set_value(out, r2->x, overlap);
+                return out;
+        }
+
+        edge = r2->x - r2->w;
+        if (edge > r1->x) {
+                // no overlap:
+                //                r1---->
+                // -----|-----|----|----|
+                //     r2---->
+                //
+                return NULL;
+        }
+
+        // r2 overlaps onto r1:
+        //   r2---->
+        // --|--|##|-----|
+        //     r1------->
+        out = range_new();
+        overlap = r1->x - edge;
+        range_set_value(out, r1->x, overlap);
+        return out;
+}
+
+static range_t *range_merge(range_t *r1, range_t *r2)
+{
+        // Note: this assumes positive values all around, no modulo
+        range_t *out = NULL;
+        int edge, overlap;
+
+        if (r1->x >= r2->x) {
+                edge = r1->x - r1->w;
+                if (edge > r2->x) {
+                        // no overlap:
+                        //   r1---->
+                        // --|-----|-----|-----|
+                        //              r2---->
+                        return NULL;
+                }
+                // r1 overlaps onto r2:
+                //   r1---->
+                // --|##|##|#####|
+                //     r2------->
+                out = range_new();
+                overlap = r2->x - edge;
+                range_set_value(out, r1->x, r1->w + r2->w - overlap);
+                return out;
+        }
+
+        edge = r2->x - r2->w;
+        if (edge > r1->x) {
+                // no overlap:
+                //                r1---->
+                // -----|-----|----|----|
+                //     r2---->
+                //
+                return NULL;
+        }
+
+        // r2 overlaps onto r1:
+        //   r2---->
+        // --|##|##|#####|
+        //     r1------->
+        out = range_new();
+        overlap = r1->x - edge;
+        range_set_value(out, r2->x, r1->w + r2->w - overlap);
+        return out;
+}
+
+static void range_set_union(struct list *set, range_t *r1)
+{
+        struct list *elem;
+
+        if (!r1) {
+                //dbg("none\n");
+                return;
+        }
+
+        //dbg("[%d %d]\n", r1->x-360, r1->w);
+
+        elem = set->next;
+
+        while (elem != set) {
+                range_t *ru;
+                range_t *r2 = outcast(elem, range_t, list);
+                elem = elem->next;
+
+                ru = range_merge(r1, r2);
+                if (ru) {
+/*                         dbg("   merged: [%d %d] + [%d %d] = [%d %d]\n", */
+/*                             r1->x-360, r1->w,   */
+/*                            r2->x-360, r2->w,  */
+/*                             ru->x-360, ru->w); */
+                        range_unref(r1);
+                        list_remove(&r2->list);
+                        range_unref(r2);
+                        r1 = ru;
+                }
+        }
+        
+        list_add(set, &r1->list);
+
+}
+
+static int range_set_sum(struct list *set)
+{
+        struct list *elem;
+        int sum = 0;
+        list_for_each(set, elem) {
+                range_t *rr=outcast(elem, range_t, list);
+                sum+=rr->w;
+        }
+        return sum;
+}
+
+static void range_set_unref_elements(struct list *set)
+{
+        struct list *elem;
+
+        elem = set->next;
+        while (elem != set) {
+                range_t *range = outcast(elem, range_t, list);
+                elem = elem->next;
+                range_unref(range);
+        }
+}
+
+static void sky_get_eclipse(struct sky *sky, 
+                            struct astral_body *outer)
+{
+        struct astral_body *inner = NULL;
+        struct list *elem = outer->list.next;
+        struct list ranges;
+        range_t r1;
+        int eclipse_arc;
+
+        //dbg(" sky_get_eclipse %s (%d)\n", outer->name, outer->arc);
+
+        outer->eclipse = 1.0;
+        list_init(&ranges);
+        range_set_value(&r1, outer->arc+360, (int)ASTRAL_BODY_ARC_WIDTH);
+
+        // Check each body listed after this one to see if it eclipses it.
+        while (elem != &sky->bodies) {
+
+                range_t r2;
+
+                inner = outcast(elem, struct astral_body,  list);
+                elem = elem->next;
+                
+                //dbg("  check %s (%d)...", inner->name, inner->arc);
+
+                range_set_value(&r2, inner->arc+360,
+                                (int)ASTRAL_BODY_ARC_WIDTH);
+                range_set_union(&ranges, range_intersect(&r1, &r2));
+        }
+
+        eclipse_arc = range_set_sum(&ranges);
+        outer->eclipse = eclipse_arc/ASTRAL_BODY_ARC_WIDTH * ECLIPSE_FACTOR;
+        range_set_unref_elements(&ranges);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+//
+// Public sky api
+//
+//////////////////////////////////////////////////////////////////////////////
+
+void sky_advance(struct sky *sky, int visible)
+{
+        struct list *elem;
+        struct astral_body *body;
+
+       screenErase(&sky->screenRect);
+
+        //dbg("sky_advance\n");
+        list_for_each(&sky->bodies, elem) {
+                body = outcast(elem, struct astral_body, list);
+                astral_body_advance_arc(body);
+                if (! visible)
+                        continue;
+                sky_paint_astral_body(sky, body->arc, 
+                                      body->phases[body->phase].sprite);
+
+                // Assume the bodies are listed in order from outermost to
+                // innermost; outer bodies will be eclipsed by inner ones
+                sky_get_eclipse(sky, body);
+        }
+
+       screenUpdate(&sky->screenRect);
+}
+
+void sky_init(struct sky *sky)
+{
+       sky->screenRect.w = SKY_W;
+       sky->screenRect.x = SKY_X;
+       sky->screenRect.y = SKY_Y;
+       sky->screenRect.h = SKY_H;
+
+        SKY_WIN_SLOPE = ((double)SKY_W + (double)SKY_SPRITE_W) / 
+                ((double)SUNSET_DEGREE - (double)SUNRISE_DEGREE);
+        SKY_WIN_OFFSET = -(double)SUNRISE_DEGREE * (double)SKY_WIN_SLOPE;
+
+        sky_compute_factors();
+        list_init(&sky->bodies);
+}
+
+void sky_start_session(struct sky *sky, int visible)
+{
+        sky_advance(sky, visible);
+}
+
+void sky_end_session(struct sky *sky)
+{
+        struct list *elem;
+        struct astral_body *body;
+
+        elem = sky->bodies.next;
+        while (elem != &sky->bodies) {
+                body = outcast(elem, struct astral_body, list);
+                elem = elem->next;
+                astral_body_del(body);
+        }        
+}
+
+void sky_add_astral_body(struct sky *sky, struct astral_body *body)
+{
+        // Need to keep them in order by astronomical distance, furthest to
+        // closest, so the sprites are rendered in the right order.
+        struct list *elem;
+        struct astral_body *other;
+
+        elem = sky->bodies.next;
+        while (elem != &sky->bodies) {
+                other = outcast(elem, struct astral_body, list);
+                // Find the first body closer than this one and insert this one
+                // before it.
+                if (other->distance < body->distance)
+                        break;
+                elem = elem->next;
+        }
+
+        list_add(elem->prev, &body->list);
+}
+
+int sky_get_ambient_light(struct sky *sky)
+{
+        struct list *elem;
+        struct astral_body *body;
+        int light = 0;
+
+        list_for_each(&sky->bodies, elem) {
+                body = outcast(elem, struct astral_body, list);
+                light += (int)((float)body->light * (1.0 - body->eclipse));
+        }
+
+        return clamp(light, 0, MAX_AMBIENT_LIGHT);
+}
+
+void sky_save(struct sky *sky, struct save *save)
+{
+        struct list *elem;
+        struct astral_body *body;
+
+        save->write(save, ";; ---------\n");
+        save->write(save, ";; Astronomy\n");
+        save->write(save, ";; ---------\n");
+
+        list_for_each(&sky->bodies, elem) {
+                body = outcast(elem, struct astral_body, list);
+                astral_body_save(body, save);
+        }
+}
diff --git a/src/sky.h b/src/sky.h
new file mode 100644 (file)
index 0000000..847ef3a
--- /dev/null
+++ b/src/sky.h
@@ -0,0 +1,83 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef sky_h
+#define sky_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "list.h"
+#include "closure.h"
+#include <SDL.h>
+
+struct phase {
+        struct sprite *sprite;
+        char *name;
+        int maxlight;
+};
+
+struct astral_body {
+        struct list list;
+        char *tag;
+        char *name;
+        int distance; // relative
+        int minutes_per_phase;
+        int minutes_per_degree;
+        int initial_arc;
+        int initial_phase;
+        int n_phases;
+        struct phase *phases;
+        int arc;
+        int phase;
+        int light;
+        closure_t *gifc;
+        struct gob *gob;
+        float eclipse;
+};
+
+struct sky {
+        SDL_Rect screenRect;
+        struct list bodies;
+};
+
+
+extern struct astral_body *astral_body_new(char *tag, char *name, int n_phases);
+extern void astral_body_del(struct astral_body *body);
+
+void sky_init(struct sky *sky);
+extern void sky_add_astral_body(struct sky *sky, struct astral_body *body);
+extern void sky_advance(struct sky *sky, int repaint);
+extern int sky_get_ambient_light(struct sky *sky);
+extern void sky_start_session(struct sky *sky, int visible);
+extern void sky_end_session(struct sky *sky);
+extern void sky_save(struct sky *sky, struct save *save);
+extern void sky_for_each(int (*fx)(struct astral_body*, void *data), void *data);
+
+//extern int astral_body_is_up(struct astral_body *body);
+//extern int astral_body_is_down(struct astral_body *body);
+extern int astral_body_is_visible (int arc);
+
+        
+END_DECL
+
+#endif
diff --git a/src/sound.c b/src/sound.c
new file mode 100644 (file)
index 0000000..b7ee5a5
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003, 2004 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ *----------------------------------------------------------------------------
+ *
+ * This file implements the sound-playing library for the nazghul engine. It
+ * wraps the SDL sound library and provides a simple mixer. The code which
+ * interacts with the SDL sound library is borrowed straight from the SDL
+ * examples, which are in the public domain (see www.libsdl.org).
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "sound.h"
+#include "debug.h"
+#include "file.h"
+#include "cfg.h"
+
+#include <assert.h>
+#include <SDL.h>
+#include <stdlib.h>
+#include <string.h>
+#include <SDL_mixer.h>
+
+#define NUM_SOUNDS 64
+#define SOUND_MAGIC 50043
+
+#define IS_SOUND(ptr) ((ptr)->magic == SOUND_MAGIC)
+
+
+struct sound {
+        int magic;
+            char *tag;
+        Mix_Chunk *data;
+        int channel;
+        //char *fname;
+        int refcount;
+        bool ambient;
+        int volume;
+        int nextVolume;
+};
+
+sound_t *sound_reverse_lookup[NUM_SOUNDS];
+
+int SOUND_MAX_VOLUME = SDL_MIX_MAXVOLUME;
+
+/* This indicates whether or not the player has turned sound on or off. */
+static int sound_enabled = 1;
+
+/* This is 1 iff SDL_Audio() is initialized and ready for use. */
+static int sound_activated = 0;
+
+static int config_to_soundvolume(const char* config)
+{
+       //our input percentages have nicely unique initial characters
+       const char* comp="O2571";
+       int i;
+       for (i=0;i<5;i++)
+       {
+               if (config[0] == comp[i])
+               {
+                       break;  
+               }
+       }
+       if (i>4)
+       {
+               i=0;    
+       }
+       return i;
+}
+
+static void sound_unref(sound_t *sound)
+{
+       assert(sound->refcount > 0);
+       
+       sound->refcount--;
+       if (! sound->refcount)
+       {
+               // make sure it isnt being played
+               if (sound->channel >= 0)
+               {
+                       // it *shouldnt* be being played, so lets die if it is.
+                       assert(false);
+                       Mix_HaltChannel(sound->channel);
+               }
+               free(sound->tag);
+               Mix_FreeChunk(sound->data);
+               free(sound);
+       }
+       
+}
+
+void sound_play(sound_t *sound, int volume, bool ambient)
+{
+
+
+       if (!sound_enabled || !sound_activated) {              
+               return;
+       }       
+
+       if (NULL_SOUND == sound)
+       {         
+           return;
+       }
+       assert(IS_SOUND(sound)); 
+       
+       if (sound->channel < 0)
+       {
+               if (ambient)
+               {
+                       sound->channel = Mix_PlayChannel(-1, sound->data,-1);
+                       Mix_VolumeChunk(sound->data,volume);
+                       sound->volume = volume;
+                       sound->ambient = true;
+                       sound->nextVolume = volume;
+               }
+               else
+               {
+                       sound->channel = Mix_PlayChannel(-1, sound->data,0);
+                       Mix_VolumeChunk(sound->data,volume);
+                       sound->volume = volume;
+                       sound->ambient = false;
+                       sound->nextVolume = 0;
+               }               
+               sound->refcount++;
+               sound_reverse_lookup[sound->channel] = sound;           
+       }
+       else if (ambient)
+       {
+               if (sound->volume < volume)
+               {
+                       Mix_VolumeChunk(sound->data,volume);
+                       sound->volume = volume;
+               }
+               if (sound->nextVolume < volume)
+               {
+                       sound->nextVolume = volume;
+               }
+       }
+       else
+       {
+               if (sound->volume < volume)
+               {
+                       sound->volume = volume;
+                       Mix_VolumeChunk(sound->data,volume);
+               }
+       }
+}
+
+void sound_played(int channel)
+{
+       sound_t *sound = sound_reverse_lookup[channel];
+       sound->channel=-1;
+       sound_reverse_lookup[channel] = NULL;
+       sound->volume=0;
+       sound_unref(sound);
+}
+
+void sound_flush_ambient()
+{
+       unsigned int i;
+       sound_t *active;
+       
+       for (i = 0; i < NUM_SOUNDS; ++i)
+       {
+               active = sound_reverse_lookup[i];
+               
+               // Skip idle or oneoff entries
+               if (! active || !active->ambient)
+                       continue;
+               
+               active->volume = active->nextVolume;
+               active->nextVolume = 0;
+               Mix_VolumeChunk(active->data,active->volume);
+       }
+}
+
+void sound_del(sound_t *sound)
+{
+        if (sound != NULL_SOUND)
+                sound_unref(sound);
+}
+
+sound_t *sound_new(const char *tag, const char *file)
+{
+   sound_t *sound;
+       char *fn;
+       Mix_Chunk *wave = NULL;
+
+       if (!sound_activated) {
+               return NULL_SOUND;
+       }
+
+        if (file == NULL)
+                return NULL_SOUND;
+
+       fn = file_mkpath(cfg_get("include-dirname"), file);
+       /* Load the sound file and convert it to 16-bit stereo at 22kHz */
+       
+       wave = Mix_LoadWAV(fn?fn:file);
+       if (!wave)
+       {
+      warn("Mix_LoadWav:%s:%s", fn?fn:file, SDL_GetError());
+       free(fn);
+               return NULL_SOUND;
+       }
+       free(fn);
+
+        /* Allocate the sound structure */
+        sound = (sound_t *)calloc(1, sizeof(*sound));
+        assert(sound);
+        
+        /* Copy the tag */
+        sound->tag = strdup(tag);
+        assert(sound->tag);
+
+        /* Initialized defaults */
+        sound->magic = SOUND_MAGIC;
+        sound->refcount = 1;
+        sound->channel = -1;
+        sound->data = wave;
+        
+        return sound;
+}
+
+int sound_init(void)
+{
+
+        if (sound_activated)
+                return 0;
+
+        /* Init the active sound list */
+
+       /* Set 16-bit stereo audio at 22Khz */
+       /* Open the audio device and start playing sound! */
+       if (Mix_OpenAudio(22050,AUDIO_S16,2,1024) < 0) {
+          warn("Mix_OpenAudio: %s", SDL_GetError());
+               return -1;
+       }
+       
+        /* Create the mutex */
+
+
+       atexit(Mix_CloseAudio);
+
+       sound_activated = 1;
+
+       for (int i=0;i<NUM_SOUNDS;i++)
+       {
+               sound_reverse_lookup[i]=NULL;   
+       }
+       Mix_AllocateChannels(NUM_SOUNDS);
+       Mix_ChannelFinished(sound_played);
+
+        return 0;
+}
+
+void sound_exit(void)
+{
+        if (! sound_activated)
+                return;
+
+        sound_activated = 0;
+
+        /* Does this invoke the mixer callback on all active sounds? If not
+         * then how will I unref active sounds? */
+        Mix_CloseAudio();
+}
+
+void sound_haltall()
+{
+       //Mix_HaltChannel(-1);
+}
+
+const char *sound_get_tag(sound_t *sound)
+{
+        return sound->tag;
+}
+
+void sound_on(void)
+{
+        sound_enabled = 1;
+}
+
+void sound_off(void)
+{
+        sound_enabled = 0;
+}
+
+int sound_is_activated(void)
+{
+        return sound_activated;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Music API
+
+Mix_Music *music_track;
+Mix_Music *prev_track = NULL;
+
+int music_volume=0;
+bool music_needtrack=false;
+
+//setting must be one of Off 25% 50% 75% 100%
+void set_music_volume(const char *setting)
+{
+       music_volume = config_to_soundvolume(setting);
+       fprintf(stderr, "vol: %s\n", setting);
+       fprintf(stderr, "vol: %d\n", music_volume);
+       int mvm = MIX_MAX_VOLUME * music_volume / 4;
+       fprintf(stderr, "vol: %d\n", mvm);
+       Mix_VolumeMusic(mvm);
+       fprintf(stderr, "vol?: %d\n", Mix_VolumeMusic(-1));
+}
+
+void music_load_track(const char *file)
+{
+       // nasty hack:
+       // SDL mixer seems to have some rather odd timing requirements.
+       // For example, I cant stop a track and immediately dispose of it
+       // so instead I will stop this track, and dispose of one I stopped earlier
+       if (prev_track)
+       {
+               Mix_FreeMusic(prev_track);
+               prev_track = NULL;
+       }
+       if (music_volume==0)
+       {
+               music_needtrack=false;
+               return; 
+       }
+       if (Mix_PlayingMusic())
+       {
+               Mix_HaltMusic();
+               prev_track = music_track;
+       }
+       char *fn = NULL;
+       if (!file_exists(file))
+       {
+               fn = file_mkpath(cfg_get("include-dirname"), file);
+       }
+       music_track=Mix_LoadMUS(fn?fn:file);
+       if (music_track)
+       {
+               Mix_PlayMusic(music_track,1);
+       }
+       else
+       {
+      warn("Mix_LoadMusic:%s:%s\n", fn?fn:file, SDL_GetError());
+       }       
+       music_needtrack=false;
+       free(fn);
+}
+
+void music_finished()
+{
+       music_needtrack=true;
+}
+
+// SDL_Mixer has a music-has-finished hook, but  you arent allowed to do anything
+// involving SDL_Mixer in that thread, so I am reduced to polling...
+bool music_need_track()
+{
+       return music_needtrack; 
+}
+
+void music_init()
+{
+       Mix_HookMusicFinished(music_finished);
+}
+
+void sound_enable(int enable)
+{
+        if (enable) {
+                sound_on();
+        } else {
+                sound_off();
+        }
+}
diff --git a/src/sound.h b/src/sound.h
new file mode 100644 (file)
index 0000000..3a849e0
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef sound_h
+#define sound_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#define NULL_SOUND NULL
+
+struct sound;
+typedef struct sound sound_t;
+
+extern int SOUND_MAX_VOLUME;
+
+extern int sound_init(void);
+extern void sound_exit(void);
+extern sound_t *sound_new(const char *tag, const char *file);
+extern void sound_del(sound_t *sound);
+extern void sound_play(sound_t *sound, int volume, bool ambient = false);
+extern const char *sound_get_tag(sound_t *sound);
+extern void sound_flush_ambient();
+extern void sound_haltall();
+
+/* These allow enabling/disabling sound at runtime. sound_on() will have no
+ * effect unless sound_init() has already been called. */
+extern void sound_on();
+extern void sound_off();
+
+/**
+ * Turn sound on or off (duplicates sound_on/sound_off with a single
+ * parameter).
+ *
+ * @param enable is non-zero to turn sound on, else it turns it off.
+ */
+extern void sound_enable(int enable);
+
+/* Returns non-zero iff sounds are ready to play (ie sound_init() has been
+ * called) */
+extern int sound_is_activated();
+
+extern void set_music_volume(const char *setting);
+extern void music_load_track(const char *file);
+extern bool music_need_track();
+extern void music_init(void);
+
+END_DECL
+
+#endif
+
diff --git a/src/species.c b/src/species.c
new file mode 100644 (file)
index 0000000..b6dd7e4
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "closure.h"
+#include "species.h"
+#include "sprite.h"
+
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+
+struct species_slot_elem {
+        struct list list;
+        int slot;
+};
+
+struct species_spell_elem {
+        struct list list;
+        class Spell *spell;
+};
+
+struct species *species_new(const char *tag,
+                            const char *name,
+                            sound_t *damage_sound,
+                            sound_t *movement_sound,
+                            int str,
+                            int intl,
+                            int dex,
+                            int spd,
+                            int vr,
+                            int hp_mod,
+                            int hp_mult,
+                            int mp_mod,
+                            int mp_mult,
+                            bool visible,
+                            int n_slots,
+                            int n_spells
+        )
+{
+        struct species *species = (struct species *)malloc(sizeof(*species));
+        assert(species);
+        memset(species, 0, sizeof(*species));
+
+        species->tag = strdup(tag);
+        assert(species->tag);
+
+        species->name = strdup(name);
+        assert(species->name);
+
+        species->damage_sound = damage_sound;
+        species->movement_sound = movement_sound;
+
+        if (n_slots > 0) {
+                species->slots = (int*)calloc(n_slots, sizeof(int));
+                assert(species->slots);
+        }
+
+        if (n_spells > 0) {
+                species->spells = (char**)calloc(n_spells, 
+                                                 sizeof(char*));
+                assert(species->spells);
+        }
+
+        species->str                = str;
+        species->intl               = intl;
+        species->dex                = dex;
+        species->spd                = spd;  // AP_per_round
+        species->vr                 = vr;
+        species->hp_mod             = hp_mod;
+        species->hp_mult            = hp_mult;
+        species->mp_mod             = mp_mod;
+        species->mp_mult            = mp_mult;
+        species->visible            = visible;
+        species->n_slots            = n_slots;
+        species->n_spells           = n_spells;
+
+        return species;
+}
+
+void species_del(struct species *species)
+{
+       if (!species)
+               return;
+       if (species->tag)
+               free(species->tag);
+       if (species->name)
+               free(species->name);
+       if (species->slots)
+               free(species->slots);
+       if (species->spells) {
+                int i;
+                for (i = 0; i < species->n_spells; i++)
+                        free(species->spells[i]);
+               free(species->spells);
+        }
+        if (species->armor_dice) {
+                free(species->armor_dice);
+        }
+        free(species);
+}
diff --git a/src/species.h b/src/species.h
new file mode 100644 (file)
index 0000000..44b6e7d
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef species_h
+#define species_h
+
+#include "macros.h"
+#include "list.h"
+#include "sound.h"
+
+BEGIN_DECL
+
+struct species {
+        char *tag;
+        struct list list;
+        char *name;
+        int str;
+        int intl;
+        int dex;
+        int spd;
+        int vr;
+        struct mmode *mmode;
+
+        int hp_mod;   /* part of base hp contributed by species */
+        int hp_mult;  /* additional hp per-level contributed by species */
+        int mp_mod;   /* similar, for mana */
+        int mp_mult;  /* similar, for mana */
+
+        struct sprite *sleep_sprite;
+        int n_slots;
+        int *slots;
+        int n_spells;
+        char **spells;
+        class ArmsType *weapon;
+        bool visible;
+        sound_t *damage_sound;
+        sound_t *movement_sound;
+        int xpval;           /* reward for killing this type */
+        char *armor_dice;    /* for scaly or chitinous types */
+        struct skill_set *skills;
+        int stationary : 1;  /* doesn't move?                */
+};
+
+extern struct species *species_new(const char *tag,
+                                   const char *name,
+                                   sound_t *damage_sound,
+                                   sound_t *movement_sound,
+                                   int str,
+                                   int intl,
+                                   int dex,
+                                   int spd,
+                                   int vr,
+                                   int hp_mod,
+                                   int hp_mult,
+                                   int mp_mod,
+                                   int mp_mult,
+                                   bool visible,
+                                   int n_slots,
+                                   int n_spells
+                                   );
+extern void species_del(struct species *species);
+
+END_DECL
+
+#endif
diff --git a/src/sprite.c b/src/sprite.c
new file mode 100644 (file)
index 0000000..c94daeb
--- /dev/null
@@ -0,0 +1,889 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#include "cmdwin.h"
+#include "images.h"
+#include "list.h"
+#include "map.h"
+#include "screen.h"
+#include "session.h"
+#include "sprite.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+/* rsurf - wraps a surface with a reference count so sprites can share them
+ * without fear of premature calls to SDL_FreeSurface(). */
+struct rsurf {
+        int ref;              /* reference count                     */
+        SDL_Surface *surf;    /* underlying surface                  */
+        char custom : 1;      /* NOT referenced by any struct images */
+};
+
+/* sprite - animation sequence with different facings */
+struct sprite {
+        char *tag;              /* Script variable name for the sprite.    */
+        int n_frames;           /* per sequence                            */
+        int n_total_frames;     /* n_frames x # facings                    */
+        SDL_Rect *frames;       /* all frames (sequences must be in order) */
+        struct rsurf *rsurf;    /* source of image                         */
+        int facing;             /* current facing sequence                 */
+        int facings;            /* bitmap of supported facing sequences    */
+        int sequence;           /* current animation sequence              */
+        struct sprite *decor;   /* decoration sprites                      */
+        int w_pix, h_pix;       /* frame dimensions (in pixels)            */
+        int faded  : 1;                /* render sprite sem-transparent           */
+        int wave   : 1;         /* vertical roll                           */
+};
+
+static struct {
+        int ticks_to_next_animation;
+} Sprite;
+
+static int sprite_zoom_factor = 1;
+static unsigned int sprite_ticks = 0;
+
+static struct rsurf *rsurf_new(SDL_Surface *surf)
+{
+        struct  rsurf *rsurf;
+
+        rsurf = (struct rsurf*)calloc(1, sizeof(*rsurf));
+        if (!rsurf) {
+                return 0;
+        }
+        rsurf->ref = 1;
+        rsurf->surf = surf;
+        return rsurf;
+}
+
+static void rsurf_unref(struct rsurf *rsurf)
+{
+        assert(rsurf->ref > 0);
+        rsurf->ref--;
+        if (!rsurf->ref) {
+                if (rsurf->surf && rsurf->custom) {
+                        SDL_FreeSurface(rsurf->surf);
+                }
+                free(rsurf);
+        }
+}
+
+/**
+ * For reasons I don't quite understand, doing an RGBA->RGBA blit with
+ * SDL_BlitSurface() seems to result in a totally transparent image. I wrote
+ * this as a debug measure, but since it works, and I don't expect it to run in
+ * a performance-critical part of the code, I'm leaving it in for now.
+ *
+ * @param source The surface to blit from.
+ * @param from The area of the source to blit from.
+ * @param dest The surface to blit to.
+ * @param to The area of the destination to blit to.
+ */
+static void sprite_custom_blit(SDL_Surface *source, SDL_Rect *from,
+                               SDL_Surface *dest, SDL_Rect *to)
+{
+        Uint8 *dpix, *spix, pix = 0;
+        int dx, dy, di, sx,  sy, si, spitch,  dpitch, pix_bytes;
+        Uint8 in_alpha;
+
+        spix = (Uint8*)(source->pixels);
+        dpix = (Uint8*)(dest->pixels);
+
+        dpitch = dest->pitch;
+        spitch = source->pitch;
+
+       pix_bytes = source->format->BytesPerPixel;
+       assert(pix_bytes == 1 || pix_bytes == 2 || pix_bytes == 4);
+       assert(dest->format->BytesPerPixel == pix_bytes);
+       
+        for (dy = 0; dy < from->h; dy++) {
+                sy = dy;
+                for (dx = 0; dx < from->w; dx++) {
+                        sx = dx;
+                        di = (dy + to->y) * dpitch + (dx + to->x) * pix_bytes;
+                        si = (sy + from->y) * spitch + (sx + from->x) * pix_bytes;
+
+                       switch(pix_bytes) {
+                       case 4: pix = *(Uint32*)spix; break;
+                       case 2: pix = *(Uint16*)spix; break;
+                       case 1: pix = *(Uint8 *)spix; break;
+                       }
+                        /* Extract the alpha component of the source pixel. */
+                        in_alpha = ((pix & source->format->Amask) 
+                                     >> source->format->Ashift);
+
+                        /* Skip transparent source pixels, leaving destination
+                         * intact. */
+                        if (SDL_ALPHA_TRANSPARENT == in_alpha) {
+                                continue;
+                        }
+
+                        /* Do a direct copy of everything else. Note that this
+                         * is only correct if the source alpha is opaque. We
+                         * really should blend semi-transparent source
+                         * pixels. */
+                       switch(pix_bytes) {
+                       case 4: *(Uint32*)dpix = pix; break;
+                       case 2: *(Uint16*)dpix = pix; break;
+                       case 1: *(Uint8 *)dpix = pix; break;
+                       }
+                }
+        }
+}
+
+
+/**
+ * Replace the sprite's current image surface with a reference-counted copy.
+ *
+ * @param sprite The sprite to modify.
+ * @returns 0 on success or -1 on error. An error occurs if the surface cannot
+ * be copied.
+ */
+static int sprite_clone_and_replace_rsurf(struct sprite *sprite)
+{
+        SDL_Surface *dest = 0;
+        SDL_Surface *source = sprite->rsurf->surf;
+        SDL_Rect to;
+        int i;
+
+        /* Create a new surface so that the original (which may be shared with
+         * other sprites) is not altered. */
+       dest = SDL_CreateRGBSurface(source->flags,
+                                    sprite->w_pix * sprite->n_total_frames,
+                                    sprite->h_pix,
+                                    source->format->BitsPerPixel,
+                                    source->format->Rmask,
+                                    source->format->Gmask,
+                                    source->format->Bmask,
+                                    source->format->Amask);
+        if (!dest) {
+               perror_sdl("SDL_CreateRGBSurface");
+               return -1;
+        }
+
+        /* Copy each frame of the sprite to the new surface. */
+        to.x = 0;
+        to.y = 0;
+        to.w = sprite->w_pix;
+        to.h = sprite->h_pix;
+        for (i = 0; i < sprite->n_total_frames; i++) {
+                to.x = i * sprite->w_pix;
+
+                /* Blit the frame. */
+                sprite_custom_blit(sprite->rsurf->surf, 
+                            &sprite->frames[i],
+                            dest, &to);
+
+                /* Fixup the frames as we go. */
+                sprite->frames[i] = to;
+        }
+
+        /* If the original surface was a custom rsurf then unref it. */
+        if (sprite->rsurf->custom) {
+                rsurf_unref(sprite->rsurf);
+        }
+
+        /* Stash the surface in a new refcounted surf wrapper. */
+        sprite->rsurf = rsurf_new(dest);
+        sprite->rsurf->custom = 1;
+
+        return 0;
+}
+
+static void sprite_blit_faded(SDL_Surface *source, SDL_Rect *from, 
+                              SDL_Rect *to)
+{
+       int dx, dy, di, sx, sy, si, spitch, dpitch;
+       Uint32 *dpix, *spix, pixel;
+        Uint8 pix_alpha;
+        SDL_Surface *tmp = 0;
+
+       tmp = SDL_CreateRGBSurface(source->flags,
+                                  from->w, from->h,
+                                  source->format->BitsPerPixel,
+                                  source->format->Rmask,
+                                  source->format->Gmask,
+                                  source->format->Bmask,
+                                  source->format->Amask);
+       if (tmp == NULL) {
+               perror_sdl("SDL_CreateRGBSurface");
+               return;
+       }
+
+       dpix = (Uint32 *) tmp->pixels;
+       spix = (Uint32 *) source->pixels;
+
+       dpitch = tmp->pitch / tmp->format->BytesPerPixel;
+       spitch = source->pitch / source->format->BytesPerPixel;
+
+       for (dy = 0; dy < from->h; dy++) {
+               sy = dy;
+               for (dx = 0; dx < from->w; dx++) {
+                       sx = dx;
+                       di = (dy * dpitch + dx);
+                       si = (sy + from->y) * spitch + (sx + from->x);
+
+                        /* Cut alpha component in half. */
+                        pixel = spix[si];
+                        pix_alpha = ((pixel & source->format->Amask) 
+                                     >> source->format->Ashift);
+                        pix_alpha /= 2;
+                        pixel &= ~source->format->Amask;
+                        pixel |= (pix_alpha << source->format->Ashift);
+
+                        /* Assign result. */
+                        dpix[di] = pixel;
+                }
+        }
+        
+        screenBlit(tmp, NULL, to);
+        SDL_FreeSurface(tmp);
+}
+
+static void sprite_paint_wave(struct sprite *sprite, int frame, int x, int y)
+{
+       SDL_Rect src;
+       SDL_Rect dest;
+        int wavecrest;
+
+        frame = (frame + sprite_ticks) % sprite->n_frames;
+
+       /* Offset the index into the current sequence */
+       frame += sprite->sequence * sprite->n_frames;
+
+        // Subtle: when rendering wave sprites zoomed, we'll get artifacts due
+        // to roundoff errors in integer division. Unless we align the
+        // wavecrest to the zoom factor. So for example, if we zoom at a factor
+        // of two then the wavecrest must be a multiple of 2. Since we only
+        // support a zoom factor of 2 right now, the simplest thing to do is
+        // always use 2.
+        wavecrest = (sprite_ticks * 2) % sprite->h_pix;
+        wavecrest = sprite->h_pix - wavecrest; // make it roll south
+
+       /* Wave sprites are painted in two blits. The first blit copies
+        * everything below the wavecrest to the top part of the onscreen tile.
+        * The second blit copies everything above the wavecrest to the
+        * bottom part of the onscreen tile. This gives the appearance of a
+        * wave rolling over the tile in a direction opposite the wavefront. */
+
+       src = sprite->frames[frame];
+       src.y += wavecrest;     /* fixme -- only works because source
+                                 * image has one column of sprites */
+       src.h -= wavecrest;
+
+       dest.x = x;
+       dest.y = y;
+       dest.w = sprite->w_pix;
+       dest.h = src.h;
+
+        if (sprite->faded) {
+                sprite_blit_faded(sprite->rsurf->surf,  &sprite->frames[frame],
+                                  &dest);
+        } else {
+                screenBlit(sprite->rsurf->surf, &src, &dest);
+        }
+
+       src = sprite->frames[frame];
+       src.h = wavecrest;
+
+       dest.x = x;
+       dest.y = dest.y + (sprite->h_pix - wavecrest) / 
+                sprite_zoom_factor;
+       dest.w = sprite->w_pix;
+       dest.h = src.h;
+        
+        if (sprite->faded) {
+                sprite_blit_faded(sprite->rsurf->surf,  &sprite->frames[frame],
+                                  &dest);
+        } else {
+                screenBlit(sprite->rsurf->surf, &sprite->frames[frame], &dest);
+        }
+
+}
+
+static void sprite_paint_normal(struct sprite *sprite, int frame, int x, int y)
+{
+       SDL_Rect dest;
+
+       dest.x = x;
+       dest.y = y;
+       dest.w = sprite->w_pix;
+       dest.h = sprite->h_pix;
+
+#ifndef TEST_PORTRAITS 
+        /* dbg hack -- the following code won't work with portraits as sprites;
+         * need a real fix for oversize sprites... */
+        /* If the sprite is larger than a tile, ASSUME (watch out!) we're
+         * blitting a giant character to the map. In this case the bottom of
+         * the sprite will still line up with the bottom of the tile and it
+         * will be horizontally-centered, making the left, right and top
+         * overlap the neighboring tiles. */
+        if (sprite->w_pix > TILE_W) {
+                dest.x -= (sprite->w_pix - TILE_W) / 2;
+                dest.y -= (sprite->h_pix - TILE_H);
+        }
+#endif                 
+        frame = (frame + sprite_ticks) % sprite->n_frames;
+       frame += sprite->sequence * sprite->n_frames;
+
+        if (sprite->faded) {
+                sprite_blit_faded(sprite->rsurf->surf,  &sprite->frames[frame],
+                                  &dest);
+        } else {
+                screenBlit(sprite->rsurf->surf, &sprite->frames[frame], &dest);
+        }
+
+}
+
+static void sprite_paint_preframed(struct sprite *sprite, int frame, int x, int y)
+{
+       SDL_Rect dest;
+
+       dest.x = x;
+       dest.y = y;
+       dest.w = sprite->w_pix;
+       dest.h = sprite->h_pix;
+
+        /* If the sprite is larger than a tile, ASSUME (watch out!) we're
+         * blitting a giant character to the map. In this case the bottom of
+         * the sprite will still line up with the bottom of the tile and it
+         * will be horizontally-centered, making the left, right and top
+         * overlap the neighboring tiles. */
+        if (sprite->w_pix > TILE_W) {
+                dest.x -= (sprite->w_pix - TILE_W) / 2;
+                dest.y -= (sprite->h_pix - TILE_H);
+        }
+        
+        frame += sprite->sequence * sprite->n_frames;
+
+        if (sprite->faded) {
+                sprite_blit_faded(sprite->rsurf->surf,  &sprite->frames[frame],
+                                  &dest);
+        } else {
+                screenBlit(sprite->rsurf->surf, &sprite->frames[frame], &dest);
+        }
+
+}
+
+static struct sprite * sprite_new_internal(int frames, int facings)
+{
+       struct sprite *sprite;
+
+       sprite = (struct sprite*)calloc(1, sizeof(*sprite));
+        if (!sprite)
+                return 0;
+
+        sprite->n_frames  = frames;
+        sprite->facing = SPRITE_DEF_FACING;
+        sprite->facings = facings;
+        sprite->n_total_frames = (sprite->n_frames 
+                                  * (sprite->facings ? 
+                                     NUM_PLANAR_DIRECTIONS : 1));
+
+       // Allocate and initialize the rect structures which index into the
+       // image. One rect per frame of animation. Note that 'facings' is a
+       // bitmask, not a count. Sprites that don't have different facings
+       // specify 'facings' as zero, so for these assume we'll want one
+       // sequence of frames. Sprites that do support facings will need as
+       // many sequences as there are directions supported by the game.
+       
+       sprite->frames = (SDL_Rect*)calloc(sprite->n_total_frames, 
+                                           sizeof(SDL_Rect));
+        if (!sprite->frames) {
+                goto abort;
+        }
+
+       return sprite;
+
+ abort:
+        sprite_del(sprite);
+        return 0;
+}
+
+void sprite_del(struct sprite *sprite)
+{
+        if (sprite->tag)
+                free(sprite->tag);
+       if (sprite->frames)
+               free(sprite->frames);
+        if (sprite->decor)
+                sprite_del(sprite->decor);
+        rsurf_unref(sprite->rsurf);
+
+        free(sprite);
+}
+
+void sprite_paint(struct sprite *sprite, int frame, int x, int y)
+{
+        while (sprite) {
+
+                if (sprite->wave) {
+                        sprite_paint_wave(sprite, frame, x, y);
+                } else {
+                        sprite_paint_normal(sprite, frame, x, y);
+                }
+                
+                sprite = sprite->decor;
+        }
+}
+
+void sprite_paint_frame(struct sprite *sprite, int frame, int x, int y)
+{
+        while (sprite) {
+
+                if (sprite->wave) {
+                        sprite_paint_wave(sprite, frame, x, y);
+                } else {
+                        sprite_paint_preframed(sprite, frame, x, y);
+                }
+                
+                sprite = sprite->decor;
+        }
+}
+
+void sprite_advance_ticks(int ticks)
+{
+        Sprite.ticks_to_next_animation -= ticks;
+        if (Sprite.ticks_to_next_animation <= 0) {
+                sprite_advance_frames();
+                cmdwin_repaint_cursor();
+                statusRepaint();
+                Sprite.ticks_to_next_animation += AnimationTicks;
+        }
+}
+
+int sprite_init(void)
+{
+        Sprite.ticks_to_next_animation = 0;
+        return 0;
+}
+
+void sprite_advance_frames(void)
+{
+        if (TimeStop) {
+                Session->time_stop_ticks++;
+        } else {
+                sprite_ticks++;
+        }
+       mapSetDirty();
+
+}
+
+int sprite_get_facing(struct sprite *sprite)
+{
+        return sprite->facing;
+}
+
+int sprite_set_facing(struct sprite *sprite, int facing)
+{
+       int bit, i;
+
+       if (facing == SPRITE_DEF_FACING) {
+               sprite->sequence = 0;
+               return 0;
+       }
+       // facing supported?
+       if ((sprite->facings & (1 << facing)) == 0) {
+                dbg("warn: sprite_set_facing: facing=%d invalid for "\
+                    "sprite %s\n",
+                    facing, sprite->tag);
+               return -1;
+        }
+
+       sprite->facing = facing;
+       sprite->sequence = 0;
+
+       // Find the sequence
+       for (i = 0; i < facing; i++) {
+               bit = (1 << i);
+               if (sprite->facings & bit)
+                       sprite->sequence++;
+       }
+
+       return 0;
+}
+
+int sprite_fade(struct sprite *sprite)
+{
+       sprite->faded = 1;
+       return 0;
+}
+
+void sprite_unfade(struct sprite *sprite)
+{
+       sprite->faded = 0;
+}
+
+void sprite_zoom_out(int factor)
+{
+        sprite_zoom_factor *= factor;
+}
+
+extern void sprite_zoom_in(int factor)
+{
+        sprite_zoom_factor /= factor;
+}
+
+struct sprite * sprite_new(const char *tag, int frames, int index, int wave, 
+                           int facings, struct images *images)
+{
+       struct sprite *sprite;
+        int col_width;
+        int row_height;
+       int i;
+        int frame;
+        int col;
+        int row;
+
+        /* Allocate it. */
+       sprite = sprite_new_internal(frames, facings);
+        if (!sprite)
+                return 0;
+
+        /* Dupe the tag if applicable. */
+        if (tag) {
+                if (!(sprite->tag = strdup(tag)))
+                        goto abort;
+        }
+
+        /* Create a new refcounted surf. */
+        if (!(sprite->rsurf = rsurf_new(images->images)))
+                goto abort;
+
+
+        /* Fill out the rest of the basic fields. */
+        sprite->wave = !!wave;
+        sprite->w_pix = images->w;
+        sprite->h_pix = images->h;
+
+        /* Fill out the frames based on the index and image info. */
+       col_width = (images->w + images->offx);
+       row_height = (images->h + images->offy);
+       for (i = 0, frame = index; 
+             i < sprite->n_total_frames; 
+             i++, frame++) {
+               col = frame % images->cols;
+               row = frame / images->cols;
+               sprite->frames[i].x = col * col_width + images->offx;
+               sprite->frames[i].y = row * row_height + images->offy;
+               sprite->frames[i].w = images->w;
+               sprite->frames[i].h = images->h;
+       }        
+
+       return sprite;
+
+ abort:
+        sprite_del(sprite);
+        return 0;
+}
+
+struct sprite *sprite_clone(struct sprite *orig, const char *tag)
+{
+        SDL_Rect *frames;
+
+        /* Allocate it. */
+        struct sprite *sprite = sprite_new_internal(orig->n_frames, 
+                                                    orig->facings);
+        if (! sprite) {
+                return 0;
+        }
+
+        /* Remember the frames pointer before we wipe it out with the copy. */
+        frames = sprite->frames;
+
+        /* Copy the sprite info. */
+        memcpy(sprite, orig, sizeof(*orig));
+
+        /* Copy the frames. */
+        sprite->frames = frames;
+        memcpy(sprite->frames, orig->frames, 
+               sprite->n_total_frames * sizeof(sprite->frames[0]));
+
+        /* Bump the refcount on the surface. */
+        sprite->rsurf->ref++;
+
+        /* Dupe the tag if applicable. */
+        if (tag) {
+                sprite->tag = strdup(tag);
+        } else if (orig->tag) {
+                sprite->tag = strdup(orig->tag);
+        }
+
+        return sprite;
+}
+
+void sprite_append_decoration(struct sprite *base, struct sprite *decor)
+{
+        assert(base);
+        while (base->decor) {
+                base = base->decor;
+        }
+        base->decor = sprite_clone(decor, decor->tag);
+}
+
+char *sprite_get_tag(struct sprite *sprite)
+{
+        return sprite->tag;
+}
+
+int sprite_is_faded(struct sprite *sprite)
+{
+        return sprite->faded;
+}
+
+int sprite_can_face(struct sprite *sprite, int facing)
+{
+        return (sprite->facings & (1 << facing));
+}
+
+/* sprite_save - save to file for reload. */
+void sprite_save(struct sprite *sprite, struct save *save)
+{
+        /* For simple sprites just save the tag. */
+        if (!sprite->decor) {
+                assert(sprite->tag);
+                save->write(save, "%s ; sprite\n", sprite->tag);
+                return;
+        }
+
+        /* For composite sprites */
+        save->write(save, ("(mk-composite-sprite (list "));
+        while (sprite) {
+                assert(sprite->tag);
+                save->append(save, "%s ", sprite->tag);
+                sprite = sprite->decor;
+        }
+        save->append(save, ")) ; composite sprite\n");
+}
+
+static void sprite_apply_matrix_to_image(SDL_Surface *source, SDL_Rect *from, 
+                                         SDL_Surface *dest,  SDL_Rect *to,
+                                         float matrix[4][3])
+{
+        Uint8 *dpix, *spix, out_pix, in_pix = 0;
+        int dx, dy, di, sx,  sy, si, spitch,  dpitch, sbytes, dbytes;
+        Uint8 in_red, in_grn, in_blu, in_alpha, out_red, out_grn, out_blu, 
+                out_alpha;
+        int ired, igrn, iblu;
+        Uint32 transparent;
+
+        spix = (Uint8*)(source->pixels);
+        dpix = (Uint8*)(dest->pixels);
+
+        dpitch = dest->pitch;
+        spitch = source->pitch;
+
+       sbytes = source->format->BytesPerPixel;
+       assert(sbytes == 1 || sbytes == 2 || sbytes == 4);
+       dbytes = dest->format->BytesPerPixel;
+       assert(dbytes == 1 || dbytes == 2 || dbytes == 4);
+       
+        /* Make a transparent pixel. If SDL_ALPHA_TRANSPARENT is non-zero that
+         * means transparency is high, so use the mask value. Otherwise zero
+         * means transparent. */
+        if (SDL_ALPHA_TRANSPARENT) {
+                transparent = dest->format->Amask;
+        } else {
+                transparent = 0;
+        }
+
+        for (dy = 0; dy < from->h; dy++) {
+                sy = dy;
+                for (dx = 0; dx < from->w; dx++) {
+                        sx = dx;
+                        di = (dy + to->y) * dpitch + (dx + to->x) * dbytes;
+                        si = (sy + from->y) * spitch + (sx + from->x) * sbytes;
+
+                       switch(sbytes) {
+                       case 4: in_pix = *(Uint32*)spix; break;
+                       case 2: in_pix = *(Uint16*)spix; break;
+                       case 1: in_pix = *(Uint8 *)spix; break;
+                       }
+                        /* Extract the alpha component of the source pixel. */
+                        in_alpha = ((in_pix & source->format->Amask) 
+                                     >> source->format->Ashift);
+
+                        /* For speed, skip transparent pixels. */
+                        if (SDL_ALPHA_TRANSPARENT == in_alpha) {
+                               switch(sbytes) {
+                               case 4: *(Uint32*)dpix = transparent; break;
+                               case 2: *(Uint16*)dpix = transparent; break;
+                               case 1: *(Uint8 *)dpix = transparent; break;
+                               }
+                                continue;
+                        }
+
+                        /* Extract the color components of the source pixel. */
+                        in_red = ((in_pix & source->format->Rmask) 
+                                   >> source->format->Rshift);
+                        in_grn = ((in_pix & source->format->Gmask) 
+                                   >> source->format->Gshift);
+                        in_blu = ((in_pix & source->format->Bmask) 
+                                   >> source->format->Bshift);
+
+                        /* Run the matrix conversion. */
+                        ired = (int)((in_red * matrix[0][0])
+                                     + (in_grn * matrix[0][1])
+                                     + (in_blu * matrix[0][2])
+                                     + matrix[3][0]);
+
+                        igrn = (int)((in_red * matrix[1][0])
+                                     + (in_grn * matrix[1][1])
+                                     + (in_blu * matrix[1][2])
+                                     + matrix[3][1]);
+                        
+                        iblu = (int)((in_red * matrix[2][0])
+                                     + (in_grn * matrix[2][1])
+                                     + (in_blu * matrix[2][2])
+                                     + matrix[3][2]);
+
+                        out_alpha = in_alpha;
+
+                        /* Clamp the result to the allowed range. */
+                        out_red = clamp(ired, 0, 
+                                        (int)(dest->format->Rmask 
+                                              >> dest->format->Rshift));
+                        out_grn = clamp(igrn, 0, 
+                                        (int)(dest->format->Gmask 
+                                              >> dest->format->Gshift));
+                        out_blu = clamp(iblu, 0, 
+                                        (int)(dest->format->Bmask 
+                                              >> dest->format->Bshift));
+
+                        /* Recombine them, along with the original alpha
+                         * component, into the destination pixel. */
+                        out_pix = (out_red << dest->format->Rshift
+                                    | out_grn << dest->format->Gshift
+                                    | out_blu << dest->format->Bshift
+                                    | out_alpha << dest->format->Ashift);
+                       switch(sbytes) {
+                       case 4: *(Uint32*)dpix = out_pix; break;
+                       case 2: *(Uint16*)dpix = out_pix; break;
+                       case 1: *(Uint8 *)dpix = out_pix; break;
+                       }
+                }
+        }
+}
+
+/* sprite_apply_matrix - applies a color conversion matrix. This is good for
+ * converting monotone or grayscale images into other tones. The matrix is
+ * applied as follows:
+ *
+ * r = R*m[0][0] + G*m[0][1] + B*m[0][2] + m[3][0]
+ * g = R*m[1][0] + G*m[1][1] + B*m[1][2] + m[3][1]
+ * b = R*m[2][0] + G*m[2][1] + B*m[2][2] + m[3][2]
+ *
+ */
+void sprite_apply_matrix(struct sprite *sprite, float matrix[4][3])
+{
+        SDL_Surface *dest = 0;
+        SDL_Surface *source = sprite->rsurf->surf;
+        SDL_Rect to;
+        int i;
+
+        /* Create a new surface so that the original (which may be shared with
+         * other sprites) is not altered. */
+       dest = SDL_CreateRGBSurface(source->flags,
+                                    sprite->w_pix * sprite->n_total_frames,
+                                    sprite->h_pix,
+                                    source->format->BitsPerPixel,
+                                    source->format->Rmask,
+                                    source->format->Gmask,
+                                    source->format->Bmask,
+                                    source->format->Amask);
+        if (!dest) {
+               perror_sdl("SDL_CreateRGBSurface");
+               return;
+        }
+
+        /* Apply the correction to each frame of the sprite. This could be
+         * optimized a bit by applying the matrix in one pass to the entire set
+         * of frames, since they are always contiguous in the image. */
+        to.x = 0;
+        to.y = 0;
+        to.w = sprite->w_pix;
+        to.h = sprite->h_pix;
+        for (i = 0; i < sprite->n_total_frames; i++) {
+                to.x = i * sprite->w_pix;
+
+                /* Apply to the image. */
+                sprite_apply_matrix_to_image(sprite->rsurf->surf, 
+                                             &sprite->frames[i],
+                                             dest, &to, matrix);
+
+                /* Fixup the frames as we go. */
+                sprite->frames[i] = to;
+        }
+
+        /* Stash the surface in a new refcounted surf wrapper. */
+        sprite->rsurf = rsurf_new(dest);
+        sprite->rsurf->custom = 1;
+}
+
+void sprite_strip_decorations(struct sprite *sprite)
+{
+        if (sprite->decor) {
+                /* Decoration sprites are always single-referenced clones, so
+                 * blow them away when they're stripped. This will recursively
+                 * delete all the trailing decor sprites. */
+                sprite_del(sprite->decor);
+                sprite->decor = 0;
+        }
+}
+
+void sprite_blit_over(struct sprite *dest, struct sprite *src)
+{
+        int i = 0;
+
+        /* Check preconditions. */
+        assert(dest->w_pix == src->w_pix);
+        assert(dest->h_pix == src->h_pix);
+        assert(dest->n_total_frames == src->n_total_frames);
+
+        /* Clone the destination sprite's surface before changing it. */
+        if (sprite_clone_and_replace_rsurf(dest))
+                return;
+
+        /* For each frame... */
+        for (i = 0; i < dest->n_total_frames; i++) {
+
+                /* Blit the source over the destination. */
+                sprite_custom_blit(src->rsurf->surf, &src->frames[i],
+                                   dest->rsurf->surf, &dest->frames[i]);
+                                
+        }
+}
+
+int sprite_num_frames(struct sprite *sprite)
+{
+       return sprite->n_frames;        
+}
+
+int sprite_facings_list(struct sprite *sprite)
+{
+       return sprite->facings; 
+}
+
+void sprite_paint_direct(struct sprite *sprite, int frame, SDL_Rect *dest)
+{
+       screenBlit(sprite->rsurf->surf, &sprite->frames[frame], dest);
+}
diff --git a/src/sprite.h b/src/sprite.h
new file mode 100644 (file)
index 0000000..2a3884b
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef sprite_h
+#define sprite_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "list.h"
+
+#include <SDL.h> /* for Uint32 */
+
+
+#define SPRITE_DEF_FACING -1
+
+struct images;
+struct sprite;
+struct save;
+
+extern int sprite_init(void);
+extern void sprite_paint(struct sprite *sprite, int frame, int x, int y);
+extern void sprite_paint_frame(struct sprite *sprite, int frame, int x, int y);
+extern void sprite_advance_frames(void);
+extern int sprite_set_facing(struct sprite *sprite, int direction);
+extern int sprite_get_facing(struct sprite *sprite);
+
+extern int sprite_fade(struct sprite *sprite);
+extern void sprite_unfade(struct sprite *sprite);
+extern void sprite_zoom_out(int factor);
+extern void sprite_zoom_in(int factor);
+extern void sprite_advance_ticks(int ticks);
+extern void sprite_append_decoration(struct sprite *sprite, 
+                                     struct sprite *decor);
+
+/* sprite_clone - clone an existing sprite and give it a new tag. */
+extern struct sprite *sprite_clone(struct sprite *orig, const char *new_tag);
+
+extern struct sprite * sprite_new(const char *tag, int frames, int index, int wave, 
+                                  int facings, struct images *image);
+extern void sprite_del(struct sprite *sprite);
+extern char *sprite_get_tag(struct sprite *sprite);
+extern int sprite_is_faded(struct sprite *sprite);
+extern int sprite_can_face(struct sprite *sprite, int facing);
+
+/* sprite_save - save to file for reload. */
+extern void sprite_save(struct sprite *sprite, struct save *save);
+
+/* sprite_apply_matrix - applies a color conversion matrix. This is good for
+ * converting monotone or grayscale images into other tones. The matrix is
+ * applied as follows:
+ *
+ * r = R*m[0][0] + G*m[0][1] + B*m[0][2] + m[3][0]
+ * g = R*m[1][0] + G*m[1][1] + B*m[1][2] + m[3][1]
+ * b = R*m[2][0] + G*m[2][1] + B*m[2][2] + m[3][2]
+ *
+ */
+void sprite_apply_matrix(struct sprite *sprite, float matrix[4][3]);
+
+/**
+ * Remove all decorations from the sprite and discard them (see
+ * sprite_append_decoration()). Useful for rebuilding decorated sprites from
+ * scratch.
+ *
+ * @param sprite The sprite to strip.
+ */
+extern void sprite_strip_decorations(struct sprite *sprite);
+
+/**
+ * Blit one sprite over another. The images of the destination sprite will be
+ * copied and then modified by the blit, so you don't have to worry about other
+ * sprites that refer to the same images. The two sprites should have the same
+ * number of frames and the same dimensions or the results are not defined. The
+ * modification will not be saved with the game, so it needs to be redone at
+ * load time.
+ *
+ * @param dest The sprite that will be modified.
+ * @param src The sprite that will blit over the other one. It won't be
+ * modified.
+ *
+ */
+extern void sprite_blit_over(struct sprite *dest, 
+                             struct sprite *src);
+                             
+extern int sprite_num_frames(struct sprite *sprite);
+extern int sprite_facings_list(struct sprite *sprite);
+
+extern void sprite_paint_direct(struct sprite *sprite, int frame, SDL_Rect *dest);
+
+END_DECL
+
+#endif
diff --git a/src/status.c b/src/status.c
new file mode 100644 (file)
index 0000000..5325dc6
--- /dev/null
@@ -0,0 +1,1788 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "status.h"
+
+#include "applet.h"
+#include "screen.h"
+#include "sprite.h"
+#include "common.h"
+#include "player.h"
+#include "object.h"
+#include "Arms.h"
+#include "ascii.h"
+#include "console.h"
+#include "sky.h"
+#include "wind.h"
+#include "foogod.h"
+#include "mmode.h"
+#include "cmdwin.h"
+#include "dice.h"
+#include "occ.h"
+#include "effect.h"
+#include "session.h"
+#include "magic.h"
+#include "clock.h"
+
+#include "ztats.h"
+#include "ztats_arms.h"
+#include "ztats_items.h"
+#include "ztats_misc.h"
+#include "ztats_pm.h"
+#include "ztats_reagents.h"
+#include "ztats_spells.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <ctype.h>
+
+#define LINE_H TILE_H
+#define Y_TO_LINE(Y) (((Y) - Status.screenRect.y) / TILE_H)
+#define N_LINES Status.numLines        /* (STAT_H / TILE_H) */
+
+#define TALL_H (SCREEN_H - 4 * BORDER_H - 8 * ASCII_H)
+#define MAX_TITLE_LEN (STAT_CHARS_PER_LINE-2)
+#define STAT_MAX_H TALL_H
+
+
+#define STAT_MODE_STACK_DEPTH 10
+
+static struct status {
+       SDL_Rect titleRect;
+       SDL_Rect screenRect;
+       SDL_Rect lineRect;
+       void (*paint) (void);
+       void (*scroll) (enum StatusScrollDir);
+       int pcIndex;
+       struct inv_entry *selectedEntry;
+       enum StatusMode mode;
+
+       /**
+         * The index of the list entry that appears at the top of the status
+         * window.
+         */
+       int topLine;
+
+       /**
+         * Not sure what this is.
+         */
+       int maxLine;
+
+       /**
+         * The number of lines in the status window.
+         */
+       int numLines;
+
+       /**
+         * The index of the list entry that is currently highlighted in the
+         * status window.
+         */
+       int curLine;
+
+       /**
+         * The text that appears in the title bar at the top of the status
+         * window.
+         */
+       char title[MAX_TITLE_LEN+1];
+
+       const char *pg_title;
+        char *pg_text;
+       SDL_Surface *pg_surf;
+       SDL_Rect pg_rect;
+       int pg_max_y;
+
+       const char *list_title;
+       int list_sz;
+       struct trade_info *trades;
+       struct stat_list_entry *list;
+       const char **strlist;
+       
+       Container *container;
+       struct filter *filter;
+       void (*show_thing)(SDL_Rect * rect, void *thing);
+
+       /**
+         * Sometimes I just don't want to repaint until I'm done doing more
+         * stuff. Repaints will be suppressed unless this counter is
+         * zero. Limited to internal use only for now.
+         */
+       int suppressRepaint;
+
+       /**
+         * New experimental super-generic stuff
+         */
+       struct stat_super_generic_data *super_generic;
+
+       enum StatusMode stack[STAT_MODE_STACK_DEPTH];
+       int top;
+        struct list applet_stack;
+
+} Status;
+
+/* filtering functions used with status_show_container() */
+static bool stat_filter_ready_arms(struct inv_entry *ie, void *fdata);
+static bool stat_filter_drop(struct inv_entry *ie, void *fdata);
+
+/* functions to show specific types of things from status_show_containe() */
+static void status_show_generic_object_type(SDL_Rect *rect, void *thing);
+static void status_show_mix_reagent(SDL_Rect *rect, void *thing);
+
+/* super-generic functions */
+static void stat_super_generic_paint();
+static void stat_super_generic_scroll(enum StatusScrollDir dir);
+
+/* Filter for the player inventory during the R)eady UI. */
+static struct filter stat_ready_arms_filter = {
+       stat_filter_ready_arms, 0
+};
+
+static struct filter stat_drop_filter = {
+       stat_filter_drop, 0
+};
+
+static bool stat_filter_usable(struct inv_entry *ie, void *fdata)
+{
+       return (ie->type->isUsable());
+}
+
+static struct filter stat_use_filter = {
+       stat_filter_usable, 0
+};
+
+static bool stat_filter_mixable(struct inv_entry *ie, void *fdata)
+{
+       return (ie->type->isMixable());
+}
+
+
+static struct filter stat_mix_filter = {
+       stat_filter_mixable, 0
+};
+
+static bool stat_filter_ready_arms(struct inv_entry *ie, void *fdata)
+{
+       if (! ie->type->isReadyable()) {
+               return false;
+       }
+                               
+       /* Are any available? */
+       if (ie->count > ie->ref)
+               return true;
+                               
+       /* Is one already readied by the current party member? */
+       if (ie->ref && 
+                       player_party->getMemberAtIndex(Status.pcIndex)->
+                               hasReadied((class ArmsType *)ie->type))
+       {
+               return true;
+       }
+
+       return false;
+}
+
+static bool stat_filter_drop(struct inv_entry *ie, void *fdata)
+{
+       return (! ie->type->isCastable()
+               && (ie->ref < ie->count));
+}
+
+static void switch_to_tall_mode(void)
+{
+       if (Status.screenRect.h == TALL_H)
+               return;
+
+       Status.screenRect.h = TALL_H;
+       Status.numLines = Status.screenRect.h / LINE_H;
+
+       foogod_set_y(STAT_Y + Status.screenRect.h + BORDER_H);
+
+       foogodRepaint();
+       consoleRepaint();
+       screen_repaint_frame();
+}
+
+static void status_set_line_height(int lines)
+{
+       int height = lines * ASCII_H;
+       
+       if (height > STAT_MAX_H) {
+               height = STAT_MAX_H;
+       }
+       
+       Status.screenRect.h = height;
+       Status.numLines = Status.screenRect.h / ASCII_H;
+       
+       foogod_set_y(STAT_Y + Status.screenRect.h + BORDER_H);
+       foogodRepaint();
+       consoleRepaint();
+       screen_repaint_frame();
+}
+
+static void switch_to_short_mode(void)
+{
+       int num_in_party = player_party->getSize();
+       int party_height = (num_in_party * TILE_H);
+
+       if (Status.screenRect.h == party_height)
+               return;
+
+       Status.numLines = num_in_party;
+       Status.screenRect.h = party_height;
+
+       foogod_set_y(STAT_Y + Status.screenRect.h + BORDER_H);
+       //console_set_y(foogod_get_y() + FOOGOD_H);
+
+       foogodRepaint();
+       consoleRepaint();
+       screen_repaint_frame();
+}
+
+int statusInit()
+{
+       memset(&Status, 0, sizeof(Status));
+
+       Status.screenRect.x = STAT_X;
+       Status.screenRect.y = STAT_Y;
+       Status.screenRect.w = STAT_W;
+       Status.screenRect.h = TILE_H;
+                                       
+       Status.titleRect.x = STAT_X;
+       Status.titleRect.y = 0;
+       Status.titleRect.w = STAT_W;    // - (2 * BORDER_W);
+       Status.titleRect.h = BORDER_H;
+
+       Status.lineRect.x = Status.screenRect.x + TILE_W;
+       Status.lineRect.y = Status.screenRect.y;
+       Status.lineRect.w = Status.screenRect.w - TILE_W;
+       Status.lineRect.h = LINE_H;
+
+       Status.numLines = Status.screenRect.h / LINE_H;
+
+       foogod_set_y(STAT_Y + Status.screenRect.h + BORDER_H);
+
+        list_init(&Status.applet_stack);
+
+#ifdef ztats_h
+        ztats_init();
+#endif
+#ifdef ztats_pm_h
+        ztats_pm_init();
+#endif
+#ifdef ztats_arms_h
+        ztats_arms_init();
+#endif
+#ifdef ztats_reagents_h
+        ztats_reagents_init();
+#endif
+#ifdef ztats_spells_h
+        ztats_spells_init();
+#endif
+#ifdef ztats_items_h
+        ztats_items_init();
+#endif
+#ifdef ztats_misc_h
+        ztats_misc_init();
+#endif
+
+       return 0;
+}
+
+void status_set_title(const char *title)
+{
+       strncpy(Status.title, title, MAX_TITLE_LEN);
+       Status.title[MAX_TITLE_LEN]=0;
+}
+
+void status_repaint_title(void)
+{
+       screenErase(&Status.titleRect);
+       screenPrint(&Status.titleRect, SP_CENTERED | SP_ONBORDER, "%s", 
+                                               Status.title);
+       screenUpdate(&Status.titleRect);
+}
+
+static char status_arms_stat_color(char *dice)
+{
+       int avg = dice_average(dice);
+       if (avg < 0)
+               return STAT_PENALTY_CLR;
+       if (avg > 0)
+               return STAT_BONUS_CLR;
+       return STAT_NULL_CLR;
+}
+
+/* status_show_arms_stats -- helper function to print the arms stats the same
+ * way for all viewers. */
+void status_show_arms_stats(SDL_Rect *rect, ArmsType *arms)
+{
+       char *hit   = arms->getToHitDice();
+       char *dmg   = arms->getDamageDice();
+
+       char *def   = arms->getToDefendDice();
+       char *armor = arms->getArmorDice();
+
+       screenPrint(rect, 0, 
+                   "^c+%cHit:^c%c%s ^c%cDmg:^c%c%s ^c%cDef:^c%c%s ^c%cArm:^c%c%s^c-", 
+
+                   STAT_LABEL_CLR,
+                   status_arms_stat_color(hit), hit,
+                   STAT_LABEL_CLR,
+                   status_arms_stat_color(dmg), dmg,
+                   STAT_LABEL_CLR,
+                   status_arms_stat_color(def), def,
+                   STAT_LABEL_CLR,
+                   status_arms_stat_color(armor), armor
+               );
+       rect->y += (TILE_H - ASCII_H);
+}
+
+/* status_show_ready_arms -- called during the R)eady command, this shows
+ * individual arms, indicating if they are available or already held by the
+ * character in question */
+static void status_show_ready_arms(SDL_Rect * rect, void *thing)
+{
+       struct inv_entry *ie = (struct inv_entry*)thing;
+       ArmsType *arms = (ArmsType*)ie->type;
+       int inUse = 0;
+       int avail = ie->count - ie->ref;
+       
+       assert(ie->count);
+       assert(avail >= 0);
+       
+       /* sprite */
+       sprite_paint(arms->getSprite(), 0, rect->x, rect->y);
+       rect->x += TILE_W;
+       
+       if (ie->ref && 
+               player_party->getMemberAtIndex(Status.pcIndex)->
+               hasReadied(arms)) {
+                       inUse = 1;
+       }
+       
+       /* quantity and name */
+       if (avail) {
+               screenPrint(rect, 0, "^c+%c%2d%c%s^c-",
+                       (inUse?STAT_INUSE_CLR:STAT_NULL_CLR),
+                       avail,
+                       (inUse?'*':' '),
+                       arms->getName());
+       } else {
+               screenPrint(rect, 0, "^c+%c--%c%s^c-",
+                       (inUse?STAT_INUSE_CLR:STAT_UNAVAIL_CLR),
+                       (inUse?'*':' '),
+                       arms->getName());
+       }
+       rect->y += ASCII_H;
+       
+       /* stats */
+       status_show_arms_stats(rect, arms);
+       rect->x -= TILE_W;
+}
+
+/* status_range_color -- return red, green or yellow to reflect the relative
+ * level of a statistic */
+char status_range_color(int cur, int max)
+{
+       if (cur > max/2)
+       {
+               return STAT_OK_CLR;
+       } 
+       else if (cur > max/4)
+       {
+               return STAT_WARNING_CLR;
+       } 
+       else
+       {
+               return STAT_CRITICAL_CLR;
+       }
+}
+
+static void status_show_character_var_stats(SDL_Rect *rect, 
+                                            class Character *pm)
+{
+       /* Show the xp, hp and mp */
+       /* Note that getXpForLevel(2) - getXpForLevel(1) != getXpForLevel(1)*/
+       screenPrint(rect, 0, 
+                       "^c+%cHP:^c%c%d^cw/%d "
+                       "^c%cMP:^c%c%d^cw/%d "
+                       "^c%cAP:^c%c%d^cw/%d "
+                       "^c%cLvl:^cw%d^c%c(%d%%)^c-"
+                       , STAT_LABEL_CLR
+                       , status_range_color(pm->getHp(), pm->getMaxHp())
+                       , pm->getHp(), pm->getMaxHp()
+
+                       , STAT_LABEL_CLR
+                       , status_range_color(pm->getMana(), pm->getMaxMana())
+                       , pm->getMana(), pm->getMaxMana()
+
+                       , STAT_LABEL_CLR
+                       , status_range_color(pm->getActionPoints(), 
+                                                                               pm->getActionPointsPerTurn())
+                       , pm->getActionPoints()
+                       , pm->getActionPointsPerTurn()
+
+                       , STAT_LABEL_CLR
+                       , pm->getLevel()
+                       , STAT_LABEL_CLR
+                       , (100 * (pm->getExperience()-pm->getXpForLevel(pm->getLevel()))/(pm->getXpForLevel(pm->getLevel()+1)-pm->getXpForLevel(pm->getLevel())))
+               );
+       rect->y += ASCII_H;
+}
+
+static void myShadeLines(int line, int n)
+{
+       SDL_Rect rect;
+       rect.x = Status.screenRect.x;
+       rect.y = Status.screenRect.y + line * TILE_H;
+       rect.w = STAT_W;
+       rect.h = ASCII_H * n;
+       screenShade(&rect, 128);
+}
+
+static void myShadeHalfLines(int line, int n)
+{
+       SDL_Rect rect;
+       rect.x = Status.screenRect.x;
+       rect.y = Status.screenRect.y + line * ASCII_H;
+       rect.w = STAT_W;
+       rect.h = ASCII_H * n;
+       screenShade(&rect, 128);
+}
+
+/* status_show_generic_object_type -- show a generic object type (just name and
+ * quantity) */
+static void status_show_generic_object_type(SDL_Rect *rect, void *thing)
+{
+       struct inv_entry *ie = (struct inv_entry*)thing;
+       if (ie->type->getSprite()) {
+                               sprite_paint(ie->type->getSprite(), 0, rect->x, rect->y);
+       }
+       
+       /* Indent past the sprite column. */
+       rect->x += TILE_W;
+
+       /* This is a single-line entry in a two-line rect, so center it
+               * vertically. */
+       rect->y += LINE_H / 4;
+
+       screenPrint(rect, 0, "%2d %s", ie->count - ie->ref, 
+                                       ie->type->getName());
+
+       /* Carriage-return line-feed */
+       rect->y += (LINE_H * 3) / 4;
+       rect->x -= TILE_W;
+}
+
+/* status_show_mix_reagent -- show a reagent during the M)ix UI. Marks reagents
+ * which have been selected for mixing. */
+static void status_show_mix_reagent(SDL_Rect *rect, void *thing)
+{
+       struct inv_entry *ie = (struct inv_entry*)thing;
+       if (ie->type->getSprite()) {
+               sprite_paint(ie->type->getSprite(), 0, rect->x, rect->y);
+       }
+       
+       /* Indent past the sprite column. */
+       rect->x += TILE_W;
+       
+       /* This is a single-line entry in a two-line rect, so center it
+               * vertically. */
+       rect->y += LINE_H / 4;
+
+       /* During mixing, if the ref field is set that means the reagent has
+               * been selected to be part of the mixture (see cmdMix() in cmd.c, this
+               * is something of a hack). Show an asterisk to mark selected
+               * reagents. */
+       screenPrint(rect, 0, "%2d%c%s", 
+                       ie->count, 
+                       (ie->ref ? '*':' '), 
+                       ie->type->getName());
+
+       /* Carriage-return line-feed */
+       rect->y += (LINE_H * 3) / 4;
+       rect->x -= TILE_W;
+}
+
+/* stat_show_container -- generic function for showing the contents of a
+ * container. Uses a filter to select certain types of contents for display,
+ * and a specialized function for that type of content. */
+static void stat_show_container()
+{
+       SDL_Rect rect;
+       struct inv_entry *ie;
+       int top = Status.topLine;
+       int line = 0;
+
+       rect = Status.screenRect;
+       rect.h = LINE_H;
+
+       for (ie = Status.container->first(Status.filter);
+                       ie != NULL; 
+                       ie = Status.container->next(ie, Status.filter))
+       {
+
+               /* Check the scrolling window */
+               if (top) {
+                       top--;
+                       continue;
+               }
+       
+               /* Use a specific function to show whatever it is. This should
+               * advance the rect to the next entry position before it
+               * returns. */
+               Status.show_thing(&rect, ie);
+       
+               /* Highlight the selected item by shading all the other
+               * entries. */
+               if (Status.selectedEntry && ie != Status.selectedEntry) {
+                       myShadeLines(line, 2);
+               }
+       
+               line++;
+       
+               /* Don't print outside the status window. */
+               if (line >= N_LINES)
+                       break;
+       }
+
+}
+
+static void stat_scroll_container(enum StatusScrollDir dir)
+{
+       struct inv_entry *tmp;
+       int n_lines;
+       int i;
+
+       n_lines = Status.container->filter_count(Status.filter);
+
+       if (!n_lines)
+               return;
+
+       switch (dir) {
+       case ScrollUp:
+               tmp = Status.container->prev(Status.selectedEntry, 
+                                                                                                                       Status.filter);
+               if (!tmp)
+                       break;
+               Status.selectedEntry = tmp;
+               if (Status.topLine &&
+                       Status.curLine < (n_lines - Status.numLines / 2))
+                       Status.topLine--;
+               Status.curLine--;
+               break;
+       case ScrollDown:
+               tmp = Status.container->next(Status.selectedEntry, 
+                                                                                                                       Status.filter);
+               if (!tmp)
+                       break;
+               Status.selectedEntry = tmp;
+               if (Status.topLine < Status.maxLine &&
+                       Status.curLine >= (Status.numLines / 2))
+                       Status.topLine++;
+               Status.curLine++;
+               break;
+       case ScrollPageUp:
+               for (i = 0; i < Status.numLines; i++) {
+                       stat_scroll_container(ScrollUp);
+               }
+               break;
+       case ScrollPageDown:
+               for (i = 0; i < Status.numLines; i++) {
+                       stat_scroll_container(ScrollDown);
+               }
+               break;
+       default:
+               break;
+       }
+}
+
+/* status_show_effect_icon -- visitor function for
+ * status_show_party_view_character_effects(), called for each effect on a
+ * character and paints the status icons if the effect has one */
+static int status_show_effect_icon(hook_entry_t *entry, void *data)
+{
+       SDL_Rect *rect = (SDL_Rect*)data;
+       struct effect *eff = entry->effect;
+
+       /* Skip effects which have no icon. */
+       if (!eff->sprite)
+               return 0;
+
+       /* Blit the effect sprite. */
+       sprite_paint(eff->sprite, 0, rect->x, rect->y);
+       
+       /* Shift the rectangle one left. */
+       rect->x -= ASCII_W;
+       
+       /* If we hit the left edge abort. */
+       if (rect->x == (Status.lineRect.x + BORDER_W)) {
+               return -1;
+       }
+
+       return 0;
+}
+
+/* status_show_party_view_character_effects -- shows the party member's effects
+ * as little mini-icons on the right side of the status line during Party View
+ * mode. */
+static void status_show_party_view_character_effects(class Character *pm, 
+                                                                                                                                       SDL_Rect *rect)
+{
+       int hook;
+
+       /* remember the left edge for the limit check in the loop */
+       int left_edge = rect->x;
+
+       /* Start the rectangle on the far right */
+       rect->x = rect->x + rect->w - ASCII_W;
+
+       /* for each effect */
+       for (hook = 0; hook < OBJ_NUM_HOOKS; hook++) {
+               pm->hookForEach(hook, status_show_effect_icon, rect);
+       }
+
+       /* restore the left edge for the caller */
+       rect->x = left_edge;
+}
+
+/* status_show_party_view_character_arms -- shows the party member's readied
+ * arms as little mini-icons on the right side of the status line during Party
+ * View mode. */
+static void status_show_party_view_character_arms(class Character *pm, 
+                                                                                                                               SDL_Rect *rect)
+{
+       class ArmsType *arms = NULL;
+
+       /* Use half the normal width for the arms icons. */
+       const int ICON_W = TILE_W/2;
+
+       /* remember the left edge for the limit check in the loop */
+       int left_edge = rect->x;
+
+       /* Start the rectangle on the far right */
+       rect->x = rect->x + rect->w - ICON_W;
+
+       /* Tell the sprite lib to scale down by 2x */
+       sprite_zoom_out(2);
+       screenZoomOut(2);
+
+               /* for each readied armament */
+       int armsIndex=0;
+       for (arms = pm->enumerateArms(&armsIndex); arms != NULL; 
+                               arms = pm->getNextArms(&armsIndex))
+       {
+
+               /* blit it */
+               sprite_paint(arms->getSprite(), 0, rect->x, rect->y);
+               
+               /* shift the rectangle one left */
+               rect->x -= ICON_W;
+               
+               /* if we hit the left edge abort */
+               if (rect->x == left_edge) {
+                                       break;
+               }
+       }
+
+       /* Tell the sprite lib to go back to unscaled sprites */
+       screenZoomIn(2);
+       sprite_zoom_in(2);
+       
+       /* restore the left edge for the caller */
+       rect->x = left_edge;
+}
+
+/* status_show_party_view_character -- show a party member during Party View
+ * mode. */
+static bool status_show_party_view_character(class Character * pm, void *data)
+{
+       // check if we've scrolled too far
+       if (Status.lineRect.y >= (Status.screenRect.y + Status.screenRect.h))
+               return true;
+
+       /* Paint the sprite. Using the time_stop_ticks as the frame arg to
+         * animate during Time Stop. */
+       sprite_paint(pm->getSprite(), Session->time_stop_ticks, Status.screenRect.x, 
+               Status.lineRect.y);
+
+       /* Paint the name on line 1 */
+       screenPrint(&Status.lineRect, 0, "%-*s", MAX_NAME_LEN,
+                       pm->getName());
+
+       /* Show the readied arms as scaled-down icons right-justified on line
+               * 1 */
+       status_show_party_view_character_arms(pm, &Status.lineRect);
+
+       /* Go to line 2 */
+       Status.lineRect.y += ASCII_H;
+
+       /* Show character stats on line 2, left-justified. */
+       status_show_character_var_stats(&Status.lineRect, pm);
+
+        /* the above auto-advances; backup to show the condition codes on the
+         * same line */
+       Status.lineRect.y -= ASCII_H;
+
+       /* Show the character effects as mini-icons right-justified on line
+         * 2 */
+       status_show_party_view_character_effects(pm, &Status.lineRect);
+       Status.lineRect.y += ASCII_H;
+
+       if (Status.pcIndex != -1 && pm->getOrder() != Status.pcIndex) {
+               /* Highlight the selected party member by shading all the other
+               * entries. */
+               myShadeLines(Y_TO_LINE(Status.lineRect.y - 2 * ASCII_H), 2);
+       }
+
+       return false;
+}
+
+static void myShowParty(void)
+{
+        /* This can happen on reload. */
+        if (! player_party) {
+                return;
+        }
+
+       /* Setup the text rectangle */
+       Status.lineRect.y = Status.screenRect.y;
+       Status.lineRect.w = Status.screenRect.w - (2 * BORDER_W);
+
+        /* Show members */
+       player_party->forEachMember(status_show_party_view_character, 0);
+
+}
+
+static void myScrollParty(enum StatusScrollDir dir)
+{
+       switch (dir) {
+       case ScrollDown:
+       case ScrollRight:
+       case ScrollPageDown:
+               Status.pcIndex = (Status.pcIndex + 1) % player_party->getSize();
+               break;
+       case ScrollUp:
+       case ScrollLeft:
+       case ScrollPageUp:
+               Status.pcIndex =
+                       (Status.pcIndex + player_party->getSize() - 1) % player_party->getSize();
+               break;
+       default:
+               break;
+       }
+}
+
+static void myPaintPage(void)
+{
+       screenBlit(Status.pg_surf, &Status.pg_rect, &Status.screenRect);
+}
+
+static void myScrollPage(enum StatusScrollDir dir)
+{
+
+       switch (dir) {
+       case ScrollLeft:
+       case ScrollRight:
+               break;
+       case ScrollUp:
+               Status.pg_rect.y = max(Status.pg_rect.y - ASCII_H, 0);
+               break;
+       case ScrollDown:
+               Status.pg_rect.y = min(Status.pg_max_y,
+                               Status.pg_rect.y + ASCII_H);
+               break;
+       case ScrollPageUp:
+               Status.pg_rect.y = max(Status.pg_rect.y -
+                               (Status.pg_rect.h - ASCII_H), 0);
+               break;
+       case ScrollPageDown:
+               Status.pg_rect.y = min(Status.pg_rect.y +
+                               (Status.pg_rect.h - ASCII_H), Status.pg_max_y);
+               break;
+       default:
+               break;
+       }
+}
+
+static int myFormatPgText()
+{
+       char *ptr;
+       int n;
+       int lines = 0;
+       int normal_lines = 0;
+       int added_lines = 0;
+       int natural_breaks = 0;
+
+       assert(Status.pg_text);
+
+       ptr = Status.pg_text;
+       n = 0;
+
+       // Pass 1: wrap words
+       if (*ptr)
+               lines = 1;
+
+       while (1)
+       {
+               n = 0;
+               while (*ptr && n < STAT_CHARS_PER_LINE) {
+                       if (*ptr == '\n') {
+                               n = 0;
+                               lines++;
+                               normal_lines++;
+                       } else
+                               n++;
+                       ptr++;
+               }
+
+               /* End of message? */
+               if (!*ptr)
+                       break;
+
+               /* At this point ptr is at the next character after the last
+               * one we're trying to fit on the line. If this character is a
+               * space or the last character was a space then this is a
+               * natural break in the line (i.e., we're not going to wrap a
+               * word by breaking the line here). */
+               if (isspace(*ptr) || isspace(*(ptr - 1))) {
+                       lines++;
+                       natural_breaks++;
+                       continue;
+               }
+
+               /* At this point we know that we do not have a natural break
+               * and we're trying to wrap a word. We need to back up to find
+               * the beginning of the word and insert a newline just prior.
+               * But if the word is too long to fit on a single line then we
+               * give up and just wrap the word. */
+               ptr -= 2;
+               n = 2;
+               while (!isspace(*ptr) && n < STAT_CHARS_PER_LINE) {
+                       ptr--;
+                       n++;
+               }
+
+               if (n != STAT_CHARS_PER_LINE)
+               {
+                       *ptr = '\n';
+                       added_lines++;
+               }
+               else
+               {
+                       ptr += n;
+               }
+       }
+
+       printf("lines=%d normal_lines=%d added_lines=%d natural_breaks=%d\n",
+                       lines, normal_lines, added_lines, natural_breaks);
+
+       return lines;
+}
+
+static void mySetPageMode(void)
+{
+       int h, rows, x, y, c;
+       char *ptr;
+
+       assert(Status.pg_title);
+       assert(Status.pg_text);
+
+       rows = myFormatPgText();
+
+       // Calculate how much space we need to hold all the text in a scratch
+       // buffer.
+       h = rows * ASCII_H;
+
+       // If we can reuse the existing scratch buffer then do so. Otherwise
+       // make a new one. If this fails then silently abort this
+       // request. Fixme: need to adjust the status ifc to return errors.
+       if (Status.pg_surf == NULL || Status.pg_surf->h < h)
+       {
+               if (Status.pg_surf) {
+                       SDL_FreeSurface(Status.pg_surf);
+               }
+               Status.pg_surf = screenCreateSurface(STAT_W, h);
+               if (!Status.pg_surf)
+                       return;
+       }
+       // Render the text to the scratch surface.
+       SDL_FillRect(Status.pg_surf, 0, Black);
+       ptr = Status.pg_text;
+       for (y = 0; y < rows && *ptr; y++)
+       {
+               for (x = 0, c = 0; x < (STAT_W / ASCII_W) && *ptr; x++)
+               {
+                       if (*ptr == '\n')
+                       {
+                               ptr++;
+                               break;
+                       }
+                       if (!c && *ptr == ' ')
+                       {
+                               ptr++;
+                               continue;
+                       }
+                       if (asciiPaint(*ptr++, c * ASCII_W, y * ASCII_H,
+                                       Status.pg_surf))
+                       {
+                               c++;
+                       }
+               }
+       }
+
+       // Position the paging rect at the top of the window.
+       Status.pg_rect.x = 0;
+       Status.pg_rect.y = 0;
+       Status.pg_rect.w = STAT_W;
+       Status.pg_rect.h = TALL_H;
+
+       // Set the srolling limit.
+       Status.pg_max_y = max(0, h - Status.pg_rect.h);
+
+       // Setup for viewing and scrolling.
+       status_set_title(Status.pg_title);
+       Status.paint = myPaintPage;
+       Status.scroll = myScrollPage;
+
+       // Clear the cmdwin and print instructions for exiting page mode.
+       cmdwin_clear();
+       cmdwin_push("(Hit ESC when done reading)");
+}
+
+static void myPaintTrade(void)
+{
+       SDL_Rect srect, nrect, prect, qrect;
+       int i, top, line;
+
+       if (!Status.list_sz)
+               return;
+
+       // *** Setup sprite, name and price rects ***
+
+       srect = Status.screenRect;
+       srect.w = TILE_W;
+       srect.h = TILE_H;
+
+       nrect = Status.screenRect;
+       if (Status.trades[0].show_sprite) {
+               // shift name left to leave room for sprite
+               nrect.x += TILE_W;
+               nrect.w -= TILE_W;
+       }
+       nrect.h = ASCII_H;
+
+       qrect = Status.screenRect;
+       if (Status.trades[0].show_sprite)
+       {
+               // shift quantity left to leave room for sprite
+               qrect.x += TILE_W;
+               qrect.w -= TILE_W;
+       }
+       
+       qrect.y += ASCII_H;
+       qrect.h = ASCII_H;
+
+       prect = Status.screenRect;
+       prect.x += TILE_W;
+       prect.w -= TILE_W;
+       prect.y += ASCII_H;
+       prect.h = ASCII_H;
+
+       // *** Show the entries in the current scroll window ***
+
+       // The top line is the index at the top of the scrolled window. All
+       // entries prior to this index are above the window and therefore
+       // unseen.
+       top = Status.topLine;
+
+       line = 0;
+
+       for (i = 0; i < Status.list_sz && line < N_LINES; i++)
+       {
+               // Skip entries until we encounter the index which is at the
+               // top of our scrolled window.
+               if (top) {
+                       top--;
+                       continue;
+               }
+               // sprite
+               if (Status.trades[i].show_sprite) {
+                       sprite_paint(Status.trades[i].sprite, 0, srect.x,
+                                       srect.y);
+               }
+               // name
+               screenPrint(&nrect, 0, "%s", Status.trades[i].name);
+
+               // quantity
+               if (Status.trades[i].show_quantity) {
+                       screenPrint(&qrect, 0, "[You have %d]", 
+                                                                                               Status.trades[i].quantity);
+               }
+               // price
+               screenPrint(&prect, SP_RIGHTJUSTIFIED, "%dgp",
+                               Status.trades[i].cost);
+
+               // Shade unselected items.
+               if (i != Status.curLine) {
+                       myShadeLines(line, 2);
+               }
+               line++;
+
+               // Advance all the rectangles to the next line.
+               srect.y += TILE_H;
+               nrect.y += TILE_H;
+               qrect.y += TILE_H;
+               prect.y += TILE_H;
+       }
+}
+
+static void statusPaintGenericList(void)
+{
+       SDL_Rect srect, l1rect, l2rect;
+       int i, top, line;
+
+       if (!Status.list_sz)
+               return;
+
+       // Setup sprite rect
+       srect = Status.screenRect;
+       srect.w = TILE_W;
+       srect.h = TILE_H;
+
+               // Setup line 1 rect1
+       l1rect = Status.screenRect;
+       if (Status.list[0].sprite) {
+               l1rect.x += TILE_W;
+               l1rect.w -= TILE_W;
+       }
+       l1rect.h = ASCII_H;
+
+       // Setup line 2 rect
+       l2rect = l1rect;
+       l2rect.y += ASCII_H;
+
+       // The top line is the index at the top of the scrolled window. All
+       // entries prior to this index are above the window and therefore
+       // unseen.
+       top = Status.topLine;
+
+       line = 0;
+
+       for (i = 0; i < Status.list_sz && line < N_LINES; i++)
+       {
+               // Skip entries until we encounter the index which is at the
+               // top of our scrolled window.
+               if (top) {
+                       top--;
+                       continue;
+               }
+
+               // paint sprite (if applicable)
+               if (Status.list[i].sprite) {
+                       sprite_paint(Status.list[i].sprite, 0, srect.x,
+                                       srect.y);
+               }
+
+               // print line 1
+               screenPrint(&l1rect, 0, "%s", Status.list[i].line1);
+
+               // print line 2
+               screenPrint(&l2rect, 0, "%s", Status.list[i].line2);
+
+
+               // Shade unselected items.
+               if (i != Status.curLine) {
+                       myShadeLines(line, 2);
+               }
+               line++;
+
+               // Advance all the rectangles to the next line.
+               srect.y += TILE_H;
+               l1rect.y += TILE_H;
+               l2rect.y += TILE_H;
+       }
+}
+
+static void statusPaintStringList(void)
+{
+       SDL_Rect srect, l1rect;
+       int i, top, line;
+
+       if (!Status.list_sz)
+               return;
+
+       // Setup sprite rect
+       srect = Status.screenRect;
+       srect.w = TILE_W;
+       srect.h = TILE_H;
+
+       // Setup line rect
+       l1rect = Status.screenRect;
+       l1rect.h = ASCII_H;
+
+       // The top line is the index at the top of the scrolled window. All
+       // entries prior to this index are above the window and therefore
+       // unseen.
+       top = Status.topLine;
+
+       line = 0;
+
+       for (i = 0; i < Status.list_sz && line < N_LINES; i++)
+       {
+               // Skip entries until we encounter the index which is at the
+               // top of our scrolled window.
+               if (top) {
+                       top--;
+                       continue;
+               }
+
+               // print line 1
+               screenPrint(&l1rect, 0, "%s", Status.strlist[i]);
+
+               // Shade unselected items.
+               if (i != Status.curLine) {
+                       myShadeHalfLines(line, 1);
+               }
+               line++;
+
+               // Advance all the rectangles to the next line.
+               srect.y += ASCII_H;
+               l1rect.y += ASCII_H;
+       }
+}
+
+static void myScrollGeneric(enum StatusScrollDir dir)
+{
+       int i;
+
+       switch (dir)
+       {
+       case ScrollUp:
+               // If the window is not at the top of the list and the current
+               // line is centered in the window then move the window up.
+               if (Status.topLine &&
+                               Status.curLine < (Status.list_sz - Status.numLines / 2))
+               {
+                       Status.topLine--;
+               }
+               // Move up the currently selected line.
+               if (Status.curLine)
+                       Status.curLine--;
+               break;
+               
+       case ScrollDown:
+               // If the window is not at the bottom of the list and the
+               // current line is centered in the window then move the window
+               // down.
+               if (Status.topLine < Status.maxLine &&
+                       Status.curLine >= (Status.numLines / 2))
+               {
+                       Status.topLine++;
+               }
+               if (Status.curLine < (Status.list_sz - 1))
+                       Status.curLine++;
+               break;
+               
+       case ScrollTop:
+               Status.topLine = 0;
+               Status.curLine = 0;
+               break;
+               
+       case ScrollBottom:
+               Status.curLine = Status.list_sz - 1;
+               if (Status.list_sz > Status.numLines)
+               {
+                       Status.topLine = Status.list_sz - Status.numLines;
+               } 
+               else
+               {
+                       Status.topLine = 0;
+               }
+               break;
+               
+       case ScrollPageUp:
+               for (i = 0; i < Status.numLines; i++)
+               {
+                       myScrollGeneric(ScrollUp);
+               }
+               break;
+               
+       case ScrollPageDown:
+               for (i = 0; i < Status.numLines; i++)
+               {
+                       myScrollGeneric(ScrollDown);
+               }
+               break;
+               
+       default:
+               break;
+       }
+}
+
+void statusRepaint(void)
+{
+       static int repainting = 0;
+        struct applet *applet;
+
+       if (Status.suppressRepaint)
+               return;
+
+       // Prevent recursive entry since it messes up the coordinate counters
+       if (repainting)
+               return;
+               
+       repainting = 1;
+
+       screenErase(&Status.screenRect);
+
+        if (Status.paint) {
+                Status.paint();
+        } else if ((applet = statusGetCurrentApplet())) {
+                applet->ops->paint(applet);
+        }
+
+
+       status_repaint_title();
+       screenUpdate(&Status.screenRect);
+
+       repainting = 0;
+}
+
+void statusFlash(int line, unsigned int color)
+{
+       enum StatusMode omode = Status.mode;
+       statusSetMode(ShowParty);
+
+       Status.lineRect.y = Status.screenRect.y + line * TILE_H;
+       if (Status.lineRect.y >= (Status.screenRect.y + Status.screenRect.h))
+               return;
+       Status.lineRect.w = Status.screenRect.w - TILE_W;
+       screenFlash(&Status.lineRect, 50, color);
+       statusRepaint();
+
+       statusSetMode(omode);
+       statusRepaint();
+}
+
+void statusScroll(enum StatusScrollDir dir)
+{
+       assert(Status.scroll);
+       Status.scroll(dir);
+       statusRepaint();
+}
+
+void statusSetMode(enum StatusMode mode)
+{
+       /* Unref the old super generic struct if applicable */
+       if (Status.mode == SuperGeneric)
+       {
+               assert(Status.super_generic);
+               if (Status.super_generic->unref)
+               {
+                       Status.super_generic->unref(Status.super_generic);
+               }
+               Status.super_generic = 0;
+       }
+
+       Status.mode = mode;
+
+       /* note: must always repaint title AFTER switching mode because
+               * switching modes repaints the border, and the * title must be painted
+               * over the border. */
+
+       switch (mode)
+       {
+               
+       case DisableStatus:
+               Status.paint=0;
+               break;
+               
+       case ShowParty:
+               switch_to_short_mode();
+               status_set_title("Party");      
+               Status.pcIndex = -1;
+               Status.scroll = 0;
+               Status.paint = myShowParty;
+               break;
+               
+       case SelectCharacter:
+               switch_to_tall_mode();
+               status_set_title("Select Member");
+               Status.scroll = myScrollParty;
+               Status.paint = myShowParty;
+               Status.pcIndex = 0;
+               break;
+               
+       case Ready:
+               switch_to_tall_mode();
+               status_set_title(player_party->
+                               getMemberAtIndex(Status.pcIndex)->getName());
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.container = player_party->inventory;
+               Status.filter = &stat_ready_arms_filter;
+               Status.maxLine = Status.container->
+                               filter_count(Status.filter) - Status.numLines;
+               Status.paint = stat_show_container;
+               Status.scroll = stat_scroll_container;
+               Status.show_thing = status_show_ready_arms;
+               Status.selectedEntry = Status.container->first(Status.filter);
+               break;
+               
+       case Use:
+               switch_to_tall_mode();
+               status_set_title("Use");
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.container = player_party->inventory;
+               Status.filter = &stat_use_filter;
+               Status.maxLine = Status.container->
+                               filter_count(Status.filter) - Status.numLines;
+               Status.paint = stat_show_container;
+               Status.scroll = stat_scroll_container;
+               Status.show_thing = status_show_generic_object_type;
+               Status.selectedEntry = Status.container->first(Status.filter);
+               break;
+               
+       case Page:
+               switch_to_tall_mode();
+               mySetPageMode();
+               break;
+               
+       case Trade:
+               switch_to_tall_mode();
+               status_set_title("Trade");
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.maxLine = Status.list_sz - Status.numLines;
+               Status.paint = myPaintTrade;
+               Status.scroll = myScrollGeneric;
+               Status.selectedEntry = 0;
+               break;
+               
+       case MixReagents:
+               switch_to_tall_mode();
+               status_set_title("Select Reagents");
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.container = player_party->inventory;
+               Status.filter = &stat_mix_filter;
+               Status.maxLine = Status.container->
+                               filter_count(Status.filter) - Status.numLines;
+               Status.paint = stat_show_container;
+               Status.scroll = stat_scroll_container;
+               Status.show_thing = status_show_mix_reagent;
+               Status.selectedEntry = Status.container->first(Status.filter);
+               break;
+               
+       case GenericList:
+               switch_to_tall_mode();
+               status_set_title(Status.list_title);
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.maxLine = Status.list_sz - Status.numLines;
+               Status.paint = statusPaintGenericList;
+               Status.scroll = myScrollGeneric;
+               Status.selectedEntry = 0;                                       
+               break;
+               
+       case StringList:
+               status_set_line_height(max(Status.list_sz, 5));
+               status_set_title(Status.list_title);
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.maxLine = Status.list_sz - Status.numLines;
+               Status.paint = statusPaintStringList;
+               Status.scroll = myScrollGeneric;
+               Status.selectedEntry = 0;                                       
+               break;
+               
+       case SuperGeneric:
+               assert(Status.super_generic);
+               switch_to_tall_mode();
+               status_set_title(Status.super_generic->title);
+               Status.topLine = 0;
+               Status.curLine = 0;
+               Status.maxLine = node_list_len(&Status.super_generic->list) 
+                               - Status.numLines;
+               Status.paint = stat_super_generic_paint;
+               Status.scroll = stat_super_generic_scroll;
+                Status.super_generic->last_shown = 0; /* unknown */
+                Status.super_generic->first_to_selected = 0;
+                Status.super_generic->first_to_last = 0; /* unknown */
+               if (node_list_empty(&Status.super_generic->list)) {
+                       Status.super_generic->first_shown = 0;
+               } else {
+                       Status.super_generic->first_shown = node_next(&Status.super_generic->list);
+               }
+               Status.super_generic->selected = Status.super_generic->first_shown;
+               break;
+       }
+
+       statusRepaint();
+}
+
+const void *statusGetSelected(enum StatusSelection sel)
+{
+       switch (sel)
+       {
+       case Character:
+               return player_party->getMemberAtIndex(Status.pcIndex);
+               
+       case InventoryItem:
+       case Reagents:
+               return Status.selectedEntry;
+               
+       case Generic:
+               return Status.list_sz ? Status.list[Status.curLine].data : 0;
+               
+       case TradeItem:
+               return Status.list_sz ? &Status.trades[Status.curLine] : 0;
+               
+       case String:
+               return Status.list_sz ? Status.strlist[Status.curLine] : 0;
+               
+       case SelectSuperGeneric:
+               assert(Status.super_generic);
+               return Status.super_generic->selected;
+               break;
+               
+       default:
+               return 0;
+       }
+}
+
+int statusGetSelectedIndex(enum StatusSelection sel)
+{
+       switch (sel)
+       {
+       case Character:
+               return Status.pcIndex;
+               
+       case Generic:
+       case TradeItem:
+       case String:
+               return Status.list_sz ? Status.curLine : -1;
+               
+       default:
+               return -1;
+       }
+}
+
+void statusSetSelectedIndex(int index)
+{
+       switch (Status.mode)
+       {
+       case StringList:
+       case Trade:
+       case GenericList:
+               while (index < Status.curLine) {
+                                       Status.scroll(ScrollUp);
+               }
+               while (index > Status.curLine) {
+                                       Status.scroll(ScrollDown);
+               }
+               /*Status.curLine = index;*/
+               statusRepaint();
+               break;
+               
+       default:
+               assert(0);
+               break;
+       }
+}
+
+void statusSelectCharacter(int partyOrderIndex)
+{
+       Status.pcIndex = partyOrderIndex;
+}
+
+void statusSetPageText(const char *title, const char *text)
+{
+       Status.pg_title = title;
+        if (Status.pg_text) {
+                free(Status.pg_text);
+                Status.pg_text = NULL;
+        }
+        /* Make a writable copy so we can insert newlines during formatting. */
+       Status.pg_text = strdup(text);
+}
+
+void statusSetTradeInfo(int list_sz, struct trade_info *trades)
+{
+       Status.list_sz = list_sz;
+       Status.trades = trades;
+}
+
+void statusUpdateTradeInfo(int list_sz, struct trade_info *trades)
+{
+       Status.list_sz = list_sz;
+       Status.trades = trades;
+       Status.maxLine = Status.list_sz - Status.numLines;
+       if (Status.curLine >= list_sz)
+               Status.curLine = max(0, list_sz - 1);
+       statusRepaint();
+}
+
+void statusSetGenericList(const char *title, int list_sz, 
+                          struct stat_list_entry *list)
+{
+       Status.list_title = title;
+       Status.list_sz = list_sz;
+       Status.list     = list;
+}
+
+void statusSetStringList(const char *title, int list_sz, const char **strings)
+{
+       Status.list_title = title;
+       Status.list_sz = list_sz;
+       Status.strlist = strings;
+}
+
+enum StatusMode statusGetMode(void)
+{
+       return Status.mode;
+}
+
+int status_get_h(void)
+{
+       return Status.screenRect.h;
+}
+
+void statusFlashSelected(unsigned int color)
+{
+       SDL_Rect rect;
+       switch (Status.mode)
+       {
+       case StringList:
+       case Trade:
+       case GenericList:
+               rect.x = Status.screenRect.x;
+               rect.y = (Status.screenRect.y 
+                                       + ((Status.curLine - Status.topLine) 
+                                               * ASCII_H));
+               if (rect.y >= (Status.screenRect.y 
+                                                       + Status.screenRect.h))
+                                       return;
+               rect.w = Status.screenRect.w;
+               rect.h = ASCII_H;
+               screenFlash(&rect, 50, color);
+               statusRepaint();
+               break;
+               
+       default:
+               break;
+       }
+}
+
+void statusDisableRepaint()
+{
+       Status.suppressRepaint++;
+}
+
+void statusEnableRepaint()
+{
+       assert(Status.suppressRepaint);
+       Status.suppressRepaint--;               
+}
+
+void statusPushMode(enum StatusMode mode)
+{
+       assert(Status.top < STAT_MODE_STACK_DEPTH);
+       Status.stack[Status.top] = Status.mode;
+       Status.top++;
+       statusSetMode(mode);
+}
+
+void statusPopMode(void)
+{
+       assert(Status.top > 0);
+       Status.top--;
+       statusSetMode(Status.stack[Status.top]);
+}
+
+static void stat_super_generic_paint()
+{
+       SDL_Rect rect = Status.screenRect;
+       struct node *node = Status.super_generic->first_shown;
+       struct node *end = &Status.super_generic->list;
+       int window_bottom = Status.screenRect.y + Status.screenRect.h;
+        Status.super_generic->first_to_last = 0;
+
+       /* check for empty list */
+       if (!node)
+       {
+               screenPrint(&rect, 0, "No Skills!");
+               return;
+       }
+
+       for (;;)
+       {
+               /* check for end-of-list */
+               if (node == end) {
+                        break;
+               }
+               
+               /* check for bottom of window */
+               if (rect.y >= window_bottom) {
+                        break;
+               }
+
+               /* Clip the rect to fit */
+               rect.h = window_bottom - rect.y;
+
+               /* Paint the entry. If it won't fit it will return non-zero,
+                 * and we won't advance any further. */
+               if (Status.super_generic->paint(Status.super_generic,
+                                                  node,
+                                                  &rect)) {
+                        break;
+                }
+
+                /* Remember the last one painted */
+                Status.super_generic->last_shown = node;
+                Status.super_generic->first_to_last++;
+                
+                /* Advance the list */
+                node = node_next(node);
+       }
+
+        Status.super_generic->first_to_last--; /* overcounted by 1 */
+}
+
+static void stat_super_generic_scroll(enum StatusScrollDir dir)
+{
+       struct stat_super_generic_data *gen = Status.super_generic;
+       struct node *first = node_next(&gen->list);
+       struct node *last = node_prev(&gen->list);
+
+       /* Check for trivial case: empty list */
+       if (node_list_empty(&gen->list)) {
+               return;
+       }
+
+       switch (dir)
+       {
+       case ScrollPageUp:
+       case ScrollUp:
+               if (gen->selected != first) {
+                       gen->selected = node_prev(gen->selected);
+                        
+                        /* If the selected item has reached the middle of the
+                         * window, and there is more stuff to see above the
+                         * window, then move the window up the list. */
+                        int selected_to_last = gen->first_to_last - gen->first_to_selected;
+                        if ((gen->first_shown != first)
+                            && (selected_to_last > gen->first_to_selected)) {
+                                gen->first_shown = node_prev(gen->first_shown);
+                        } else {
+                                gen->first_to_selected--;
+                        }
+               }
+               break;
+               
+       case ScrollPageDown:
+       case ScrollDown:
+               if (gen->selected != last) {
+                       gen->selected = node_next(gen->selected);
+                        
+                        /* If the selected item has reached the middle of the
+                         * window, and there is more stuff to see below the
+                         * window, then move the window down the list. */
+                        int selected_to_last = gen->first_to_last - gen->first_to_selected;
+                        if ((gen->last_shown != last)
+                            && (selected_to_last <= gen->first_to_selected)) {
+                                gen->first_shown = node_next(gen->first_shown);
+                        } else {
+                                gen->first_to_selected++;
+                        }
+               }
+               break;
+               
+       case ScrollTop:
+               gen->selected = first;
+               break;
+               
+       case ScrollBottom:
+               gen->selected = last;
+               break;
+               
+       default:
+               break;
+       }
+}
+
+void statusSetSuperGenericData(struct stat_super_generic_data *data)
+{
+       if (data == Status.super_generic) {
+               return;
+       }
+       
+       if (Status.super_generic
+               && Status.super_generic->unref) {
+                       Status.super_generic->unref(Status.super_generic);
+       }
+       
+       Status.super_generic = data;
+       data->refcount++;
+}
+
+void statusBrowseContainer(class Container *container, const char *title)
+{
+       switch_to_tall_mode();
+       status_set_title(title);
+       Status.topLine = 0;
+       Status.curLine = 0;
+       Status.container = container;
+       Status.filter = &stat_drop_filter;
+       Status.maxLine = container->filter_count(Status.filter) - Status.numLines;
+       Status.paint = stat_show_container;
+       Status.scroll = stat_scroll_container;
+       Status.show_thing = status_show_generic_object_type;
+       Status.selectedEntry = container->first(Status.filter);
+        statusRepaint();
+}
+
+void statusRunApplet(struct applet *applet)
+{
+        /* set the window height */
+        if (! applet->ops->get_desired_height) {
+                switch_to_tall_mode();
+        } else {
+                int hpix = applet->ops->get_desired_height(applet);
+                hpix = min(hpix, TALL_H);
+                hpix = max(hpix, LINE_H);
+                status_set_line_height(hpix/ASCII_H);
+        }
+
+        list_add(&Status.applet_stack, &applet->list); /* push */
+        Status.paint = NULL; /* so statusRepaint will use applet->ops->paint */
+        applet->ops->run(applet, &Status.screenRect, Session); /* returns when applet done */
+        list_remove(&applet->list); /* pop */
+}
+
+struct applet *statusGetCurrentApplet(void)
+{
+        if (! list_empty(&Status.applet_stack)) {
+                return list_entry(Status.applet_stack.next, struct applet, list);
+        }
+        return NULL;
+}
diff --git a/src/status.h b/src/status.h
new file mode 100644 (file)
index 0000000..bf398a6
--- /dev/null
@@ -0,0 +1,258 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef status_h
+#define status_h
+
+#include "Arms.h"
+#include "macros.h"
+#include "common.h"
+#include "dimensions.h"
+#include "node.h"
+
+BEGIN_DECL
+
+#define STAT_LIST_CHARS_PER_LINE (STAT_CHARS_PER_LINE - (TILE_W / ASCII_W))
+
+/* Standard color scheme for status visual elements */
+#define STAT_LABEL_CLR          'G'
+#define STAT_BONUS_CLR          'g'
+#define STAT_PENALTY_CLR        'r'
+#define STAT_NULL_CLR           'w'
+#define STAT_OK_CLR             'g'
+#define STAT_WARNING_CLR        'y'
+#define STAT_CRITICAL_CLR       'r'
+#define STAT_FRIENDLY_CLR       'g'
+#define STAT_NEUTRAL_CLR        'y'
+#define STAT_HOSTILE_CLR        'r'
+#define STAT_PARTY_MEMBER_CLR   'c'
+#define STAT_INUSE_CLR          'g'
+#define STAT_UNAVAIL_CLR        'G'
+
+struct trade_info {
+        struct sprite *sprite;
+        const char *name;
+        int quantity;
+        int cost;
+        void *data; /* object type */
+        char *sales_pitch;
+        char show_quantity:1;
+        char show_sprite:1;
+};
+
+struct stat_list_entry {
+        struct sprite *sprite;
+        char line1[STAT_LIST_CHARS_PER_LINE + 1];
+        char line2[STAT_LIST_CHARS_PER_LINE + 1];
+        void *data;
+};
+
+struct stat_super_generic_data {
+        const char *title;
+        struct node list;
+        struct node *selected;
+        struct node *first_shown;
+        struct node *last_shown;
+        int first_to_selected;
+        int first_to_last;
+        int (*paint)(struct stat_super_generic_data *self, struct node *node, 
+                     SDL_Rect *rect);
+        void (*unref)(struct stat_super_generic_data *self);
+        int refcount;
+        void *data;
+};
+
+enum StatusScrollDir {
+        ScrollUp = 0,
+        ScrollDown,
+        ScrollRight,
+        ScrollLeft,
+        ScrollPageUp,
+        ScrollPageDown,
+        ScrollTop,
+        ScrollBottom
+};
+                                                               
+enum StatusMode {
+        ShowParty,
+        SelectCharacter,
+        Ready,
+        Use,
+        Page,
+        Trade,
+        MixReagents,
+        GenericList,
+        StringList,
+        DisableStatus,
+        SuperGeneric
+};
+                                       
+enum StatusSelection {
+        Character,
+        InventoryItem,
+        TradeItem,
+        Reagents,
+        Generic,
+        String,
+        SelectSuperGeneric
+};
+
+extern int statusInit(void);
+extern void statusRepaint(void);
+extern void statusFlash(int line, unsigned int color);
+                                                               
+extern void statusSetMode(enum StatusMode mode);
+extern enum StatusMode statusGetMode(void);
+extern void statusScroll(enum StatusScrollDir dir);
+extern const void *statusGetSelected(enum StatusSelection sel);
+extern void statusSelectCharacter(int partyOrderIndex);
+
+extern void statusSetPageText(const char *title, const char *text);
+extern void statusSetTradeInfo(int list_sz, struct trade_info *trades);
+extern void statusUpdateTradeInfo(int list_sz, 
+                                  struct trade_info *trades);
+extern int status_get_h(void);
+        
+
+/**
+ * Setup a generic list for use with the GenericList mode. A generic list has
+ * two lines and an optional icon per list entry. This call has no effect on
+ * the UI until it is followed by a statusSetMode(GenericList) call.
+ *
+ * @param title The title to show in the GenericList mode. This call does not
+ * make its own copy, so 'title' must remain a valid pointer until the caller
+ * is done using this mode and changes to another mode.
+ *
+ * @param list_sz The number of entries in the list.
+ *
+ * @param list An array of pointers to the list entries. Like the 'title', this
+ * call does not make its own copy, so all the pointers must remain valid while
+ * the GenericList mode is in use.
+ */
+extern void statusSetGenericList(const char *title, int list_sz, 
+                                 struct stat_list_entry *list);
+
+/**
+ * Setup a list of plain string entries for use with the StringList mode. Each
+ * string will take up one line in the status display. This call has no effect
+ * on the UI until it is followed by a statusSetMode(StringList) call.
+ *
+ * @param title The title to show in the StringList mode. This call does not
+ * make its own copy, so 'title' must remain a valid pointer until the caller
+ * is done using this mode and changes to another mode.
+ *
+ * @param list_sz The number of entries in the list.
+ *
+ * @param list An array of pointers to the list entries. Like the 'title', this
+ * call does not make its own copy, so all the pointers must remain valid while
+ * the StringList mode is in use.
+ */
+extern void statusSetStringList(const char *title, int list_sz, const char **list);
+
+/**
+ * When in one of the list modes, this forces the list entry at the given index
+ * to be highlighted.
+ *
+ * @param index The index of the entry to be selected. The first entry has
+ * index 0.
+ */
+extern void statusSetSelectedIndex(int index);
+
+/**
+ * Similar to statusGetSelected, but get the integer index.
+ *
+ * @param sel The type of index to get. Supported values are Character,
+ * Generic, TradeItem and String.
+ *
+ * @returns The index or -1 if an invalid type is used or the corresponding
+ * list has no entries.
+ */
+extern int statusGetSelectedIndex(enum StatusSelection sel);
+
+/**
+ * Flash the line of the currently selected item.
+ *
+ * @param color The color to flash. See the list in screen.h.
+ */
+extern void statusFlashSelected(unsigned int color);
+
+/**
+ * Temporarily disable repainting. This increments an internal "suppression
+ * counter" inside status. When the counter is non-zero the status window will
+ * not repaint itself.
+ */
+extern void statusDisableRepaint();
+
+/**
+ * Enable repainting again. This decrements an internal "suppression
+ * counter" inside status. When the counter is non-zero the status window will
+ * not repaint itself.
+ */
+extern void statusEnableRepaint();
+
+extern void statusPushMode(enum StatusMode mode);
+extern void statusPopMode();
+extern void statusSetSuperGenericData(struct stat_super_generic_data *data);
+
+/**
+ * Show the filtered contents of a container in the status browser and let the
+ * player scroll through them. To retrieve a pointer to the inv_entry struct
+ * for the current highlighteed item, call statusGetSelected(InventoryItem).
+ *
+ * @param container is the container object to browse
+ * @param title is shown at the top of the status window
+ */
+extern void statusBrowseContainer(class Container *container, const char *title);
+
+/**
+ * Set the text of the title at the top of the status window.
+ */
+extern void status_set_title(const char *title);
+extern void status_repaint_title(void);
+
+/**
+ * Given a range of values [0, max] and a current value, map the value to a
+ * color in the domain [OK, WARNING, CRITICAL] (this is specifically for hit
+ * points, as you might expect, but might be useful for other stuff).
+ */
+extern char status_range_color(int cur, int max);
+
+/**
+ * Paint armament statistics in a standard way.
+ */
+extern void status_show_arms_stats(SDL_Rect *rect, ArmsType *arms);
+
+/**
+ * This pushes the current applet onto the applet stack and invokes it's run
+ * function. When that function returns, it pops it from the applet stack. Note
+ * that applets may run other applets in a strictly nested fashion by calling
+ * this function.
+ */
+extern void statusRunApplet(struct applet *applet);
+
+/**
+ * Returns the applet at the top of the applet stack.
+ */
+extern struct applet *statusGetCurrentApplet(void);
+
+END_DECL
+
+#endif
diff --git a/src/templ.c b/src/templ.c
new file mode 100644 (file)
index 0000000..fabe304
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "templ.h"
+#include "closure.h"
+
+#include <assert.h>
+#include <config.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#include <string.h>
+
+/* unchecked array accesses */
+#define templ_get_unch(templ,x,y) ((templ)->grid[templ_i((templ),(x),(y))])
+#define templ_set_unch(templ,x,y,v) ((templ)->grid[templ_i((templ),(x),(y))]=(v))
+
+/* translate to coords relative to template upper left corner */
+#define templ_translate(templ,x,y) \
+  do {                           \
+    (x) = (x) - (templ)->ux;      \
+    (y) = (y) - (templ)->uy;      \
+  } while (0) 
+
+#define templ_in_range(templ,x,y)         \
+  (((x) >= 0) && ((x) < (templ)->w)      \
+    && ((y) >= 0) && ((y) < (templ)->h))
+
+static void templ_del(struct templ *templ)
+{
+        assert(!templ->refcount);
+        free(templ->grid);
+        free(templ);
+}
+
+struct templ *templ_new(int w, int h)
+{
+        struct templ *templ = (struct templ*)calloc(1, sizeof(*templ));
+        assert(templ);
+        templ->grid = (char*)calloc(w * h, sizeof(char));
+        assert(templ->grid);
+        templ->w = w;
+        templ->h = h;
+        templ->refcount = 1;
+        return templ;
+}
+
+struct templ *templ_new_from_range(int rad)
+{
+        int ww = rad * 2 + 1;
+        struct templ *templ = templ_new(ww, ww);
+        int i = 0, x, y;
+
+        /* mark all the template cells within the radius */
+        for (y = 0; y < ww; y++) {
+                int dy = (y>rad) ? (y-rad) : (rad-y); /* abs(y-rad) */
+                for (x = 0; x < ww; x++, i++) {
+                        int dx = (x>rad) ? (x-rad) : (rad-x); /* abs(x-rad) */
+
+                        /* angband quick-and-dirty distance formula: */
+                        int d = ((dy>dx) ? (dy+(dx>>1)) : (dx+(dy>>1)));
+
+                        if (d <= rad) {
+                                templ->grid[i] = 1;
+                        }
+                }
+        }
+        
+        return templ;
+}
+
+void templ_ref(struct templ *templ)
+{
+        templ->refcount++;
+}
+
+void templ_unref(struct templ *templ)
+{
+        assert(templ->refcount > 0);
+        templ->refcount--;
+        if (!templ->refcount) {
+                templ_del(templ);
+        }
+}
+
+char templ_get(struct templ *templ, int x, int y)
+{
+        templ_translate(templ, x, y);
+        if (! templ_in_range(templ, x, y)) {
+                return 0;
+        }
+
+        return templ_get_unch(templ, x, y);
+}
+
+int templ_set(struct templ *templ, int x, int y, char val)
+{
+        templ_translate(templ, x, y);
+        if (! templ_in_range(templ, x, y)) {
+                return -1;
+        }
+        templ_set_unch(templ, x, y, val);
+        return 0;
+}
+
+void templ_set_origin(struct templ *templ, int x, int y)
+{
+        templ->ux = x - templ->w / 2;
+        templ->uy = y - templ->h / 2;
+}
+
+void templ_for_each(struct templ *grd, 
+                    int (*cb)(struct templ *, int, int, void *),
+                    void *data)
+{
+        int x1, y1, x2, y2;
+        templ_ref(grd);
+        for (y1 = 0; y1 < grd->h; y1++) {
+                y2 = y1 + grd->uy;
+                for (x1 = 0; x1 < grd->w; x1++) {
+
+                        /* run the cb only on tiles in the templ */
+                        if (templ_get_unch(grd, x1, y1)) {
+                                x2 = x1 + grd->ux;
+                                if (cb(grd, x2, y2, data)) {
+                                        goto done;
+                                }
+                        }
+                }
+        }
+ done:
+        templ_unref(grd);
+}
diff --git a/src/templ.h b/src/templ.h
new file mode 100644 (file)
index 0000000..38b32f1
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2007 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef templ_h
+#define templ_h
+
+/* A templ is a grid of cells that are either on (1) or off (0). 'templ' is
+ * short for 'template', which is a reserved word in c++. */
+struct templ {
+        int refcount;    /* reference count                      */
+        int ux, uy;      /* upper left corner                    */
+        int w, h;        /* width and height                     */
+        char *grid;      /* cells                                */
+};
+
+#define templ_i(templ,x,y) ((y)*(templ)->w+(x))
+#define templ_x(templ,i) ((i)%(templ)->w)
+#define templ_y(templ,i) ((i)/(templ)->w)
+
+extern struct templ *templ_new(int w, int h);
+extern struct templ *templ_new_from_range(int rad);
+extern void templ_ref(struct templ *grd);
+extern void templ_unref(struct templ *grd);
+extern char templ_get(struct templ *grd, int x, int y);
+extern int templ_set(struct templ *grd, int x, int y, char val);
+extern void templ_set_origin(struct templ *grd, int x, int y);
+extern void templ_for_each(struct templ *grd, 
+                           int (*cb)(struct templ *tmple, int x, int y, void *data),
+                           void *data);
+
+#endif
diff --git a/src/terrain.c b/src/terrain.c
new file mode 100644 (file)
index 0000000..858a377
--- /dev/null
@@ -0,0 +1,312 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "terrain.h"
+#include "debug.h"
+#include "sprite.h"
+#include "common.h"
+#include "object.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+//int TERRAIN_MAGIC = 0xc01dbee3;
+
+extern struct terrain *terrain_new(const char *tag, 
+                                   const char *name,
+                                   struct sprite *sprite,
+                                   int pclass, 
+                                   int alpha, 
+                                   int light)
+{
+       struct terrain *terrain;
+
+        terrain = (struct terrain*)calloc(1, sizeof(*terrain));
+        assert(terrain);
+
+        terrain->magic         = TERRAIN_MAGIC;
+        terrain->tag           = strdup(tag);
+       terrain->name          = strdup(name);
+        terrain->sprite        = sprite;
+       terrain->pclass        = pclass;
+       terrain->alpha         = alpha;
+        terrain->light         = light;
+       return terrain;
+}
+
+void terrain_del(struct terrain *terrain)
+{
+        if (terrain->tag) {
+                free(terrain->tag);
+        }
+       if (terrain->name) {
+               free(terrain->name);
+        }
+        if (terrain->effect) {
+                closure_unref(terrain->effect);
+        }
+        free(terrain);
+}
+
+#define BOGUS_MAX_SIZE 255     // Hack, should get a constant from somewhere
+// LONGEST_TERRAIN_GLYPH would be appropriate for glyph_str...
+
+void palette_entry_print(FILE * fp, int indent,
+                        struct terrain_palette_entry *entry)
+{
+       static char glyph_str[BOGUS_MAX_SIZE + 1];
+    static char   tag_str[BOGUS_MAX_SIZE + 1];
+       assert(fp);
+    assert(entry);
+    
+    snprintf(glyph_str, BOGUS_MAX_SIZE, "\"%s\"", entry->glyph);
+    snprintf(tag_str,   BOGUS_MAX_SIZE, "%s)",    entry->terrain->tag);
+    
+       INDENT;
+    fprintf(fp, "(list  %-6s %-20s  ;; \"%s\"\n", glyph_str, tag_str, entry->terrain->name);
+} // palette_entry_print()
+
+struct terrain_palette *terrain_palette_new(const char *tag)
+{
+       struct terrain_palette *palette = new struct terrain_palette;
+       assert(palette);
+       memset(palette, 0, sizeof(struct terrain_palette));
+
+        list_init(&palette->lookup_head);
+        list_init(&palette->edit_head);
+        palette->tag = strdup(tag);
+        palette->widest_glyph = 0;
+        palette->num_entries = 0;
+
+       return palette;
+}
+
+struct terrain_palette_entry *
+terrain_palette_entry_new(char *glyph, struct terrain *terrain)
+{
+        struct terrain_palette_entry *entry;
+        entry = (struct terrain_palette_entry *)malloc(sizeof(*entry));
+        list_init(&entry->lookup_list);
+        list_init(&entry->edit_list);
+        entry->glyph = strdup(glyph);
+        assert(entry->glyph);
+        entry->terrain = terrain;
+        return entry;
+}
+
+void terrain_palette_entry_del(struct terrain_palette_entry *entry)
+{
+        // For each entry free the glyph (because we strdup'd our own copy) but
+        // leave the terrain alone (it's a singleton and belongs to someone
+        // else).
+        free(entry->glyph);
+        free(entry);
+}
+
+void terrain_palette_del(struct terrain_palette *pal)
+{
+        struct list *elem;
+
+        elem = pal->edit_head.next;
+        while (elem != &pal->edit_head) {
+                struct terrain_palette_entry *entry;
+                entry = outcast(elem, struct terrain_palette_entry, edit_list);
+                elem = elem->next;
+                terrain_palette_entry_del(entry);
+        }
+
+        if (pal->tag)
+                free(pal->tag);
+        delete pal;
+}
+
+void terrain_palette_add(struct terrain_palette *pal, char *glyph, 
+                         struct terrain *ter)
+{
+        struct terrain_palette_entry *entry;
+        int n = strlen(glyph);
+
+        entry = terrain_palette_entry_new(glyph, ter);
+        list_add_tail(&pal->lookup_head, &entry->lookup_list);
+        list_add_tail(&pal->edit_head, &entry->edit_list);
+        pal->num_entries++;
+        if (pal->widest_glyph < n)
+                pal->widest_glyph = n;
+}
+
+struct terrain_palette_entry *palette_entry(struct terrain_palette *palette, int n)
+{
+        struct list *elem;
+
+        assert(palette);
+        if (palette->num_entries < 1) {
+                dbg("palette_terrain_for_glyph() num_entries == 0\n");
+                return 0;
+        }
+        if (n < 0 || n >= palette->num_entries) {
+                dbg("palette_terrain_for_glyph() called with out-of-bounds "\
+                    "arg n=%d\n", n);
+                return 0;
+        }
+
+        elem = palette->edit_head.next;
+        while (n) {
+                elem = elem->next;
+                n--;
+        }
+
+        return outcast(elem, struct terrain_palette_entry, edit_list);
+}
+
+char *palette_glyph(struct terrain_palette *palette, int n)
+{
+        struct terrain_palette_entry *entry;
+
+        entry = palette_entry(palette, n);
+        if (entry)
+                return entry->glyph;
+        return 0;
+}
+
+struct terrain_palette_entry *
+palette_entry_for_terrain(struct terrain_palette * pp, struct terrain * tt)
+{
+        struct list *elem;
+        struct terrain_palette_entry *entry;
+
+        list_for_each(&pp->lookup_head, elem) {
+                entry = outcast(elem, struct terrain_palette_entry, lookup_list);
+                if (tt == entry->terrain)
+                        return entry;
+        }
+
+        return 0;  // Did not find the terrain
+}
+
+char * palette_glyph_for_terrain (struct terrain_palette * pp, struct terrain * tt)
+{
+        struct terrain_palette_entry *entry;
+
+        entry = palette_entry_for_terrain(pp, tt);
+        if (entry)
+                return entry->glyph;
+        return 0;  // Did not find the terrain
+}
+
+struct terrain *palette_terrain(struct terrain_palette *palette, int n)
+{
+        struct terrain_palette_entry *entry;
+
+        entry = palette_entry(palette, n);
+        if (entry)
+                return entry->terrain;
+        return 0;
+}
+
+struct terrain *palette_terrain_for_glyph(struct terrain_palette *palette,
+                                         char *glyph)
+{
+        struct list *elem;
+        struct terrain_palette_entry *entry;
+
+        list_for_each(&palette->lookup_head, elem) {
+                entry = outcast(elem, struct terrain_palette_entry, lookup_list);
+                if (! strcmp(glyph, entry->glyph)) {
+                        /* Odds are good that we'll want this same terrain in
+                         * the near future, so move it to the front of the list
+                         * (if not already there) to improve performance during
+                         * startup. */
+                        if (elem != palette->lookup_head.next) {
+                                list_remove(elem);
+                                list_add(&palette->lookup_head, elem);
+                        }
+                        return entry->terrain;
+                }
+        }
+
+        return 0;  // Did not find the terrain
+}                              // palette_terrain_for_glyph()
+
+struct terrain_palette * palette_contains_terrain (struct terrain_palette *pp, 
+                                                   struct terrain *tt)
+{
+        // The current user of this function is 
+        // combat.c create_camping_map().
+        // It is used to find a palette (any palette)
+        // which contains a certain fill terrain.
+        // 
+        // For other uses, I wonder if returning the index 
+        // where it is found, or -1 for not found, 
+        // would be more useful?
+        struct terrain_palette_entry *entry;
+
+        entry = palette_entry_for_terrain(pp, tt);
+        if (entry)
+                return pp;
+        return 0;  // Did not find the terrain
+}
+
+void palette_print(FILE * fp, int indent, struct terrain_palette *palette)
+{
+        struct list *elem;
+       assert(fp);
+
+    // (kern-mk-palette 'pal_expanded
+    //     (list
+    //         ;; There are 999 entries in this palette
+    //         ;; The widest glyph is 4 characters
+    //         (list "__" t_deep)
+    //         (list ".." t_grass)
+    //     )
+    // )
+
+
+       INDENT;
+       fprintf(fp, "(kern-mk-palette '%s\n", palette->tag);
+       indent += INDENTATION_FACTOR;
+
+       INDENT;
+       fprintf(fp, "(list\n");
+       indent += INDENTATION_FACTOR;
+    INDENT;
+    fprintf(fp, ";; There are %d entries in this palette\n", palette->num_entries);
+    INDENT;
+    fprintf(fp, ";; The widest glyph is %d characters\n",   palette->widest_glyph);
+    
+    list_for_each(&palette->edit_head, elem) {
+        struct terrain_palette_entry *entry;
+        entry = outcast(elem, struct terrain_palette_entry, edit_list);
+               palette_entry_print(fp, indent, entry);
+       }
+
+    fprintf(fp, "\n");
+
+    indent -= INDENTATION_FACTOR;
+    INDENT;
+    fprintf(fp, ")\n");
+
+    indent -= INDENTATION_FACTOR;
+    INDENT;
+    fprintf(fp, ") ;; palette %s\n", palette->tag);
+       fprintf(fp, "\n");
+} // palette_print()
diff --git a/src/terrain.h b/src/terrain.h
new file mode 100644 (file)
index 0000000..46df3ad
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef terrain_h
+#define terrain_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include "list.h"
+#include "object.h"
+#include "ptable.h"     /* for ptable_get() */
+
+#include <stdio.h>      /* for FILE */
+#include <closure.h>
+
+struct sprite;
+
+#define terrain_combat_map(t) ((t)->combat_map)
+
+/* Terrain effects */
+#define TERRAIN_NEUTRAL 0
+#define TERRAIN_POISON  EFFECTPOISON
+#define TERRAIN_BURN    EFFECT_BURN
+
+//extern int TERRAIN_MAGIC;
+#define TERRAIN_MAGIC (0xc01dbee3)
+
+#define terrain_pclass(t) ((t)->pclass)
+
+struct terrain {
+        int magic;
+        struct list session_list; /* list of all terrains in this session */
+        char *tag;
+        char *name;
+        struct sprite *sprite;
+        struct terrain_map *combat_map;
+        unsigned char alpha;
+        int pclass;
+        int light;
+        closure_t *effect; /* when stood on */
+        closure_t *renderCombat; /* closure to set up combat map */
+};
+
+extern struct terrain *terrain_new(const char *tag, const char *name, 
+                                   struct sprite *sprite,
+                                   int pclass, 
+                                   int alpha, 
+                                   int light);
+extern void terrain_del(struct terrain *terrain);
+extern void terrain_alloc_mmode_table(int n_mmodes);
+
+#define LONGEST_TERRAIN_GLYPH   4
+
+struct terrain_palette_entry {
+    struct list lookup_list; /* listed by fast lookup order */
+    struct list edit_list; /* listed by palette order */
+    char           * glyph;
+    struct terrain * terrain;
+};
+
+void palette_entry_print(FILE * fp, int indent,
+                         struct terrain_palette_entry *entry);
+
+struct terrain_palette {
+    struct list list; /* list of palettes */
+    char *tag;
+    int widest_glyph; 
+    int current_terrain_index;
+    int free_index;
+    int num_entries;
+    struct list lookup_head; /* list of terrains for lookup */
+    struct list edit_head; /* list of terrains for editor */
+};
+
+struct terrain_palette * palette_contains_terrain (struct terrain_palette *pp, struct terrain *tt);
+struct terrain_palette * terrain_palette_new(const char *tag);
+void terrain_palette_del(struct terrain_palette *pal);
+void terrain_palette_add(struct terrain_palette *pal, char *glyph, struct terrain *ter);
+char * palette_glyph(struct terrain_palette *pp, int n);
+char * palette_glyph_for_terrain (struct terrain_palette * pp, struct terrain * tt);
+struct terrain_palette_entry *palette_entry(struct terrain_palette *palette, int n);
+struct terrain * palette_terrain(struct terrain_palette *pp, int n);
+struct terrain * palette_terrain_for_glyph(struct terrain_palette *pp, char *glyph);
+struct terrain * palette_current_terrain(struct terrain_palette * pp);
+void palette_print(FILE * fp, int indent, struct terrain_palette *pp);
+
+END_DECL
+
+#endif // terrain_h
diff --git a/src/terrain_editor.c b/src/terrain_editor.c
new file mode 100644 (file)
index 0000000..c052636
--- /dev/null
@@ -0,0 +1,845 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "applet.h"
+#include "cmdwin.h"
+#include "cursor.h"
+#include "event.h"
+#include "foogod.h"
+#include "log.h"
+#include "map.h"
+#include "place.h"
+#include "session.h"
+#include "sprite.h"
+#include "terrain.h"
+#include "terrain_editor.h"
+#include "vmask.h"
+
+/**
+ * The generic status pane.
+ */
+struct terrain_editor_pane {
+    struct list list;
+    struct terrain_editor_applet *app;
+    void (*paint)(struct terrain_editor_pane *pane);
+    int (*key_handler)(struct terrain_editor_pane *pane, int key, int keymod);
+    bool (*mouse_click_handler)(struct terrain_editor_pane *pane, int sx, int sy);
+};
+
+/**
+ * The terrain palette status pane.
+ */
+struct terrain_editor_palette {
+    struct terrain_editor_pane base;
+    int top_index; /* index of terrain in ulc of palette window */
+    int max_top_index; /* value for which last entry is on the bottom of the palette window */
+    int max_cols, max_rows; /* dimensions of the palette window */
+};
+
+/**
+ * Status window applet structure for the terrain editor. The terrain editor
+ * keeps a list of panes which appear in the status window. For example, the
+ * terrain palette is one, the help screen another, and there may be one in the
+ * future for selecting different editing tools, etc.
+ */
+struct terrain_editor_applet {
+    struct applet base;
+    struct list panes; /* list of status panes */
+    struct list cmds; /* list of commands (for undo/redo) */
+    struct terrain_editor_palette *pal; /* keep a pointer for ops_run init */
+    struct terrain_editor_pane *pane; /* current pane */
+    struct place *place; /* place being edited */
+    struct terrain *terrain; /* currently selected terrain to paint with */
+    struct list *lastcmd; /* last command executed */
+    struct terrain_map *origmap; /* clone of original map (for undo/redo) */
+    struct terrain *quick[10]; /* quick terrain selection table */
+    int x, y; /* cursor location in place (at least initially) */
+};
+
+typedef enum {
+    CMD_PAINT = 0,
+    CMD_FILL = 1
+} terrain_editor_cmd_code_t;
+
+struct terrain_editor_cmd_paint {
+    int x, y;
+    struct terrain *terrain;    
+};
+
+struct terrain_editor_cmd_fill {
+    int x, y;
+    struct terrain *oldter, *newter;    
+};
+
+struct terrain_editor_cmd {
+    struct list list;
+    terrain_editor_cmd_code_t code;
+    union {
+        struct terrain_editor_cmd_paint paint;
+        struct terrain_editor_cmd_fill fill;
+    } parms;
+};
+
+/*
+ * emit_terraform_status - print the active terrain palette entry to the
+ * console during terraform mode
+ */
+void emit_terraform_status (const char * msg, struct terrain * tt)
+{
+    log_msg("[%s]: %s '%s'", msg, tt->tag, tt->name);
+}
+
+static void terrain_editor_cmd_del(struct terrain_editor_cmd *cmd)
+{
+    free(cmd);
+}
+
+static void terrain_editor_cmd_fill_exec(struct terrain *nt, struct terrain *ot, struct place *place, int x, int y)
+{
+    struct terrain *ct = place_get_terrain(place, x, y);
+
+    /* base case 1: off-map */
+    if (!ct)
+        return;
+
+    /* base case 2: current terrain does not match old terrain */
+    if (ct != ot)
+        return;
+
+    /* recursive case - change current terrain to new terrain */
+    place_set_terrain(place, x, y, nt);
+    vmask_invalidate(place, x, y, 1, 1);
+
+    /* recur on four neighbors */
+    terrain_editor_cmd_fill_exec(nt, ot, place, x-1, y);
+    terrain_editor_cmd_fill_exec(nt, ot, place, x+1, y);
+    terrain_editor_cmd_fill_exec(nt, ot, place, x, y-1);
+    terrain_editor_cmd_fill_exec(nt, ot, place, x, y+1);
+}
+
+static void terrain_editor_cmd_exec(struct terrain_editor_applet *tea, struct terrain_editor_cmd *cmd)
+{
+    switch (cmd->code) {
+    case CMD_PAINT:
+    {
+        struct terrain *ter = cmd->parms.paint.terrain;
+        int x = cmd->parms.paint.x;
+        int y = cmd->parms.paint.y;
+
+        place_set_terrain(tea->place, x, y, ter);
+        vmask_invalidate(tea->place, x, y, 1, 1);
+    }
+    break;
+    case CMD_FILL:
+    {
+        struct terrain *oldter = cmd->parms.fill.oldter;
+        struct terrain *newter = cmd->parms.fill.newter;
+        int x = cmd->parms.fill.x;
+        int y = cmd->parms.fill.y;
+
+        terrain_editor_cmd_fill_exec(newter, oldter, tea->place, x, y);
+    }
+    break;
+    default:
+        assert(0);
+        break;
+    }
+}
+
+static struct terrain_editor_cmd *terrain_editor_cmd_paint_new(int x, int y, struct terrain *terrain)
+{
+    struct terrain_editor_cmd *cmd = (struct terrain_editor_cmd *)calloc(1, sizeof(*cmd));
+    if (!cmd) {
+        return NULL;
+    }
+    cmd->code = CMD_PAINT;
+    cmd->parms.paint.x = x;
+    cmd->parms.paint.y = y;
+    cmd->parms.paint.terrain = terrain;
+    return cmd;
+}
+
+static struct terrain_editor_cmd *terrain_editor_cmd_fill_new(int x, int y, struct terrain *oldter, struct terrain *newter)
+{
+    struct terrain_editor_cmd *cmd = (struct terrain_editor_cmd *)calloc(1, sizeof(*cmd));
+    if (!cmd) {
+        return NULL;
+    }
+    cmd->code = CMD_FILL;
+    cmd->parms.fill.x = x;
+    cmd->parms.fill.y = y;
+    cmd->parms.fill.oldter = oldter;
+    cmd->parms.fill.newter = newter;
+    return cmd;
+}
+
+static void terrain_editor_del_cmd_list(struct terrain_editor_applet *tea, struct list *elem)
+{
+    while (elem != &tea->cmds) {
+        struct terrain_editor_cmd *cmd = list_entry(elem, struct terrain_editor_cmd, list);
+        elem = elem->next;
+        list_remove(&cmd->list);
+        terrain_editor_cmd_del(cmd);
+    }
+
+}
+
+static void terrain_editor_submit_cmd(struct terrain_editor_applet *tea, struct terrain_editor_cmd *cmd)
+{
+    /* if there are commands in the 'redo' part of the command list then delete
+     * them */
+    terrain_editor_del_cmd_list(tea, tea->lastcmd->next);
+
+    /* enqueue command */
+    list_add_tail(&tea->cmds, &cmd->list);
+
+    /* advance last command pointer */
+    tea->lastcmd = &cmd->list;
+
+    /* exec command */
+    terrain_editor_cmd_exec(tea, cmd);
+    mapSetDirty();
+    mapUpdate(0);
+}
+
+static void terrain_editor_undo(struct terrain_editor_applet *tea)
+{
+    /* if no commands queued then done */
+    if (tea->lastcmd == &tea->cmds) {
+        return;
+    }
+
+    /* delete current map */
+    terrain_map_unref(tea->place->terrain_map);
+
+    /* restore original map */
+    tea->place->terrain_map = terrain_map_clone(tea->origmap, tea->origmap->tag);
+    assert(tea->place->terrain_map);
+
+    vmask_flush_all();
+
+    /* replay commands up to last */
+    struct list *elem = tea->cmds.next;
+    while (elem != tea->lastcmd) {
+        struct terrain_editor_cmd *cmd = list_entry(elem, struct terrain_editor_cmd, list);
+        elem = elem->next;
+        terrain_editor_cmd_exec(tea, cmd);
+    }
+
+    /* back up last command pointer */
+    tea->lastcmd = tea->lastcmd->prev;
+
+    mapSetDirty();        
+    mapUpdate(0);
+
+}
+
+static void terrain_editor_redo(struct terrain_editor_applet *tea)
+{
+    /* if no more commands in list then done */
+    if (tea->lastcmd->next == &tea->cmds) {
+        return;
+    }
+
+    /* advance last command pointer */
+    tea->lastcmd = tea->lastcmd->next;
+
+    /* replay last command */
+    struct terrain_editor_cmd *cmd = list_entry(tea->lastcmd, struct terrain_editor_cmd, list);
+    terrain_editor_cmd_exec(tea, cmd);
+
+    mapSetDirty();        
+    mapUpdate(0);
+
+}
+
+/**
+ * Submit a command to set a tile to the current terrain.
+ */
+static void terrain_editor_req_paint(struct terrain_editor_applet *tea, int x, int y)
+{
+    if (tea->terrain != place_get_terrain(tea->place, x, y)) {
+        struct terrain_editor_cmd *cmd = terrain_editor_cmd_paint_new(x, y, tea->terrain);
+        terrain_editor_submit_cmd(tea, cmd);
+    }
+}
+
+/**
+ * Submit a command to fill a region with the current terrain.
+ */
+static void terrain_editor_req_fill(struct terrain_editor_applet *tea, int x, int y)
+{
+    struct terrain *oldter = place_get_terrain(tea->place, x, y);
+    if (tea->terrain != oldter) {
+        struct terrain_editor_cmd *cmd = terrain_editor_cmd_fill_new(x, y, oldter, tea->terrain);
+        terrain_editor_submit_cmd(tea, cmd);
+    }
+}
+
+/**
+ * Describe a tile in detail, DM mode.
+ */
+static void terrain_editor_look_at_xy(struct terrain_editor_applet *tea, int x, int y)
+{
+    if (!mapTileIsVisible(x, y) ) {
+        log_begin("(Out of LOS) At XY=(%d,%d) you see ", x, y);
+        place_describe(tea->place, x, y, PLACE_DESCRIBE_ALL);
+        log_end(NULL);
+        return;
+    }
+    log_begin("At XY=(%d,%d) you see ", x, y);
+    place_describe(tea->place, x, y, PLACE_DESCRIBE_ALL);
+    log_end(NULL);
+}
+
+static int terrain_editor_palette_key_handler(struct terrain_editor_pane *pane, int key, int keymod)
+{
+    DECL_CAST(struct terrain_editor_palette, pal, pane);
+
+    switch (key) {
+    case SDLK_PAGEUP:
+        if (pal->top_index >= pal->max_cols) {
+            pal->top_index -= pal->max_cols;
+            statusRepaint();
+        }
+        return 0;
+
+    case SDLK_PAGEDOWN:
+        if (pal->top_index < pal->max_top_index) {
+            pal->top_index += pal->max_cols;
+            statusRepaint();
+        }
+        return 0;
+
+    case SDLK_HOME:
+        pal->top_index = 0;
+        statusRepaint();
+        return 0;
+
+    case SDLK_END:
+        pal->top_index = pal->max_top_index;
+        statusRepaint();
+        return 0;
+    }
+
+    return 0;
+}
+
+/*
+ * terrain_editor_key_handler - key handler function for terraform mode
+ */
+static int terrain_editor_key_handler(struct KeyHandler * kh, int key, int keymod)
+{
+    DECL_CAST(struct terrain_editor_applet, tea, kh->data);
+    struct session *session = tea->base.session;
+
+    printf("key=%x keymod=%x\n", key, keymod);
+
+    if (key == '\n' || key == SDLK_SPACE || key == SDLK_RETURN) {
+        int x = session->crosshair->getX();
+        int y = session->crosshair->getY();
+        terrain_editor_req_paint(tea, x, y);
+        return 0;  /* Keep on keyhandling */
+    }
+
+    if (keyIsDirection(key)) {
+        int dir = keyToDirection(key);
+        /* SAM: TODO: The Terraform cursor should not be allowed to go
+         *            past the Viewport bounds...
+         */
+        /* gjm: why not? */
+        session->crosshair->move(directionToDx(dir), directionToDy(dir));
+        mapSetDirty();
+        int x = session->crosshair->getX();
+        int y = session->crosshair->getY();
+        terrain_editor_look_at_xy(tea, x, y);
+
+        /* If the CTRL key is held down then also run the target function to
+         * paint the tile. */
+        if (keymod & KMOD_CTRL) {
+            terrain_editor_req_paint(tea, x, y);
+        }
+        return 0;  /* Keep on keyhandling */
+    }
+
+    if (key >= '0' && key <= '9') {
+        // Number key 0..9 == get/set quick terrain
+        int qt = key - '0';
+    
+        if ((keymod && KMOD_LCTRL) || (keymod && KMOD_RCTRL)) {
+            // Control-NUM == set quick terrain to current:
+            tea->quick[qt] = tea->terrain;
+            log_msg("[Set Quick %d]: %s '%s'", qt, tea->terrain->tag, tea->terrain->name);
+            return 0;
+        } else {
+            // Plain NUM == set current terrain from quick terrain:
+            if (!tea->quick[qt]) {
+                log_msg("[Quick %d]: empty!");
+            } else {
+                tea->terrain = tea->quick[qt];
+                log_msg("[Quick %d]: %s '%s'", qt, tea->terrain->tag, tea->terrain->name);
+            }
+        }
+        return 0;
+    }
+
+    switch (key) {
+
+    case KEY_SHIFT_EAST:
+    {
+        struct list *list = tea->pane->list.next;
+        if (list == &tea->panes) {
+            list = list->next;
+        }
+        assert(list != &tea->panes);
+        tea->pane = outcast(list, struct terrain_editor_pane, list);
+        statusRepaint();
+    }
+    break;
+
+    case KEY_SHIFT_WEST:
+    {
+        struct list *list = tea->pane->list.prev;
+        if (list == &tea->panes) {
+            list = list->prev;
+        }
+        assert(list != &tea->panes);
+        tea->pane = outcast(list, struct terrain_editor_pane, list);
+        statusRepaint();
+    }
+    break;
+
+    case 'c':
+        /* Set the terrain beneath the cursor as the current "pen" */
+        tea->terrain = place_get_terrain(session->crosshair->getPlace(),
+                                         session->crosshair->getX(),
+                                         session->crosshair->getY());
+        emit_terraform_status("Copy", tea->terrain);
+        return 0;
+
+    case 'f':
+        terrain_editor_req_fill(tea, session->crosshair->getX(), session->crosshair->getY());
+        emit_terraform_status("Flood-Fill", tea->terrain);
+        return 0;
+
+    case KEY_CTRL_R:
+        terrain_editor_redo(tea);
+        return 0;        
+
+    case KEY_CTRL_Z:
+        terrain_editor_undo(tea);
+        return 0;
+
+    case SDLK_ESCAPE:
+        return 1; /* done */
+    }
+
+    /* pass it to the pane handler */
+    if (tea->pane->key_handler) {
+        return tea->pane->key_handler(tea->pane, key, keymod);
+    }
+
+    return 0;
+}
+
+/**
+ * Handle mouse clicks on the map viewer. (mx, my) are the place coordinates
+ * clicked.
+ */
+static bool terrain_editor_map_click(struct terrain_editor_applet *tea, int mx, int my)
+{
+#if 1
+    struct session *session = tea->base.session;
+    class Cursor *crosshair = session->crosshair;
+    int cx = crosshair->getX();
+    int cy = crosshair->getY();
+
+    /* Did the crosshair move? */
+    if ((cx != mx) || (cy != my)) {
+
+        /* Move the crosshair */
+        crosshair->move(mx - cx, my - cy);
+        mapSetDirty();
+
+        /* Need to run our visitor function on each tile? */
+        terrain_editor_look_at_xy(tea, mx, my);
+    }
+#endif
+    terrain_editor_req_paint(tea, mx, my);
+
+    return false;
+}
+
+/**
+ * terrain_editor_next - return the next terrain in the session terrain list or
+ * NULL if this is the last.
+ */
+static terrain *terrain_editor_next(struct terrain_editor_applet *tea, struct terrain *ter)
+{
+    struct list *head = &tea->base.session->terrains;
+    struct list *elem = ter->session_list.next;
+    if (elem == head) {
+        return NULL;
+    }
+    return list_entry(elem, struct terrain, session_list);
+}
+
+/**
+ * terrain_editor_lookup - find the terrain at the given index in the session
+ * terrain list and return it, or NULL if the index is beyond the end of the
+ * list.
+ */
+static terrain *terrain_editor_lookup(struct terrain_editor_applet *tea, int index)
+{
+    struct list *head = &tea->base.session->terrains;
+    struct list *elem = head->next;
+    while (index && (elem != head)) {
+        index--;
+        elem = elem->next;
+    }
+    if (index) {
+        return NULL;
+    }
+
+    return list_entry(elem, struct terrain, session_list);
+}
+
+/**
+ * Handle mouse clicks on the palette viewer. (sx, sy) are the screen
+ * coordinates clicked.
+ */
+static bool terrain_editor_palette_mouse_click_handler(struct terrain_editor_pane *pane, int pane_x, int pane_y)
+{
+    DECL_CAST(struct terrain_editor_palette, pal, pane);
+
+    /* Convert pane pixel coordinates to row and column */
+    int row = pane_y / TILE_H;
+    int col = pane_x / TILE_W;
+
+    /* Convert row and column to palette index */
+    int index = pal->top_index + col + (row * pal->max_cols);
+    
+    /* Lookup */
+    struct terrain *newter = terrain_editor_lookup(pane->app, index);
+    if (newter) {
+        pane->app->terrain = newter;
+        emit_terraform_status("Set ", pane->app->terrain);
+    }
+
+    return false;
+}
+
+/*
+ * terrain_editor_mouse_button_handler - mouse button handler function for
+ * terraform mode
+ */
+static bool terrain_editor_mouse_button_handler(struct MouseButtonHandler *mh, SDL_MouseButtonEvent *event)
+{
+    DECL_CAST(struct terrain_editor_applet, tea, mh->data);
+    int mx = event->x;
+    int my = event->y;
+    
+    /* Clicked on the map? */
+    if (! mapScreenToPlaceCoords(&mx, &my)) {
+        return terrain_editor_map_click(tea, mx, my);
+    }
+    
+    /* Clicked on the palette window? */
+    if (point_in_rect(event->x, event->y, &tea->base.dims)) {
+        tea->pane->mouse_click_handler(tea->pane, event->x - tea->base.dims.x, event->y - tea->base.dims.y);
+    }
+    
+    return false;
+}
+
+/*
+ * terrain_editor_mouse_motion_handler - mouse motion handler function for
+ * terraform mode
+ */
+static bool terrain_editor_mouse_motion_handler(struct MouseMotionHandler *mh, SDL_MouseMotionEvent *event)
+{
+    DECL_CAST(struct terrain_editor_applet, tea, mh->data);
+    int mx = event->x;
+    int my = event->y;
+    int dragging = event->state & SDL_BUTTON(1);
+
+    
+    /* Clicked on the map? */
+    if (dragging && ! mapScreenToPlaceCoords(&mx, &my)) {
+        return terrain_editor_map_click(tea, mx, my);
+    }
+    return false;
+}
+
+
+/**
+ * Start and run the terrain editor until player quits back to game.
+ */
+static void terrain_editor_applet_ops_run(struct applet *applet, SDL_Rect *dims, struct session *session)
+{
+    /* Initialize the base applet */
+    applet->dims = *dims;
+    applet->session = session;
+
+    /* Initialize the custom applet fields */
+    DECL_CAST(struct terrain_editor_applet, tea, applet);
+    tea->pal->max_cols = dims->w / TILE_W;
+    tea->pal->max_rows = dims->h / TILE_H;
+    assert(! list_empty(&session->terrains));
+    tea->terrain = list_entry(session->terrains.next, struct terrain, session_list);
+    tea->pal->max_top_index = list_len(&session->terrains) - (tea->pal->max_cols * tea->pal->max_rows);
+    if (tea->pal->max_top_index < 0) {
+        tea->pal->max_top_index = 0;
+    }
+
+    /* Initialize the status window */
+    status_set_title("Terrain Editor");
+    statusRepaint();
+
+    /* Initialize the cmdwin window */
+    cmdwin_clear();
+    cmdwin_spush("Terraform");
+    cmdwin_spush("<target> (ESC to exit)");
+
+    /* Initialize the console */
+    log_begin_group();
+    log_msg("---Terraform---");
+    log_msg("Place %s",     tea->place->tag  );
+    log_msg("      \"%s\"", tea->place->name );
+    log_msg("Map   %s",     tea->place->terrain_map->tag    );
+    log_msg("");
+    
+    emit_terraform_status("Set ", tea->terrain);
+    terrain_editor_look_at_xy(tea, tea->x, tea->y);
+
+    /* Position the cursor */
+    session->crosshair->setRange(99);
+    session->crosshair->setViewportBounded(1);
+    session->crosshair->setOrigin(tea->x, tea->y);
+    session->crosshair->relocate(tea->place, tea->x, tea->y);
+    mapSetDirty();
+
+    /* Initialize the foogod hints */
+    foogodSetHintText("SHIFT+\200\201=scroll ESC=exit");
+    foogodSetMode(FOOGOD_HINT);        
+  
+    /* Setup the key handler */
+    struct KeyHandler kh;
+    kh.fx = terrain_editor_key_handler;
+    kh.data = tea;
+    eventPushKeyHandler(&kh);
+
+    /* Setup the mouse click handler */
+    struct MouseButtonHandler mbh;
+    mbh.fx = terrain_editor_mouse_button_handler;
+    mbh.data = tea;
+    eventPushMouseButtonHandler(&mbh);
+
+    /* Setup the mouse movement handler */
+    struct MouseMotionHandler mmh;
+    mmh.fx = terrain_editor_mouse_motion_handler;
+    mmh.data = tea;
+    eventPushMouseMotionHandler(&mmh);
+
+    /* Enter interactive mode */
+    eventHandle();
+
+    /* Done -  cleanup */
+    foogodSetMode(FOOGOD_DEFAULT);
+    cmdwin_pop();
+    eventPopKeyHandler();
+    eventPopMouseButtonHandler();
+    eventPopMouseMotionHandler();
+    session->crosshair->remove();
+    mapSetDirty();
+  
+    cmdwin_spush("Done.");
+    log_msg("---Terraform Done---");
+
+    
+    log_end_group();
+    
+}
+
+/**
+ * Paint the help screen
+ */
+static void terrain_editor_help_paint(struct terrain_editor_pane *pane)
+{
+    static const char *text[] = {
+        "  PageUp/PageDn/ = Scroll palette up/down",
+        "       Home/End  = Scroll to begin/end",
+        "     Arrow Keys  = Move cursor",
+        "     SPACE/ENTER = Paint terrain",
+        " CTRL-Arrow Keys = Paint continuously",
+        "               C = Copy from ground",
+        "               F = Flood-fill",
+        "SHIFT-Arrow Keys = Flip/scroll status",
+        "      1234567890 = Get from QuickKey",
+        " CTRL-1234567890 = Set QuickKey",
+        "          CTRL-Z = undo",
+        "          CTRL-R = redo",
+        "             ESC = Exit back to game",
+        NULL
+    };
+
+    SDL_Rect rect = pane->app->base.dims;
+    rect.h = ASCII_H;
+    rect.y += ASCII_H;
+
+    /* Naively assume we don't have to worry about wrapping/scrolling... since
+     * we probably won't unless the list starts getting long. */
+
+    for (int i = 0; text[i]; i++) {
+        screenPrint(&rect, 0, text[i]);
+        rect.y += ASCII_H;
+    }
+
+    status_set_title("Editor: Commands");
+}
+
+/**
+ * Paint the terrain palette pane.
+ */
+static void terrain_editor_palette_paint(struct terrain_editor_pane *pane)
+{
+    DECL_CAST(struct terrain_editor_palette, pal, pane);
+    SDL_Rect *dims = &pane->app->base.dims;
+    int y = dims->y;
+    struct terrain *ter = terrain_editor_lookup(pane->app, pal->top_index);
+    for (int row = 0; ter && (row < pal->max_rows); row++) {
+        int x = dims->x;
+        for (int col = 0; ter && (col < pal->max_cols); col++) {
+            sprite_paint(ter->sprite, 0, x, y);
+            ter = terrain_editor_next(pane->app, ter);
+            x += TILE_W;
+        }
+        y += TILE_H;
+    }
+    screenUpdate(dims);
+
+    status_set_title("Editor: Palette");
+}
+
+/**
+ * Called by statusRepaint(), this repaints the status window only, the map and
+ * console continue to be updated in their usual way.
+ */
+static void terrain_editor_applet_ops_paint(struct applet *applet)
+{
+    DECL_CAST(struct terrain_editor_applet, tea, applet);
+    tea->pane->paint(tea->pane);
+}
+
+struct applet_ops terrain_editor_applet_ops = {
+    terrain_editor_applet_ops_run,
+    terrain_editor_applet_ops_paint,
+    NULL, /* get_desired_height */
+};
+
+static void terrain_editor_applet_del(struct terrain_editor_applet *tea)
+{
+    /* delete the command list */
+    terrain_editor_del_cmd_list(tea, tea->cmds.next);
+
+    /* delete the panes */
+    struct list *list = tea->panes.next;
+    while (list != &tea->panes) {
+        struct terrain_editor_pane *pane = outcast(list, struct terrain_editor_pane, list);
+        list = list->next;
+        free(pane);
+    }
+
+    /* unref the clone of the original map */
+    if (tea->origmap) {
+        terrain_map_unref(tea->origmap);
+    }
+
+    free(tea);
+}
+
+static struct terrain_editor_applet *terrain_editor_applet_new(struct place *place, int x, int y)
+{
+    struct terrain_editor_pane *help;
+
+    /* Create the base instance */
+    struct terrain_editor_applet *tea = (struct terrain_editor_applet *)calloc(1, sizeof(*tea));
+    if (!tea) {
+        return NULL;
+    }
+
+    list_init(&tea->panes);
+    list_init(&tea->cmds);
+    tea->lastcmd = &tea->cmds;
+    tea->base.ops = &terrain_editor_applet_ops;
+    tea->place = place;
+    tea->x = x;
+    tea->y = y;
+
+    if (!(tea->origmap = terrain_map_clone(tea->place->terrain_map, tea->place->terrain_map->tag))) {
+        goto abort;
+    }
+
+    terrain_map_ref(tea->origmap);
+
+    /* Add the help pane */
+    help = (struct terrain_editor_pane *)calloc(1, sizeof(*help));
+    if (!help) {
+        goto abort;
+    }
+
+    help->paint = terrain_editor_help_paint;
+    help->key_handler = NULL;
+    help->mouse_click_handler = NULL;
+    help->app = tea;
+    list_add_tail(&tea->panes, &help->list);
+
+    /* Add the terrain palette pane */
+    tea->pal = (struct terrain_editor_palette *)calloc(1, sizeof(*(tea->pal)));
+    if (!tea->pal) {
+        goto abort;
+    }
+
+    tea->pal->base.paint = terrain_editor_palette_paint;
+    tea->pal->base.key_handler = terrain_editor_palette_key_handler;
+    tea->pal->base.mouse_click_handler = terrain_editor_palette_mouse_click_handler;
+    tea->pal->base.app = tea;
+    list_add_tail(&tea->panes, &tea->pal->base.list);
+
+    tea->pane = help;
+
+    return tea;
+
+ abort:
+    terrain_editor_applet_del(tea);
+    return NULL;
+}
+
+void terrain_editor_run(struct place *place, int x, int y)
+{
+    struct terrain_editor_applet *tea = terrain_editor_applet_new(place, x, y);
+    if (tea) {
+        statusRunApplet(&tea->base);
+        statusSetMode(ShowParty);
+        terrain_editor_applet_del(tea);
+    }
+}
diff --git a/src/terrain_editor.h b/src/terrain_editor.h
new file mode 100644 (file)
index 0000000..740fa14
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+#ifndef terrain_editor_h
+#define terrain_editor_h
+
+extern void terrain_editor_run(struct place *place, int x, int y);
+
+#endif
diff --git a/src/terrain_map.c b/src/terrain_map.c
new file mode 100644 (file)
index 0000000..9ae1ec6
--- /dev/null
@@ -0,0 +1,609 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "terrain_map.h"
+#include "terrain.h"
+#include "map.h"
+#include "session.h"
+#include "common.h"
+
+#include <assert.h>
+
+struct terrain_map *terrain_map_new(const char *tag, unsigned int w,
+                                    unsigned int h,
+                                    struct terrain_palette * pal)
+{
+       struct terrain_map *terrain_map;
+       CREATE(terrain_map, struct terrain_map, 0);
+       if (tag) {
+                terrain_map->tag = strdup(tag);
+                assert(terrain_map->tag);
+        }
+       terrain_map->w = w;
+       terrain_map->h = h;
+        terrain_map->palette = pal;
+       terrain_map->terrain =
+                (struct terrain **) malloc(sizeof(struct terrain *) * w * h);
+        terrain_map->refcount = 1;
+        assert(terrain_map->terrain);
+       memset(terrain_map->terrain, 0, sizeof(struct terrain *) * w * h);
+       return terrain_map;
+}
+
+struct terrain_map *terrain_map_clone(struct terrain_map *orig, const char *tag)
+{
+       struct terrain_map *map;
+
+        if (!orig->palette) {
+                err("terrain_map_clone() \n"
+                    " called to clone a map (tag '%s') without a palette,\n"
+                    " this may be or cause a problem elsewhere.\n", 
+                    orig->tag);
+        }
+        
+       map = terrain_map_new(tag, orig->w, orig->h, orig->palette);        
+       memcpy(map->terrain, orig->terrain,
+              sizeof(struct terrain *) * orig->w * orig->h);
+
+        map->composite = orig->composite;
+        map->submap_w = orig->submap_w;
+        map->submap_h = orig->submap_h;
+        
+       return map;
+}
+
+void terrain_map_rotate(struct terrain_map *map, int degree)
+{
+    // SAM:
+    // One thing we will want to provide for in the future
+    // is maps with terrain with different orientations.
+    // The canonical example is diagonal wall sections
+    // for NW,NE,SW,SE corners.
+    // 
+    // A map containing such pieces looks strange after rotation.
+    // Presumably in future some means will exist of specifying 
+    // that a terrain has an "orientation" or "facing" which must 
+    // be preserved (by substitution of terrain and/or sprite) 
+    // when the map is rotated.
+       struct terrain **rbuf;
+       int x1, y1, x2, y2;
+       int w2 = map->w;
+        int h2 = map->h;
+     
+       // Originally I tried a rotation matrix with a naive implementation,
+       // but I overlooked the problem that tile coordinates do not match up
+       // naturally with the point-based coordinates of the numeric axis
+       // assumed by such an alg. Yes, you twiddle things to work but I don't
+       // think it's worth it given the limited nature of the rotations I
+       // support here. So I fell back on a set of straightforward copy
+       // routines.
+
+       rbuf =
+           (struct terrain **) malloc(sizeof(struct terrain *) * map->w *
+                                      map->h);
+       if (rbuf == NULL) {
+               err("malloc failed");
+               return;
+       }
+       // First convert the degrees to one of the four cases.
+       degree = degree % 360;
+       degree = degree / 90;
+
+       switch (degree) {
+       case 0:
+               // Nothing to do.
+               return;
+       case 1:
+               // 90 degree clockwise rotation:
+               // 
+               // 0  1  2    9  6  3  0
+               // 3  4  5 => 10 7  4  1
+               // 6  7  8    11 8  5  2
+               // 9 10 11
+               w2 = map->h;
+               h2 = map->w;
+               for (y1 = 0, x2 = w2 - 1; y1 < map->h; y1++, x2--) {
+                       for (x1 = 0, y2 = 0; x1 < map->w; x1++, y2++) {
+                               rbuf[y2 * w2 + x2] =
+                                   map->terrain[y1 * map->w + x1];
+                       }
+               }
+               break;
+       case 2:
+               // 180 degree rotation:
+               // 
+               // 0  1  2    11 10  9 
+               // 3  4  5 =>  8  7  6
+               // 6  7  8     5  4  3
+               // 9 10 11     2  1  0
+               w2 = map->w;
+               h2 = map->h;
+               for (y1 = 0, y2 = h2 - 1; y1 < map->h; y1++, y2--) {
+                       for (x1 = 0, x2 = w2 - 1; x1 < map->w; x1++, x2--) {
+                               rbuf[y2 * w2 + x2] =
+                                   map->terrain[y1 * map->w + x1];
+                       }
+               }
+               break;
+       case 3:
+               // 90 degree counter-clockwise rotation:
+               // 
+               // 0  1  2    2  5  8 11
+               // 3  4  5 => 1  4  7 10
+               // 6  7  8    0  3  6  9
+               // 9 10 11
+               w2 = map->h;
+               h2 = map->w;
+               for (y1 = 0, x2 = 0; y1 < map->h; y1++, x2++) {
+                       for (x1 = 0, y2 = h2 - 1; x1 < map->w; x1++, y2--) {
+                               rbuf[y2 * w2 + x2] =
+                                   map->terrain[y1 * map->w + x1];
+                       }
+               }
+               break;
+       default:
+               assert(false);
+       }
+
+       // debug
+
+       // Free the original copy.
+       free(map->terrain);
+
+       // Replace the original with the rotated copy.
+       map->terrain = rbuf;
+       map->w = w2;
+       map->h = h2;
+
+}
+
+void terrain_map_unref(struct terrain_map *terrain_map)
+{
+        assert(terrain_map->refcount);
+        terrain_map->refcount--;
+        if (!terrain_map->refcount) {
+                if (terrain_map->tag)
+                        free(terrain_map->tag);
+                if (terrain_map->terrain)
+                        free(terrain_map->terrain);
+                free(terrain_map);
+        }
+}
+
+void terrain_map_blit(struct terrain_map *dest, int dest_x, int dest_y,
+                      struct terrain_map *src,  int src_x,  int src_y,
+                      int w, int h)
+{
+       int x, y;
+       struct terrain **dptr, **sptr;
+
+       // truncate dimensions if nec
+       w = min(dest->w - dest_x, min(w, min(dest->w, src->w)));
+       h = min(dest->h - dest_y, min(h, min(dest->h, src->h)));
+
+       for (y = 0; y < h; y++) {
+               dptr = dest->terrain + ((y + dest_y) * dest->w + dest_x);
+               sptr = src->terrain + ((y + src_y) * src->w + src_x);
+               for (x = 0; x < w; x++) {
+                       *dptr++ = *sptr++;
+               }
+       }
+}
+
+void terrain_map_fill(struct terrain_map *map, int x, int y, int w, int h,
+                     struct terrain *fill)
+{
+       int x2, y2;
+    assert(map);
+    assert(fill);
+
+       for (y2 = y; y2 < (y + h); y2++) {
+               if (y2 < 0)
+                       continue;
+               if (y2 >= map->h)
+                       break;
+               for (x2 = x; x2 < (x + w); x2++) {
+                       if (x2 < 0)
+                               continue;
+                       if (x2 >= map->w)
+                               break;
+                       map->terrain[y2 * map->w + x2] = fill;
+               }
+       }
+}
+
+#define PREFER_COMPACT_MAPS 1
+extern void terrain_map_print(FILE * fp, int indent, struct terrain_map *map)
+{
+    int x, y, compact;
+    struct terrain_palette * palette;
+       assert(fp);
+    assert(map);
+
+    palette = map->palette;
+    if (!palette) {
+        // No point in carrying on without a palette.
+        printf("terrain_map_print(): No palette for map '%s'.", map->tag);
+        exit(1);
+    }
+
+    // (kern-mk-map 'm_map www hhh pal_expanded
+    //     (list
+    //         ; 0  1  2  3
+    //         ".. .. .. ..";  //  0
+    //         ".. .. .. ..";  //  1
+    //         ".. .. .. ..";  //  2
+    //     )
+    // ) ;; map m_map
+
+
+       INDENT;
+    // fprintf(fp, "MAP '%s' {\n", map->tag);
+    fprintf(fp, "(kern-mk-map '%s %d %d %s\n", map->tag, map->w, map->h, palette->tag);
+       indent += INDENTATION_FACTOR;
+
+    compact = (PREFER_COMPACT_MAPS && palette->widest_glyph == 1);
+    if (compact) {
+      INDENT; fprintf(fp, ";; Compact map (glyphs are 1 char wide)\n");
+    }
+
+    INDENT; fprintf(fp, "(list\n");
+    print_horizontal_guideline(fp, indent, map);
+
+       indent += INDENTATION_FACTOR;
+
+    int w = palette->widest_glyph;
+       for (y = 0; y < map->h; y++) {
+      INDENT; fprintf(fp, "\"");
+
+      for (x = 0; x < map->w; x++) {
+        int i = (y * map->w) + x;
+        struct terrain * tt = map->terrain[i];
+        char * glyph = palette_glyph_for_terrain(palette, tt);
+        if (!glyph) {
+          // SAM: 
+          // There are still circumstance(s) where this can happen.
+          // One example is a ship map blitted onto another combat map.
+          // The ship hull terrain is not in the standard palette,
+          // and each such terrain will hit this clause.
+          // 
+          // No point in carrying on.
+          printf("terrain_map_print(): No glyph at XY=(%d,%d) map '%s'.", x, y, map->tag);
+          exit(1);
+        }
+        fprintf(fp, "%*s%s", w, glyph, (compact) ? "" : " ");
+      } // for (x)
+
+      fprintf(fp, "\";  // %3d\n", y);
+       } // for (y)
+
+       indent -= INDENTATION_FACTOR;
+    // SAM: BUG: The horizontal guide after the list of terrain produces a complaint from Scheme.  Why?
+    // print_horizontal_guideline(fp, indent, map);
+       INDENT; 
+    fprintf(fp, ")\n");
+
+       indent -= INDENTATION_FACTOR;
+       INDENT; 
+    fprintf(fp, ") ;; map %s\n", map->tag);
+       fprintf(fp, "\n");
+}
+
+
+void print_horizontal_guideline (FILE * fp, int indent, struct terrain_map *map)
+{
+    // Note that the horizontal coordinates guide-lines below
+    // will only be lined up correctly if INDENTATION_FACTOR == 2
+    struct terrain_palette * palette;
+    int compact;
+       assert(fp);
+    assert(map);
+
+    palette = map->palette;
+    compact = (PREFER_COMPACT_MAPS && palette->widest_glyph == 1);
+
+    if (compact) {
+      // These templates will suffice for maps of up to width 80
+      int w = map->w * palette->widest_glyph;
+      static char line1_template[] = 
+        "          1111111111222222222233333333334444444444555555555566666666667777777777";
+      static char line2_template[] =
+        "01234567890123456789012345678901234567890123456789012345678901234567890123456789";
+      char * line_1 = strdup(line1_template);
+      char * line_2 = strdup(line2_template);
+      if (w <= 80) {
+        line_1[w] = '\0';
+        line_2[w] = '\0';
+      }
+      INDENT; fprintf(fp, ";; %s\n", line_1);
+      INDENT; fprintf(fp, ";; %s\n", line_2);
+    }
+    else if (palette->widest_glyph == 1) {
+      // These templates will suffice for maps of up to width 50
+      int w = map->w * (palette->widest_glyph + 1);
+      static char line1_template[] = 
+        "                    1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 ";
+      static char line2_template[] =
+        "0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 ";
+      char * line_1 = strdup(line1_template);
+      char * line_2 = strdup(line2_template);
+      if (w <= 50*2) {
+        line_1[w] = '\0';
+        line_2[w] = '\0';
+      }
+      INDENT; fprintf(fp, ";; %s\n", line_1);
+      INDENT; fprintf(fp, ";; %s\n", line_2);
+    }
+    else if (palette->widest_glyph == 2) {
+      // These templates will suffice for maps of up to width 40
+      int w = map->w * (palette->widest_glyph + 1);
+      static char line1_template[] = 
+        "                               1  1  1  1  1  1  1  1  1  1  2  2  2  2  2  2  2  2  2  2  3  3  3  3  3  3  3  3  3  3  ";
+      static char line2_template[] =
+        " 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5  6  7  8  9  ";
+      char * line_1 = strdup(line1_template);
+      char * line_2 = strdup(line2_template);
+      if (w < 40*3) {
+        line_1[w] = '\0';
+        line_2[w] = '\0';
+      }
+      INDENT; fprintf(fp, ";; %s\n", line_1);
+      INDENT; fprintf(fp, ";; %s\n", line_2);
+    }
+    // TODO: width 3 and 4 palettes.
+}
+
+static void terrain_map_composite_print_block_header (struct save * save, int nn, int n_blocks, int x, int y, int sub_w, int sub_h) {
+    int  west_x,  east_x;
+    int north_y, south_y;
+
+    west_x = x * sub_w;
+    east_x = ((x+1) * sub_w) - 1;
+
+    north_y = y * sub_h;
+    south_y = ((y+1) * sub_h) - 1;
+
+    save->write(save,
+               ";; Map Block #%d/%d (%d,%d)\n",
+               nn, n_blocks, x, y);
+    save->write(save,
+               ";;   NW=%3d,%-3d  NE=%3d,%-3d \n",
+               west_x, north_y, /* NW corner */
+               east_x, north_y  /* NE corner */ );
+    save->write(save,
+               ";;   SW=%3d,%-3d  SE=%3d,%-3d \n",
+               west_x, south_y, /* SW corner */
+               east_x, south_y  /* SE corner */ );
+    save->write(save, "\n");
+}
+
+static void terrain_map_composite_save(struct save *save, struct terrain_map *map)
+{
+    int w, h, sub_w, sub_h;
+    int x, y, sub_x, sub_y;
+    int nn;
+    const char * tag;
+
+        map->saved = save->session_id;
+
+       sub_w = map->submap_w;
+       sub_h = map->submap_h;
+
+        w = map->w / sub_w;
+        h = map->h / sub_h;
+
+        /* write the composite map constructor */
+        if (map->tag)
+           tag = map->tag;
+        else
+           tag = "nil";
+
+        save->enter(save, 
+                   "(kern-mk-composite-map %s%s %d %d\n", 
+                   map->tag ? "'" : "", tag, 
+                   w, h);
+       save->write(save,
+                   ";; %d x %d map blocks: %d blocks, each %d x %d tiles\n",
+                   w, h, (w * h), sub_w, sub_h);
+
+       save->write(save, ";; Map block layout:\n");
+       nn = 1;
+       for (y = 0; y < h; y++) {
+           save->write(save, ";; ");
+           for (x = 0; x < w; x++) {
+               fprintf(save->file, 
+                       "Block %2d (%d,%d)  ",
+                       nn, x, y);
+               nn++;
+           }
+           fprintf(save->file, "\n");
+       }
+       fprintf(save->file, "\n");
+
+        /* for each submap */
+       nn = 1;
+        for (y = 0; y < h; y++) {
+                for (x = 0; x < w; x++) {
+                   /* write the submap constructor */
+                   save->enter(save, 
+                               "(kern-mk-map nil %d %d %s\n", 
+                               sub_w, sub_h, map->palette->tag);
+                   terrain_map_composite_print_block_header(save, nn, (w*h), x, y, sub_w, sub_h);
+
+                        /* write the submap terrain list */
+                        save->enter(save, "(list\n");
+
+                        for (sub_y = y*map->submap_h; 
+                             sub_y < y*map->submap_h+map->submap_h; 
+                             sub_y++) {
+
+                                save->write(save, "\"");
+
+                                for (sub_x = x*map->submap_w; 
+                                     sub_x < x*map->submap_w+map->submap_w; 
+                                     sub_x++) {                        
+                                        char *glyph;
+                                        
+                                        glyph = palette_glyph_for_terrain(
+                                                map->palette,
+                                                map->terrain[sub_y*map->w+sub_x]);
+                                        if (! glyph) {
+                                                err("map %s: no glyph in palette %s "\
+                                                    "for terrain at [%d %d]\n", map->tag,
+                                                    map->palette->tag, sub_x, sub_y);
+                                                assert(glyph);
+                                        }
+                                        
+                                        // print with no indentation (same line)
+                                        fprintf(save->file, "%2s ", glyph);
+                                }
+                                fprintf(save->file, "\"\n");
+                        }
+                        
+                        save->exit(save, ")\n");
+                        save->exit(save, ")\n");
+                       nn++;
+                }
+        }
+        
+        save->exit(save, ")\n");
+}
+
+void terrain_map_save(struct save *save, void *val)
+{
+        struct terrain_map *map;
+        int x, y, i;
+
+        map = (struct terrain_map*)val;
+
+        if (map->saved == save->session_id) {
+                save->write(save, "%s\n", map->tag);
+                return;
+        }
+
+        if (map->composite) {
+                terrain_map_composite_save(save, map);
+                return;
+        }
+
+        save->enter(save, "(kern-mk-map\n");
+        if (map->tag)
+                save->write(save, "'%s ", map->tag);
+        else
+                save->write(save, "nil ");
+        save->write(save, "%d %d %s\n", map->w, map->h, map->palette->tag);
+        save->enter(save, "(list\n");
+
+        i = 0;
+        for (y = 0; y < map->h; y++) {
+                save->write(save, "\"");
+
+                for (x = 0; x < map->w; x++) {                        
+                        char *glyph;
+
+                        glyph = palette_glyph_for_terrain(map->palette,
+                                                          map->terrain[i]);
+                        if (! glyph) {
+                                err("map %s: no glyph in palette %s "\
+                                         "for terrain at [%d %d]\n", map->tag,
+                                         map->palette->tag, x, y);
+                                assert(glyph);
+                        }
+
+                        // print with no indentation (same line)
+                        fprintf(save->file, "%2s ", glyph);
+
+                        i++;
+                }
+                fprintf(save->file, "\"\n");
+        }
+        save->exit(save, ")\n");
+        save->exit(save, ")\n");
+
+        map->saved = save->session_id;
+}
+
+static int terrain_not_sup(struct terrain *tt, int n_not_sup, struct terrain **not_sup)
+{
+        int i;
+        for (i = 0; i < n_not_sup; i++) {
+                if (tt == not_sup[i])
+                        return 1;
+        }
+
+        return 0;
+}
+
+static int terrain_map_match_pattern(struct terrain_map *map, int ox, int oy, 
+                                     struct terrain *inf, 
+                                     int n_not_sup,
+                                     struct terrain **not_sup
+                                     )
+{
+        int rule = 0;
+
+        /* north */
+        if (! terrain_not_sup(terrain_map_get_terrain(map, ox, oy - 1),
+                              n_not_sup, not_sup))
+                rule += 1;
+
+        /* west */
+        if (! terrain_not_sup(terrain_map_get_terrain(map, ox - 1, oy),
+                              n_not_sup, not_sup))
+                rule += 2;
+
+        /* east */
+        if (! terrain_not_sup(terrain_map_get_terrain(map, ox + 1, oy),
+                              n_not_sup, not_sup))
+                rule += 4;
+
+        /* south */
+        if (! terrain_not_sup(terrain_map_get_terrain(map, ox, oy + 1),
+                              n_not_sup, not_sup))
+                rule += 8;
+
+        return rule;
+}
+
+void terrain_map_blend(struct terrain_map *map, 
+                       struct terrain *inf,
+                       int n_not_sup,
+                       struct terrain **not_sup,
+                       struct terrain *range[16])
+{
+        int x, y, rule;
+
+        for (y = 1; y < (map->h - 1); y++) {
+
+                for (x = 1; x < (map->w - 1); x++) {
+
+                        if (terrain_map_get_terrain(map, x, y) == inf) {
+
+                                rule = terrain_map_match_pattern(map, x, y, inf, n_not_sup, not_sup);
+
+                                if (rule) {
+                                        map->terrain[y*map->w+x] = range[rule];
+                                }
+
+                        }
+                }
+        }
+}
diff --git a/src/terrain_map.h b/src/terrain_map.h
new file mode 100644 (file)
index 0000000..30e46a7
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef terrain_map_h
+#define terrain_map_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+#include <stdio.h>
+
+#include "list.h"
+
+extern char *TERRAIN_MAP_MAGIC;
+
+struct terrain_map {
+        char *tag;
+        int w;
+        int h;
+        struct terrain_palette * palette;
+        struct terrain **terrain;
+
+        void *handle;  /* pointer to session handle */
+        int saved;     /* 1 iff already saved       */
+        int refcount;
+
+        /* added to support composite maps */
+        int submap_w;        /* submap width      */
+        int submap_h;        /* submap height     */
+        char composite : 1;  /* save as composite */
+};
+
+extern struct terrain_map *terrain_map_new(const char *tag, 
+                                           unsigned int w, 
+                                           unsigned int h,
+                                           struct terrain_palette * pal);
+#define terrain_map_ref(map) ((map)->refcount++)
+extern void terrain_map_unref(struct terrain_map *map);
+extern struct terrain_map *terrain_map_clone(struct terrain_map *orig, 
+                                             const char *tag);
+extern void terrain_map_rotate(struct terrain_map *map, int degree);
+extern void terrain_map_blit(struct terrain_map *dest, int dest_x,
+                             int dest_y, struct terrain_map *src,
+                             int src_x, int src_y, int w, int h);
+extern void terrain_map_fill(struct terrain_map *map, int x, int y, int w, int h, struct terrain *fill);
+extern void terrain_map_print(FILE * fp, int indent,
+                              struct terrain_map *map);
+extern void print_horizontal_guideline (FILE * fp, int indent, 
+                                        struct terrain_map *map);
+
+extern void terrain_map_save(struct save *, void *val);
+extern void terrain_map_blend(struct terrain_map *map, 
+                              struct terrain *inf,
+                              int n_nonsup,
+                              struct terrain **nonsup,
+                              struct terrain *range[16]);
+
+
+static inline void terrain_map_set_terrain(struct terrain_map *map, int x, int y, struct terrain *val)
+{
+    map->terrain[y * map->w + x] = val;
+
+}
+
+static inline struct terrain *terrain_map_get_terrain(struct terrain_map *map, int x, int y)
+{
+    return map->terrain[y * map->w + x];
+}
+
+
+END_DECL
+
+#endif
diff --git a/src/tick.c b/src/tick.c
new file mode 100644 (file)
index 0000000..b3fac15
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "tick.h"
+
+#include <assert.h>
+#include <SDL.h>
+#include <SDL_thread.h>
+
+#include "common.h" /* TICK_EVENT */
+
+static int tick_paused = 0;
+static int tick_killed = 0;
+static SDL_Thread *tick_thread = NULL;
+
+static int tick_main(void *data)
+{
+       long msecs;
+       SDL_Event tick_event;
+
+        msecs = (long)data;
+       tick_event.type = SDL_USEREVENT;
+       tick_event.user.code = TICK_EVENT;
+
+        while (! tick_killed) {
+                SDL_Delay(msecs);
+                if (! tick_paused)
+                        SDL_PushEvent(&tick_event);
+       }
+
+        return 0;
+}
+
+void tick_start(long msecs)
+{
+        assert(! tick_thread);
+        tick_paused = 0;
+        tick_killed = 0;
+        if (msecs > 0)
+                tick_thread  = SDL_CreateThread(tick_main, (void*)msecs);
+}
+void tick_kill(void)
+{
+        tick_killed = 1;
+        if (tick_thread)
+                SDL_WaitThread(tick_thread, NULL);
+}
+
+void tick_pause(void)
+{
+        tick_paused = 1;
+}
+
+void tick_run(void)
+{
+        tick_paused = 0;
+}
diff --git a/src/tick.h b/src/tick.h
new file mode 100644 (file)
index 0000000..ec90db4
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2002, 2003 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+extern void tick_start(long msecs);
+extern void tick_kill(void);
+extern void tick_pause(void);
+extern void tick_run(void);
diff --git a/src/tree.c b/src/tree.c
new file mode 100644 (file)
index 0000000..05d199e
--- /dev/null
@@ -0,0 +1,175 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "tree.h"
+
+#include <assert.h>
+#include <string.h>
+
+static inline int tree_cmp(struct tree *t1, struct tree *t2)
+{
+        assert(t1->key_type == t2->key_type);
+        
+        switch (t1->key_type) {
+
+        case tree_i_key:
+                return t1->key.i_key - t2->key.i_key;
+                break;
+
+        case tree_s_key:
+                return strcmp(t1->key.s_key, t2->key.s_key);
+                break;
+
+        default:
+                assert(false);
+                break;
+        }
+
+        return 0;
+}
+
+void tree_insert(struct tree **root, struct tree *node)
+{
+       struct tree *parent = 0;
+       struct tree *current = *root;
+
+       while (current) {
+
+               parent = current;
+
+               if (tree_cmp(node, current) < 0)
+                       current = current->left;
+               else
+                       current = current->right;
+       }
+
+       node->p = parent;
+       if (!parent) {
+               *root = node;
+       } else if (tree_cmp(node, parent) < 0) {
+               parent->left = node;
+       } else {
+               parent->right = node;
+       }
+}
+
+void tree_delete(struct tree **root, struct tree *node)
+{
+       struct tree *splout;
+       struct tree *child;
+
+       /* Find a node to splice out */
+       if (!node->left || !node->right)
+               splout = node;
+       else
+               splout = tree_successor(node);
+
+       /* Find the non-null child of the node being spliced, or use null if
+        * there are no children. */
+       if (splout->left)
+               child = splout->left;
+       else
+               child = splout->right;
+
+       /* Splice out the node we picked */
+       if (child)
+               child->p = splout->p;
+       if (!splout->p) {
+               *root = child;
+       } else if (splout == splout->p->left) {
+               splout->p->left = child;
+       } else {
+               splout->p->right = child;
+       }
+
+       /* If the node spliced out was not the target node then use it to
+        * replace the target node */
+       if (splout != node)
+               tree_replace(root, node, splout);
+}
+
+struct tree *tree_successor(struct tree *node)
+{
+       struct tree *ptr;
+
+       if (node->right)
+               return tree_minimum(node->right);
+
+       ptr = node->p;
+
+       while (ptr && ptr->right == node) {
+               node = ptr;
+               ptr = ptr->p;
+       }
+
+       return ptr;
+}
+
+struct tree *tree_minimum(struct tree *node)
+{
+       while (node->left)
+               node = node->left;
+       return node;
+}
+
+void tree_replace(struct tree **root, struct tree *out, struct tree *in)
+{
+       in->p = out->p;
+
+       if (!out->p)
+               *root = in;
+       else if (out == out->p->right)
+               out->p->right = in;
+       else
+               out->p->left = in;
+
+       in->left = out->left;
+       if (in->left)
+               in->left->p = in;
+
+       in->right = out->right;
+       if (in->right)
+               in->right->p = in;
+}
+
+struct tree *tree_i_search(struct tree *root, int key) {
+        while (root && root->key.i_key != key) {
+                assert(root->key_type == tree_i_key);
+                if (key < root->key.i_key)
+                        root = root->left;
+                else
+                        root = root->right;
+        }
+        return root;
+}
+
+struct tree *tree_s_search(struct tree *root, const char *key)
+{
+        while (root && strcmp(root->key.s_key, key)) {
+                assert(root->key_type == tree_s_key);
+                if (strcmp(key, root->key.s_key) < 0)
+                        root = root->left;
+                else
+                        root = root->right;
+        }
+        return root;
+}
+        
diff --git a/src/tree.h b/src/tree.h
new file mode 100644 (file)
index 0000000..a2850d2
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef tree_h
+#define tree_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define tree_entry(ptr,type,field) \
+        ((type*)((char*)(ptr)-(unsigned long)(&((type *)0)->field)))
+
+        enum tree_key_type {
+                tree_i_key, // integer key
+                tree_s_key  // string key
+        };
+
+        struct tree {
+                enum tree_key_type key_type;
+                union {
+                        int i_key;
+                        char *s_key;
+                } key;
+                struct tree *left;
+                struct tree *right;
+                struct tree *p;
+        };
+
+        extern void tree_insert(struct tree **root, struct tree *node);
+        extern void tree_delete(struct tree **root, struct tree *node);
+        extern struct tree *tree_successor(struct tree *node);
+        extern struct tree *tree_minimum(struct tree *node);
+        extern void tree_replace(struct tree **root, struct tree *out, struct tree *in);
+        extern struct tree *tree_i_search(struct tree *root, int key);
+        extern struct tree *tree_s_search(struct tree *root, const char *key);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
new file mode 100644 (file)
index 0000000..961e310
--- /dev/null
@@ -0,0 +1,402 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "vehicle.h"
+#include "sprite.h"
+#include "common.h"
+#include "sound.h"
+#include "place.h"
+#include "map.h"
+#include "console.h"
+#include "wind.h"
+#include "player.h"
+#include "session.h"
+#include "log.h"
+
+/* This is the number of wilderness turns an unnamed vehicle will hang around
+ * before being garbage collected. Note that wilderness turns only pass when
+ * the player is actually walking around in the wilderness. Kamping, loitering
+ * and combat don't count. */
+#define VEHICLE_DEF_TTL 256
+
+#include <unistd.h>
+
+// ----------------------------------------------------------------------------
+//
+// VehicleType
+//
+// ----------------------------------------------------------------------------
+
+
+VehicleType::VehicleType(const char *tag, const char *name, struct sprite *sprite,
+                         struct terrain_map *_map,
+                         ArmsType *_ordnance,
+                         bool _vulnerable,
+                         bool _killsOccupants,
+                         bool _mustTurn,
+                         char *_mv_desc,
+                         sound_t *_mv_sound,
+                         int _tailwind_penalty,
+                         int _headwind_penalty,
+                         int _crosswind_penalty,
+                         int _max_hp,
+                         int _speed
+        )
+        : ObjectType(tag, name, sprite, vehicle_layer)
+{
+        map = _map;
+        formation = NULL;
+        ordnance = _ordnance;
+        is_vulnerable = _vulnerable;
+        kills_occupants = _killsOccupants;
+        must_turn = _mustTurn;
+        mv_desc = strdup(_mv_desc);
+        assert(mv_desc);
+        mv_sound = _mv_sound;
+        tailwind_penalty = _tailwind_penalty;
+        headwind_penalty = _headwind_penalty;
+        crosswind_penalty = _crosswind_penalty;
+
+        max_hp = _max_hp; // override base class default
+        speed  = _speed;  // override base class default
+}
+
+VehicleType::~ VehicleType() 
+{
+        if (mv_desc)
+                free(mv_desc);
+}
+
+class Object *VehicleType::createInstance()
+{
+       class Vehicle *obj = new Vehicle(this);
+        assert(obj);
+       return obj;
+}
+
+int VehicleType::getWindPenalty(int facing)
+{
+       int vdx, vdy, wdx, wdy, base_speed;
+
+       base_speed = getSpeed();
+
+       if (!mustTurn())
+                return 1;
+
+       vdx = directionToDx(facing);
+       vdy = directionToDy(facing);
+       wdx = directionToDx(windGetDirection());
+       wdy = directionToDy(windGetDirection());
+
+       // take the vector dot product
+        int dotprod = (vdx * wdx + vdy * wdy);
+        if (dotprod < 0) {
+            // with the wind
+            return tailwind_penalty;
+        } else if (0 == dotprod) {
+            // tacking across the wind
+            return crosswind_penalty;
+        } else {
+            // against the wind
+            return headwind_penalty;
+        }
+}
+
+bool VehicleType::mustTurn()
+{
+        return must_turn;
+}
+
+bool VehicleType::isVulnerable()
+{
+        return is_vulnerable;
+}
+
+bool VehicleType::killsOccupants()
+{
+        return kills_occupants;
+}
+
+int VehicleType::getType() 
+{
+        return VEHICLE_TYPE_ID;
+}
+
+bool VehicleType::isType(int classID) 
+{ 
+        if (classID == VEHICLE_TYPE_ID)
+                return true;
+        return ObjectType::isType(classID);
+}
+
+class ArmsType *VehicleType::getOrdnance() 
+{
+        return ordnance;
+}
+
+char *VehicleType::getMvDesc() 
+{
+        return mv_desc;
+}
+
+sound_t *VehicleType::get_movement_sound() 
+{
+        return mv_sound;
+}
+
+// ----------------------------------------------------------------------------
+//
+// Vehicle
+//
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// The constructor used by VehicleType::createInstance()
+// ----------------------------------------------------------------------------
+Vehicle::Vehicle(VehicleType *type)
+        : Object(type), name(0)
+{
+       setFacing(NORTH);
+       hp = type->getMaxHp();
+}
+
+
+// ----------------------------------------------------------------------------
+// The constructor used by kern_mk_vehicle()
+// ----------------------------------------------------------------------------
+Vehicle::Vehicle(VehicleType *type, int _facing, int _hp)
+        : Object(type), name(0)
+{
+       occupant = NULL;
+        setFacing(_facing);
+       hp = _hp;
+}
+
+Vehicle::~Vehicle()
+{
+        if (name)
+                free(name);
+}
+
+int Vehicle::get_facing_to_fire_weapon(int dx, int dy)
+{
+       if (dx)
+               return NORTH;
+       if (dy)
+               return EAST;
+       return -1;
+}
+
+bool Vehicle::fire_weapon(int dx, int dy, class Object *user)
+{
+       class ArmsType *ordnance;
+
+       ordnance = getOrdnance();
+       assert(ordnance);
+
+       // check facing
+       int vdir = getFacing();
+       if (((vdir == NORTH || vdir == SOUTH) && dy) ||
+           ((vdir == EAST || vdir == WEST) && dx)) {
+               return false;
+       }
+
+        ordnance->fireInDirection(getPlace(), getX(), getY(), dx, dy, user);
+        return true;
+}
+
+bool Vehicle::turn(int dx, int dy, int *cost)
+{
+       *cost = 0;
+
+       if (getFacing() == vector_to_facing(dx, dy))
+               return false;
+
+       if (!setFacing(vector_to_facing(dx, dy)))
+               return false;
+
+       *cost = getObjectType()->getSpeed();
+       return true;
+}
+
+int Vehicle::getMovementCostMultiplier()
+{
+        return getObjectType()->getWindPenalty(getFacing());
+}
+
+void Vehicle::damage(int amount)
+{
+        Object::damage(amount);
+       hp -= amount;
+       hp = max(0, hp);
+       hp = min(hp, getObjectType()->getMaxHp());
+
+       if (hp == 0)
+               destroy();
+}
+
+struct formation *Vehicle::get_formation()
+{
+       return getObjectType()->formation;
+}
+
+struct place *Vehicle::getPlace()
+{
+        if (occupant)
+                return occupant->getPlace();
+        return Object::getPlace();
+}
+
+int Vehicle::getX()
+{
+        if (occupant != NULL)
+                return occupant->getX();
+        return Object::getX();
+}
+
+int Vehicle::getY()
+{
+        if (occupant != NULL)
+                return occupant->getY();
+        return Object::getY();
+}
+
+bool Vehicle::mustTurn()
+{
+        return getObjectType()->mustTurn();   
+}
+
+bool Vehicle::isVulnerable()
+{
+        return getObjectType()->isVulnerable();       
+}
+
+void Vehicle::destroy()
+{
+        Object::destroy();
+
+        if (occupant != NULL &&
+            getObjectType()->killsOccupants()) {                
+                occupant->destroy();
+                setOccupant(0);
+        }
+}
+
+bool Vehicle::isType(int classID) 
+{ 
+        if (classID == VEHICLE_ID)
+                return true;
+        return Object::isType(classID);
+}
+
+int Vehicle::getType() 
+{
+        return VEHICLE_ID;
+}
+
+class VehicleType *Vehicle::getObjectType() 
+{ 
+        return (class VehicleType *) Object::getObjectType();
+}
+
+class ArmsType *Vehicle::getOrdnance() 
+{ 
+        return getObjectType()->getOrdnance();
+}
+
+char *Vehicle::getMvDesc() 
+{
+        return getObjectType()->getMvDesc();
+}
+
+sound_t *Vehicle::get_movement_sound()
+{
+        return getObjectType()->get_movement_sound();
+}
+
+void Vehicle::save(struct save *save)
+{
+        save->enter(save, "(let ((kveh (kern-mk-vehicle %s %d %d)))\n",
+                    getObjectType()->getTag(), getFacing(), getHp());
+        if (name) {
+                save->write(save, "(kern-vehicle-set-name kveh \"%s\")\n", name);
+        }
+        if (getTTL() != -1) {
+                save->write(save, "(kern-obj-set-ttl kveh %d)\n", getTTL());
+        }
+        save->exit(save, "kveh) ;; vehicle \n");
+}
+
+struct mmode *Vehicle::getMovementMode()
+{
+        return getObjectType()->mmode;
+}
+
+const char *Vehicle::getName()
+{
+        if (name)
+                return name;
+        return Object::getName();
+}
+
+void Vehicle::setName(char *val)
+{
+        name = strdup(val);
+        assert(name);
+}
+
+class Object *Vehicle::getOccupant()
+{
+        return occupant;
+}
+
+void Vehicle::setOccupant(class Object *val)
+{
+        if (val) {
+                assert(!occupant);
+                occupant = val;
+                obj_inc_ref(occupant);
+                Object::setTTL(this, -1);
+        } else if (occupant) {
+                obj_dec_ref(occupant);
+                occupant = 0;
+
+                /* Unnamed vehicles will expire after a while. */
+                if (!name) {
+                        Object::setTTL(this, VEHICLE_DEF_TTL);
+                }
+        }
+}
+
+bool Vehicle::isNamed()
+{
+        return name != 0;
+}
+
+void Vehicle::describe()
+{
+        if (name) {
+                log_continue("the %s", name);
+        } else {
+                Object::describe();
+        }
+}
diff --git a/src/vehicle.h b/src/vehicle.h
new file mode 100644 (file)
index 0000000..ad06734
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#ifndef vehicle_h
+#define vehicle_h
+
+#include "object.h"
+#include "sound.h"
+#include <closure.h>
+
+class VehicleType:public ObjectType {
+ public:
+       virtual int getType();
+        virtual bool isType(int classID);
+        VehicleType(const char *tag, const char *name, struct sprite *sprite,
+                    struct terrain_map *map,
+                    class ArmsType *ordnance,
+                    bool vulnerable,
+                    bool killsOccupants,
+                    bool mustTurn,
+                    char *mv_desc,
+                    sound_t *mv_sound,
+                    int tailwind_penalty,
+                    int headwind_penalty,
+                    int crosswind_penalty,
+                    int maxHp,
+                    int speed
+                    );
+       virtual ~VehicleType();
+       virtual class ArmsType *getOrdnance();
+       virtual char *getMvDesc();
+       virtual sound_t *get_movement_sound();
+       virtual bool mustTurn();
+        virtual class Object *createInstance();
+        virtual int getWindPenalty(int facing);
+        
+
+        bool isVulnerable();
+        bool killsOccupants();
+
+        struct formation *formation;
+        struct terrain_map *map;
+        closure_t *renderCombat;
+        struct mmode *mmode;
+
+ protected:
+        class ArmsType *ordnance;
+        bool is_vulnerable;
+        bool kills_occupants; /* on destroy */
+        bool must_turn;
+        char *mv_desc;
+        sound_t *mv_sound;
+        int pmask;
+        int tailwind_penalty;
+        int headwind_penalty;
+        int crosswind_penalty;
+        int maxHp;
+};
+
+class Vehicle:public Object {
+ public:
+        virtual bool isType(int classID);
+       virtual int getType();
+        Vehicle (VehicleType*);
+        Vehicle (VehicleType*, int facing, int hp);
+       virtual ~Vehicle();
+        virtual class VehicleType *getObjectType();
+       virtual const char *getName();
+        virtual int getX();
+        virtual int getY();
+        virtual class ArmsType *getOrdnance();
+        virtual struct mmode *getMovementMode();
+       virtual char *getMvDesc();
+        virtual sound_t *get_movement_sound();
+       virtual bool mustTurn();
+        virtual int get_facing_to_fire_weapon(int dx, int dy);
+        virtual bool fire_weapon(int dx, int dy, class Object *user);
+        virtual struct formation *get_formation();
+        virtual struct place *getPlace();
+        virtual void destroy();
+        virtual void save(struct save *save);
+        virtual void describe();
+
+        bool isVulnerable();
+        bool turn(int dx, int dy, int *cost);
+        int getMovementCostMultiplier();
+        void damage(int amount);
+        void setName(char *val);
+        class Object *getOccupant();
+        void setOccupant(class Object *val);
+        bool isNamed();
+
+ protected:
+        char *name;
+        class Object *occupant;
+};
+
+#endif                         // vehicle_h
diff --git a/src/vmask.c b/src/vmask.c
new file mode 100644 (file)
index 0000000..81d2164
--- /dev/null
@@ -0,0 +1,319 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+
+#include "vmask.h"
+#include "tree.h"
+#include "list.h"
+#include "place.h"
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+#define VMASK_MAX_KEY_LEN 64
+#define VMASK_MAX_ENTRIES 128
+#define VMASK_HI_WATER    VMASK_MAX_ENTRIES
+#define VMASK_LO_WATER    (VMASK_HI_WATER - VMASK_HI_WATER / 4)
+
+#define vmask_key(V)      ((V)->tree.key.s_key)
+
+struct vmask {
+        struct tree tree;  // used by lookup-table
+        struct list list;  // used by lru-q
+        char *data;        // visibility mask data
+};
+
+
+static struct tree *vmask_root;
+static struct list vmask_q;
+static int vmask_n_entries;
+
+void vmask_dump(struct vmask *vmask)
+{
+        int x, y, i = 0;
+
+        //dbg("vmask_dump: %s\n", vmask_key(vmask));
+
+        for (x = 0; x < VMASK_W; x++) {
+                printf("%d", x % 10);
+        }
+        printf("\n");
+
+        for (y = 0; y < VMASK_H; y++) {
+                for (x = 0; x < VMASK_W; x++) {
+                        printf("%c", vmask->data[i] ? '#' : '.');
+                        i++;
+                }
+                printf(" %d\n", y % 10);
+        }
+}
+
+static void vmask_error(const char *msg)
+{
+        fprintf(stderr, "vmask.c: %s\n", msg);
+        exit(1);
+}
+
+static void vmask_make_key(char *key, struct place *place, int x, int y)
+{
+        snprintf(key, VMASK_MAX_KEY_LEN, "%d:%d:%p", x, y, place);
+}
+
+
+static struct vmask *vmask_lookup(const char *key)
+{
+        struct vmask *vmask;
+        struct tree *tree;
+
+        //dbg("vmask_lookup: %s\n", key);
+
+        tree = tree_s_search(vmask_root, key);
+        if (NULL == tree)
+                return NULL;
+
+        vmask = tree_entry(tree, struct vmask, tree);
+        return vmask;
+}
+
+static void vmask_delete(struct vmask *vmask)
+{
+        //dbg("vmask_delete: %s\n", vmask_key(vmask));
+        list_remove(&vmask->list);
+        tree_delete(&vmask_root, &vmask->tree);
+        free(vmask->tree.key.s_key);
+        free(vmask);
+        vmask_n_entries--;
+}
+
+static void vmask_insert(struct vmask *vmask)
+{
+        //printf("vmask_insert: %s\n", vmask_key(vmask));
+        list_add(&vmask_q, &vmask->list);
+        tree_insert(&vmask_root, &vmask->tree);
+        vmask_n_entries++;
+}
+
+static void vmask_purge(void)
+{
+        struct vmask *vmask;
+        struct list *tail;
+
+        //printf("vmask_purge\n");
+
+        // --------------------------------------------------------------------
+        // Remove and destroy the least-recently-used vmasks until we are down
+        // to the low-water mark.
+        // --------------------------------------------------------------------
+
+        while(vmask_n_entries > VMASK_LO_WATER) {
+                tail = vmask_q.prev;
+                vmask = list_entry(tail, struct vmask, list);
+                vmask_delete(vmask);
+        }
+}
+
+static void vmask_los(struct vmask *vmask, struct place *place, 
+                      int center_x, int center_y)
+{
+        /* First, build an "alpha mask", which is a grid corresponding to the
+         * surrounding tiles. Each cell in the grid indicates if a tile blocks
+         * line-of-sight or lets it pass. */
+       int x;
+        int y;
+        int start_x = center_x - VMASK_W / 2;
+        int start_y = center_y - VMASK_H / 2;
+        int end_x   = start_x + VMASK_W;
+        int end_y   = start_y + VMASK_H;
+       int index   = 0;
+
+        for (y = start_y; y < end_y; y++) {
+                for (x = start_x; x < end_x; x++) {
+                        LosEngine->alpha[index] = place_visibility(place, x, 
+                                                                   y);
+                       index++;
+               }
+       }
+        
+        /* Next invoke the los engine and copy the results into the new
+         * vmask */
+        LosEngine->r = max(VMASK_W, VMASK_H);
+        LosEngine->compute(LosEngine);
+        memcpy(vmask->data, LosEngine->vmask, VMASK_SZ);
+}
+
+static struct vmask *vmask_create(const char *key, struct place *place, int x, int y)
+{
+        struct vmask *vmask;
+
+        //dbg("vmask_create: %s\n", key);
+
+        // --------------------------------------------------------------------
+        // Remove least-recently-used vmasks if we need to make room for
+        // a new one.
+        // --------------------------------------------------------------------
+
+        if (vmask_n_entries >= VMASK_HI_WATER) {
+                vmask_purge();
+        }
+
+        // --------------------------------------------------------------------
+        // Allocate and initialize a new vmask structure. Setup the tree to
+        // use the given string key.
+        // --------------------------------------------------------------------
+
+        vmask = (struct vmask*)calloc(1, sizeof(struct vmask) + VMASK_SZ);
+        if (NULL == vmask)
+                return vmask;
+
+        list_init(&vmask->list);
+        vmask->data = (char *)vmask + sizeof(struct vmask);
+        vmask->tree.key_type  = tree_s_key;
+        vmask->tree.key.s_key = strdup(key);
+        if (NULL == vmask->tree.key.s_key) {
+                free(vmask);
+                return NULL;
+        }
+
+        // --------------------------------------------------------------------
+        // Finally, fill out the vmask based on the line-of-sight
+        // characteristics of the given location, and then insert it into the
+        // tree and the priority list.
+        // --------------------------------------------------------------------
+
+        vmask_los(vmask, place, x, y);
+        vmask_insert(vmask);
+        /*vmask_dump(vmask);*/
+
+        return vmask;
+}
+
+static void vmask_prioritize(struct vmask *vmask)
+{
+        // --------------------------------------------------------------------
+        // Move the vmask from wherever it was in the least-recently-used queue
+        // up to the front.
+        // --------------------------------------------------------------------
+
+        list_remove(&vmask->list);
+        list_add(&vmask_q, &vmask->list);
+}
+
+// ----------------------------------------------------------------------------
+//
+//                                Public API
+//
+// ----------------------------------------------------------------------------
+
+// ----------------------------------------------------------------------------
+// Call this once to initialize the library on startup.
+// ----------------------------------------------------------------------------
+
+int vmask_init(void)
+{
+        vmask_root = NULL;
+        list_init(&vmask_q);
+        vmask_n_entries = 0;
+
+        return 0;
+}
+
+
+// ----------------------------------------------------------------------------
+// Fetch the vmask corresponding to the given location. The vmask is gauranteed
+// to be valid until the next call to vmask_get(), at which point all bets are
+// off. I expect the typical usage will be for callers to only use one at a
+// time, and to make their own copy in the rare cases where they need to deal
+// with more than one at a time.
+// ----------------------------------------------------------------------------
+
+char *vmask_get(struct place *place, int x, int y)
+{
+        struct vmask *vmask;
+        char key[VMASK_MAX_KEY_LEN + 1];
+
+        x = place_wrap_x(place, x);
+        y = place_wrap_y(place, y);
+
+        vmask_make_key(key, place, x, y);
+        vmask = vmask_lookup(key);
+        if (NULL == vmask) {
+                vmask = vmask_create(key, place, x, y);
+        }
+        if (NULL == vmask)
+                vmask_error("Can't create vmask");
+        vmask_prioritize(vmask);
+
+        //vmask_dump(vmask);
+
+        return vmask->data;
+}
+
+
+// ----------------------------------------------------------------------------
+// Invalidate all vmasks in the area surrounding the given location. You should
+// call this whenever you do something that will change the line-of-sight
+// properties of a tile. It will force the surrounding vmasks to recompute
+// their line-of-sight the next time somebody tries to fetch them.
+//
+// Note that the 'w' and 'h' indicate a rectangle of tiles whose line-of-sight
+// property have changed. For a single tile they would each be 1. Don't worry
+// about trying to evaluate the extent of the damage: the function will
+// automatically figure out which vmasks are affected.
+// ----------------------------------------------------------------------------
+
+void vmask_invalidate(struct place *place, int x, int y, int w, int h)
+{
+        char key[VMASK_MAX_KEY_LEN + 1];
+        struct vmask *vmask;
+
+        int start_x = x - MAP_TILE_W / 2;
+        int start_y = y - MAP_TILE_H / 2;
+        int end_x   = start_x + w + MAP_TILE_W;
+        int end_y   = start_y + h + MAP_TILE_H;
+
+       //dbg("vmask_invalidate: %s [%d %d %d %d]\n", place->name, x,  y, w, h);
+
+        for (y = start_y; y < end_y; y++) {
+                int wrap_y =  place_wrap_y(place, y);
+                for (x = start_x; x < end_x; x++) {
+                        vmask_make_key(key, place, place_wrap_x(place, x), 
+                                       wrap_y);
+                        vmask = vmask_lookup(key);
+                        if (NULL != vmask) {
+                                vmask_delete(vmask);
+                        }
+                }
+        }
+}
+
+void vmask_flush_all(void)
+{
+        struct vmask *vmask;
+        struct list *tail;
+
+        while(vmask_n_entries) {
+                tail = vmask_q.prev;
+                vmask = list_entry(tail, struct vmask, list);
+                vmask_delete(vmask);
+        }
+}
diff --git a/src/vmask.h b/src/vmask.h
new file mode 100644 (file)
index 0000000..c5b3956
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef vmask_h
+#define vmask_h
+
+#include "dimensions.h"
+
+#define VMASK_W    (MAP_TILE_W * 2 + 1)
+#define VMASK_H    (VMASK_W)
+#define VMASK_SZ   (VMASK_W * VMASK_H)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+        // --------------------------------------------------------------------
+        // Call this once to initialize the library on startup.
+        // --------------------------------------------------------------------
+
+        extern int vmask_init(void);
+
+        // --------------------------------------------------------------------
+        // Fetch the vmask corresponding to the given location. The vmask is
+        // gauranteed to be valid until the next call to vmask_get(), at which
+        // point all bets are off. I expect the typical usage will be for
+        // callers to only use one at a time, and to make their own copy in the
+        // rare cases where they need to deal with more than one at a time. 
+        // --------------------------------------------------------------------
+
+        extern char *vmask_get(struct place *place, int x, int y);
+
+
+        // --------------------------------------------------------------------
+        // Invalidate all vmasks in the area surrounding the given
+        // location. You should call this whenever you do something that will
+        // change the line-of-sight properties of a tile. It will force the
+        // surrounding vmasks to recompute their line-of-sight the next time
+        // somebody tries to fetch them.
+        //
+        // Note that the 'w' and 'h' indicate a rectangle of tiles whose
+        // line-of-sight property have changed. For a single tile they would
+        // each be 1. Don't worry about trying to evaluate the extent of the
+        // damage: the function will automatically figure out which vmasks are
+        // affected.
+        // --------------------------------------------------------------------
+
+        extern void vmask_invalidate(struct place *place, int x, int y, int w, int h);
+
+        // --------------------------------------------------------------------
+        // Invalidate all vmasks everywhere.
+        // --------------------------------------------------------------------
+
+        extern void vmask_flush_all(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/src/wind.c b/src/wind.c
new file mode 100644 (file)
index 0000000..237e8dd
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "wind.h"
+#include "wq.h"
+#include "common.h"
+#include "screen.h"
+#include "session.h"
+#include "log.h"
+
+static SDL_Rect windRect;
+static int windDirection;
+static int windDuration;
+
+void windAdvanceTurns(void)
+{
+       if (windDuration > 0) {
+               windDuration--;
+               return;
+       }
+
+       if (rand() % 100 < WIND_CHANGE_PROBABILITY) {
+            int dir = rand() % NUM_WIND_DIRECTIONS;
+            windSetDirection(dir, 10);
+       }
+}
+
+int windInit(void)
+{
+       windRect.w = WIND_W;
+       windRect.x = WIND_X;
+       windRect.y = WIND_Y;
+       windRect.h = WIND_H;
+
+       windDirection = NORTH;
+        windDuration = 0;
+
+        return 0;
+}
+
+void windSetDirection(int dir, int dur)
+{
+    if (HERE == dir || dir >= NUM_WIND_DIRECTIONS) {
+        return;
+    }
+
+    if (dir != windDirection) {
+        log_msg("The wind shifts to the %s", directionToString(dir));
+    }
+
+    windDirection = dir;
+    windDuration = dur;
+    windRepaint();
+}
+
+int windGetDirection(void)
+{
+       return windDirection;
+}
+
+void windRepaint(void)
+{
+       screenErase(&windRect);
+       screenPrint(&windRect, SP_CENTERED, "Wind:%s",
+                   directionToString(windDirection));
+       screenUpdate(&windRect);
+}
+
+void windSave(struct save *save)
+{
+        save->write(save, "(kern-set-wind %d %d)\n", windDirection, 
+                    windDuration);
+}
diff --git a/src/wind.h b/src/wind.h
new file mode 100644 (file)
index 0000000..9b127b3
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef wind_h
+#define wind_h
+
+#include "macros.h"
+
+BEGIN_DECL
+
+extern int windInit(void);
+extern void windSetDirection(int dir, int duration);
+extern int windGetDirection(void);
+extern void windAdvanceTurns(void);
+extern void windRepaint(void);
+extern void windSave(struct save *save);
+
+END_DECL
+
+
+#endif
diff --git a/src/wq.c b/src/wq.c
new file mode 100644 (file)
index 0000000..6c3e443
--- /dev/null
+++ b/src/wq.c
@@ -0,0 +1,98 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#include "wq.h"
+#include "common.h"
+
+void wqAddJob(struct list *wq, struct wq_job *newJob)
+{
+       struct list *list;
+       struct wq_job *aJob;
+
+        //dbg("wqAddJob: %08lx\n", newJob);
+
+
+       list_for_each(wq, list) {
+               aJob = outcast(list, struct wq_job, list);
+               if (aJob->tick > newJob->tick)
+                       break;
+       }
+
+       list_add_aux(list->prev, list, &newJob->list);
+
+
+}
+
+void wqRunToTick(struct list *wq, int tick)
+{
+       struct list *list;
+
+       list = wq->next;
+       while (list != wq) {
+
+               struct list *tmp;
+               struct wq_job *aJob;
+
+               aJob = outcast(list, struct wq_job, list);
+               if (aJob->tick > tick)
+                       break;
+
+               tmp = list->next;
+               list_remove(list);
+                //dbg("wqRunToTick: %08lx\n", aJob);
+                aJob->run(aJob, wq);
+               list = tmp;
+
+       }
+}
+
+void wqCreateJob(struct list *wq, int tick, int period, void *data,
+                void (*run) (struct wq_job *, struct list * wq))
+{
+       struct wq_job *job;
+
+       job = (struct wq_job *) malloc(sizeof(struct wq_job));
+       if (!job) {
+               warn("Failed to allocate job");
+               return;
+       }
+
+       job->tick = tick;
+       job->period = period;
+       job->data = data;
+       job->run = run;
+
+        //dbg("wqCreateJob: %08lx\n", job);
+
+       wqAddJob(wq, job);
+}
+
+void wq_job_del(struct wq_job *job)
+{
+        list_remove(&job->list);
+        free(job);
+}
+
+void wqReschedule(struct list *wq, struct wq_job *job)
+{
+       job->tick += job->period;
+       wqAddJob(wq, job);
+}
diff --git a/src/wq.h b/src/wq.h
new file mode 100644 (file)
index 0000000..ad6daed
--- /dev/null
+++ b/src/wq.h
@@ -0,0 +1,47 @@
+//
+// nazghul - an old-school RPG engine
+// Copyright (C) 2002, 2003 Gordon McNutt
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+// Suite 330, Boston, MA 02111-1307 USA
+//
+// Gordon McNutt
+// gmcnutt@users.sourceforge.net
+//
+#ifndef wq_h
+#define wq_h
+
+#include "macros.h"
+#include "list.h"
+
+BEGIN_DECL
+
+struct wq_job {
+        struct list list;
+        int tick;
+        int period;
+        void *data;
+        void (*run) (struct wq_job *, struct list * wq);        
+};
+
+extern void wqAddJob(struct list *wq, struct wq_job *job);
+extern void wqRunToTick(struct list *wq, int tick);
+extern void wqCreateJob(struct list *wq, int tick, int period, void *data, 
+                        void (*run) (struct wq_job *, struct list * wq));
+extern void wq_job_del(struct wq_job *);
+extern void wqReschedule(struct list *wq, struct wq_job *job);
+
+END_DECL
+
+#endif
diff --git a/src/ztats.c b/src/ztats.c
new file mode 100644 (file)
index 0000000..648d5fb
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats.h"
+
+#include "applet.h"
+#include "cmdwin.h"
+#include "event.h"
+#include "foogod.h"
+#include "macros.h"
+#include "player.h"
+#include "screen.h"
+#include "session.h"
+
+#include <string.h>
+
+struct ztats {
+        struct applet base;
+        struct list panes;
+        struct ztats_pane *current;
+};
+
+/**
+ * For now there's a global singleton for the ztats applet, but whenever
+ * possible try to write functions that get passed in a pointer.
+ */
+static struct ztats ztats;
+
+static void ztats_op_paint(struct applet *applet)
+{
+        DECL_CAST(struct ztats, ztats, applet);
+
+        screenErase(&applet->dims);
+        ztats->current->ops->paint(ztats->current);
+        screenUpdate(&applet->dims);
+
+        status_repaint_title();
+}
+
+static void ztats_scroll(struct ztats *ztats, enum StatusScrollDir dir)
+{
+        struct list *list = 0;
+
+        if (! ztats->current) {
+                return;
+        }
+
+        /* let the pane have first crack at handling it */
+        if (ztats->current->ops->scroll 
+            && ztats->current->ops->scroll(ztats->current, dir)) {
+                ztats_op_paint(&ztats->base);
+                return;
+        }
+
+        switch (dir) {
+        case ScrollRight:
+                list = ztats->current->list.next;
+                if (list == &ztats->panes) {
+                        list = list->next;
+                        assert(list != &ztats->panes);
+                }
+                break;
+        case ScrollLeft:
+                list = ztats->current->list.prev;
+                if (list == &ztats->panes) {
+                        list = list->prev;
+                        assert(list != &ztats->panes);
+                }
+                break;
+        default:
+                /* ignore non-horizontal scrolling */
+                return;
+        }
+
+        ztats->current = list_entry(list, struct ztats_pane, list);
+        if (ztats->current->ops->enter) {
+                ztats->current->ops->enter(ztats->current, ztats->base.session->player, dir, &ztats->base.dims);
+        }
+
+        ztats_op_paint(&ztats->base);
+
+}
+
+static int ztats_key_handler(struct KeyHandler * handler, int key, int keymod)
+{
+        DECL_CAST(struct ztats, ztats, handler->data);
+
+       switch (key) {
+       case KEY_NORTH:
+               ztats_scroll(ztats, ScrollUp);
+               break;
+       case KEY_SOUTH:
+               ztats_scroll(ztats, ScrollDown);
+               break;
+       case KEY_EAST:
+               ztats_scroll(ztats, ScrollRight);
+               break;
+       case KEY_WEST:
+               ztats_scroll(ztats, ScrollLeft);
+               break;
+       case SDLK_PAGEUP:
+       case SDLK_KP9:
+               ztats_scroll(ztats, ScrollPageUp);
+               break;
+       case SDLK_PAGEDOWN:
+       case SDLK_KP3:
+               ztats_scroll(ztats, ScrollPageDown);
+               break;
+       case SDLK_RETURN:
+       case SDLK_SPACE:
+       case SDLK_KP_ENTER:
+        case KEY_HERE:
+       case '\n':
+                if (ztats->current->ops->select) {
+                        ztats->current->ops->select(ztats->current);
+                        ztats_op_paint(&ztats->base); /* in case applet ran */
+                }
+               return 0;
+       case SDLK_ESCAPE:
+       case 'q':
+               return 1;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static void ztats_op_run(struct applet *applet, SDL_Rect *dims, struct session *session)
+{
+        DECL_CAST(struct ztats, ztats, applet);
+
+        if (list_empty(&ztats->panes)) {
+                return;
+        }
+
+       cmdwin_clear();
+       cmdwin_spush("Stats");
+       cmdwin_spush("<ESC to exit>");
+        foogodSetHintText("\200\201=scroll ESC=exit");
+        foogodSetMode(FOOGOD_HINT);        
+        
+        applet->dims = *dims;
+        applet->session = session;
+
+        ztats->current = list_entry(ztats->panes.next, struct ztats_pane, list);
+        ztats->current->ops->enter(ztats->current, session->player, ScrollRight, dims);
+        ztats_op_paint(applet);
+
+        eventRunKeyHandler(ztats_key_handler, ztats);
+
+        foogodSetMode(FOOGOD_DEFAULT);
+       cmdwin_pop();
+       cmdwin_spush("ok");
+
+        /* Reset to NULL; else if the current pane removes itself during a
+         * session teardown it will trigger a scroll action, which will
+         * probably crash. */
+        ztats->current = NULL;
+
+}
+
+void ztats_init(void)
+{
+        static struct applet_ops ztats_ops = {
+                ztats_op_run,
+                ztats_op_paint
+        };
+
+        memset(&ztats, 0, sizeof(&ztats));
+        list_init(&ztats.panes);
+        ztats.base.ops = &ztats_ops;
+}
+
+void ztats_add_pane(struct ztats_pane *pane)
+{
+        list_add_tail(&ztats.panes, &pane->list);
+}
+
+void ztats_rm_pane(struct ztats_pane *pane)
+{
+        if (pane == ztats.current) {
+                ztats_scroll(&ztats, ScrollRight);
+                if (pane == ztats.current) {
+                        /* last pane in the list */
+                        ztats.current = NULL;
+                }
+        }
+
+        list_remove(&pane->list);
+}
+
+struct applet *ztats_get_applet(void)
+{
+        return &ztats.base;
+}
diff --git a/src/ztats.h b/src/ztats.h
new file mode 100644 (file)
index 0000000..30cd69b
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_h
+#define ztats_h
+
+#include "ztats_pane.h"
+#include "Party.h"
+#include "status.h"
+
+#include <SDL.h>
+
+extern void ztats_init();
+extern void ztats_add_pane(struct ztats_pane *pane);
+extern void ztats_rm_pane(struct ztats_pane *pane);
+
+extern struct applet *ztats_get_applet(void);
+
+#endif
diff --git a/src/ztats_arms.c b/src/ztats_arms.c
new file mode 100644 (file)
index 0000000..6e865d2
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_arms.h"
+
+#include "Arms.h"
+#include "screen.h"
+#include "sprite.h"
+#include "ztats.h"
+#include "ztats_container_pane.h"
+
+
+static void ztats_arms_paint_item(struct inv_entry *ie, SDL_Rect *rect)
+{
+       ArmsType *arms = (ArmsType*)ie->type;
+       
+       assert(ie->count);
+       
+       /* sprite */
+       sprite_paint(arms->getSprite(), 0, rect->x, rect->y);
+       rect->x += TILE_W;
+       
+       /* quantity and name */
+       if (ie->ref) {
+               screenPrint(rect, 0, "%2d %s ^c+%c[%d in use]^c-", ie->count, arms->getName(), STAT_INUSE_CLR, ie->ref);
+       } else {
+               screenPrint(rect, 0, "%2d %s", ie->count, arms->getName());
+       }
+       rect->y += ASCII_H;
+       
+       /* stats */
+       status_show_arms_stats(rect, arms);
+       rect->x -= TILE_W;
+}
+
+static bool ztats_arms_filter_cb(struct inv_entry *ie, void *fdata)
+{
+       return (ie->type->isReadyable());
+}
+
+
+void ztats_arms_init(void)
+{
+        static struct ztats_container_pane pane;
+        static struct ztats_container_pane_ops ops = {
+                ztats_arms_paint_item
+        };
+        static struct filter filter = {
+                ztats_arms_filter_cb,
+                NULL
+        };
+
+        ztats_container_pane_init(&pane, "Armaments", &filter, &ops);
+        ztats_add_pane(&pane.base);
+}
diff --git a/src/ztats_arms.h b/src/ztats_arms.h
new file mode 100644 (file)
index 0000000..f28153e
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_arms_h
+#define ztats_arms_h
+
+void ztats_arms_init(void);
+
+#endif
diff --git a/src/ztats_container_pane.c b/src/ztats_container_pane.c
new file mode 100644 (file)
index 0000000..da7a908
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_container_pane.h"
+
+#include "screen.h"
+#include "sprite.h"
+
+#include <string.h>
+
+static int ztats_container_pane_count_items(struct ztats_container_pane *zcp)
+{
+        class Container *container = zcp->base.party->getInventory();
+        if (! container) {
+                return 0;
+        }
+
+        assert(zcp->ops);
+        assert(zcp->filter);
+
+        return container->filter_count(zcp->filter);
+}
+
+void ztats_container_pane_enter(struct ztats_pane *pane, class Party *party, enum StatusScrollDir via, SDL_Rect *dims)
+{
+        struct ztats_container_pane *zcp = (struct ztats_container_pane*)pane;
+        ztats_pane_enter(pane, party, via, dims);
+        assert(zcp->title);
+        status_set_title(zcp->title);
+        zcp->top_line = 0;
+        zcp->num_lines = dims->h / TILE_H;
+        zcp->max_line = ztats_container_pane_count_items(zcp) - zcp->num_lines;
+}
+
+int ztats_container_pane_scroll(struct ztats_pane *pane, enum StatusScrollDir dir)
+{
+        struct ztats_container_pane *zcp = (struct ztats_container_pane*)pane;
+
+       switch (dir) {
+       case ScrollUp:
+               if (zcp->top_line > 0) {
+                       zcp->top_line--;
+                }
+               break;
+       case ScrollDown:
+               if (zcp->top_line < zcp->max_line) {
+                       zcp->top_line++;
+                }
+               break;
+       case ScrollPageUp:
+               zcp->top_line -= zcp->num_lines;
+               if (zcp->top_line < 0) {
+                       zcp->top_line = 0;
+                }
+               break;
+       case ScrollPageDown:
+               zcp->top_line = min(zcp->max_line, zcp->top_line + zcp->num_lines);
+               break;
+       case ScrollLeft:
+       case ScrollRight:
+        default:
+                return 0;
+       }
+
+        return 1;
+}
+
+void ztats_container_pane_paint(struct ztats_pane *pane)
+{
+        struct ztats_container_pane *zcp = (struct ztats_container_pane*)pane;
+       SDL_Rect rect = pane->dims;
+       int top = zcp->top_line;
+        class Container *container = pane->party->getInventory();
+       struct inv_entry *ie;
+       int line = 0;
+
+        if (! container) {
+                screenPrint(&rect, 0, "No inventory!");
+                return;
+        }
+
+       rect.h = ASCII_H;
+
+       for (ie = container->first(zcp->filter); ie != NULL; ie = container->next(ie, zcp->filter)) {
+
+               if (top) {
+                       top--;
+                       continue;
+               }
+       
+                zcp->ops->paint_item(ie, &rect);
+               line++;
+       
+               /* Don't print outside the status window. */
+               if (line >= zcp->num_lines) {
+                       break;
+                }
+       }
+
+}
+
+void ztats_container_pane_init(struct ztats_container_pane *zcp, const char *title, struct filter *filter, struct ztats_container_pane_ops *ops)
+{
+        static struct ztats_pane_ops base_ops = {
+                ztats_container_pane_enter,
+                ztats_container_pane_scroll,
+                ztats_container_pane_paint
+        };
+
+        memset(zcp, 0, sizeof(*zcp));
+        zcp->base.ops = &base_ops;
+        zcp->title = title;
+        zcp->filter = filter;
+        zcp->ops = ops;
+}
+
+void ztats_container_paint_item_generic(struct inv_entry *ie, SDL_Rect *rect)
+{
+       if (ie->type->getSprite()) {
+                sprite_paint(ie->type->getSprite(), 0, rect->x, rect->y);
+       }
+       
+       /* Indent past the sprite column. */
+       rect->x += TILE_W;
+
+       /* This is a single-line entry in a two-line rect, so center it
+               * vertically. */
+       rect->y += TILE_H / 4;
+
+       screenPrint(rect, 0, "%2d %s", ie->count - ie->ref, ie->type->getName());
+
+       /* Carriage-return line-feed */
+       rect->y += (TILE_H * 3) / 4;
+       rect->x -= TILE_W;
+}
diff --git a/src/ztats_container_pane.h b/src/ztats_container_pane.h
new file mode 100644 (file)
index 0000000..80e6e8a
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_container_pane_h
+#define ztats_container_pane_h
+
+#include "Container.h"
+#include "object.h"
+#include "ztats_pane.h"
+
+#include <SDL.h>
+
+struct ztats_container_pane_ops {
+        void (*paint_item)(struct inv_entry *ie, SDL_Rect *rect);
+};
+
+struct ztats_container_pane {
+        struct ztats_pane base;
+        const char *title;
+        struct ztats_container_pane_ops *ops;
+        struct filter *filter;
+        int top_line;
+        int max_line;
+        int num_lines;
+};
+
+extern void ztats_container_pane_init(struct ztats_container_pane *zcp, const char *title, struct filter *filter, struct ztats_container_pane_ops *ops);
+extern void ztats_container_paint_item_generic(struct inv_entry *ie, SDL_Rect *rect);
+
+#endif
diff --git a/src/ztats_items.c b/src/ztats_items.c
new file mode 100644 (file)
index 0000000..c0cb1da
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_items.h"
+
+#include "Arms.h"
+#include "screen.h"
+#include "sprite.h"
+#include "ztats.h"
+#include "ztats_container_pane.h"
+
+
+static bool ztats_items_filter_cb(struct inv_entry *ie, void *fdata)
+{
+       return (ie->type->isUsable());
+}
+
+
+void ztats_items_init(void)
+{
+        static struct ztats_container_pane pane;
+        static struct ztats_container_pane_ops ops = {
+                ztats_container_paint_item_generic,
+        };
+        static struct filter filter = {
+                ztats_items_filter_cb,
+                NULL
+        };
+
+        ztats_container_pane_init(&pane, "Usable Items", &filter, &ops);
+        ztats_add_pane(&pane.base);
+}
diff --git a/src/ztats_items.h b/src/ztats_items.h
new file mode 100644 (file)
index 0000000..1149c03
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_items_h
+#define ztats_items_h
+
+void ztats_items_init(void);
+
+#endif
diff --git a/src/ztats_misc.c b/src/ztats_misc.c
new file mode 100644 (file)
index 0000000..62adb7c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_misc.h"
+
+#include "screen.h"
+#include "sprite.h"
+#include "ztats.h"
+#include "ztats_container_pane.h"
+
+
+static bool ztats_misc_filter_cb(struct inv_entry *ie, void *fdata)
+{
+       return (! ie->type->isReadyable()
+               && ! ie->type->isMixable()
+               && ! ie->type->isCastable()
+               && ! ie->type->isUsable());
+}
+
+void ztats_misc_init(void)
+{
+        static struct ztats_container_pane pane;
+        static struct ztats_container_pane_ops ops = {
+                ztats_container_paint_item_generic,
+        };
+        static struct filter filter = {
+                ztats_misc_filter_cb,
+                NULL
+        };
+
+        ztats_container_pane_init(&pane, "Miscellaneous", &filter, &ops);
+        ztats_add_pane(&pane.base);
+}
diff --git a/src/ztats_misc.h b/src/ztats_misc.h
new file mode 100644 (file)
index 0000000..2b556cc
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_misc_h
+#define ztats_misc_h
+
+void ztats_misc_init(void);
+
+#endif
diff --git a/src/ztats_pane.c b/src/ztats_pane.c
new file mode 100644 (file)
index 0000000..9c3cf1b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_pane.h"
+
+void ztats_pane_enter(struct ztats_pane *pane, class Party *party, enum StatusScrollDir via, SDL_Rect *dims)
+{
+        pane->party = party;
+        pane->dims = *dims;
+}
diff --git a/src/ztats_pane.h b/src/ztats_pane.h
new file mode 100644 (file)
index 0000000..d1b9b97
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_pane_h
+#define ztats_pane_h
+
+#include "list.h"
+#include "Party.h"
+#include "status.h"
+
+#include <SDL.h>
+
+struct ztats_pane_ops {
+        void (*enter)(struct ztats_pane *pane, class Party *party, enum StatusScrollDir via, SDL_Rect *dims);
+        /* Scroll returns non-zero iff it handled the scroll request */
+        int (*scroll)(struct ztats_pane *pane, enum StatusScrollDir dir);
+        void (*paint)(struct ztats_pane *pane);
+        void (*select)(struct ztats_pane *pane);
+};
+
+struct ztats_pane {
+        struct list list;
+        SDL_Rect dims;
+        class Party *party;
+        struct ztats_pane_ops *ops;
+};
+
+extern void ztats_pane_enter(struct ztats_pane *pane, class Party *party, enum StatusScrollDir via, SDL_Rect *dims);
+
+#endif
diff --git a/src/ztats_pm.c b/src/ztats_pm.c
new file mode 100644 (file)
index 0000000..1ee4753
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_pm.h"
+
+#include "effect.h"
+#include "mmode.h"
+#include "occ.h"
+#include "screen.h"
+#include "sprite.h"
+#include "ztats.h"
+
+#include <string.h>
+
+
+struct ztats_pm {
+        struct ztats_pane base;
+        int order;
+};
+
+/* status_show_member_arms -- called during Ztats when showing Party Members,
+ * this shows individual arms held by the member */
+static void ztats_pm_paint_arms(SDL_Rect * rect, ArmsType *arms)
+{
+       sprite_paint(arms->getSprite(), 0, rect->x, rect->y);
+       rect->x += TILE_W;
+
+       /* name */
+       // SAM: I don't like cluttering the name line, but the range and AP 
+       //      are essential information, and previous attempts at multi-line 
+       //      status entries foundered.  So, until the thing can be re-written...
+       screenPrint(rect, 0, "%s  (Rng:%d, AP:%d, Spd:%d)", 
+                   arms->getName(), arms->getRange(), arms->getRequiredActionPoints(), arms->get_AP_mod() );
+       rect->y += ASCII_H;
+
+       /* stats */
+       status_show_arms_stats(rect, arms);
+       rect->x -= TILE_W;
+}
+
+static int ztats_pm_paint_effect(hook_entry_t *entry, void *data)
+{
+       SDL_Rect *rect = (SDL_Rect*)data;
+       struct effect *effect = entry->effect;
+
+       /* No name implies invisible to UI. */
+       if (!effect->name) {
+               return 0;
+       }
+
+       /* Blit the effect icon, if it has one */
+       if (effect->sprite) {
+                sprite_paint(effect->sprite, 0, rect->x, rect->y);
+       }
+
+       rect->x += ASCII_W;
+
+       if (EFFECT_NONDETERMINISTIC == entry->effect->duration) {
+               screenPrint(rect, 0, " %s", entry->effect->name);
+       } else if (EFFECT_PERMANENT == entry->effect->duration) {
+               screenPrint(rect, 0, " %s (permanent)", entry->effect->name);
+       } else {
+               screenPrint(rect, 0, " %s [%d min]", entry->effect->name, 
+                       clock_alarm_remaining(&entry->expiration));
+       }
+       rect->x -= ASCII_W; /* back up to start next effect at column 0 */
+       rect->y += ASCII_H;
+
+       return 0;
+}
+
+
+void ztats_pm_enter(struct ztats_pane *pane, class Party *party, enum StatusScrollDir via, SDL_Rect *dims)
+{
+        struct ztats_pm *pm = (struct ztats_pm*)pane;
+
+        ztats_pane_enter(pane, party, via, dims);
+
+        if (! pane->party->getSize()) {
+                status_set_title("Nobody");
+                return;
+        }
+
+        if (ScrollLeft == via) {
+                pm->order = pane->party->getSize() - 1;
+        } else {
+                pm->order = 0;
+        }
+
+        class Character *ch = pane->party->getMemberByOrder(pm->order);
+        assert(ch);
+        status_set_title(ch->getName());
+}
+
+int ztats_pm_scroll(struct ztats_pane *pane, enum StatusScrollDir dir)
+{
+        struct ztats_pm *pm = (struct ztats_pm*)pane;
+
+        if (! pane->party->getSize()) {
+                return 0;
+        }
+
+        switch (dir) {
+        case ScrollRight:
+                if (pm->order == (pane->party->getSize() - 1)) {
+                        return 0;
+                }
+                pm->order++;
+                break;
+        case ScrollLeft:
+                if (pm->order == 0) {
+                        return 0;
+                }
+                pm->order--;
+                break;
+        default:
+                return 0;
+        }
+
+        class Character *ch = pane->party->getMemberByOrder(pm->order);
+        assert(ch);
+        status_set_title(ch->getName());
+        return 1;
+}
+
+void ztats_pm_paint(struct ztats_pane *pane)
+{
+        struct ztats_pm *pm = (struct ztats_pm*)pane;
+       struct mmode *mmode;
+       int i;
+
+        SDL_Rect rect = pane->dims;
+       
+        if (! pane->party->getSize()) {
+                screenPrint(&rect, 0, "Empty party!");
+                return;
+        }
+
+        class Character *ch = pane->party->getMemberByOrder(pm->order);
+        assert(ch);
+
+       /* Push the current color. */
+       screenPrint(&rect, 0, "^c+=");
+
+       // Show experience level and XP information:
+       screenPrint(&rect, 0, 
+                   "^c%cLevel:^cw%d "
+                   "^c%cXP:^cw%d "
+                   "^c%cNext Level:^cw%d ",
+
+                   STAT_LABEL_CLR,ch->getLevel(),
+                   STAT_LABEL_CLR,ch->getExperience(),
+                   STAT_LABEL_CLR,ch->getXpForLevel(ch->getLevel()+1)
+           );
+       rect.y += ASCII_H;
+
+       // Show the basic character attributes:
+       screenPrint(&rect, 0, 
+                   "^c%cStr:^cw%d "
+                   "^c%cInt:^cw%d "
+                   "^c%cDex:^cw%d ",
+
+                   STAT_LABEL_CLR, ch->getStrength(),
+                   STAT_LABEL_CLR, ch->getIntelligence(),
+                   STAT_LABEL_CLR, ch->getDexterity()
+               );
+       rect.y += ASCII_H;
+
+       // Show highly variable information such as HP/max, MP/max, and AP/max
+       screenPrint(&rect, 0, 
+                   "^c%cHP:^c%c%d^cw/%d "
+                   "^c%cMP:^c%c%d^cw/%d "
+                   "^c%cAP:^c%c%d^cw/%d ",
+
+                   STAT_LABEL_CLR, 
+                   status_range_color(ch->getHp(), ch->getMaxHp()),
+                   ch->getHp(), ch->getMaxHp(),
+
+                   STAT_LABEL_CLR, 
+                   status_range_color(ch->getMana(), ch->getMaxMana()),
+                   ch->getMana(), ch->getMaxMana(),
+
+                   STAT_LABEL_CLR, 
+                   status_range_color(ch->getActionPoints(), ch->getActionPointsPerTurn()), 
+                   ch->getActionPoints(), ch->getActionPointsPerTurn()
+               );
+       rect.y += ASCII_H;
+
+       // Show species, class, and movement mode:
+       mmode = ch->getMovementMode();
+       assert(mmode);
+       screenPrint(&rect, 0, 
+                   "^c%cSpecies:    ^cw%s", 
+                   STAT_LABEL_CLR, ch->species ? ch->species->name:"Unknown");
+       rect.y += ASCII_H;
+
+       screenPrint(&rect, 0, 
+                   "^c%cOccupation: ^cw%s", 
+                   STAT_LABEL_CLR, ch->occ ? ch->occ->name : "None");
+       rect.y += ASCII_H;
+
+       screenPrint(&rect, 0, 
+                   "^c%cMovement:   ^cw%s", 
+                   STAT_LABEL_CLR, mmode->name);
+       rect.y += ASCII_H;
+       rect.y += ASCII_H;
+
+       /* Show effects */
+       screenPrint(&rect, 0 /*SP_CENTERED*/ , "^c%c*** Effects ***^cw", 
+                                               STAT_LABEL_CLR);
+       rect.y += ASCII_H;
+       for (i = 0; i < OBJ_NUM_HOOKS; i++) {
+                ch->hookForEach(i, ztats_pm_paint_effect, &rect);
+       }
+       rect.y += ASCII_H;
+
+       /* Show arms */
+       screenPrint(&rect, 0 /*SP_CENTERED*/ , "^c%c*** Arms ***^cw", STAT_LABEL_CLR);
+       rect.y += ASCII_H;
+
+#if 1
+       int armsIndex=0;
+       class ArmsType *arms = ch->enumerateArms(&armsIndex);
+       while (arms != NULL) {
+               ztats_pm_paint_arms(&rect, arms);
+               arms = ch->getNextArms(&armsIndex);
+       }
+#else
+       /* This was an experiment with enumerating the slots instead of the
+         * readied arms. I couldn't get the formatting to look very good, so I
+         * punted. */
+       for (i = 0; i < ch->species->n_slots; i++) {
+               class ArmsType *arms = ch->getArmsInSlot(i);
+               if (arms) {
+                       status_show_member_arms(&rect, i, arms);
+               } else {
+                       rect.x += TILE_W;
+                       screenPrint(&rect, 0, "^c+y%d:^cG(empty)^c-", i);
+                       rect.x -= TILE_W;
+                       rect.y += ASCII_H;
+               }
+       }
+#endif
+
+       /* Pop the saved current color. */
+       screenPrint(&rect, 0, "^c-");
+
+
+       // fixme: currently this will overprint and it doesn't support
+       // scrolling. These may be necessary if the status window is not large
+       // enough.
+
+
+}
+
+void ztats_pm_init(void)
+{
+        static struct ztats_pane_ops ztats_pm_ops = {
+                ztats_pm_enter,
+                ztats_pm_scroll,
+                ztats_pm_paint
+        };
+
+        static struct ztats_pm ztats_pm;
+
+        memset(&ztats_pm, 0, sizeof(ztats_pm));
+        ztats_pm.base.ops = &ztats_pm_ops;
+        ztats_add_pane(&ztats_pm.base);
+}
diff --git a/src/ztats_pm.h b/src/ztats_pm.h
new file mode 100644 (file)
index 0000000..91742f8
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_pm_h
+#define ztats_pm_h
+
+void ztats_pm_init(void);
+
+#endif
diff --git a/src/ztats_reagents.c b/src/ztats_reagents.c
new file mode 100644 (file)
index 0000000..15e0843
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_reagents.h"
+
+#include "screen.h"
+#include "sprite.h"
+#include "ztats.h"
+#include "ztats_container_pane.h"
+
+
+static void ztats_reagents_paint_item(struct inv_entry *ie, SDL_Rect *rect)
+{
+       if (ie->type->getSprite()) {
+               sprite_paint(ie->type->getSprite(), 0, rect->x, rect->y);
+       }
+       
+       /* Indent past the sprite column. */
+       rect->x += TILE_W;
+       
+       /* This is a single-line entry in a two-line rect, so center it
+         * vertically. */
+       rect->y += TILE_H / 4;
+
+       /* During mixing, if the ref field is set that means the reagent has
+         * been selected to be part of the mixture (see cmdMix() in cmd.c, this
+         * is something of a hack). Show an asterisk to mark selected
+         * reagents. */
+       screenPrint(rect, 0, "%2d%c%s", ie->count, (ie->ref ? '*':' '), ie->type->getName());
+
+       /* Carriage-return line-feed */
+       rect->y += (TILE_H * 3) / 4;
+       rect->x -= TILE_W;
+}
+
+static bool ztats_reagents_filter_cb(struct inv_entry *ie, void *fdata)
+{
+       return (ie->type->isMixable());
+}
+
+
+void ztats_reagents_init(void)
+{
+        static struct ztats_container_pane pane;
+        static struct ztats_container_pane_ops ops = {
+                ztats_reagents_paint_item
+        };
+        static struct filter filter = {
+                ztats_reagents_filter_cb,
+                NULL
+        };
+
+        ztats_container_pane_init(&pane, "Reagents", &filter, &ops);
+        ztats_add_pane(&pane.base);
+}
diff --git a/src/ztats_reagents.h b/src/ztats_reagents.h
new file mode 100644 (file)
index 0000000..38a9e86
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_reagents_h
+#define ztats_reagents_h
+
+void ztats_reagents_init(void);
+
+#endif
diff --git a/src/ztats_spells.c b/src/ztats_spells.c
new file mode 100644 (file)
index 0000000..5df8865
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#include "ztats_spells.h"
+
+#include "magic.h"
+#include "screen.h"
+#include "session.h"
+#include "sprite.h"
+#include "ztats.h"
+#include "ztats_container_pane.h"
+
+static void ztats_spells_paint_item(struct inv_entry *ie, SDL_Rect *rect)
+{
+       char code[MAX_SYLLABLES_PER_SPELL+1] = { 0 };
+       struct spell *spell = 0;
+
+       /* This assumes the type name matches the spelled-out code name, and
+         * doesn't include extra stuff like " spell" at the end. Eg, "Vas Flam"
+         * is great but "Vas Flam spell" will come back as "Vas Flam Sanct" or
+         * possibly an error. */
+       if (! magic_spell_name_to_code(&Session->magic, code, sizeof(code), ie->type->getName())) {
+               spell = magic_lookup_spell(&Session->magic, code);
+       }
+
+       /* Blit the sprite on the left */
+       if (spell && spell->sprite) {
+               sprite_paint(spell->sprite, 0, rect->x, rect->y);
+       }
+       rect->x += TILE_W;
+
+       /* Print basic info available in the type. */
+       screenPrint(rect, 0, "%2d %s", ie->count, ie->type->getName());
+       rect->y += ASCII_H;
+
+       /* Print info only available in the spell struct. */
+       if (spell) {
+               screenPrint(rect, 0, 
+                       "^c+GLvl:^c+y%d^c- MP:^c+b%d^c- AP:^c+r%d^c-^c-",
+                       spell->level, 
+                       spell->cost, spell->action_points);
+       }
+
+       /* Carriage-return line-feed */
+       rect->y += ASCII_H;
+       rect->x -= TILE_W;
+}
+
+static bool ztats_spells_filter_cb(struct inv_entry *ie, void *fdata)
+{
+       return (ie->type->isCastable());
+}
+
+
+void ztats_spells_init(void)
+{
+        static struct ztats_container_pane pane;
+        static struct ztats_container_pane_ops ops = {
+                ztats_spells_paint_item
+        };
+        static struct filter filter = {
+                ztats_spells_filter_cb,
+                NULL
+        };
+
+        ztats_container_pane_init(&pane, "Spells", &filter, &ops);
+        ztats_add_pane(&pane.base);
+}
diff --git a/src/ztats_spells.h b/src/ztats_spells.h
new file mode 100644 (file)
index 0000000..c48d2c8
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * nazghul - an old-school RPG engine
+ * Copyright (C) 2008 Gordon McNutt
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Gordon McNutt
+ * gmcnutt@users.sourceforge.net
+ */
+
+#ifndef ztats_spells_h
+#define ztats_spells_h
+
+void ztats_spells_init(void);
+
+#endif
diff --git a/worlds/Makefile.am b/worlds/Makefile.am
new file mode 100644 (file)
index 0000000..37e3b5b
--- /dev/null
@@ -0,0 +1,3 @@
+SUBDIRS = haxima-1.002
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/worlds/Makefile.in b/worlds/Makefile.in
new file mode 100644 (file)
index 0000000..27ae1ca
--- /dev/null
@@ -0,0 +1,542 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = worlds
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-dvi-recursive install-exec-recursive \
+       install-html-recursive install-info-recursive \
+       install-pdf-recursive install-ps-recursive install-recursive \
+       installcheck-recursive installdirs-recursive pdf-recursive \
+       ps-recursive uninstall-recursive
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+       $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+       distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = haxima-1.002
+MAINTAINERCLEANFILES = Makefile.in
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu worlds/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu worlds/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @fail= failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+       @fail= failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(MKDIR_P) "$(distdir)/$$subdir" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+           $(am__relativize); \
+           new_distdir=$$reldir; \
+           dir1=$$subdir; dir2="$(top_distdir)"; \
+           $(am__relativize); \
+           new_top_distdir=$$reldir; \
+           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+           ($(am__cd) $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$new_top_distdir" \
+               distdir="$$new_distdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               am__skip_mode_fix=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+       install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+       all all-am check check-am clean clean-generic ctags \
+       ctags-recursive distclean distclean-generic distclean-tags \
+       distdir dvi dvi-am html html-am info info-am install \
+       install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-pdf install-pdf-am install-ps install-ps-am \
+       install-strip installcheck installcheck-am installdirs \
+       installdirs-am maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+       tags-recursive uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/worlds/haxima-1.002/640x480_splash.png b/worlds/haxima-1.002/640x480_splash.png
new file mode 100644 (file)
index 0000000..7824e9a
Binary files /dev/null and b/worlds/haxima-1.002/640x480_splash.png differ
diff --git a/worlds/haxima-1.002/Makefile.am b/worlds/haxima-1.002/Makefile.am
new file mode 100644 (file)
index 0000000..2c0f051
--- /dev/null
@@ -0,0 +1,14 @@
+haximadir   = $(datadir)/nazghul/haxima
+bin_SCRIPTS = haxima.sh
+CLEANFILES = haxima.sh
+SUBDIRS = music
+
+haxima.sh: Makefile
+       echo '#!/bin/sh' > $@ 
+       echo '"@bindir@/nazghul" -I "@datadir@/nazghul/haxima" -G "$$HOME/.haxima" "$$@"' >> $@
+
+haxima_DATA = $(wildcard *.scm) $(wildcard *.png) $(wildcard *.wav)
+
+EXTRA_DIST = $(haxima_DATA)
+MAINTAINERCLEANFILES = Makefile.in
+
diff --git a/worlds/haxima-1.002/Makefile.in b/worlds/haxima-1.002/Makefile.in
new file mode 100644 (file)
index 0000000..8f96261
--- /dev/null
@@ -0,0 +1,636 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = worlds/haxima-1.002
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(haximadir)"
+SCRIPTS = $(bin_SCRIPTS)
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+       html-recursive info-recursive install-data-recursive \
+       install-dvi-recursive install-exec-recursive \
+       install-html-recursive install-info-recursive \
+       install-pdf-recursive install-ps-recursive install-recursive \
+       installcheck-recursive installdirs-recursive pdf-recursive \
+       ps-recursive uninstall-recursive
+DATA = $(haxima_DATA)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive        \
+  distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+       $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+       distdir
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+  dir0=`pwd`; \
+  sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+  sed_rest='s,^[^/]*/*,,'; \
+  sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+  sed_butlast='s,/*[^/]*$$,,'; \
+  while test -n "$$dir1"; do \
+    first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+    if test "$$first" != "."; then \
+      if test "$$first" = ".."; then \
+        dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+        dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+      else \
+        first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+        if test "$$first2" = "$$first"; then \
+          dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+        else \
+          dir2="../$$dir2"; \
+        fi; \
+        dir0="$$dir0"/"$$first"; \
+      fi; \
+    fi; \
+    dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+  done; \
+  reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+haximadir = $(datadir)/nazghul/haxima
+bin_SCRIPTS = haxima.sh
+CLEANFILES = haxima.sh
+SUBDIRS = music
+haxima_DATA = $(wildcard *.scm) $(wildcard *.png) $(wildcard *.wav)
+EXTRA_DIST = $(haxima_DATA)
+MAINTAINERCLEANFILES = Makefile.in
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu worlds/haxima-1.002/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu worlds/haxima-1.002/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binSCRIPTS: $(bin_SCRIPTS)
+       @$(NORMAL_INSTALL)
+       test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)"
+       @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \
+       done | \
+       sed -e 'p;s,.*/,,;n' \
+           -e 'h;s|.*|.|' \
+           -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \
+       $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \
+         { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+           if ($$2 == $$4) { files[d] = files[d] " " $$1; \
+             if (++n[d] == $(am__install_max)) { \
+               print "f", d, files[d]; n[d] = 0; files[d] = "" } } \
+           else { print "f", d "/" $$4, $$1 } } \
+         END { for (d in files) print "f", d, files[d] }' | \
+       while read type dir files; do \
+            if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+            test -z "$$files" || { \
+              echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+              $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+            } \
+       ; done
+
+uninstall-binSCRIPTS:
+       @$(NORMAL_UNINSTALL)
+       @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \
+       files=`for p in $$list; do echo "$$p"; done | \
+              sed -e 's,.*/,,;$(transform)'`; \
+       test -n "$$list" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(bindir)" && rm -f $$files
+install-haximaDATA: $(haxima_DATA)
+       @$(NORMAL_INSTALL)
+       test -z "$(haximadir)" || $(MKDIR_P) "$(DESTDIR)$(haximadir)"
+       @list='$(haxima_DATA)'; test -n "$(haximadir)" || list=; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(haximadir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(haximadir)" || exit $$?; \
+       done
+
+uninstall-haximaDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(haxima_DATA)'; test -n "$(haximadir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(haximadir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(haximadir)" && rm -f $$files
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+#     (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+       @fail= failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       target=`echo $@ | sed s/-recursive//`; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           dot_seen=yes; \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done; \
+       if test "$$dot_seen" = "no"; then \
+         $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+       fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+       @fail= failcom='exit 1'; \
+       for f in x $$MAKEFLAGS; do \
+         case $$f in \
+           *=* | --[!k]*);; \
+           *k*) failcom='fail=yes';; \
+         esac; \
+       done; \
+       dot_seen=no; \
+       case "$@" in \
+         distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+         *) list='$(SUBDIRS)' ;; \
+       esac; \
+       rev=''; for subdir in $$list; do \
+         if test "$$subdir" = "."; then :; else \
+           rev="$$subdir $$rev"; \
+         fi; \
+       done; \
+       rev="$$rev ."; \
+       target=`echo $@ | sed s/-recursive//`; \
+       for subdir in $$rev; do \
+         echo "Making $$target in $$subdir"; \
+         if test "$$subdir" = "."; then \
+           local_target="$$target-am"; \
+         else \
+           local_target="$$target"; \
+         fi; \
+         ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+         || eval $$failcom; \
+       done && test -z "$$fail"
+tags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+       done
+ctags-recursive:
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+       done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+       list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       set x; \
+       here=`pwd`; \
+       if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+         include_option=--etags-include; \
+         empty_fix=.; \
+       else \
+         include_option=--include; \
+         empty_fix=; \
+       fi; \
+       list='$(SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test ! -f $$subdir/TAGS || \
+             set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+         fi; \
+       done; \
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       shift; \
+       if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+         test -n "$$unique" || unique=$$empty_fix; \
+         if test $$# -gt 0; then \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             "$$@" $$unique; \
+         else \
+           $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+             $$unique; \
+         fi; \
+       fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES)  $(TAGS_DEPENDENCIES) \
+               $(TAGS_FILES) $(LISP)
+       list='$(SOURCES) $(HEADERS)  $(LISP) $(TAGS_FILES)'; \
+       unique=`for i in $$list; do \
+           if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+         done | \
+         $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+             END { if (nonempty) { for (i in files) print i; }; }'`; \
+       test -z "$(CTAGS_ARGS)$$unique" \
+         || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+            $$unique
+
+GTAGS:
+       here=`$(am__cd) $(top_builddir) && pwd` \
+         && $(am__cd) $(top_srcdir) \
+         && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+       -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           test -d "$(distdir)/$$subdir" \
+           || $(MKDIR_P) "$(distdir)/$$subdir" \
+           || exit 1; \
+         fi; \
+       done
+       @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+         if test "$$subdir" = .; then :; else \
+           dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+           $(am__relativize); \
+           new_distdir=$$reldir; \
+           dir1=$$subdir; dir2="$(top_distdir)"; \
+           $(am__relativize); \
+           new_top_distdir=$$reldir; \
+           echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+           echo "     am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+           ($(am__cd) $$subdir && \
+             $(MAKE) $(AM_MAKEFLAGS) \
+               top_distdir="$$new_top_distdir" \
+               distdir="$$new_distdir" \
+               am__remove_distdir=: \
+               am__skip_length_check=: \
+               am__skip_mode_fix=: \
+               distdir) \
+             || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(SCRIPTS) $(DATA)
+installdirs: installdirs-recursive
+installdirs-am:
+       for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(haximadir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+       -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am: install-haximaDATA
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-binSCRIPTS
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-binSCRIPTS uninstall-haximaDATA
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+       install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+       all all-am check check-am clean clean-generic ctags \
+       ctags-recursive distclean distclean-generic distclean-tags \
+       distdir dvi dvi-am html html-am info info-am install \
+       install-am install-binSCRIPTS install-data install-data-am \
+       install-dvi install-dvi-am install-exec install-exec-am \
+       install-haximaDATA install-html install-html-am install-info \
+       install-info-am install-man install-pdf install-pdf-am \
+       install-ps install-ps-am install-strip installcheck \
+       installcheck-am installdirs installdirs-am maintainer-clean \
+       maintainer-clean-generic mostlyclean mostlyclean-generic pdf \
+       pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+       uninstall-binSCRIPTS uninstall-haximaDATA
+
+
+haxima.sh: Makefile
+       echo '#!/bin/sh' > $@ 
+       echo '"@bindir@/nazghul" -I "@datadir@/nazghul/haxima" -G "$$HOME/.haxima" "$$@"' >> $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/worlds/haxima-1.002/abandoned-cellar.scm b/worlds/haxima-1.002/abandoned-cellar.scm
new file mode 100644 (file)
index 0000000..e646091
--- /dev/null
@@ -0,0 +1,125 @@
+;;----------------------------------------------------------------------------
+;; Cellar of Abandoned Farm
+;;
+;; This is the root cellar where Ilya his when the trolls attacked her farm.
+;; She left Puska - a quest item - here in her hiding place. Initially it is
+;; infested with spider eggs. A fair number of food items may be found here as
+;; well, and some other basic materials. A paralyzed troll and a few troll
+;; corpses should also decorate the place. The paralyzed troll might as well
+;; have a conversation to make things interesting.
+;;----------------------------------------------------------------------------
+
+(kern-mk-map 
+ 'm_abandoned_cellar 32 32 pal_expanded
+ (list
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr rr {{ {{ {{ rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. {{ {{ {{ {{ .. {{ {{ rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. .. .. .. .. .. .. .. {{ {{ rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ .. .. .. .. .. .. .. .. .. .. {{ rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ .. {{ {{ {{ .. .. .. .. {{ rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr {{ {{ .. .. .. {{ rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ {{ {{ {{ {{ rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ .. {{ {{ rr rr rr "
+  "rr rr rr rr rr x! .. x! rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ {{ rr rr rr "
+  "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ rr rr rr rr "
+  "rr rr rr rr rr .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr x! .. x! rr rr rr rr rr rr rr rr rr rr {{ {{ {{ .. {{ {{ rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. .. .. .. {{ {{ rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ .. .. .. .. .. {{ {{ rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. {{ {{ {{ rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  ) ;; map m_abandoned_cellar
+ )
+
+(kern-mk-place 'p_abandoned_cellar ; tag
+               "Musty Cellar"     ; name
+               nil                ; sprite
+               m_abandoned_cellar ; map
+               #f                 ; wraps
+               #t                 ; underground
+               #f                 ; large-scale (wilderness)
+               #f                 ; tmp combat place
+               nil                ; subplaces
+
+               ;; neighbors
+               (list
+                (list p_abandoned_farm up)
+                )
+
+               ;; objects
+               (list
+                (list (mk-ladder-up 'p_abandoned_farm 6 25) 6 25)
+
+                ;; existing webs
+                (list (kern-mk-obj web-type 1) 5 12)
+                (list (kern-mk-obj web-type 1) 5 13)
+                (list (kern-mk-obj web-type 1) 5 14)
+                (list (kern-mk-obj web-type 1) 6 11)
+                (list (kern-mk-obj web-type 1) 6 12)
+                (list (kern-mk-obj web-type 1) 6 13)
+                (list (kern-mk-obj web-type 1) 6 14)
+                (list (kern-mk-obj web-type 1) 6 15)
+                (list (kern-mk-obj web-type 1) 7 12)
+                (list (kern-mk-obj web-type 1) 7 13)
+                (list (kern-mk-obj web-type 1) 7 14)
+                (list (kern-mk-obj web-type 1) 7 15)
+                (list (kern-mk-obj web-type 1) 7 16)
+                (list (kern-mk-obj web-type 1) 8 13)
+                (list (kern-mk-obj web-type 1) 9  12)
+                (list (kern-mk-obj web-type 1) 9  13)
+                (list (kern-mk-obj web-type 1) 9  14)
+                (list (kern-mk-obj web-type 1) 10 12)
+                (list (kern-mk-obj web-type 1) 10 13)
+                (list (kern-mk-obj web-type 1) 10 14)
+                (list (kern-mk-obj web-type 1) 11 12)
+                (list (kern-mk-obj web-type 1) 11 13)
+                (list (kern-mk-obj web-type 1) 11 14)
+                (list (kern-mk-obj web-type 1) 9  16)
+                (list (kern-mk-obj web-type 1) 10 16)
+                (list (kern-mk-obj web-type 1) 10 17)
+                (list (kern-mk-obj web-type 1) 10 16)
+                (list (kern-mk-obj web-type 1) 11 17)
+                (list (kern-mk-obj web-type 1) 11 18)
+
+                ;; spider eggs
+                (list (mk-spider-egg) 5 13)
+                (list (mk-spider-egg) 6 15)
+                (list (mk-spider-egg) 7 12)
+                (list (mk-spider-egg) 9  14)
+                (list (mk-spider-egg) 11 14)
+                (list (mk-spider-egg) 10 16)
+                (list (mk-spider-egg) 11 18)
+
+                ;; troll victims
+                (put (mk-npc 'troll 3) 11 12)
+
+                ;; puska
+                (list (kern-mk-obj t_puska 1) 10 18)
+
+                )
+               nil ; hooks
+               nil ; edge entrances
+               )
+
+;; ----------------------------------------------------------------------------
+;; The entry hooks must be kern-loaded from a separate file, since they are
+;; read-only and not saved with the session.
+;; ----------------------------------------------------------------------------
+
+(mk-place-music p_abandoned_cellar 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/abandoned-farm.scm b/worlds/haxima-1.002/abandoned-farm.scm
new file mode 100644 (file)
index 0000000..1e67ea3
--- /dev/null
@@ -0,0 +1,84 @@
+;;----------------------------------------------------------------------------
+;; Abandoned Farm
+;;
+;; The abandoned farm is a wrecked homestead. Not long ago (weeks or at most
+;; months) renegade trolls attacked, killing the husband and wife who lived
+;; here. On start-of-game the trolls are still here, but they are locked in a
+;; life-and-death battle with a group of giant wood spiders.
+;;
+;; The farm has a cellar which contains a quest item. The farm itself should
+;; contain the bones or corpses of the man and woman, who were eaten by the
+;; trolls. Their remains should lie near the troll's campsite. I'd like to make
+;; burying their remains a quest item if I can, since the woman is Gregor's
+;; daughter and Ilya's mother.
+;;
+;; One or two very frightened sheep might also remain, and quite a few have
+;; been eaten by the trolls.
+;;----------------------------------------------------------------------------
+
+(kern-mk-map 
+ 'm_abandoned_farm 32 32 pal_expanded
+ (list
+               "tt tt || || || || || || || || || || || tt tt .. .. .. tt || || || || || || || || tt tt tt tt tt "
+               "tt tt || || || || || || || || || || || || tt .. .. .. ta || || || || tt || || || || tt tt bb tt "
+               "|| || || || || || || || || || tt || || || tt tA .. .. t% tt || || tt tt tt || || || || tt tt tt "
+               "|| || || || || || || || || tt tt tt || || tt t5 .. .. .. tt || tt tt tt tt tt || || || tt tt tt "
+               "|| || || || || || || || || || tt || || || tt tc .. .. .. tt || || tt tt tt tt || || || || || tt "
+               "|| || || || || || || || || || || || || || tt t# .. .. tC tt || || || tt || tt tt tt || || || || "
+               "|| || || || || || || || || || || || || tt tt .. .. .. t3 tt tt || || || || tt || tt tt tt tt || "
+               "|| || || tt tt || || || || || tt tt tt tt tc .. .. tC tt tt tt tt tt || tt tt || || || tt tt tt "
+               "|| || || tt tt tt tt tt tt tt tc t# .. .. .. .. .. tb tt tt tt tt tt tt tt || || || tt tt bb tt "
+               "|| || || tt tt tt tt tt tt tc t# .. bb bb bb bb bb bb bb bb tD ta tt tt tt tt tt || || tt tt tt "
+               "|| || tt tt t# .. .. .. .. .. .. bb .. .. .. .. .. .. tb tt td t& te bb ta tt tt tt || || tt || "
+               "|| || tt tt .. bb rr rr wr rr rr rr .. .. .. .. .. .. .. .. .. .. t% tf bb tt tt tt || || || || "
+               "|| || tt tt .. rr .. cc cc cc cc rr .. .. .. .. .. .. .. .. .. && .. .. bb tt tt tt || || || || "
+               "|| tt tt tt .. rr cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. .. .. .. bb tt bb ta || || || || "
+               "tt tt tt tc .. wr cc cc cc cc cc wr .. .. .. .. .. .. .. .. .. bb .. tf bb tt td t# .. t% |A || "
+               "t% ta tc t# .. rr cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. .. .. .. bb te t# .. .. .. t% |A "
+               ".. .. .. .. .. rr cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. .. .. .. bb .. .. tC tf tA .. .. "
+               ".. .. .. .. .. rr rr rr cc rr rr bb rr cc rr .. .. .. .. .. .. .. .. .. bb .. tC t7 bb t7 tA .. "
+               "t5 tA .. .. .. rr cc cc cc cc cc cc .. cc rr .. .. .. .. .. .. .. .. .. bb .. t3 tt tt tt tt tt "
+               "tt t5 tA .. .. wr cc cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. bb .. tt tt tt tt tt bb "
+               "tt tt t5 .. .. rr cc cc cc cc cc .. cc cc rr rr rr rr wr rr rr bb rr bb .. tC tt tt tt tt tt tt "
+               "tt tt tt tA .. rr cc cc cc [[ @@ ]] cc cc rr cc cc cc cc cc .. .. rr .. tC t3 tt || || || tt tt "
+               "|| || tt t5 .. wr cc cc cc cc cc cc cc cc rr cc cc cc cc cc cc cc rr .. t3 tt || || || || || tt "
+               "|| || tt tt .. rr cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc wr tC tt || || || || || || tt "
+               "|| || || tt .. rr rr rr cc cc cc cc cc cc rr cc cc cc cc cc cc .. rr t3 tt || || || tt || || || "
+               "|| || || tt .. rr cc cc cc cc cc [[ @@ ]] rr cc cc cc cc cc .. .. bb tt tt || || || || || || || "
+               "|| || || tt .. rr rr rr rr wr rr rr rr rr rr rr rr rr wr rr rr rr rr tt tt || || || || || || tt "
+               "|| || || tt tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. tC t3 tt tt tt || || || || || tt tt "
+               "|| || tt tt tt tt tt tt tt tt tt tt tt t5 tA .. .. .. tC t3 tt tt tt tt tt tt || || || || tt tt "
+               "|| || tt tt || || || || || || || || tt tt t5 tA .. tC t3 tt tt || || || tt tt || || || || tt tt "
+               "|| || || || || || || || || || || || || tt tt t5 .. t3 tt tt || || || || || || || || || tt tt tt "
+               "|| || || || || || || || || || || || || || tt tt .. tt tt || || || tt || || || || || tt tt tt tt "
+ ))
+
+
+(kern-mk-place 'p_abandoned_farm  ; tag
+               "Abandoned Farm"   ; name
+               s_hamlet           ; sprite
+               m_abandoned_farm   ; map
+               #f                 ; wraps
+               #f                 ; underground
+               #f                 ; large-scale (wilderness)
+               #f                 ; tmp combat place
+               nil                ; subplaces
+               nil                ;; neighbors
+
+               ;; objects
+               (list
+                (put (mk-monman) 0 0)
+                (put (spawn-pt 'queen-spider) 9 23)
+                (put (spawn-pt 'troll) 19 13)
+                (put (spawn-pt 'troll) 19 14)
+               (put (kern-mk-obj t_spell_book_enchantment_curses 1) 10 12)  ;; Belonged to Ilya's mother
+                (list (mk-door-in-rock) 13 17)
+                (list (mk-door-in-rock) 7 25)
+                (list (mk-ladder-down 'p_abandoned_cellar 6 25) 6 25)
+                               (list (mk-broken-clock s_clock_hand_s s_clock_hand_ne "The clock reads 6:12") 6 23)
+                )
+               (list 'on-entry-to-dungeon-room) ; hooks
+               nil ; edge entrances
+               )
+
+(mk-place-music p_abandoned_farm 'ml-outdoor-adventure)
diff --git a/worlds/haxima-1.002/abe.scm b/worlds/haxima-1.002/abe.scm
new file mode 100644 (file)
index 0000000..af5d98a
--- /dev/null
@@ -0,0 +1,260 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define abe-lvl 3)
+(define abe-species sp_human)
+(define abe-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Green Tower
+;;----------------------------------------------------------------------------
+(define abe-bed gt-abe-bed)
+(define abe-mealplace gt-ws-tbl2)
+(define abe-workplace gt-ruins)
+(define abe-leisureplace gt-ws-hall)
+(kern-mk-sched 'sch_abe
+               (list 0  0 abe-bed          "sleeping")
+               (list 7  0 abe-mealplace    "eating")
+               (list 8  0 abe-workplace    "working")
+               (list 12 0 abe-mealplace    "eating")
+               (list 13 0 abe-workplace    "working")
+               (list 18 0 abe-mealplace    "eating")
+               (list 19 0 abe-leisureplace "idle")
+               (list 22 0 abe-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (abe-mk) (list #f))
+(define (abe-met? gob) (car gob))
+(define (abe-met! gob) (set-car! gob #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Abe is a scholar who knows much of the runes.
+;; He fled from Absalot with the Alchemist, and now lives in Green Tower.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (abe-hail knpc kpc)
+  (kern-print "You meet a young, bookish-looking fellow.\n")
+  (if (abe-met? (gob knpc))
+      (say knpc "Hello again.")
+      (begin
+        (abe-met! (gob knpc))
+        (say knpc "Hello. Say, aren't you a Wanderer?")
+        (if (yes? kpc)
+            (say knpc "I am most honored! I can't believe my good fortune. "
+                 "I have so many questions for you. When you get the time. "
+                 "If you don't mind.")
+            (say knpc "Oh, of course not. Sorry. I just thought... never mind.")))))
+
+(define (abe-default knpc kpc)
+  (say knpc "I'll look that up in the archives when I get a chance."))
+
+(define (abe-name knpc kpc)
+  (say knpc "Oh. Yes. I'm Abe."))
+
+(define (abe-join knpc kpc)
+  (say knpc "Oh, no, I couldn't possibly... I'm not really that sort of person."))
+
+(define (abe-job knpc kpc)
+  (say knpc "I'm a scholar. I'm studying the ruins here in Green Tower. Have you examined them?")
+  (if (no? kpc)
+      (say knpc "They're in the southwest corner of town. Fascinating.")
+      (begin
+        (say knpc "Did you know there are more below the surface?")
+        (yes? kpc)
+        (say knpc "Yes, just like Absalot!"))))
+
+(define (abe-absa knpc kpc)
+  (say knpc "Not many know that beneath Absalot is an older city. "
+       "The ruins beneath Absalot are very similar to the ruins here in Green Tower. "
+       "I am certain they were built by the same civilization!"))
+
+(define (abe-rune knpc kpc)
+  (if (any-in-inventory? kpc rune-types)
+      (begin
+        (say knpc "\n[He whistles softly]\n"
+            "You have some of the Eight Keys to the Demon Gate?\n"
+            "I shall examine them for you!")
+               (quest-data-update 'questentry-runeinfo 'abe 1)
+        (quest-data-update-with 'questentry-runeinfo 'keys 1 (quest-notify (grant-party-xp-fn 20)))
+       (if (any-in-inventory? kpc (list t_rune_k))
+           (say knpc "[He examines a rune] This is the Rune of Knowledge!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_p))
+           (say knpc "[He examines a rune] This is the Rune of Power!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_s))
+           (say knpc "[He examines a rune] This is the Rune of Skill!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_c))
+           (say knpc "[He examines a rune] This is the Rune of Curiousity!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_f))
+           (say knpc "[He examines a rune] This is the Rune of Freedom!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_w))
+           (say knpc "[He examines a rune] This is the Rune of Wisdom!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_d))
+           (say knpc "[He examines a rune] This is the Rune of Discretion!")
+           )
+       (if (any-in-inventory? kpc (list t_rune_l))
+           (say knpc "[He examines a rune] This is the Rune of Leadership!")
+           )
+       (if (has-all-runes? kpc) 
+           (say knpc "This is incredible!\n"
+                "You have all of the Eight Keys to the Demon Gate!!!\n"
+                "What do you intend to do with them?")
+           )
+       )
+      (say knpc "There are many runes. Perhaps if you brought me an example...?")))
+
+(define (abe-demo knpc kpc)
+  (say knpc "The Demon Gate was sealed shut by the Wise long ago. "
+       "Its location was blotted from all records, but legend puts it somewhere to the north. ")
+               (quest-data-update 'questentry-runeinfo 'abe 1)
+            (quest-data-update 'questentry-runeinfo 'keys 1)
+               (quest-data-update-with 'questentry-runeinfo 'gate 1 (quest-notify (grant-party-xp-fn 30)))
+       )
+
+(define (abe-keys knpc kpc)
+  (say knpc "Yes, the Demon Gate was locked with eight locks and the keys separated. "
+       "Each takes the form of a powerful rune. "
+       "They've been lost or hidden since then."))
+       
+(define (abe-eigh knpc kpc)
+       (say knpc "Legend says that there are eight runes in all, are you seeking the others?")
+       (if (yes? kpc)
+               (say knpc "The old stories speak of some, such as King Clovis' charm, or the void temple.")
+               (say knpc "Just idle curiosity? Believe me, I understand.")))
+
+(define (abe-clov knpc kpc)
+     (say knpc "There's a legend that King Clovis carried one as a charm. "
+           "He fell in battle during the goblin wars, but it was never found on his body. "
+           "Perhaps someone (perhaps a ^c+mgoblin^c-!) looted his corpse and took it.")
+           (quest-data-assign-once 'questentry-rune-f)
+           )
+           
+(define (abe-temp knpc kpc)
+       (say knpc "Northwest of Oparine, there is a temple floating in the void. No one can reach it,"
+                       " but legends say that a rune was sealed up there by the ancients.")
+                       (quest-data-assign-once 'questentry-rune-d)
+                       )
+      
+(define (abe-void knpc kpc)
+  (say knpc "The Shard, the moons and the stars all habitate a great void. "
+       "The ancients could sail across the void in ships, the way we sail across a sea!")
+       (quest-data-update 'questentry-whereami 'shard 2)
+       )
+
+(define (abe-ship knpc kpc)
+  (say knpc "I know of the void ships, but not how they worked. "
+       "Even the Master Wrights have lost the technique for making them."
+       (quest-data-update 'questentry-whereami 'shard 2)
+       ))
+
+(define (abe-wrig knpc kpc)
+  (say knpc "Wrights specialize in the making of things. "
+       "The Engineer is the greatest living Wright."))
+
+(define (abe-quee knpc kpc)
+  (say knpc "I'm not sure what you're insinuating."))
+
+(define (abe-civi knpc kpc)
+  (say knpc "I don't know much about the civilization that built the ruins, but clues indicate it was quite wicked by our standards! Do you know what I mean?")
+  (if (yes? kpc)
+      (say knpc "Then I won't mention it!")
+      (say knpc "Human sacrifice, cannibalism, demon worship. Accursed practices!")))
+
+(define (abe-accu knpc kpc)
+  (say knpc "Yes, the Accursed have a long history. They may be a convenient political bogeyman, "
+       "but there is enough evidence to suggest they do, or did, exist."))
+
+(define (abe-bye knpc kpc)
+  (say knpc "Let me know if you find any more ruins!"))
+
+(define (abe-alch knpc kpc)
+  (say knpc "Ah, how is the secretive old rascal? I haven't seen him since we were neighbors."))
+
+(define (abe-neig knpc kpc)
+  (say knpc "In Absalot. Before we had to flee."))
+
+(define (abe-flee knpc kpc)
+  (say knpc "[He sighs] It's a long story. Ask around. It doesn't matter anymore."))
+
+(define (abe-gobl knpc kpc)
+  (say knpc "Ask Deric or Gen about goblins, they have a lot of experience with them."))
+
+(define abe-conv
+  (ifc green-tower-conv
+
+       ;; basics
+       (method 'default abe-default)
+       (method 'hail abe-hail)
+       (method 'bye abe-bye)
+       (method 'job abe-job)
+       (method 'name abe-name)
+       (method 'join abe-join)
+       
+
+       (method 'absa abe-absa)
+       (method 'rune abe-rune)
+       (method 'demo abe-demo)
+       (method 'gate abe-demo)
+       (method 'keys abe-keys)
+       (method 'key  abe-keys)
+       (method 'eigh abe-eigh)
+       (method 'quee abe-quee)
+       (method 'king abe-clov)
+       (method 'clov abe-clov)
+       (method 'char abe-clov)
+       (method 'temp abe-temp)
+       (method 'civi abe-civi)
+       (method 'accu abe-accu)
+       (method 'bye  abe-bye)
+       (method 'ruin abe-job)
+
+       (method 'void abe-void)
+       (method 'ship abe-ship)
+       (method 'sail abe-ship)
+       (method 'wrig abe-wrig)
+       (method 'alch abe-alch)
+       (method 'neig abe-neig)
+       (method 'flee abe-flee)
+       (method 'gobl abe-gobl)
+       ))
+
+(define (mk-abe)
+  (bind 
+   (kern-mk-char 
+    'ch_abe           ; tag
+    "Abe"             ; name
+    abe-species         ; species
+    abe-occ              ; occ
+    s_companion_wizard ; sprite
+    faction-men      ; starting alignment
+    2 1 1            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    abe-lvl
+    #f               ; dead
+    'abe-conv         ; conv
+    sch_abe           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_staff
+                                                t_armor_leather
+                                                )              ; readied
+    )
+   (abe-mk)))
diff --git a/worlds/haxima-1.002/abigail.scm b/worlds/haxima-1.002/abigail.scm
new file mode 100644 (file)
index 0000000..557aa6d
--- /dev/null
@@ -0,0 +1,106 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define abigail-lvl 1)
+(define abigail-species sp_forest_goblin)
+(define abigail-occ oc_wrogue)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Green Tower
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_abigail
+               (list 0 0 abigail-bed "sleeping")
+               (list 7 0 gt-ws-hall "idle")
+               (list 8 0 gt-woods "idle")
+               (list 12 0 gt-ws-hall "idle")
+               (list 13 0 gt-ruins "idle")
+               (list 18 0 gt-ws-hall "idle")
+               (list 19 0 gt-tower "idle")
+               (list 20 0 abigail-bed "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (abigail-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Abigail is a female goblin child, who lives in Green Tower.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (abigail-hail knpc kpc)
+  (kern-log-msg "You meet a goblin child.")
+  (say knpc "Hi.")
+  )
+
+(define (abigail-default knpc kpc)
+  (say knpc "[She shrugs]")
+  )
+
+(define (abigail-name knpc kpc)
+  (say knpc "Guto says my name is Abigail.")
+  )
+
+(define (abigail-bye knpc kpc)
+  (say knpc "Bye-bye!")
+  )
+
+(define (abigail-guto knpc kpc)
+  (say knpc "Doris is my guto."))
+
+(define (abigail-dori knpc kpc)
+  (say knpc "That's my guto!"))
+
+(define (abigail-gobl knpc kpc)
+  (say knpc "The green people, like me. I'm both!"))
+
+(define (abigail-both knpc kpc)
+  (say knpc "I talk to goblins. I talk to people. See? Both!"))
+
+(define abigail-conv
+  (ifc nil
+
+       ;; basics
+       (method 'default abigail-default)
+       (method 'hail abigail-hail)
+       (method 'bye abigail-bye)
+       (method 'name abigail-name)
+
+       (method 'guto abigail-guto)
+       (method 'dori abigail-dori)
+       (method 'gobl abigail-gobl)
+       (method 'both abigail-both)
+       ))
+
+(define (mk-abigail)
+  (bind 
+   (kern-mk-char 
+    'ch_abigail           ; tag
+    "Abigail"             ; name
+    abigail-species         ; species
+    abigail-occ              ; occ
+    s_goblin_child     ; sprite
+    faction-men      ; starting alignment
+    0 0 1            ; str/int/dex
+    0  ; hp bonus
+    0 ; hp per-level bonus
+    0 ; mp off
+    1 ; mp gain
+    max-health ; hp
+    0                   ; xp
+    max-health ; mp
+    0
+    abigail-lvl
+    #f               ; dead
+    'abigail-conv         ; conv
+    sch_abigail           ; sched
+    'townsman-ai              ; special ai
+    nil
+    nil              ; readied
+    )
+   (abigail-mk)))
diff --git a/worlds/haxima-1.002/ability.scm b/worlds/haxima-1.002/ability.scm
new file mode 100644 (file)
index 0000000..075c610
--- /dev/null
@@ -0,0 +1,421 @@
+;;----------------------------------------------------------------------------
+;; Ability "class"
+;;----------------------------------------------------------------------------
+
+(define default-aap 50)
+
+(define (mk-ability name level mana ap rng proc)
+  (list name level mana (* ap default-aap) proc rng))
+
+(define (ability-name ability) (car ability))
+(define (ability-level-required ability) (cadr ability))
+(define (ability-mana-cost ability) (caddr ability))
+(define (ability-ap-cost ability) (cadddr ability))
+(define (ability-proc ability) (list-ref ability 4))
+(define (ability-range ability) (list-ref ability 5))
+
+(define (can-use-ability? ability kchar)
+  ;;(println " can-use-ability?" display ability)
+  (and (<= (kern-get-magic-negated) 0)
+       (>= (kern-char-get-mana kchar)
+           (ability-mana-cost ability))
+       (>= (kern-char-get-level kchar)
+           (ability-level-required ability))))
+
+(define (use-ability ability kchar . args)
+  (let ((result (apply (ability-proc ability) (cons kchar args))))
+        (if result
+               (begin
+                 (kern-char-dec-mana kchar (ability-mana-cost ability))
+                 (kern-obj-dec-ap kchar (ability-ap-cost ability))
+               )
+        )
+    (if (<= (kern-char-get-mana kchar) 0)
+        (kern-log-msg (kern-obj-get-name kchar) " is exhausted!"))
+    result))
+
+
+;;----------------------------------------------------------------------------
+;; Ability procedures
+;;----------------------------------------------------------------------------
+
+(define (vampiric-touch-proc kchar ktarg)
+  (let ((amount (min (* (kern-dice-roll "1d3")
+                        (kern-char-get-level kchar))
+                     (kern-char-get-hp ktarg))))
+    (kern-obj-inc-ref ktarg)
+    (kern-obj-apply-damage ktarg "life drained" amount)
+    (kern-obj-heal kchar amount)
+    (kern-log-msg (kern-obj-get-name kchar)
+                  " drains life from "
+                  (kern-obj-get-name ktarg)
+                  "!")
+    (kern-obj-dec-ref ktarg))
+  #t)
+
+(define (disease-touch-proc kchar ktarg)
+  (if (kern-obj-add-effect ktarg ef_disease nil)
+      (kern-log-msg (kern-obj-get-name kchar)
+                    " inflicts "
+                    (kern-obj-get-name ktarg)
+                    " with Disease!"))
+  #t)
+
+(define (disarm kchar ktarg)
+  (let ((readied (kern-char-get-readied-weapons ktarg)))
+    (if (null? readied)
+        #f
+        (if (> (kern-char-get-level kchar)
+               (+ (kern-dice-roll "1d3-1")
+                  (kern-char-get-level ktarg)))
+            (let ((ktype (random-select readied)))
+              (kern-log-msg (kern-obj-get-name kchar)
+                            " disarms "
+                            (kern-obj-get-name ktarg))
+              (kern-char-unready ktarg ktype)
+              (kern-obj-remove-from-inventory ktarg ktype 1)
+              (kern-obj-put-at (kern-mk-obj ktype 1)
+                               (kern-obj-get-location ktarg))
+              )
+            (kern-log-msg  (kern-obj-get-name kchar)
+                           " fails to disarm "
+                           (kern-obj-get-name ktarg))
+            #t))))
+
+(define (heal-proc kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts a healing spell on "
+                (if (eqv? kchar ktarg)
+                    "self"
+                    (kern-obj-get-name ktarg)))
+       (kern-obj-heal ktarg 
+               (+ 2 (kern-dice-roll "1d10")
+                       (kern-dice-roll (string-append "2d" (number->string (occ-ability-whitemagic kchar)))))))
+
+(define (great-heal-proc kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts a great healing spell on "
+                (if (eqv? kchar ktarg)
+                    "self"
+                    (kern-obj-get-name ktarg)))
+  (kern-obj-heal ktarg (kern-dice-roll "4d20+20")))
+
+;;----------------------------------------------------------------------------
+;; field spells
+(define (cast-field-proc kchar loc ktype)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts "(kern-type-get-name ktype) "!")
+  (kern-obj-put-at (kern-mk-obj ktype 1) loc))
+  
+(define (cast-fire-field-proc kchar ktarg)
+  (cast-field-proc kchar 
+                   (kern-obj-get-location ktarg)
+                   F_fire))
+  
+(define (cast-poison-field-proc kchar ktarg)
+  (cast-field-proc kchar 
+                   (kern-obj-get-location ktarg)
+                   F_poison))
+  
+(define (cast-sleep-field-proc kchar ktarg)
+  (cast-field-proc kchar 
+                   (kern-obj-get-location ktarg)
+                   F_sleep))
+  
+(define (cast-energy-field-proc kchar ktarg)
+  (cast-field-proc kchar 
+                   (kern-obj-get-location ktarg)
+                   F_energy))
+  
+;;----------------------------------------------------------------------------
+;; missile spells
+
+;; cast-magic-missile-proc -- damage goes up with level of caster
+(define (cast-magic-missile-proc kchar ktarg)
+       (powers-magic-missile kchar ktarg (occ-ability-blackmagic kchar)))
+
+(define (cast-poison-missile-proc kchar ktarg)
+       (powers-poison kchar ktarg (occ-ability-blackmagic kchar)))
+
+(define (cast-fireball-proc kchar ktarg)
+       (let ((target (kern-obj-get-location ktarg))
+                       (power (occ-ability-blackmagic kchar)))
+               (and (powers-fireball-collateral-check kchar target power)
+                       (powers-fireball kchar target power))
+       ))
+
+(define (cast-kill-proc kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts kill at "
+                (kern-obj-get-name ktarg))
+  (cast-missile-proc kchar ktarg t_deathball))
+
+(define (cast-acid-missile-proc kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " hurls acid missile at "
+                (kern-obj-get-name ktarg))
+  (cast-missile-proc kchar ktarg t_acid_bolt))
+
+(define (web-spew-proc kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " spews web at "
+                (kern-obj-get-name ktarg))
+  (define (spew-in-dir dir)
+    (define (ensnare-loc loc)
+      (kern-obj-put-at (kern-mk-obj web-type 1) loc))
+    (let ((loc (kern-obj-get-location kchar)))
+      (cast-wind-spell2 loc
+                        ensnare-loc
+                        dir
+                        (/ (kern-char-get-level kchar) 2))))
+  (let* ((v (loc-diff (kern-obj-get-location kchar)
+                      (kern-obj-get-location ktarg)
+                      ))
+         (dir (loc-to-cardinal-dir v)))
+    (spew-in-dir dir)))
+
+(define (teleport-proc kchar loc)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " teleports")
+  (kern-obj-relocate kchar loc nil))
+
+(define (fire-wind-proc3 kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " blasts fire at "
+                (kern-obj-get-name ktarg))
+  (define (spew-in-dir dir)
+    (define (ensnare-loc loc)
+      (kern-obj-put-at (kern-mk-obj F_fire 1) loc))
+    (let ((loc (kern-obj-get-location kchar)))
+      (cast-wind-spell2 loc
+                        ensnare-loc
+                        dir
+                        4)))
+  (let* ((v (loc-diff (kern-obj-get-location kchar)
+                      (kern-obj-get-location ktarg)
+                      ))
+         (dir (loc-to-cardinal-dir v)))
+    (spew-in-dir dir)))
+    
+(define (fire-wind-proc kchar ktarg)
+       ;;(println "flamewind")
+       (let ((target (kern-obj-get-location ktarg))
+                       (power (occ-ability-blackmagic kchar)))
+               (and (powers-cone-fire-test kchar target power)
+                       (begin 
+                               ;;(println "flamewind2")
+                               (kern-log-msg (kern-obj-get-name kchar)
+                       " blasts fire at "
+                       (kern-obj-get-name ktarg))
+                       (powers-cone-fire kchar target power)
+                 ))
+       ))
+
+(define (lightning-bolt-proc kchar ktarg)
+       (let ((target (kern-obj-get-location ktarg))
+                       (power (occ-ability-blackmagic kchar)))
+               (and (powers-lightning-collateral-check kchar target power)
+                       (begin (kern-log-msg (kern-obj-get-name kchar)
+                       " streams lightning at "
+                       (kern-obj-get-name ktarg))
+                       (powers-lightning kchar target power)
+                  ))
+       ))
+  
+
+;;----------------------------------------------------------------------------
+;; summoning
+(define (cast-summon-proc kchar gen-npct quantity)
+  (define (run-loop count)
+    (cond ((<= count 0) 0)
+          (else
+           (let* ((lvl (+ (kern-dice-roll "1d2") (/ (kern-char-get-level kchar) 2)))
+                  (knpc (spawn-npc (gen-npct) lvl))
+                  (loc (pick-loc (kern-obj-get-location kchar) knpc))
+                  )
+             (cond ((null? loc) 
+                    (kern-obj-dec-ref knpc)
+                    0)
+                   (else
+                    (kern-being-set-base-faction knpc (kern-being-get-base-faction kchar))
+                    (kern-obj-set-temporary knpc #t)
+                    (kern-obj-put-at knpc loc)
+                    (+ 1 (run-loop (- count 1)))))))))
+  (cond ((> (run-loop quantity)
+            0)
+         (kern-log-msg (kern-obj-get-name kchar) " summons help")
+         #t)
+        (else
+         (kern-log-msg (kern-obj-get-name kchar) " fails to summon help")
+         #f)))
+
+(define (summon-skeleton-proc kchar)
+  ;;(println "summon-skeleton-proc")
+  (cast-summon-proc kchar
+                    (lambda () 
+                      (random-select (list 'skeletal-warrior 'skeletal-spear-thrower)))
+                    (/ (kern-char-get-level kchar) 2)
+                    ))
+                    
+(define (summon-slime-proc kchar)
+  ;;(println "summon-slime-proc")
+  (cast-summon-proc kchar
+                    (lambda () 'green-slime)
+                    (/ (kern-char-get-level kchar) 2)
+                    ))
+
+(define (summon-demon-proc kchar)
+  (cast-summon-proc kchar
+                    (lambda () 'demon)
+                    1))
+
+(define (summon-wolf-proc kchar)
+  (cast-summon-proc kchar
+                    (lambda () 'wolf)
+                    1))
+
+(define (summon-ratling-proc kchar)
+  (cast-summon-proc kchar
+                    (lambda () 'ratling-swarmer)
+                    (* (kern-char-get-level kchar) 3)
+                    ))
+
+;;----------------------------------------------------------------------------
+;; enslave -- aka charm
+(define (enslave-proc kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " enslaves "
+                (kern-obj-get-name ktarg))
+  (kern-obj-add-effect ktarg 
+                       ef_charm 
+                       (charm-mk (kern-being-get-current-faction kchar))))
+
+;;----------------------------------------------------------------------------
+;; chomp-deck -- convert deck terrain into shallow water terrain
+(define (chomp-deck-proc kchar loc)
+  (cond ((not (is-deck? (kern-place-get-terrain loc))) #f)
+                 ((not (null? (get-being-at loc))) #f)
+        (else
+         (kern-place-set-terrain loc t_shallow)
+         (msg-log-visible (kern-obj-get-location kchar) (kern-obj-get-name kchar) " chomps through the deck!")
+         (map kern-obj-remove
+               (kern-get-objects-at loc))
+         (if (kern-place-is-combat-map? (loc-place loc))
+                               (let* ((vehicle (kern-party-get-vehicle (kern-get-player))))
+                                       (if (not (null? vehicle))
+                                               (begin 
+                                                  (shake-map 10)
+                                                       (kern-obj-apply-damage vehicle "breakage" (floor (/ (kern-obj-get-hp vehicle) 7)))
+                                               )
+                                       )
+                               )
+                       )
+         #t)))
+
+(define (deck-to-sludge-proc kchar loc)
+  (cond ((not (is-deck? (kern-place-get-terrain loc))) #f)
+        (else
+         (kern-place-set-terrain loc t_shallow_sludge)
+         (kern-log-msg (kern-obj-get-name kchar) " chomps through the deck!")
+         #t)))
+
+;;----------------------------------------------------------------------------
+;; narcotize -- mass sleep
+(define (narcotize-proc kchar)
+  (let ((hostiles (all-hostiles kchar)))
+    (cond ((null? hostiles) #f)
+          (else
+           (kern-log-msg (kern-obj-get-name kchar)
+                         " beckons slumber to its foes")
+           (map (lambda (ktarg)
+                  (if (> (- (+ (kern-dice-roll "1d20") 
+                               (kern-char-get-level kchar)) 
+                            (kern-char-get-level ktarg))
+                         12)
+                      (begin
+                        (apply-sleep ktarg)
+                        (kern-log-msg (kern-obj-get-name ktarg) " succumbs!")
+                        )
+                      (kern-log-msg (kern-obj-get-name ktarg) " resists!")))
+                hostiles)
+           #t))))
+
+;;----------------------------------------------------------------------------
+;; turn invisible
+(define (turn-invisible-proc kchar)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " vanishes!")
+  (kern-obj-add-effect kchar ef_invisibility nil))
+
+;;----------------------------------------------------------------------------
+;; Ability declarations
+;;
+;;  L = level
+;;  M = mana
+;;  A = action points
+;;  R = range
+;;
+;;----------------------------------------------------------------------------
+
+;;                                      name                  L M A R proc
+(define vampiric-touch      (mk-ability "vampiric touch"      3 3 2 1 vampiric-touch-proc))
+(define disease-touch       (mk-ability "disease touch"       6 6 1 1 disease-touch-proc))
+(define disarm              (mk-ability "disarm"              4 2 2 1 disarm))
+(define heal-ability        (mk-ability "heal"                1 1 1 2 heal-proc))
+(define great-heal-ability  (mk-ability "great heal"          4 4 2 2 great-heal-proc))
+(define cast-fire-field     (mk-ability "cast fire field"     3 3 2 1 cast-fire-field-proc))
+(define cast-poison-field   (mk-ability "cast poison field"   3 3 2 1 cast-poison-field-proc))
+(define cast-sleep-field    (mk-ability "cast sleep field"    3 3 2 1 cast-sleep-field-proc))
+(define cast-energy-field   (mk-ability "cast energy field"   4 4 2 1 cast-energy-field-proc))
+(define cast-magic-missile  (mk-ability "cast magic missile"  1 1 1 6 cast-magic-missile-proc))
+(define cast-poison-missile (mk-ability "cast poison missile" 2 2 1 6 cast-poison-missile-proc))
+(define cast-fireball       (mk-ability "cast fireball"       3 3 1 6 cast-fireball-proc))
+(define cast-kill           (mk-ability "cast kill"           7 7 2 4 cast-kill-proc))
+(define cast-acid-missile   (mk-ability "cast acid missile"   4 4 1 4 cast-acid-missile-proc))
+(define web-spew            (mk-ability "spew web"            4 4 2 5 web-spew-proc))
+(define teleport            (mk-ability "teleport"            6 6 2 0 teleport-proc))
+(define summon-skeleton     (mk-ability "summon skeleton"     6 6 4 0 summon-skeleton-proc))
+(define summon-slimes       (mk-ability "summon slimes"       2 2 3 0 summon-slime-proc))
+(define summon-demon        (mk-ability "summon demon"        8 8 6 0 summon-demon-proc))
+(define summon-wolves       (mk-ability "summon wolves"       4 4 2 0 summon-wolf-proc))
+(define summon-ratlings     (mk-ability "summon ratlings"     1 2 4 0 summon-ratling-proc))
+(define chomp-deck          (mk-ability "chomp deck"          2 4 3 1 chomp-deck-proc))
+(define deck-to-sludge      (mk-ability "chomp deck"          1 1 1 1 deck-to-sludge-proc))
+(define enslave             (mk-ability "enslave"             3 4 2 4 enslave-proc))
+(define narcotize           (mk-ability "narcotize"           5 6 3 0 narcotize-proc))
+(define cast-fire-wind      (mk-ability "fire wind"           6 6 2 9 fire-wind-proc))
+(define turn-invisible      (mk-ability "turn invisible"      7 7 2 0 turn-invisible-proc))
+(define cast-lightning-bolt (mk-ability "lightning bolt"      4 4 2 9 lightning-bolt-proc))
+
+;;----------------------------------------------------------------------------
+;; Abilities listed by various attributes
+;;----------------------------------------------------------------------------
+
+(define melee-spells
+  (list cast-fire-field
+        cast-sleep-field
+        cast-poison-field
+        cast-energy-field))
+
+(define all-field-spells
+  (list cast-fire-field
+        cast-poison-field
+        cast-sleep-field
+        cast-energy-field
+        ))
+
+;; ranged-spells -- damaging spells which take a target kchar as an arg.
+(define fireball-spell cast-fireball)
+(define poison-missile-spell cast-poison-missile)
+(define acid-missile-spell cast-acid-missile)
+(define kill-spell cast-kill)
+(define all-ranged-spells
+  (list 
+   cast-magic-missile
+   poison-missile-spell
+   fireball-spell
+   cast-fire-wind
+   cast-acid-missile
+   cast-lightning-bolt
+   ))
+
diff --git a/worlds/haxima-1.002/absalot.scm b/worlds/haxima-1.002/absalot.scm
new file mode 100644 (file)
index 0000000..de219e4
--- /dev/null
@@ -0,0 +1,98 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_absalot 41 36 pal_expanded
+ (list
+               "tt tt tt tt tc .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. cc .. .. .. .. .. .. .. .. .. .. .. .. .. ta tt tt tt tt tt "
+               "tt xx xx xx xx xx xx xx xx xx xx xx xx .. .. .. xx xx xx xx .. cc .. xx xx xx xx .. .. %7 .. .. .. .. .. t% ta tt tt tt tt "
+               "tt xx ,, xx xx xx xx xx xx xx xx xx xx .. .. .. xx ,, ,, xx .. cc .. xx ,, ,, xx .. %b %% %d .. .. .. .. .. .. .. t% ta tt "
+               "tt xx ?? xx .L .I .B .R .A .R .Y xx xx xx .. .. xx ,, .. .. .. cc .. ,, ,, ,, xx .. .. %e .. .. .. .. .. .. .. .. .. t% ta "
+               "tc rr ,, ,, ,, ,, tt ,, ,, .. ,, ,, ,, xx .. .. xx xx xx .. .. cc .. xx xx xx xx .. .. .. xx xx xx xx xx xx xx xx xx .. .. "
+               ".. xx ,, ,, ,, t3 tt td ,, ,, ,, ,, ,, rr .. .. .. .. .. .. .. cc .. .. .. .. .. .. .. xx bb .A .C .A .D .E .M .Y xx xx .. "
+               ".. xx .. ,, 00 te ,, 00 ,, .. 00 ,, ,, xx .. .. xx xx rr rr .. cc .. xx xx xx .. .. .. bb ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. "
+               ".. xx ,, ,, 00 ,, ,, 00 ,, ,, 00 ,, ,, xx .. .. xx ,, ,, rr .. cc .. ,, ,, ,, xx .. .. xx rr ,, ,, ,, ,, .. ,, ,, ,, xx .. "
+               ".. xx ,, ,, 00 ,, ,, 00 ,, .. 00 ,, ,, xx .. .. xx ,, ,, ,, .. cc .. xx ,, ,, xx .. .. xx ,, ,, 00 ,, ,, ,, 00 ,, ,, xx .. "
+               ".. rr ,, ,, .. ,, ,, 00 ,, ,, 00 ,, ,, rr .. .. xx xx .. xx .. cc .. bb xx xx xx .. .. xx ,, .. .. ,, ,, ,, 00 ,, ,, xx .. "
+               ".. xx ,, ,, 00 ,, ,, 00 ,, ,, 00 ,, ,, rr .. .. .. .. .. .. .. cc .. .. .. .. .. %7 .. xx ,, ,, 00 00 00 00 00 ,, ,, xx .. "
+               ".. tC t7 ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx tC t7 pp ,, pp ,, ,, cc ,, ,, pp .. %3 %% %% rr ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. "
+               ".. tb tt bb ,, ,, ,, ,, ,, ,, ,, .. ,, xx tb tt td ,, .. ,, ,, cc ,, ,, ,, .. %a %% .. rr .. ,, ,, .. ,, ,, rr ,, ,, xx .. "
+               ".. t% ta td xx xx xx ,, .. xx xx xx rr xx t% te pp ,, ,, ,, ,, cc ,, ,, ,, ,, .. %e .. rr rr xx xx xx ,, rr xx xx xx xx .. "
+               ".. .. .. .. .. .. .. cc .. .. .. .. .. .. .. .. .. .. ,, ,, .. cc cc ,, ,, ,, ,, .. .. .. .. .. .. .. cc .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ,, ,, cc cc cc cc cc cc cc ,, ,, .. .. .. .. .. .. .. cc .. .. .. .. .. .. "
+               "cc cc cc cc cc .. cc cc cc cc cc cc .. cc cc cc cc cc cc .F .O .R .U .M cc cc cc cc cc cc cc .. cc cc .. cc cc cc cc cc cc "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ,, ,, cc cc .. cc cc cc cc ,, ,, .. .. .. .. cc .. .. .. .. .. bb .. .. bb "
+               "%5 .. .. .. xx xx ,, xx .. .. xx xx ,, xx .. .. ,, ,, ,, .. cc cc cc ,, ,, ,, ,, .. .. .. xx ,, rr xx ,, xx .. .. .. .. .. "
+               "%% %5 .. .. xx ,, ,, xx .. .. xx .. ,, xx .. .. pp ,, ,, .. .. cc ,, .. ,, ,, pp .. .. xx ,, ,, xx ,, .. xx tC t7 tA .. bb "
+               "%% %% .. .. xx ,, ,, rr %5 .. xx ,, ,, xx .. .. ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, .. .. xx .. ,, xx ,, .. .. tb tt td .. .. "
+               "%% %% .. .. xx xx rr rr %% .. xx xx xx xx t7 tA .. ,, pp ,, ,, cc ,, ,, pp ,, pp .. .. rr xx xx .. .. .. xx .. bb .. .. bb "
+               "%% %% %5 .. .. .. .. %% %c .. .. .. .. tb tt td .. .. .. .. .. cc .. .. .. .. .. tC t7 tA .. .. .. .. .. .. .. .. .. .. .. "
+               "%% %% %c .. %3 %% %% %% .. .. .. .. .. t% te t# .. .. .. .. .. cc tC t7 tA .. .. tb tt td .. .. .. .. .. .. .. bb .. .. bb "
+               "%% %c .. .. %a %% %% %% .. .. .. xx xx xx xx bb xx rr .. .. .. cc tb tt td tA .. bb tt bb .. bb .. bb .. .. .. .. .. .. .. "
+               "%% .. .. .. .. %a %% %c .. .. xx .. ,, ,, ,, ,, ,, xx xx .. .. cc t% te tF t7 bb .G .A .R .. .E .N .S bb .. .. bb .. .. bb "
+               "%% .. %3 %5 .. .. %% .. .. .. xx .M .. .G .I .C .K .S xx .. .. cc .. t% tb tt td .. .. tt tt tt .. .. .. .. .. .. .. .. .. "
+               "%% %% %% %% %5 .. %% %5 .. .. xx ,, ,, ,, ,, ,, ,, ,, sA .. .. bb .. .. bb te bb .. t3 tt tt tt t5 .. bb .. bb .. .. .. bb "
+               "%% %% %% bb %% %% %% %% %5 .. xx ,, ,, ,, .. ,, ,, ,, ,, cc cc .. .. .. .. .. .. .. ta tt tt tt tt tA .. .. .. .. .. .. .. "
+               "%% %% %% %% ~5 %% %% %% %c .. xx ,, ,, ,, ,, ,, .. .. xx .. .. cc .. .. .. .. .. .. t% tt tt tt tt tt tt t5 tA .. .. bb .. "
+               "%% bb %% ~3 ~~ %% %% bb .. .. .. .F .U .T .U .R .E .S xx .. .. cc .. .. .. %3 %% %5 .. ta tt tt tt tt tt tt tt t5 .. .. .. "
+               "%% .. %% ~2 ~~ ~5 %% %% .. .. xx xx ,, ,, ,, ,, ,, xx xx .. .. cc bb .. bb %% bb %% %5 .. t% ta tt tt bb tt bb tt bb tC t3 "
+               "%% bb %% ~a ~8 ~c %% bb .. .. %a xx xx .. aa ,, xx xx .. %7 .. cc .. %3 %% %% %% %% %% %5 .. t% tt tt tt tt tt tt tt tt tt "
+               "%% %% %% %% %% %% %% %c .. %7 .. %% xx ,, ,, ,, xx %% %% %% .. .. .. %% %% %% %% %% %% %% %5 .. tt bb tt tt tt tt || || || "
+               "%% %% %% bb %% bb %% .. .. %% .. %% xx xx xx xx xx %% %% %c .. cc .. %a %% %% %% %% %% %% %% bb ta tt tt tt tt || || || || "
+               "%% %% %% %% %% %% %% .. %% %% %% %% %% %% %% %% %% %% %% .. .. cc .. .. %% %% %% %% %% %% %% .. .. t% tt || || || || || || "
+))
+
+;;----------------------------------------------------------------------------
+;; NPC's
+;;----------------------------------------------------------------------------
+
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_absalot     ; tag
+ "Absalot"      ; name
+ s_ruin      ; sprite
+ m_absalot      ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+
+  (put (mk-ladder-down 'p_old_absalot 11 27) 2 2)
+  (put (mk-clock) 12 4)
+  (put (mk-broken-clock s_clock_stopped s_clock_stopped "The clock is broken beyond repair") 34 8)
+  
+  )
+
+ nil ; hooks
+
+ (list  ;; edge entrances
+  (list east  0 16)
+  (list south 21 0) 
+  (list north 21 35)
+  (list west  40 16)
+  (list northeast 7 35)
+  )
+ )
+
+;; corpses
+(put-random-stuff p_absalot
+                  (mk-rect 0 0 41 36)
+                  (lambda (loc)
+                    (or (eqv? (kern-place-get-terrain loc) t_grass)
+                        (eqv? (kern-place-get-terrain loc) t_flagstones)
+                        (eqv? (kern-place-get-terrain loc) t_bog)
+                        (eqv? (kern-place-get-terrain loc) t_cobblestone)
+                        (eqv? (kern-place-get-terrain loc) t_trees)
+                        ))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse) loc))
+                  20)
+
+(mk-place-music p_absalot 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/addons.png b/worlds/haxima-1.002/addons.png
new file mode 100644 (file)
index 0000000..a039902
Binary files /dev/null and b/worlds/haxima-1.002/addons.png differ
diff --git a/worlds/haxima-1.002/adornments.png b/worlds/haxima-1.002/adornments.png
new file mode 100644 (file)
index 0000000..2b33bba
Binary files /dev/null and b/worlds/haxima-1.002/adornments.png differ
diff --git a/worlds/haxima-1.002/ai.scm b/worlds/haxima-1.002/ai.scm
new file mode 100644 (file)
index 0000000..500b3c1
--- /dev/null
@@ -0,0 +1,718 @@
+;;----------------------------------------------------------------------------
+;; procedures for using items or spells on self or others
+
+;; use-potion? -- use potion on self if desired and available
+(define (use-potion? kchar)
+  (or (and (wants-healing? kchar)
+           (has-heal-potion? kchar)
+           (drink-heal-potion kchar))
+      (and (wants-mana? kchar)
+           (has-mana-potion? kchar)
+           (drink-mana-potion kchar))))
+
+(define (use-torch? kchar)
+  (if (not (is-in-darkness? kchar))
+      #f
+      (begin
+        (kern-obj-add-effect kchar ef_weaklight nil)
+        #t)))
+
+(define (use-heal-spell-on-self? kchar)
+  ;;;;(display "use-heal-spell-on-self?")(newline)
+  (and (wants-healing? kchar)
+       (can-use-ability? heal-ability kchar)
+       (use-ability heal-ability kchar kchar)))
+
+(define (use-great-heal-spell-on-self? kchar)
+  ;;;;(display "use-great-heal-spell-on-self?")(newline)
+  (and (wants-great-healing? kchar)
+       (can-use-ability? great-heal-ability kchar)
+       (use-ability great-heal-ability kchar kchar)))
+
+(define (use-spell-on-self? kchar)
+  ;;;;(display "use-spell-on-self?")(newline)
+  (or (use-great-heal-spell-on-self? kchar)
+      (use-heal-spell-on-self? kchar)))
+
+;; use-melee-spell-on-foe? -- randomly select from a list of melee spells and
+;; return #t iff the spell is used
+(define (use-melee-spell-on-foe? kchar ktarg spell-list)
+  (let ((spell (random-select (filter (lambda (spell)
+                                        (can-use-ability? spell kchar))
+                                      spell-list))))
+    (if (null? spell)
+        #f
+        (use-ability spell kchar ktarg))))
+
+(define (use-melee-spell-on-foes? kchar spell-list)
+  (foldr (lambda (val ktarg)
+           (or val
+               (use-melee-spell-on-foe? kchar ktarg spell-list)))
+         #f 
+         (get-hostiles-in-range kchar 1)))
+
+
+(define (use-ranged-spell-on-foe? kchar ktarg spell-list)
+  (if (> (kern-dice-roll "1d20") 10)
+      (let ((abil (random-select (filter (lambda (abil)
+                                           (and (can-use-ability? abil kchar)
+                                                (can-hit? kchar 
+                                                          ktarg 
+                                                          (ability-range abil))))
+                                         spell-list))))
+        (if (null? abil)
+            #f
+            (use-ability abil kchar ktarg)))
+      #f))
+
+(define (use-ranged-spell-on-foes? kchar spell-list)
+  (foldr (lambda (val ktarg)
+           (or val
+               (use-ranged-spell-on-foe? kchar ktarg spell-list)))
+         #f 
+         (all-visible-hostiles kchar)))
+
+(define (use-heal-spell-on? kchar ktarg)
+  ;;(println "use-heal-spell-on?")
+  (or (and (wants-great-healing? ktarg)
+           (can-use-ability? great-heal-ability kchar)
+           (use-ability great-heal-ability kchar ktarg)
+           )
+      (and (wants-healing? ktarg)
+           (can-use-ability? heal-ability kchar)
+           (use-ability heal-ability kchar ktarg)
+           )))
+
+(define (use-heal-spell-on-ally? kchar)
+  ;;(println "use-heal-spell-on-ally?")
+  (and (or (can-use-ability? heal-ability kchar)
+           (can-use-ability? great-heal-ability kchar))
+       (foldr (lambda (val ktarg)
+                (or val
+                    (use-heal-spell-on? kchar ktarg)))
+              #f 
+              (all-in-range (kern-obj-get-location kchar)
+                            2
+                            (all-visible-allies kchar)))))
+
+;;----------------------------------------------------------------------------
+;; procedures for searching for nearby things
+
+(define (get-nearest-patient kchar)
+  (let ((kloc (kern-obj-get-location kchar)))
+    (foldr (lambda (kpatient ktarg)
+             ;;(display "  checking ")(dump-char ktarg)
+             (if (and (wants-healing? ktarg)
+                      (or (null? kpatient)                      
+                          (< (kern-get-distance kloc 
+                                                (kern-obj-get-location ktarg))
+                             (kern-get-distance kloc 
+                                                (kern-obj-get-location kpatient)))))
+                 ktarg
+                 kpatient))
+           nil
+           (all-visible-allies kchar))))
+
+
+;;----------------------------------------------------------------------------
+;; procedures for pursuing or avoiding
+
+(define (avoid-melee? kchar)
+  ;;;;(display "avoid-melee? kchar")(newline)
+  (let ((nearby-foes (get-hostiles-in-range kchar 1)))
+    (if (null? nearby-foes)
+        #f
+        (evade kchar nearby-foes))))
+
+;; This is for medics. A patient is an ally that needs healing. If a patient is
+;; less than 2 tiles away then do nothing. If a patient is more than 2 tiles
+;; away then pathfind toward it.
+(define (move-toward-patient? kchar)
+  (let ((patient (get-nearest-patient kchar)))
+    (if (null? patient)
+        #f
+        (begin
+          ;;(display "selected ")(dump-char patient)
+          (if (in-range? (kern-obj-get-location kchar)
+                         2
+                         patient)
+              #f
+              (pathfind kchar (kern-obj-get-location patient)))))))
+
+
+(define (move-away-from-foes? kchar)
+  ;;(println "move-away-from-foes?")
+  (evade kchar (all-visible-hostiles kchar)))
+
+(define (in-melee-range-of-foes? kchar)
+  (> (length (get-hostiles-in-range kchar 1))
+     0))
+
+;; stuck? -- #t iff kchar cannot safely move to a neighboring tile
+(define (stuck? kchar)
+  ;;(println " stuck?")
+  (let* ((cloc (kern-obj-get-location kchar))
+         (kplace (loc-place cloc))
+         (x (loc-x cloc))
+         (y (loc-y cloc)))
+    (foldr (lambda (x loc)
+             (and x 
+                  (not (is-good-loc? kchar loc))))
+           #t
+           (list (mk-loc kplace (- x 1) y)
+                 (mk-loc kplace (+ x 1) y)
+                 (mk-loc kplace x (- y 1))
+                 (mk-loc kplace x (+ y 1))))))
+  
+
+(define (blink-offset kchar)
+  (let ((origin (kern-obj-get-location kchar)))
+    (loc-add origin
+             (loc-norm (apply loc-add 
+                              (map (lambda (kfoe)
+                                     (loc-diff origin
+                                               (kern-obj-get-location kfoe)))
+                                   (all-visible-hostiles kchar)))))))
+
+(define (choose-blink-loc kchar)
+  (let ((loc (blink-offset kchar)))
+    ;;(println "choose-blink-loc " loc)
+    (if (and (not (null? loc))
+             (not (loc-equal? loc
+                              (kern-obj-get-location kchar)))
+             (passable? loc kchar)
+             (not (is-bad-terrain-at? loc))
+             (not (any-object-types-at? loc all-field-types))
+             (not (occupied? loc)))
+        loc
+        nil)))
+
+(define (choose-random-blink-loc kchar)
+  ;;(println "   choose-random-blink-loc")
+  (random-loc-place-iter (loc-place (kern-obj-get-location kchar))
+                         (lambda (loc)
+                           ;;(println "    check loc" loc)
+                           (and (not (loc-equal? loc
+                                                 (kern-obj-get-location kchar)))
+                                (passable? loc kchar)
+                                (not (is-bad-terrain-at? loc))
+                                (not (any-object-types-at? loc all-field-types))
+                                (not (occupied? loc))
+                                (null? (get-hostiles-in-range-of-loc kchar 3 loc))
+                                ))
+                         3))
+
+(define (blink-away-from-foes kchar)
+  ;;(println " blink-away-from-foes")
+  (if (not (can-use-ability? teleport kchar))
+      #f
+      (let ((loc (choose-random-blink-loc kchar)))
+        ;;(println " blink-away-from-foes:" loc)
+        (if (null? loc)
+            #f
+            (use-ability teleport kchar loc)))))
+
+;; Bandit AI --------------------------------------------------
+
+(define bandit-taunts 
+  (list 
+   "Yer money or yer life!"
+   "Have at 'cher!"
+   "Yer a dead man, ye are!"
+   "Oy!  You!  Gerrout!"
+   "'Ave at 'im, boys!"
+   "Circle round, we've got a dead one!"
+   "Dibs on 'is boots!"
+   "Stranger, meetcha couple my friends..."
+   ))
+
+(define (bandit-taunt kbandit ktarg)
+  (taunt kbandit ktarg bandit-taunts)
+  (npcg-set-taunted! (gob kbandit) #t))
+
+(define (bandit-ai kchar)
+  (let ((ktarg (ai-select-target kchar)))
+    (if (null? ktarg)
+        (ai-wander kchar)
+        (begin
+          (or (npcg-taunted? (gob kchar))
+              (bandit-taunt kchar ktarg))
+          (or (ai-attack-target kchar ktarg)
+              (ai-pathfind-to-target kchar ktarg))))))
+
+;; --------------------------------------------------
+;; sound effects            
+              
+(kern-mk-sound 'npc-sound-bark          "dog_9.wav")
+
+(define (npc-sound ksound prob)
+       (lambda (kobject)
+               (if (< (kern-dice-roll "1d100") prob)
+                       (kern-sound-play-at ksound (kern-obj-get-location kobject))
+               )
+               #f
+       ))
+
+(define npc-dosound-bark (npc-sound npc-sound-bark 8))
+
+;; --------------------------------------------------
+
+(define (animal-ai kchar)
+  (get-off-bad-tile? kchar))
+
+(define (wolf-ai kchar)
+       (or (npc-dosound-bark kchar)
+               (animal-ai kchar)))
+  
+(define (nolight-ai kchar)
+  (or 
+   (get-off-bad-tile? kchar)
+   (use-potion? kchar)
+   ))
+
+(define (std-ai kchar)
+  (or 
+   (get-off-bad-tile? kchar)
+   (use-potion? kchar)
+   (use-torch? kchar)
+   ))
+
+(define (nixie-ai kchar)
+  (nolight-ai kchar))
+
+;; Invoke a summoning ability if allies are outnumbered by a certain amount
+(define (ai-summon kchar ability)
+  (and (can-use-ability? ability kchar)
+       (< (num-visible-allies kchar) (* 2 (num-visible-hostiles kchar)))
+       (use-ability ability kchar)))
+
+(define (use-enslave? kchar)
+  (if (or (not (can-use-ability? enslave kchar))
+          (<= (kern-dice-roll "1d20") 16))
+      #f
+      (let ((hostiles (filter
+                       not-disabled?
+                       (all-visible-hostiles kchar))))
+        (if (null? hostiles)
+            #f
+            (let ((ktarg (nearest-obj kchar hostiles)))
+              (if (not (can-hit? kchar ktarg (ability-range enslave)))
+                  #f
+                  (use-ability enslave kchar ktarg)
+              ))))))
+          
+(define (use-narcotize? kchar)
+  (if (or (not (can-use-ability? narcotize kchar))
+          (<= (kern-dice-roll "1d20") 17))
+      #f
+      (let ((hostiles (filter
+                       not-disabled?
+                       (all-visible-hostiles kchar))))
+        ;;(println " hostiles=" hostiles)
+        (if (null? hostiles)
+            #f
+            (use-ability narcotize kchar)
+            ))))
+          
+(define (goto-post kchar)
+  ;;;;(println "goto-post")
+  (let ((guard (gob kchar)))
+    (if (npcg-has-post? guard)
+        (let ((post (cons (loc-place (kern-obj-get-location kchar))
+                          (npcg-get-post guard))))
+          ;;;;(println "post:" post)
+          (pathfind kchar post)))))
+
+(define (summon-demon? kchar)
+  (if (and (> (kern-dice-roll "1d20") 18)
+           (can-use-ability? summon-demon kchar))
+      (use-ability summon-demon kchar)
+      #f))
+
+(define (summon-wolves? kchar)
+  (if (and (> (kern-dice-roll "1d20") 18)
+           (can-use-ability? summon-wolves kchar))
+      (use-ability summon-wolves kchar)
+      #f))
+
+(define (summon-ratlings? kchar)
+  (cond ((not (can-use-ability? summon-ratlings kchar)) #f)
+        ;;((null? (get-hostiles-in-range kchar 4)) #f)
+        (else
+         (use-ability summon-ratlings kchar))))
+
+(define (turn-invisible? kchar)
+  (and (> (kern-dice-roll "1d20") 14)
+       (not (is-invisible? kchar))
+       (can-use-ability? turn-invisible kchar)
+       (use-ability turn-invisible kchar)))
+
+;;----------------------------------------------------------------------------
+;; spell-sword-ai -- aggressive, selfish fighter that uses magic for combat.
+(define (spell-sword-ai kchar)
+  ;;(display "spell-sword-ai ")(dump-char kchar)
+  (or (std-ai kchar)
+      (use-spell-on-self? kchar)
+      (use-melee-spell-on-foes? kchar melee-spells)
+      (use-ranged-spell-on-foes? kchar all-ranged-spells)))
+
+(define (warlock-ai kchar)
+  ;;(display "warlock-ai ")(dump-char kchar)
+  (or (std-ai kchar)
+      (use-spell-on-self? kchar)
+      (summon-demon? kchar)
+      (use-ranged-spell-on-foes? kchar all-ranged-spells)
+      ))
+
+(define (dryad-ai kchar)
+  (or 
+   (summon-wolves? kchar)
+   (use-narcotize? kchar)
+   (use-ranged-spell-on-foes? kchar all-field-spells)
+      ))
+
+(define (demon-ai kchar)
+  (display "demon-ai ")(dump-char kchar)
+  (or (std-ai kchar)
+      (turn-invisible? kchar)
+      ))
+
+(define (gazer-ai kchar)
+  ;;(display "gazer-ai")(dump-char kchar)
+  (or (std-ai kchar)
+      (use-narcotize? kchar)
+      (use-enslave? kchar)))
+
+(define (shaman-ai kchar)
+  (or (std-ai kchar)
+      (use-heal-spell-on-ally? kchar)
+      (move-toward-patient? kchar)
+      (spell-sword-ai kchar)
+      (move-away-from-foes? kchar)))
+
+(define (priest-ai kchar)
+  (or (std-ai kchar)
+      (and (in-melee-range-of-foes? kchar)
+           (blink-away-from-foes kchar))
+      (spell-sword-ai kchar)))
+
+(define (wisp-ai kchar)
+  (display "wisp-ai ")(dump-char kchar)
+  (or (animal-ai kchar)
+         (use-torch? kchar)
+      (and (wants-healing? kchar)
+           (in-melee-range-of-foes? kchar)
+           (blink-away-from-foes kchar))
+      (use-ranged-spell-on-foes? kchar all-field-spells)
+      ))
+
+(define (generic-ai kchar)
+  (std-ai kchar))
+
+;; Death knights can use Vampiric Touch at L3 and Disease at L6
+(define (death-knight-ai kchar)
+  (or (nolight-ai kchar)
+      (let ((vt (can-use-ability? vampiric-touch kchar))
+            (dis (can-use-ability? disease-touch kchar)))
+        (if (not (or vt dis))
+            #f
+            (let ((victims (get-hostiles-in-range kchar 1)))
+              (if (null? victims)
+                  #f
+                  (if (wants-healing? kchar)
+                      (use-ability vampiric-touch kchar (car victims))
+                      (if (and dis
+                               (>= (kern-dice-roll "1d20") 16))
+                          (use-ability disease-touch kchar (car victims))
+                          #f))))))))
+
+(define (rat-ai kchar)
+  (or (animal-ai kchar)
+      (use-ranged-spell-on-foes? kchar 
+                                 (list disease-touch))))
+
+(define (craven-archer-ai kchar)
+  ;;(println "craven-archer-ai")
+  (or (nolight-ai kchar)
+      (and (stuck? kchar)
+           (in-melee-range-of-foes? kchar)
+           (blink-away-from-foes kchar))))
+
+(define (medik-ai kchar)
+  ;;(println "medik-ai")
+  (or (std-ai kchar)
+      (use-heal-spell-on-ally? kchar)
+      (move-toward-patient? kchar)
+      (move-away-from-foes? kchar)))
+
+;; guard-ai
+(define (try-to-use-disarm kchar)
+    ;;(display "try-to-use-ability")(newline)
+    (if (can-use-ability? disarm kchar)
+        (let ((victims (get-hostiles-in-range kchar 1)))
+          (and (not (null? victims))
+               (>= (kern-dice-roll "1d20") 16)
+               (or (use-ability disarm kchar (car victims))
+                   #t)))
+        #f))
+(define (guard-ai kchar)
+  (or (std-ai kchar)
+      (if (any-visible-hostiles? kchar)
+          (try-to-use-disarm kchar)
+          (goto-post kchar))))
+
+
+;; ranger-ai -- nothing special, but can act like a guard
+(define (ranger-ai kchar)
+  (or (std-ai kchar)
+      (if (any-visible-hostiles? kchar)
+          #f
+          (goto-post kchar)
+          )))
+
+;; A lich will summon undead minions
+(define (lich-ai kchar)
+  (display "lich-ai:") (dump-char kchar)
+  (or (nolight-ai kchar)
+      (ai-summon kchar summon-skeleton)
+      (spell-sword-ai kchar)))
+
+(define (flee kchar)
+  (println (kern-obj-get-name kchar) " flees")
+  (kern-char-set-fleeing kchar #t)
+  )
+
+;; A kraken will chomp through planking to get at its foes. If foes exist, and
+;; they are not in melee range, and the kraken cannot pathfind to them, it will
+;; attempt a directional move toward them. If the move is blocked by deck, the
+;; kraken will destroy the deck, using the given ability. The ability varies by
+;; kraken type to match the expected terrain that the deck should be converted
+;; into.
+(define (generic-kraken-ai kchar ability)
+  (let ((foes (all-visible-hostiles kchar)))
+    (if (null? foes)
+        (flee kchar)
+        (let* ((kfoe (nearest-obj kchar foes))
+               (dest (kern-obj-get-location kfoe)))
+          (if (pathfind kchar dest)
+              #f
+              (if (not (null? (get-hostiles-in-range kchar 1)))
+                  #f
+                  (let* ((cloc (kern-obj-get-location kchar))
+                         (vect (loc-to-delta (loc-diff cloc dest)))
+                         (dest (loc-add cloc vect)))
+                    (if (passable? dest kchar)
+                        (kern-obj-move kchar (loc-x vect) (loc-y vect))
+                        (or (and (is-deck? (kern-place-get-terrain dest))
+                                 (can-use-ability? ability kchar)
+                                 (use-ability ability kchar dest))
+                            (flee kchar)
+                        )))))))))
+
+(define (submerge kchar) 
+  ;;(println "SUBMERGE")
+  (kern-obj-set-submerged kchar #t)
+  )
+
+(define (surface kchar) 
+  ;;(println "SURFACE") 
+  (kern-obj-set-submerged kchar #f)
+  )
+
+(define (generic-kraken-ai kchar ability)
+  (let ((foes (all-visible-hostiles kchar)))
+    (if (null? foes)
+        (begin
+          ;;(println "no foes, flee.")
+          (flee kchar)
+          )
+        (if (not (null? (get-hostiles-in-range kchar 1)))
+            (begin
+              ;;(println "foes in range 1, attack.")
+              (surface kchar)
+              #f)
+            (let* ((kfoe (nearest-obj kchar foes))
+                   (dest (kern-obj-get-location kfoe)))
+              ;;(println "no foes in range, submerging and selecting " (kern-obj-get-name kfoe) " as target...")
+              (submerge kchar)
+              (if (pathfind kchar dest)
+                  (begin
+                    ;;(println " pathfinding...")
+                    #f
+                    )
+                  (let* ((cloc (kern-obj-get-location kchar))
+                         (vect (loc-to-delta (loc-diff cloc dest)))
+                         (dest (loc-add cloc vect)))
+                    ;;(println " can't pathfind...")
+                    (if (passable? dest kchar)
+                        (begin
+                          ;;(println "   moving directly.")
+                          (kern-obj-move kchar (loc-x vect) (loc-y vect))
+                          )
+                        (begin
+                          ;;(println "   trying to chomp...")
+                          (if (and (is-deck? (kern-place-get-terrain dest))
+                                   (can-use-ability? ability kchar)
+                                   (use-ability ability kchar dest))
+                              (begin
+                                ;;(println "    success!")
+                                (surface kchar)
+                                #t)
+                              (begin
+                                ;;(println "    can't chomp, so flee.")
+                                (flee kchar)
+                                )
+                              ))))))))))
+
+;; A kraken will chomp through planking to get at its foes. If foes exist, and
+;; they are not in melee range, and the kraken cannot pathfind to them, it will
+;; attempt a directional move toward them. If the move is blocked by deck, the
+;; kraken will destroy the deck.
+(define (kraken-ai kchar)
+  (generic-kraken-ai kchar chomp-deck))
+
+;; The sludge kraken spawns tentacles.
+(define (sludge-kraken-ai kchar)
+  (define (spawn ktarg)
+    (let* ((lvl (kern-char-get-level kchar))
+           (knpc (spawn-npc 'sludge-tentacle lvl))
+           (loc (pick-loc (kern-obj-get-location ktarg) knpc))
+           )
+      (cond ((null? loc) 
+             (kern-obj-dec-ref knpc)
+             #f)
+            (else
+             (kern-being-set-base-faction knpc 
+                                          (kern-being-get-base-faction kchar))
+             (kern-obj-put-at knpc loc)
+             #t))))
+  (define (spawn-tentacle?)
+    (let ((ktarg (random-select (all-visible-hostiles kchar)))
+          (tentacles (filter is-sludge-tentacle? 
+                             (kern-place-get-beings (loc-place (kern-obj-get-location kchar)))))
+          )
+      ;;(println ktarg tentacles)
+      (cond ((null? ktarg) #f)
+            ((< (length tentacles) 
+                (* 2 (kern-char-get-level kchar)))
+             (spawn ktarg))
+            (else
+             #f))))
+  (or (animal-ai kchar)
+      (spawn-tentacle?)))
+
+;; Sludge kraken tentacles work like sea krakens, but convert deck to sludge
+;; instead of shoals.
+(define (sludge-tentacle-ai kchar)
+  (generic-kraken-ai kchar deck-to-sludge))
+
+;; sea-serpent-ai -- spit fireballs every once in a while
+(define (sea-serpent-ai kchar)
+  (let ((ktarg (nearest-visible-hostile kchar)))
+    (cond ((null? ktarg) #f)
+          (else
+           (and (> (kern-dice-roll "1d20") 14)
+                (use-ranged-spell-on-foes? kchar (list fireball-spell)))))))
+
+;; subtle: like dryads, don't let kernal AI run because hydra's don't move, but
+;; if I give them mmode-none they won't get placed in wilderness combat
+(define (hydra-ai kchar)
+  ;;(display "hydra-ai")(dump-char kchar)
+  (or (ai-summon kchar summon-slimes)
+      (use-ranged-spell-on-foes? kchar (list poison-missile-spell
+                                             acid-missile-spell
+                                             ))
+      ))
+
+(define (dragon-ai kchar)
+  (or (std-ai kchar)
+      (and (> (kern-dice-roll "1d20") 14)
+           (use-ranged-spell-on-foes? kchar 
+                                      (list fireball-spell 
+                                            cast-fire-wind
+                                            )))))
+
+;; townsman-ai -- may be extended in the future to do things like flee from
+;; invaders, for now just do the basics and light up a torch if it gets dark.
+(define (townsman-ai kchar)
+  (std-ai kchar))
+
+;; ratlings fear snakes
+(define (ratling-ai kchar)
+  (define (evade-snakes?)
+    (let ((snakes (filter is-snake? (get-hostiles-in-range kchar 4))))
+      (cond ((null? snakes) #f)
+            (else (evade kchar snakes)))))
+  (or (std-ai kchar)
+      (evade-snakes?)))
+
+(define (ratling-sorcerer-ai kchar)
+  (or (ratling-ai kchar)
+      (summon-ratlings? kchar)
+      (move-away-from-foes? kchar)))
+
+;; snakes eat rats and ratlings, recovering hp
+(define (snake-ai kchar)
+  (define (eat-ratling?)
+    (let ((ratlings (filter is-rat? (get-hostiles-in-range kchar 1))))
+      (cond ((null? ratlings) #f)
+            (else
+             (kern-log-msg (kern-obj-get-name kchar)
+                           " eats "
+                           (kern-obj-get-name (car ratlings)))
+             (kern-obj-remove (car ratlings))
+             (kern-obj-heal kchar 2)
+             #t
+             ))))
+  (or (std-ai kchar)
+      (eat-ratling?)))
+
+;; carabid beetles tunnel through stone
+(define (carabid-ai kchar)
+  ;;(println "carabid-ai")
+  (define (tunnel loc kter)
+    ;;(println "tunnel")
+    (kern-place-set-terrain (kern-obj-get-location kchar) kter)
+    (kern-place-set-terrain loc t_gravel)
+    (kern-obj-relocate kchar loc nil)
+    #t)
+  (define (tunnel?)
+    ;;(println "tunnel?")
+    (let* ((loc (random-neighbor-loc kchar))
+           (kter (kern-place-get-terrain loc)))
+      ;;(println "loc=" loc)
+      (cond ((or (eqv? kter t_wall)
+                 (eqv? kter t_wall_rock))
+             (tunnel loc t_boulder))
+            ((eqv? kter t_boulder) (tunnel loc t_gravel))
+            (else #f))))
+  (or (animal-ai kchar)
+      (tunnel? kchar)))
+
+(define (eat-corpse? kchar)
+  (cond ((wants-healing? kchar)
+         (let ((kcorpse (find-nearest kchar t_corpse)))
+           (cond ((null? kcorpse) #f)
+                 (else
+                  (cond ((loc-equal? (kern-obj-get-location kchar)
+                                     (kern-obj-get-location kcorpse))
+                         (kern-log-msg (kern-obj-get-name kchar) " eats " (kern-obj-get-name kcorpse))
+                         (kern-obj-remove kcorpse)
+                         (kern-obj-heal kchar (kern-dice-roll "1d10+2"))
+                         #t)
+                        (else
+                         (pathfind kchar (kern-obj-get-location kcorpse))
+                         ))))))
+        (else
+         #f)))
+
+;; griffin's recover hp by eating corpses
+(define (griffin-ai kchar)
+  (or (get-off-bad-tile? kchar)
+      (eat-corpse? kchar)))
+
+;; FIXME: need to do something here. Geomancers should be able to do things
+;; like transform terrain, convert boulders into trolls, convert rock walls
+;; into boulders, etc. (Note: the old troll AI is broken, too).
+(define (geomancer-ai kchar)
+  (std-ai kchar))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/alchemist.scm b/worlds/haxima-1.002/alchemist.scm
new file mode 100644 (file)
index 0000000..9394540
--- /dev/null
@@ -0,0 +1,471 @@
+;;----------------------------------------------------------------------------
+;; The Alchemist is numbered among the Wise, but he's not a very nice person.
+;; He's very clever, very greedy and likes to trick people. He is also very
+;; knowledgeable. He knows there is a rune buried in trigrave, and that the
+;; enchanter knows what the runes are for. He also knows that one of then
+;; entrances to the MAN's hideout is in the northwest.
+;;
+;; The Alchemist would be very happy to obtain the blood of a hydra, dragon and
+;; lich. He will also teach the player how to make potions for gold?
+;;----------------------------------------------------------------------------
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Oparine
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_alch
+               (list 0   0  alkemist-shop "idle")
+               (list 2   0  alkemist-bed  "sleeping")
+               (list 8   0  bilge-water-seat-9   "eating")
+               (list 9   0  alkemist-shop "working")
+               (list 12  0  bilge-water-seat-9 "eating")
+               (list 13  0  alkemist-shop "working")
+               (list 17  0  bilge-water-seat-9 "eating")
+               (list 18  0  bilge-water-hall "idle")
+               (list 19  0  sea-witch-shop   "idle")
+               (list 20  0  alkemist-shop "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (alch-mk)
+       (list
+        (mk-quest) ;; dragon
+        #f ;; lich
+        #f ;; hydra
+        ))
+
+
+(define (alchq-dragon gob) (car gob))
+(define (alchq-lich? gob) (cadr gob))
+(define (alchq-hydra? gob) (caddr gob))
+(define (alchq-lich! gob val) (set-car! (cdr gob) val))
+(define (alchq-hydra! gob val) (set-car! (cddr gob) val))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+(define alch-catalog
+  (list
+   (list t_heal_potion             18 "When you run out of Mani or mana in the pitch of battle, these will save your life!")
+   (list t_cure_potion             18 "An Nox may be cheaper, but nothing works better than my cure potions!")
+   (list t_mana_potion             18 "No other potions rejuvenate your mana like mine do!")
+   
+   (list t_poison_immunity_potion  18 "Prevention is better than a cure! With my immunity potions you need never fear poison again!")
+   (list t_invisibility_potion    100 "One quaff of this and your enemies will never find you!")
+   (list t_str_potion             999 "The strength of a troll will be yours with this potion!" )  ;; limited stock would be nice...
+   (list t_dex_potion             999 "Your arrows will fly straight as truth when you drink this potion!")  ;; limited stock would be nice...
+   (list t_int_potion             999 "The wise man seeks more wisdom! With this potion, it can be yours for a very reasonable price!")  ;; limited stock would be nice...
+   (list t_info_potion            150 "The sage said to 'Know thyself'. This potion will help!")
+   
+   (list t_oil                      6 "Hurl fire at your foes! Protect your flanks or cover your retreat with flaming fields of death!")
+   (list t_slime_vial              25 "More fun than a barrel of monkeys! Confound your foes with a multiplying army of slimes!")
+   ))
+
+(define alch-merch-msgs
+  (list "I'm afraid my shop is closed now. Come by between 9:00AM to 5:00PM."
+        "I'm sure I have something you'll like! [He rubs his hands briskly]"
+        "I sometimes buy used goods... at a discount of course."
+        "Yes, let's get down to business!"
+        "You'll be back for more when you see for yourself how good my potions are!"
+        "I hope you don't regret passing up these fine potions."
+        "I can probably find some use for these."
+        "I doubt you'll find a better offer anywhere else."
+        "A pleasure doing business with you!"
+        "Perhaps next time."
+        ))
+
+;; Basics...
+(define (alch-hail knpc kpc)
+  (say knpc "[You meet a short, fat old man with a long nose] "
+       "Hello and welcome, Traveler!"))
+
+(define (alch-default knpc kpc)
+  (say knpc "I'm afraid I can't help you with that."))
+
+(define (alch-name knpc kpc)
+  (say knpc "I'm known as the Alchemist.")
+  (quest-data-update 'questentry-alchemist 'found 1)
+  (quest-data-complete 'questentry-alchemist)
+  )
+
+(define (alch-join knpc kpc)
+  (say knpc "Too busy! And far too old for adventures."))
+
+(define (alch-job knpc kpc)
+  (say knpc "I make potions, dabble in mysteries, that sort of thing. "
+       "If you want to buy something just say so!"))
+
+(define (alch-bye knpc kpc)
+  (say knpc "Farewell! Come back again soon!"))
+
+;; Trade...
+(define (alch-trade knpc kpc) (conv-trade knpc kpc "trade" alch-merch-msgs alch-catalog))
+(define (alch-buy knpc kpc) (conv-trade knpc kpc "buy" alch-merch-msgs alch-catalog))
+(define (alch-sell knpc kpc) (conv-trade knpc kpc "sell" alch-merch-msgs alch-catalog))
+
+;; Rune...
+;; offered: shown k rune
+;; accepted: sent to find p rune
+;; done: known to have found p rune
+(define (alch-dragon-reward knpc kpc)
+  (say knpc "Oh, yes, the rune...")
+       (prompt-for-key)
+  (say knpc
+          "The paladins have built several fortifications in the "
+          "deeps of Kurpolis. One of the runes was buried in the "
+          "foundations of the deepest fort.")
+       (prompt-for-key)
+  (say knpc
+          "A pick and shovel may be enough to get it out again, "
+          "but it might be difficult with a dozen paladins breathing "
+          "down your neck.")
+          (quest-data-assign-once 'questentry-rune-p)
+          (quest-rune-p-update)
+          )
+          
+(define (alch-dragon-done knpc kpc)
+  (say knpc "I am afraid I dont know the locations of the other "
+                                       "runes. Try asking the rest of the Wise."))
+               
+(define (alch-dragon-quest knpc kpc qstat)
+       (if (kern-conv-get-yes-no? kpc)
+               (cond
+                       ((quest-done? qstat)
+                               (alch-dragon-done knpc kpc)
+                               )
+                       ((in-inventory? kpc t_rune_p)
+                               (quest-done! qstat #t)
+                               (say knpc "I see you have collected the Rune of Power.")
+                               (alch-dragon-done knpc kpc)
+                               )
+                       ((quest-accepted? qstat)
+                               (alch-dragon-reward knpc kpc qstat)
+                               )
+                       ((in-inventory? kpc t_dragons_blood 1)
+                         (begin
+                               (say knpc "I know where ones is buried, "
+                                        "and I'll tell you in exchange for that vial of "
+                                        "dragon's blood you're carrying. Deal?")
+                               (if (kern-conv-get-yes-no? kpc)
+                                       (begin
+                                                 (quest-accepted! qstat #t)
+                                                 (kern-obj-remove-from-inventory kpc 
+                                                                                                                 t_dragons_blood 
+                                                                                                                 1)
+                                                 (kern-obj-add-to-inventory knpc
+                                                                                                        t_dragons_blood
+                                                                                                        1)
+                                                 (say knpc "[He eyes the vial hungrily] "
+                                                          "Yes! It's just what I need!")
+                                                       (quest-data-update 'questentry-dragon 'done 1)
+                                                       (quest-data-complete 'questentry-dragon)
+                                                       (quest-data-assign-once 'questentry-dragon)
+                                                 (alch-dragon-reward knpc kpc))
+                                       (begin
+                                               (say knpc "Well, I suppose if you dig up the "
+                                               "whole Shard you'll someday find it without "
+                                               "my help. Good luck!")
+                                               (quest-data-assign-once 'questentry-dragon)
+                                       ))
+                               ))
+                       (#t
+                               (say knpc "Then perhaps we can exchange favors. "
+                                  "I happen to know where one of these runes "
+                                  "is buried. I'll tell you its location if you "
+                                  "bring me a vial of dragon's blood. ")
+                               (quest-data-assign-once 'questentry-dragon)))
+               (say knpc "Well, if you are, I happen to know where one is "
+                  "hidden.")))
+
+(define (alch-more knpc kpc)
+       (let ((qstat (alchq-dragon (gob knpc))))
+               (say knpc "Abe knows more about the runes themselves. Are you "
+                       "interested in finding the others?")
+               (quest-data-update-with 'questentry-runeinfo 'abe 1 (quest-notify nil))
+               (alch-dragon-quest knpc kpc qstat)
+       ))
+                  
+(define (alch-rune knpc kpc)
+       (if (not (null? (quest-data-getvalue 'questentry-dragon 'rerune)))
+               (alch-more knpc kpc)
+               (begin
+                       (say knpc "[He gets a canny look] Runes, eh? I've seen a few in my time. "
+                          "Have you one to look at?")
+                       (if (kern-conv-get-yes-no? kpc)
+                               (if (in-inventory? kpc t_rune_k 1)
+                                       (begin
+                                         (say knpc "Yes, I see. This once belonged to the Enchanter, "
+                                                  "I believe. I hope you didn't steal it! "
+                                                  "I have seen several more like it, "
+                                                  "but the person you really should speak to "
+                                                  "is Abe.")
+                                                       (quest-data-update 'questentry-dragon 'rerune 1)
+                                                  (quest-data-update-with 'questentry-runeinfo 'abe 1 (quest-notify nil))
+                                         )
+                                       (say knpc "I don't see it. Perhaps you dropped it?"))
+                               (say knpc "I might be able to help if you could show me.")))
+               ))
+
+(define (alch-abe knpc kpc)
+  (say knpc "An old acquaintance of mine. "
+       "Last I heard he was studying the ruins at Green Tower."))
+
+(define (alch-drag knpc kpc)
+  (say knpc "I've never done it personally, but if one wants to obtain some "
+       "dragon's blood my understanding is that one must kill a dragon! "
+       "I hear they're common as cows in the regions of the Fire Sea."
+                       )
+       (quest-data-update-with 'questentry-dragon 'sea 1 (quest-notify nil)))
+
+
+;; The Wise...
+(define (alch-necr knpc kpc)
+  (say knpc "The Necromancer is an old acquaintance of mine. "
+       "Since the razing of Absalot he's retired to the underworld. "
+       "'Tis a pity, but we've lost touch."))
+
+(define (alch-ench knpc kpc)
+  (say knpc "The Enchanter is a great and knowledgable Wizard. "
+       "I'm afraid we don't always see eye-to-eye. "
+       "Lately he's been pre-occupied with the Accursed."
+       ))
+
+(define (alch-man-reward knpc kpc)
+       (say knpc "In the mountains of "
+          "the northeast, along their southern face, "
+          "there is a secret passage. It is near coordinates "
+          "[92 10]."))
+
+(define (alch-man knpc kpc)
+  (let ((qstat (gob knpc)))
+         (say knpc "I've never met the MAN. "
+                  "Being the most accomplished of Wrogues, "
+                  "he probably has a fortune stashed in his hideout. "
+                  "If I were the adventurous type I might go seek it out myself. "
+                  "What about you?")
+         (if (kern-conv-get-yes-no? kpc)
+               (cond
+                       ((alchq-hydra? qstat)
+                               (say knpc "I've heard, from a reliable source, of an entrance "
+                                       "to the MAN's secret hideout.")
+                               (alch-man-reward knpc kpc))
+                       ((in-inventory? kpc t_hydras_blood 1)
+                               (begin
+                                       (say knpc "I've heard, from a reliable source, of an entrance "
+                                               "to the MAN's secret hideout. I'll tell you in exchange "
+                                               "for that vial of hydra's blood in your pack. Yes?")
+                                       (if (kern-conv-get-yes-no? kpc)
+                                               (begin
+                                                       (alchq-hydra! qstat #t)
+                                                       (kern-obj-remove-from-inventory kpc 
+                                                               t_hydras_blood 
+                                                               1)
+                                                       (kern-obj-add-to-inventory knpc
+                                                               t_hydras_blood
+                                                               1)
+                                                       (say knpc "[He fairly drools over the noxious stuff] "
+                                                               "Oh, lovely... lovely!")
+                                                       (say knpc "Ahem.")
+                                                       (alch-man-reward knpc kpc))
+                                               (say knpc "'Tis a pity. You have no use for the "
+                                                       "vial, and I am too old to go treasure-hunting."))))
+                       (#t 
+                               (say knpc "Well, I do hear many things, many of which are only "
+                                       "rumour. But a reliable source has told me of where to find "
+                                       "an entrance to the MAN's hideout. If you bring me a vial of "
+                                       "hydra's blood I'll disclose it to you.")))
+          (say knpc "For fie, Wanderer! "
+                       "I thought you were the adventurous type."))))
+
+(define (alch-hydr knpc kpc)
+  (say knpc "The hydra is a most difficult foe. "
+       "I understand that striking them only increases their strength! "
+       "But if you do succeed in killing one their blood is quite useful "
+       "to the arcane arts."))
+
+(define (alch-warr knpc kpc)
+  (say knpc "On a few occasions I have met the Warritrix. "
+       "Her ferocity is legendary, "
+       "but I found her to be very calm and gracious in her demeanor. "
+       "I understand she refused to take part in the destruction of "
+       "Absalot."))
+
+(define (alch-engi knpc kpc)
+  (say knpc "I've never met the Engineer, "
+       "I understand he is quite the recluse."))
+
+(define (alch-alch knpc kpc)
+  (say knpc "Yes, that's me. I am the Alchemist.")
+  (quest-data-update 'questentry-alchemist 'found 1)
+  (quest-data-complete 'questentry-alchemist)
+  )
+
+
+;; Absalot...
+(define (alch-absa-reward knpc kpc)
+       (say knpc "There was a fortress overlooking a river of fire. "
+                "Pity it wasn't manned, it might have turned Glasdrin's invasion. "
+                "It will make a perilous crossing if monsters have taken it over.")
+       (prompt-for-key)
+       (say knpc 
+                "There is, however, an older route that bypasses the fortress. "
+                "Probe the east wall of the first cavern, "
+                "you will find a hidden passage.")
+       (prompt-for-key)
+       (say knpc
+                "You will still need to cross the river of fire. "
+                "There is a statue upon the river. Speak the password 'ONUS' to pass unharmed. "
+                "Write that password down!")
+       (prompt-for-key)
+       (say knpc
+                "The passage rejoins the main route near the stairway which leads up to "
+                "the lost city. You won't escape all the hazards of the journey, "
+                "but it should make your life somewhat easier."))
+
+(define (alch-absa knpc kpc)
+  (let ((qstat (gob knpc)))
+    (say knpc "The passage to Absalot was always dangerous even when it was maintained. "
+         "You wouldn't happen to be thinking of going there?")
+    (if (kern-conv-get-yes-no? kpc)
+        (cond
+         ((alchq-lich? qstat)
+          (alch-absa-reward knpc kpc))
+         ((in-inventory? kpc t_lichs_blood 1)
+          (say knpc "In exchange for that vial of lich's blood I'd be "
+               "happy to tell you of a back door. What do you say?")
+          (if (kern-conv-get-yes-no? kpc)
+              (begin
+                (alchq-lich! qstat #t)
+                (kern-obj-remove-from-inventory kpc 
+                                                t_lichs_blood 
+                                                1)
+                (kern-obj-add-to-inventory knpc
+                                           t_lichs_blood
+                                           1)
+                (say knpc "[He grins and winks] Just the stuff I need!")
+                (alch-absa-reward knpc kpc))
+              (say knpc "I see. No doubt you have IMPORTANT plans for "
+                   "that lich's blood. I can always get some from "
+                   "another adventurer.")))
+         (else
+          (say knpc "Bring me a vial of lich's blood and I'll tell you "
+               "a secret way.")))
+        (say knpc "It's just a ruin now anyways. Everything was destroyed "
+             "when it was sacked."))))
+
+(define (alch-sack knpc kpc)
+  (say knpc "Oh yes, didn't you know? Absalot was sacked by the armies "
+       "of Glasdrin, Green Tower and Oparine. Destroyed for its wickedness, "
+       "they say. [He chuckles without humour]"))
+
+(define (alch-esca knpc kpc)
+  (say knpc "Er... did I say that? I can't imagine why. Anyone who escaped "
+       "from Absalot would have the death sentence on their head."))
+
+(define (alch-wick knpc kpc)
+  (say knpc "Yes, Absalot was so wicked that every man, woman and child "
+       "who dwelt there had to be put to the sword. Lucky for us to have "
+       "paladins willing to carry out this righteous work! "
+       "[You detect a hint of irony in his raised eyebrows and innocent "
+       "expression]"))
+
+(define (alch-lich knpc kpc)
+  (say knpc "A lich is an undead wizard. This foul thing corrupts all it "
+       "touches and commands armies of the dead. Its blood has many uses "
+       "in necromancy, which is not my specialty."))
+
+;; The Accursed...
+(define (alch-accu knpc kpc)
+  (say knpc "The so-called Accursed are a secret society blamed for "
+       "many heinous deeds, but who can say how much of that is rumour?"))
+
+;; Townsfolk
+(define (alch-lia knpc kpc)
+  (say knpc "A bewitching creature! "
+       "If I could, I would break her curse. In fact, I would do it for free. "
+       "Call me an old fool!"))
+
+(define alch-conv
+  (ifc basic-conv
+       (method 'default alch-default)
+       (method 'hail alch-hail)
+       (method 'bye alch-bye) 
+       (method 'job alch-job)
+       (method 'name alch-name)
+       (method 'join alch-join)
+
+       (method 'trad alch-trade)
+       (method 'buy  alch-buy)
+       (method 'sell alch-sell)
+       (method 'poti alch-buy)
+
+       (method 'rune alch-rune)
+       (method 'more alch-more)
+       (method 'drag alch-drag)
+
+       (method 'necr alch-necr)
+       (method 'ench alch-ench)
+       (method 'man  alch-man)
+       (method 'hydr alch-hydr)
+       (method 'warr alch-warr)
+       (method 'engi alch-engi)
+       (method 'alch alch-alch)
+
+       (method 'absa alch-absa)
+       (method 'sack alch-sack)
+       (method 'esca alch-esca)
+       (method 'wick alch-wick)
+       (method 'lich alch-lich)
+
+       (method 'accu alch-accu)
+
+       (method 'lia alch-lia)
+       (method 'abe alch-abe)
+
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-alchemist)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_alchemist ;;.....tag
+     "Alchemist" ;;.......name
+     sp_human ;;.....species
+     oc_wright ;;...occupation
+     s_companion_tinker ;;......sprite
+     faction-men ;;..faction
+     0 ;;............custom strength modifier
+     4 ;;............custom intelligence modifier
+     1 ;;............custom dexterity modifier
+     0 ;;............custom base hp modifier
+     0 ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     8  ;;..current level
+     #f ;;...........dead?
+     'alch-conv ;;...conversation (optional)
+     sch_alch ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+     nil ;;..........container (and contents)
+     (list t_dagger
+                               t_armor_leather
+                               )  ;;......... readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (alch-mk)))
diff --git a/worlds/haxima-1.002/alex.scm b/worlds/haxima-1.002/alex.scm
new file mode 100644 (file)
index 0000000..79137e0
--- /dev/null
@@ -0,0 +1,142 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define alex-lvl 8)
+(define alex-species sp_human)
+(define alex-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Paladin's Hold, in the Keep guarding Kurpolis.
+;;----------------------------------------------------------------------------
+(define alex-bed ph-bed3)
+(define alex-mealplace ph-tbl3)
+(define alex-workplace ph-hall)
+(define alex-leisureplace ph-dine)
+(kern-mk-sched 'sch_alex
+               (list 0  0 alex-bed          "sleeping")
+               (list 7  0 alex-mealplace    "eating")
+               (list 8  0 alex-workplace    "working")
+               (list 12 0 alex-mealplace    "eating")
+               (list 13 0 alex-workplace    "working")
+               (list 18 0 alex-mealplace    "eating")
+               (list 19 0 alex-leisureplace "idle")
+               (list 22 0 alex-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (alex-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Alex is a Captain in the Glasdrin Militia, 
+;; serving in the second garrison which guards 
+;; the undead-filled prison level of Kurpolis.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (alex-hail knpc kpc)
+  (say knpc "Welcome, adventurer, and find some measure of safety behind our walls."))
+
+(define (alex-name knpc kpc)
+  (say knpc "I am Captain Alex of the Glasdrin militia."))
+
+(define (alex-job knpc kpc)
+  (say knpc "I am a warmage, and commander of this garrison. Do you mean to pass through our gates?")
+  (if (yes? kpc)
+      (alex-pass knpc kpc)
+      (say knpc "If you change your mind and need the password come ask me.")))
+
+(define (alex-bye knpc kpc)
+  (say knpc "Watch your back out there."))
+
+(define (alex-warm knpc kpc)
+  (say knpc "A warmage specializes in combat spells. You know what my biggest problem is?")
+  (yes? kpc)
+  (say knpc "Finding reagents. Be sure and stock up before traveling any deeper!"))
+
+(define (alex-garr knpc kpc)
+  (say knpc "This is one of three garrisons the militia keeps in Kurpolis. "
+       "The first garrison guards the entrance to Kurpolis to keep monsters from getting to the surface. ")
+  (prompt-for-key)
+  (say knpc "This, the second garrison, manages the prison below and keeps the undead at bay.")
+  (prompt-for-key)
+  (say knpc "The third garrison guards the way to... well, to someplace no one has any business going. ")
+  )
+
+(define (alex-unde knpc kpc)
+  (say knpc "This level of Kurpolis is an ancient keep, mostly controlled by the undead. Do you want to know what I think?")
+  (if (yes? kpc)
+      (say knpc "I think the undead are in the service of a lich.")
+      (say knpc "Then I won't trouble you with my opinion!")))
+
+(define (alex-lich knpc kpc)
+  (say knpc "What is a lich? Why, it's an undead wizard. A lich can command the dead as well as cast all manner of spells. A most troublesome foe."))
+
+(define (alex-pass knpc kpc)
+  (say knpc "The password is deep."))
+
+(define (alex-thir knpc kpc)
+  (say knpc "We've lost contact with the third garrison. "
+       "One of the soldiers from that regiment is in our prison below. "
+       "I'm afraid he is quite insane. The deep places can do that to a man."))
+
+(define (alex-pris knpc kpc)
+  (say knpc "If you want to visit the prison take the ladder down."))
+
+(define (alex-firs knpc kpc)
+  (say knpc "If you want to visit the first garrison take the ladder up, then travel north and then west."))
+
+(define alex-conv
+  (ifc kurpolis-conv
+
+       ;; basics
+       (method 'hail alex-hail)
+       (method 'bye alex-bye)
+       (method 'job alex-job)
+       (method 'name alex-name)
+
+       (method 'warm alex-warm)
+       (method 'garr alex-garr)
+       (method 'comm alex-garr)
+       (method 'lich alex-lich)
+       (method 'pass alex-pass)
+
+       (method 'thir alex-thir)
+       (method 'pris alex-pris)
+       (method 'firs alex-firs)
+       ))
+
+(define (mk-alex)
+  (bind 
+   (kern-mk-char 
+    'ch_alex           ; tag
+    "Alex"             ; name
+    alex-species         ; species
+    alex-occ              ; occ
+    s_companion_wizard     ; sprite
+    faction-men      ; starting alignment
+    2 5 1            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    alex-lvl
+    #f               ; dead
+    'alex-conv         ; conv
+    sch_alex           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_sword
+               t_shield
+               t_leather_helm
+                                                t_armor_leather_2
+                                                )               ; readied
+    )
+   (alex-mk)))
diff --git a/worlds/haxima-1.002/altar-room.scm b/worlds/haxima-1.002/altar-room.scm
new file mode 100644 (file)
index 0000000..02c0380
--- /dev/null
@@ -0,0 +1,35 @@
+(mk-dungeon-room
+ 'p_altar_room "Altar Room"
+ (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx pp ,, ,, ,, pp xx xx xx xx xx xx xx "
+      "xx xx ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, xx xx "
+      "xx xx ,, cc cc cc cc cc cc aa cc cc cc cc cc cc ,, xx xx "
+      "xx xx ,, cc ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, cc ,, xx xx "
+      "xx xx ,, cc ,, xx xx pp ,, cc ,, pp xx xx ,, cc ,, xx xx "
+      "xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx "
+      "xx pp ,, cc ,, pp xx xx vv vv vv xx xx pp ,, cc ,, pp xx "
+      "xx ,, cc cc cc ,, ,, vv vv vv vv vv ,, ,, cc cc cc ,, xx "
+      "xx ,, cc aa cc cc cc vv vv vv vv vv cc cc cc aa cc ,, xx "
+      "xx ,, cc cc cc ,, ,, vv vv vv vv vv ,, ,, cc cc cc ,, xx "
+      "xx pp ,, cc ,, pp xx xx vv vv vv xx xx pp ,, cc ,, pp xx "
+      "xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx "
+      "xx xx ,, cc ,, xx xx pp ,, cc ,, pp xx xx ,, cc ,, xx xx "
+      "xx xx ,, cc ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, cc ,, xx xx "
+      "xx xx ,, cc cc cc cc cc cc aa cc cc cc cc cc cc ,, xx xx "
+      "xx xx ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx pp ,, ,, ,, pp xx xx xx xx ,, ,, xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+ (put (mk-ladder-up 'p_death_knights_hold 17 9) 17 17)
+
+ ;; boss L20 warlock (first time only)
+ (put (mk-npc 'warlock 20) 9 6)
+
+ ;; subservient warlocks (respawn)
+ (put (spawn-pt 'warlock) 9 12)
+ (put (spawn-pt 'warlock) 6 9)
+ (put (spawn-pt 'warlock) 12 9)
+ )
+
+(mk-place-music p_altar_room 'ml-dungeon-adventure)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/amy.scm b/worlds/haxima-1.002/amy.scm
new file mode 100644 (file)
index 0000000..422d8b7
--- /dev/null
@@ -0,0 +1,139 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define amy-lvl 1)
+(define amy-species sp_human)
+(define amy-occ oc_wright)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the Poor House (at least until such time as she joins the Wanderer).
+;;----------------------------------------------------------------------------
+(define amy-bed poorh-bed2)
+(define amy-mealplace poorh-sup2)
+(define amy-workplace poorh-pasture)
+(define amy-leisureplace poorh-dining)
+(kern-mk-sched 'sch_amy
+               (list 0  0 amy-bed          "sleeping")
+               (list 7  0 amy-mealplace    "eating")
+               (list 8  0 amy-workplace    "working")
+               (list 12 0 amy-mealplace    "eating")
+               (list 13 0 amy-workplace    "working")
+               (list 18 0 amy-mealplace    "eating")
+               (list 19 0 amy-leisureplace "idle")
+               (list 22 0 amy-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (amy-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Amy is a female tinker, fallen upon hard times.
+;; She currently dwells in the Poor House.
+;; Amy is a potential party member.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (amy-hail knpc kpc)
+  (meet "You meet a practical-looking tinker woman.")
+  (say knpc "Hello.")
+  )
+
+(define (amy-name knpc kpc)
+  (say knpc "You can call me Amy.")
+  )
+
+(define (amy-join knpc kpc)
+  (if (is-player-party-member? knpc)
+      (say knpc "I already joined you!")
+      (begin
+        (say knpc "I thought you'd never ask!")
+        (join-player knpc)
+        (kern-conv-end)
+        )))
+
+(define (amy-job knpc kpc)
+  (say knpc "Well, I'm a tinker by trade, "
+       "but I haven't had much luck finding work lately.")
+  )
+
+(define (amy-bye knpc kpc)
+  (say knpc "So long.")
+  )
+
+(define (amy-mean knpc kpc)
+  (say knpc "He's great. "
+       "I don't know where I'd go if it weren't for the poor house. "
+       "He doesn't even stare at my boobs all that much.")
+  )
+
+(define (amy-tink knpc kpc)
+  (say knpc "A tinker is a wandering wright. "
+       "We travel from town to town, fixing things up for people.")
+  )
+
+(define (amy-luck knpc kpc)
+  (say knpc "People are nervous of strangers now, "
+       "what with the Accursed and all.")
+  )
+  
+(define (amy-accu knpc kpc)
+  (say knpc "The Accursed are a secret cult who "
+       "follow evil ways.")
+  )
+
+;; Quest-related
+
+(define amy-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'hail amy-hail)
+       (method 'bye amy-bye)
+       (method 'job amy-job)
+       (method 'name amy-name)
+       (method 'join amy-join)
+       
+
+       (method 'mean amy-mean)
+       (method 'tink amy-tink)
+       (method 'luck amy-luck)
+       (method 'accu amy-accu)
+       ))
+
+(define (mk-amy)
+  (bind 
+   (kern-mk-char 
+    'ch_amy           ; tag
+    "Amy"             ; name
+    amy-species         ; species
+    amy-occ              ; occ
+    s_companion_tinker ; sprite
+    faction-men      ; starting alignment
+    2 4 4            ; str/int/dex
+    pc-hp-off  ; hp bonus
+    pc-hp-gain ; hp per-level bonus
+    1 ; mp off
+    1 ; mp gain
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    amy-lvl
+    #f               ; dead
+    'amy-conv         ; conv
+    sch_amy           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list
+     t_armor_leather
+     t_leather_helm
+     t_sling
+     t_sword
+    ))
+   (amy-mk)))
diff --git a/worlds/haxima-1.002/anaxes.scm b/worlds/haxima-1.002/anaxes.scm
new file mode 100644 (file)
index 0000000..2aba8d4
--- /dev/null
@@ -0,0 +1,216 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define anaxes-lvl 6)
+(define anaxes-species sp_lich)
+(define anaxes-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; No schedule (Cave Shrine within Brundegart).
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (anaxes-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Anaxes is the lich/shade of a long-dead wizard, who once served 
+;; Luximene and later rebelled against him.
+;; Anaxes abides in the Cave Shrine within the lost realm of Brundegart.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (anaxes-hail knpc kpc)
+  (meet "[You meet the proud shade of a long-dead wizard]")
+  (say knpc "Art thou the agent of Luximene?")
+  (if (yes? kpc)
+      (say knpc "But who else? [He chuckles grimly] "
+           "Thou hast broken through the defenses, "
+           "but thy foul master will not find me toothless!")
+      (say knpc "Deny it not, I know he seeks to slay me for my rebellion!"))
+  (aside kpc 'ch_nate 
+         "[Whispering] Milord, Luximene has been dead for ages!")
+  )
+
+
+(define (anaxes-default knpc kpc)
+  (say knpc "[He silently regards you]"))
+
+(define (anaxes-name knpc kpc)
+  (say knpc "I am Anaxes, formerly of the Twelve."))
+
+(define (anaxes-luxi knpc kpc)
+  (say knpc "Luximene is not a man, but a demon in a mask! "
+       "He hath sown dissent and conquered in its wake, "
+       "and now seeks to dethrone the gods.")
+  (prompt-for-key)
+  (say knpc "He hath ordered his own image to be erected in the shrines. "
+       "This is too much! Now his perfidy is made plain! ")
+  (prompt-for-key)
+  (say knpc "So long as I draw breath, the Shrine of Brune will not be defiled!")
+  (aside kpc 'ch_nate "Ah! The name of the god at last! I feared it was forgotten forever!")
+  (cond ((has? kpc t_lich_skull 1)
+         (say knpc "Wait! What have you there? [He points to Luximene's skull] What doth this mean? Is Luximene then dead?")
+         (yes? kpc)
+         (say knpc "[He ignores you. The light in his eyes begins to fade and his voice grows weak] It is over...")
+         (prompt-for-key kpc)
+         (say knpc "[He collapses in a heap] ...Isin! ...Isin...")
+         (aside kpc 'ch_nate "Dibs on his boots.")
+         (kern-conv-end)
+         (kern-char-kill knpc))))
+
+(define (anaxes-gods knpc kpc)
+  (say knpc "The gods will take a terrible vengeance on the Shard for its "
+       "faithlessness! Luximene and his followers will be consumed by fire and "
+       "drowned in blood at the last battle! "
+       "Vigilance to the faithful!"))
+
+(define (anaxes-brun knpc kpc)
+  (say knpc "This is the Shrine of Brune, god of vigilance. "
+       "I rebelled against Luximene's order to disgrace it with his image. "
+       "I ordered the entrace to Brune-Guard sealed, and awaited the siege. ")
+  )
+
+(define (anaxes-vigi knpc kpc)
+  (say knpc "We have failed in our vigilance! "
+       "Luximene has deceived us all, and now we must pay the price for failure."))
+
+(define (anaxes-fail knpc kpc)
+  (say knpc "We have failed the gods, it is no wonder they have forsaken us!"))
+
+(define (anaxes-twel knpc kpc)
+  (say knpc "I was among the Twelve Counselors of Luximene. "
+       "To my shame I helped him achieve his empire. "
+       "I thought a strong ruler would bring order to the Shard, "
+       "and rein in the heresies of the Accursed. "
+       "Alas! We were all deceived!"))
+
+(define (anaxes-accu knpc kpc)
+  (say knpc "In the years that followed the Sundering, "
+       "the priesthood became corrupted. "
+       "All manner of wretched men claimed to speak on behalf of the gods, "
+       "polluting the worship of the gods with their foul practices. ")
+  (prompt-for-key)
+  (say knpc "Under Luximene we waged war on the heretics. "
+       "We burned the false priests at the stake and put their "
+       "verminous followers to the sword. "))
+
+(define (anaxes-bye knpc kpc)
+  (say knpc "On thy guard, defiler of the holy! I shall resist you; "
+       "and should I fall in battle, I will strike from beyond the grave!")
+  (aside kpc 'ch_nate "[Muttering] Methinks he is ahead of schedule.")
+  (kern-being-set-base-faction knpc faction-monster)
+  )
+
+(define (anaxes-job knpc kpc)
+  (say knpc "I was one of Luximene's Twelve, trusted with the command of "
+       "this fortress and its watch-tower. "
+       "But Luximene has ordered the desecration of the shrines, "
+       "and I have rebelled!")
+  (aside kpc 'ch_nate 
+         "[Whispering] This lich thinks himself a wizard living in the time of Luximene. Can it be that he once was?")
+  )
+
+(define (anaxes-fort knpc kpc)
+  (say knpc "This fortress is Brune-Guard, so-called for this Shrine of Brune, "
+       "and for the vigilance of the tower. It is virtually impregnable to siege."))
+
+(define (anaxes-towe knpc kpc)
+  (say knpc "The watch-tower of Brune-Guard looks far over the sea, the forest, "
+       "the mountains, and deep into the sky. From time beyond memory, "
+       "from before the Sundering, the vigilant have kept lookout here for "
+       "danger below or signs from above."))
+
+(define (anaxes-sund knpc kpc)
+  (say knpc "The Sundering is the cataclysm that nearly destroyed this world. "
+       "Surely thou dost know this! "
+       "Unless thou art a demon from beyond the void..."))
+
+(define anaxes-conv
+  (ifc nil
+
+       ;; basics
+       (method 'accu anaxes-accu)
+       (method 'assa anaxes-luxi)
+       (method 'bye anaxes-bye)
+       (method 'brun anaxes-brun)
+       (method 'default anaxes-default)
+       (method 'defe anaxes-fort)
+       (method 'fail anaxes-fail)
+       (method 'fait anaxes-vigi)
+       (method 'fort anaxes-fort)
+       (method 'god  anaxes-gods)
+       (method 'gods anaxes-gods)
+       (method 'hail anaxes-hail)
+       (method 'job  anaxes-job)
+       (method 'luxi anaxes-luxi)
+       (method 'mast anaxes-luxi)
+       (method 'name anaxes-name)
+       (method 'rebe anaxes-luxi)
+       (method 'shri anaxes-vigi)
+       (method 'sund anaxes-sund)
+       (method 'towe anaxes-towe)
+       (method 'twel anaxes-twel)
+       (method 'vigi anaxes-vigi)
+       ))
+
+(define (mk-anaxes)
+  (let ((kchar
+         (bind 
+          (kern-char-force-drop
+           (kern-mk-char 
+            'ch_lux          ; tag
+            "Anaxes"         ; name
+            anaxes-species   ; species
+            anaxes-occ       ; occ
+            s_lich           ; sprite
+            faction-men      ; starting alignment
+            0 0 0            ; str/int/dex
+            0 0              ; hp mod/mult
+            0 0              ; mp mod/mult
+            max-health       ; hp
+            -1               ; xp
+            max-health       ; mp
+            0
+            anaxes-lvl       ; level
+            #f               ; dead
+            'anaxes-conv     ; conv
+            nil              ; sched
+            'lich-ai         ; special ai
+            (mk-inventory
+             ;; hack: as the kernel is currently written, he won't drop his
+             ;; readied arms on death, and he won't ready arms from inventory
+             ;; (its all messed up), but he will drop his inventory. So put
+             ;; some decent arms in as loot.
+             (list (list 1 t_armor_chain)
+                   (list 1 t_chain_coif)
+                   (list 1 t_morning_star)
+                   (list 1 t_shield)
+                   (list 3 mandrake)
+                   (list 3 nightshade)
+                   (list 8 sulphorous_ash)
+                   (list 5 blood_moss)
+                   (list 5 black_pearl)
+                   (list 50 t_gold_coins)
+                   (list 1 t_anaxes_letter)
+                   (list 1 t_lichs_blood)
+                   ))
+            ;; readied
+            (list
+             t_armor_chain_4
+             t_chain_coif_4
+             t_morning_star_2
+             t_shield_4
+             )
+            ) ; kern-mk-char
+           #t) ; kern-char-force-drop
+          (anaxes-mk)) ; bind
+         ))
+    (map (lambda (eff) (kern-obj-add-effect kchar eff nil))
+         undead-effects)
+    kchar))
diff --git a/worlds/haxima-1.002/ancient-derelict.scm b/worlds/haxima-1.002/ancient-derelict.scm
new file mode 100644 (file)
index 0000000..ecdb4b4
--- /dev/null
@@ -0,0 +1,65 @@
+(kern-mk-map
+ 'm_ancient_derelict 19 19 pal_expanded
+       (list
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ "
+                       "^^ {{ {{ bb {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {3 {5 {{ {{ ^^ "
+                       "{{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {3 #A bb {5 {{ ^^ "
+                       "{{ {{ {{ {3 {1 {5 {{ {{ {{ ^^ ^^ ^^ {{ {2 ee .. {4 {{ ^^ "
+                       "{{ {{ {3 .. .. #A #r #E {{ ^^ ^^ #A {{ {2 .. ee #C {{ ^^ "
+                       "{1 {1 .. .. .. .. ee ee {{ {{ ^^ {{ {3 .. .. {4 {{ ^^ ^^ "
+                       ".. .. #E .. ee ee ee ee ee {{ {{ {{ ee ee .. #C ^^ ^^ ^^ "
+                       ".. .. bb ee ee ee ee ee ee ee {1 ee ee ee ee #F {1 {5 ^^ "
+                       ".. .. #B .. ee ee ee ee ee ee ee ee ee ee .. ee #C .. {1 "
+                       ".. .. .. .. .. ee ee ee ee ee ee .. .. #D #r .. #C .. .. "
+                       "{8 {8 bb .. #D #r #G #H #D .. #r #r .. .. .. .. .. bb .. "
+                       "{{ {{ {a .. .. .. .. .. .. bb .. .. .. .. .. .. .. .. .. "
+                       "{{ {{ {{ {a {8 {8 .. .. .. .. .. .. .. {8 {8 {8 bb .. .. "
+                       "^^ {{ bb {{ {{ {{ {a {8 .. .. .. .. {c {{ {{ {{ {{ {a {8 "
+                       "^^ ^^ {{ {{ {{ {{ {{ {{ {2 .. .. {c {{ {{ {{ {{ {{ {{ {{ "
+                       "^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {2 .. {4 {{ ^^ ^^ ^^ {{ {{ {{ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {2 .. {4 {{ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+       )
+ )
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_ancient_derelict ; tag
+ "Ancient Derelict"   ; name
+ s_void_ship          ; sprite
+ m_ancient_derelict  ; map
+ #f               ; wraps
+ #f                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ ;; neighbors
+ (list
+  )
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+  (put (spawn-pt 'wisp) 7 9)
+  (put (spawn-pt 'wisp) 10 9)
+  (put (kern-mk-obj t_power_core 1) 12 5)
+  (put (mk-corpse2
+        '(
+         (1 t_staff)
+         (1 t_vas_rel_por_scroll)
+         )) 9 10)
+  
+  )
+
+ (list 'on-entry-to-dungeon-room) ; hooks
+ (list ; edge entrances
+       (list southeast 0 4)
+       (list northeast 0 14)
+ )
+ )
+
+(mk-place-music p_ancient_derelict 'ml-outdoor-adventure)
diff --git a/worlds/haxima-1.002/angela.scm b/worlds/haxima-1.002/angela.scm
new file mode 100644 (file)
index 0000000..0f53026
--- /dev/null
@@ -0,0 +1,189 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; In Glasdrin.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_ange
+               (list 0  0  ga-bed "sleeping")
+               (list 6  0  ghg-s2     "eating")
+               (list 7  0  gpi-counter       "working")
+               (list 11 0  ghg-s2     "eating")
+               (list 12 0  gpi-counter       "working")
+               (list 17 0  ghg-s2     "eating")
+               (list 18 0  gpi-counter "working")
+               (list 23 0  ga-bed "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (ange-mk) (list 'townsman))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Angela is a female innkeeper, who runs the Palisades Inn in Glasdrin.
+;; She is a gracious, mysterious woman.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (ange-hail knpc kpc)
+  (say knpc "[You meet a charming lady] Welcome, traveler."))
+
+(define (ange-default knpc kpc)
+  (say knpc "I'm afraid I don't know."))
+
+(define (ange-name knpc kpc)
+  (say knpc "I am Angela. And you are?")
+  (let ((name (kern-conv-get-string kpc)))
+    (say knpc "I am most pleased to meet you, " name 
+         ". I hope you enjoy your stay in Glasdrin.")))
+
+(define (ange-join knpc kpc)
+  (say knpc "You flatter me! It's been years since I've had a good adventure, "
+       "but I must decline."))
+
+(define (ange-job knpc kpc)
+  (say knpc "I'm the Innkeeper of Glasdrin. "
+       "If you'd like a room just ask!"))
+
+(define (ange-bye knpc kpc)
+  (say knpc "Farewell, traveler, I do hope you come back soon!"))
+
+;; Trade...
+(define (ange-trade knpc kpc)
+  (if (not (string=? "working" (kern-obj-get-activity knpc)))
+      (say knpc "Oh, do please stop by when I'm at my counter! "
+           "The Palisades is open from 7:00AM to 11:00PM. "
+           "I hope to see you then!")
+      (let ((door (eval 'glasdrin-inn-room-1-door)))
+        ;; is the room still open?
+        (if (not (door-locked? (kobj-gob door)))
+            ;; yes - remind player
+            (say knpc "Room 1 is yours until you leave town!")
+            ;; no - ask if player needs a room
+            (begin
+              (say knpc "Do you need a room?")
+              (if (kern-conv-get-yes-no? kpc)
+                  ;; yes - player wants a room
+                  (begin
+                    (say knpc 
+                         "That will be " glasdrin-inn-room-price " gold. "
+                         "The room is yours until you leave town. "
+                         "Is this to your liking?")
+                    (if (kern-conv-get-yes-no? kpc)
+                        ;; yes - player agrees to the price
+                        (let ((gold (kern-player-get-gold)))
+                          ;; does player have enough gold?
+                          (if (>= gold glasdrin-inn-room-price)
+                              ;; yes - player has enough gold
+                              (begin
+                                (say knpc "Wonderful! You're in room 1, "
+                                     "our very best! Enjoy your stay.")
+                                (kern-player-set-gold 
+                                 (- gold 
+                                    glasdrin-inn-room-price))
+                                (send-signal knpc door 'unlock)
+                                (kern-conv-end)
+                                )
+                              ;; no - player does not have enouvh gold)
+                              (say knpc "Oh dear, I'm afraid you don't have "
+                                   "enough gold! I do hope when your fortunes "
+                                   "improve you'll come back and stay." )))
+                        ;; no - player does not agree to the price
+                        (say knpc "I do wish you would stay, "
+                             "I rarely get such intriguing guests!")))
+                  ;; no - player does not want a room
+                  (say knpc "Oh, I am so disappointed, "
+                       "you seem like a very interesting guest! "
+                       "Perhaps another time.")))))))
+
+;; Inn...
+(define (ange-inn knpc kpc)
+  (say knpc "The Palisades is a very fine inn, if I say so myself."))
+
+(define (ange-adve knpc kpc)
+  (say knpc "As you may know, all citizens of Glasdrin must serve a tour of "
+       "duty. I was a quartermaster, and once I even went with the paladins "
+       "on patrol."))
+
+(define (ange-patr knpc kpc)
+  (say knpc "It was a lovely walk, and camping under the stars was grand. "
+       "But then gints attacked and ruined the whole mood."))
+
+(define (ange-gint knpc kpc)
+  (say knpc "Gints are like stocky men but enormous and two-headed. "
+       "They once were common in the mountains, but the vigilance of Glasdrin "
+       "has driven them into caves. They are most fearsome brutes. "
+       "I've seen them hurl grown, heavily armored men like missiles at their "
+       "own comrades!"))
+
+;; Townspeople...
+(define (ange-glas knpc kpc)
+  (say knpc "Glasdrin is a fair city, do you not think so?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Indeed.")
+      (say knpc "No doubt you have seen magnificent cities in your travels. "
+           "I suppose I love it because it is home.")))
+
+(define (ange-patc knpc kpc)
+  (say knpc "Patch is the best healer around. "
+       "He can even call back the recently deceased, "
+       "if their wounds are not too grievous."))
+
+(define ange-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default ange-default)
+       (method 'hail ange-hail)
+       (method 'bye ange-bye)
+       (method 'job ange-job)
+       (method 'name ange-name)
+       (method 'join ange-join)
+       
+       ;; trade
+       (method 'trad ange-trade)
+       (method 'room ange-trade)
+       (method 'buy ange-trade)
+       (method 'sell ange-trade)
+
+       ;; inn
+       (method 'inn  ange-inn)
+       (method 'adve ange-adve)
+       (method 'gint ange-gint)
+       (method 'patr ange-patr)
+
+       ;; town & people
+       (method 'glas ange-glas)
+       (method 'patc ange-patc)
+
+       ))
+
+(define (mk-angela)
+  (bind 
+   (kern-mk-char 'ch_angela          ; tag
+                 "Angela"            ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_townswoman        ; sprite
+                 faction-glasdrin         ; starting alignment
+                 0 1 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'ange-conv          ; conv
+                 sch_ange            ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_dagger)))                 ; container
+                 (list t_dagger
+                                                )                  ; readied
+                 )
+   (ange-mk)))
diff --git a/worlds/haxima-1.002/angriss-lair.scm b/worlds/haxima-1.002/angriss-lair.scm
new file mode 100644 (file)
index 0000000..5c40d53
--- /dev/null
@@ -0,0 +1,229 @@
+;; ----------------------------------------------------------------------------
+;; Map
+;; ----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_angriss_lair 19 19 pal_expanded
+       (list
+               "|| || || || || || || || tt tt tt || || || tt || || || || "
+               "|| || || || || || || || || tt || || || tt tt tt || || || "
+               "|| || || || || || bb bb bb bb || || || bb .. bb || || || "
+               "|| || || || bb bb bb t3 t5 bb bb || bb .. .. .. bb || || "
+               "|| || || bb .. .. t3 || || t5 bb .. .. .. .. .. bb || || "
+               "|| || || bb .. .. ta || || tc .. .. .. .. .. bb || || || "
+               "|| || || bb bb bb .. .. .. .. .. .. .. bb bb || || || || "
+               "|| || || || bb bb .. bb .. .. tC t3 tt t5 bb || || || || "
+               "tt || || || bb || || || bb .. tb || || tt td bb || || tt "
+               "tt tt || || bb || tF || bb .. t% |A || tc t# bb || tt tt "
+               "tt || || || bb || || || bb bb .. .. .. .. bb || || || tt "
+               "|| || || || bb bb bb bb .. .. .. bb .. bb bb bb || || || "
+               "|| || || bb .. tC t3 t5 tA .. .. bb .. || || bb || || || "
+               "|| || || bb .. t3 || || td .. bb .. .. t% || bb || || || "
+               "|| || || bb .. ta || |C t# .. bb .. .. .. .. bb || || || "
+               "|| || || || bb .. .. .. .. bb || bb bb .. bb || || || || "
+               "|| || || || || bb .. bb bb || || || tt tt tt || || || || "
+               "|| || || || || tt tt tt || tt || || || tt || || || || || "
+               "|| || || || || || tt || tt tt tt || || || || || || || || "
+       )
+       
+
+ )
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_angriss_lair ; tag
+ "Entrance to Angriss's Lair"   ; name
+ s_spider_web     ; sprite
+ m_angriss_lair  ; map
+ #f               ; wraps
+ #f                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ ;; neighbors
+ (list
+  )
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+  (put (mk-ladder-down 'p_spider_cave 6 9) 6 9)
+  (put (mk-ladder-down 'p_spider_cave 15 4) 15 4)
+  
+  (put (spawn-pt 'giant-spider faction-spider) 6 9)
+  (put (spawn-pt 'giant-spider faction-spider) 15 4)
+  (put (spawn-pt 'giant-spider faction-spider) 7 4)
+  (put (spawn-pt 'giant-spider faction-spider) 6 13)
+  (put (spawn-pt 'giant-spider faction-spider) 14 12)
+
+  )
+
+ (list 'on-entry-to-dungeon-room
+       'quest-rune-f-lair
+       ) ; hooks
+ nil ; edge entrances
+ )
+
+(mk-place-music p_angriss_lair 'ml-outdoor-adventure)
+
+(kern-load "angriss.scm")
+
+(mk-dungeon-room
+ 'p_angriss_throne_room  "Angriss's Throne Room"
+ (list
+               "rn rn rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn rn rn rn "
+               "rn rn r8 r4 .. .. .. .. .. .. .. .. .. .. r2 rn r8 rn rn "
+               "rn rc .. re .. .. bb .. .. .. .. .. .. .. ra r4 .. ra rn "
+               "r4 .. .. .. .. .. bb bb .. bb bb bb .. .. .. re .. .. r2 "
+               "r4 .. .. .. .. bb .. bb bb bb .. bb r7 .. .. .. .. .. r2 "
+               "r4 .. .. .. bb bb .. .. .. .. bb rb rc bb .. .. .. .. r2 "
+               "rn r5 .. .. bb .. .. bb bb .. .. bb bb .. bb .. .. .. r2 "
+               "rn rc .. bb .. .. bb .. .. .. .. .. bb .. bb bb .. .. r2 "
+               "r4 .. .. bb .. bb .. .. .. .. .. bb .. .. bb .. .. rb rn "
+               "r4 .. .. bb .. .. bb .. .. .. .. .. bb .. bb .. .. .. r2 "
+               "r4 .. .. bb bb .. bb .. .. .. .. .. bb bb .. bb .. .. r2 "
+               "r4 .. .. .. .. .. bb bb .. .. .. bb bb .. .. bb .. .. r2 "
+               "r4 .. .. .. bb rf bb .. bb .. bb .. .. bb bb .. .. .. r2 "
+               "r4 .. .. .. bb bb bb bb bb bb bb .. bb bb bb .. .. .. r2 "
+               "r4 bb .. .. .. bb .. rf bb .. bb .. .. bb .. .. .. .. r2 "
+               "r4 bb bb .. .. .. bb bb bb bb .. bb .. .. .. .. .. .. r2 "
+               "rn rd .. .. .. .. .. .. .. .. .. .. .. .. r7 .. .. bb r2 "
+               "r4 bb bb .. bb .. .. .. .. .. .. .. .. r3 r4 .. bb bb r2 "
+               "rn r1 r1 r1 r1 r1 r5 .. .. .. .. .. r3 rn rn r1 r1 r1 rn "
+  )
+ (put (mk-angriss) 9 9)
+
+ (put (kern-mk-obj F_web_perm 1) 9  6)
+ (put (kern-mk-obj F_web_perm 1) 10 6)
+ (put (kern-mk-obj F_web_perm 1) 7  7)
+ (put (kern-mk-obj F_web_perm 1) 8  7)
+ (put (kern-mk-obj F_web_perm 1) 9  7)
+ (put (kern-mk-obj F_web_perm 1) 10 7)
+ (put (kern-mk-obj F_web_perm 1) 11 7)
+ (put (kern-mk-obj F_web_perm 1) 6  8)
+ (put (kern-mk-obj F_web_perm 1) 7  8)
+ (put (kern-mk-obj F_web_perm 1) 8  8)
+ (put (kern-mk-obj F_web_perm 1) 9  8)
+ (put (kern-mk-obj F_web_perm 1) 10 8)
+ (put (kern-mk-obj F_web_perm 1) 7  9)
+ (put (kern-mk-obj F_web_perm 1) 8  9)
+ (put (kern-mk-obj F_web_perm 1) 9  9)
+ (put (kern-mk-obj F_web_perm 1) 10 9)
+ (put (kern-mk-obj F_web_perm 1) 11 9)
+ (put (kern-mk-obj F_web_perm 1) 7  10)
+ (put (kern-mk-obj F_web_perm 1) 8  10)
+ (put (kern-mk-obj F_web_perm 1) 9  10)
+ (put (kern-mk-obj F_web_perm 1) 10 10)
+ (put (kern-mk-obj F_web_perm 1) 11 10)
+
+ (put (kern-mk-obj F_web_perm 1) 8  11)
+ (put (kern-mk-obj F_web_perm 1) 9  11)
+ (put (kern-mk-obj F_web_perm 1) 10 11)
+
+ (put (kern-mk-obj F_web_perm 1) 9  12)
+
+ (put (kern-mk-obj F_web_perm 1) 11 12)
+ (put (kern-mk-obj F_web_perm 1) 11 13)
+ (put (kern-mk-obj F_web_perm 1) 11 14)
+ (put (kern-mk-obj F_web_perm 1) 12 14)
+ (put (kern-mk-obj F_web_perm 1) 5 6)
+ )
+
+(mk-place-music p_angriss_throne_room 'ml-dungeon-adventure)
+
+;; corpse & treasure heaps
+(put-random-stuff p_angriss_throne_room
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_grass))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  50)
+
+;; spider eggs
+(put-random-stuff p_angriss_throne_room
+                  (mk-rect 6 6 7 7)
+                  (lambda (loc) #t)
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-spider-egg) loc))
+                  20)
+
+
+
+(mk-dungeon-room
+ 'p_spider_cave "Spider Cave"
+       (list
+               "rn r8 r8 r8 r8 r8 rc .. .. .. .. .. r2 rn r8 r8 r8 r8 rn "
+               "r4 bb .. .. .. .. .. .. .. .. .. .. r2 rc bb .. bb bb r2 "
+               "rn r5 .. .. .. .. .. .. .. .. .. r3 rc bb .. .. .. bb r2 "
+               "rn rn r5 .. r7 .. .. .. tC t7 tA r6 .. .. .. .! .. bb r2 "
+               "rn rn rn r9 rn rd .. tC t3 tt t5 r6 .. .. .! .! .! .. r2 "
+               "rn rn rc bb re t3 tt tt tt tt tc r6 bb .. .. .! .. .. r2 "
+               "rn rc .. tC t3 tt tt tt tt tt t# ra r5 bb bb .. .. bb r2 "
+               "r4 .. tC t3 tt tt tt tt tt tt tA .. ra r9 r9 r9 r9 r9 rn "
+               "r4 .. t3 tt tt .! .! .! tt tt t5 tA .. .. bb .. .. .. r2 "
+               "r4 .. tt tt tt .! .! .! tt tt tt td .. .. .. .. .. rb rn "
+               "r4 .. tt tt tt .! .! .! tt tt tc t# .. .. bb .. .. .. r2 "
+               "r4 .. ta tt tt tt tt tt tt tc r7 .. .. .. .. bb .. .. r2 "
+               "r4 .. t% ta tt tc bb ta tc r3 r4 bb .. r3 rd .. .. rb rn "
+               "r4 .. .. t% te rb r1 r1 r9 r8 r8 r9 r9 rc bb rf .. .. r2 "
+               "r4 bb .. rf .. .. ra rc .. .. bb .. .. bb .. .. .. .. r2 "
+               "rn r5 bb .. .. .. .. .. .. .. .. bb .. .. .. .. .. .. r2 "
+               "rn rc .. .. .. bb .. .. .. .. bb .. .. .. .. bb .. bb r2 "
+               "r4 .. .. .. .. .. .. .. r3 r1 r1 r1 r5 .. .. .. .. r3 rn "
+               "rn r1 r1 r1 r1 r1 r1 r1 rn rn rn rn rn r1 r1 r1 r1 rn rn "
+       )
+       
+ (put (mk-ladder-up 'p_angriss_lair 6 9) 6 9)
+ (put (mk-ladder-up 'p_angriss_lair 15 4) 15 4)
+
+ (put (spawn-pt 'queen-spider faction-spider) 9 0)
+ (put (spawn-pt 'queen-spider faction-spider) 15 15)
+ (put (spawn-pt 'queen-spider faction-spider) 1 17)
+
+ ;; meat locker
+ (put (mk-corpse) 15 1)
+ (put (mk-corpse) 12 3)
+ (put (mk-corpse) 12 4)
+ (put (mk-corpse) 16 6)
+ (put (mk-corpse) 17 4)
+ (put (mk-spider-egg) 15 1)
+ (put (mk-spider-egg) 12 3)
+ (put (mk-spider-egg) 12 4)
+ (put (mk-spider-egg) 16 6)
+ (put (mk-spider-egg) 17 4)
+ (put (kern-mk-obj web-type 1) 15 1)
+ (put (kern-mk-obj web-type 1) 12 3)
+ (put (kern-mk-obj web-type 1) 12 4)
+ (put (kern-mk-obj web-type 1) 16 6)
+ (put (kern-mk-obj web-type 1) 17 4)
+ (put (kern-mk-obj web-type 1) 17 5)
+ (put (kern-mk-obj web-type 1) 15 6)
+ (put (kern-mk-obj web-type 1) 13 5)
+ (put (kern-mk-obj t_spell_book_white_magick_2 1) 15 1)
+ (put (kern-mk-obj t_gold_coins 52) 14 2)
+ (put (kern-mk-obj t_gold_coins 34) 17 5)
+ (put (kern-mk-obj t_bow 1) 15 6)
+ (put (kern-mk-obj t_arrow 34) 13 5)
+ (put (kern-mk-obj t_leather_helm 1) 16 2)
+ (put (kern-mk-obj t_halberd 1) 12 3)
+ (put (kern-mk-obj t_heal_potion 3) 15 1)
+ (put (kern-mk-obj t_mana_potion 5) 16 6)
+ (put (kern-mk-obj t_spell_book_force_magick_battle 1) 17 6)
+)
+
+(mk-place-music p_spider_cave 'ml-dungeon-adventure)
+
+(mk-dungeon-level 
+ (list p_angriss_throne_room)
+ (list p_spider_cave)
+ )
diff --git a/worlds/haxima-1.002/angriss.scm b/worlds/haxima-1.002/angriss.scm
new file mode 100644 (file)
index 0000000..f85417b
--- /dev/null
@@ -0,0 +1,234 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define angriss-lvl 20)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; No schedule.  (Angriss' Lair)
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (angriss-mk)
+  (list #f (mk-quest)))
+
+(define (angriss-quest angriss) (cadr angriss))
+(define (angriss-spoke? angriss) (car angriss))
+(define (angriss-spoke! angriss) (set-car! angriss #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Angriss is Queen of the Spiders, dwelling in Angriss' Lair.
+;; Suspicious, jealous, alien.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (angriss-hail knpc kpc)
+  (say knpc "Hideous Soft One, who\n"
+       "comes uninvited, be quick\n"
+       "in honor, or die."))
+
+(define (angriss-default knpc kpc)
+  (say knpc "[Still as a statue in her web, she gives no response]"))
+
+(define (angriss-name knpc kpc)
+  (say knpc "To Men, Angriss; to\n"
+       "the Goblins, Ruka; to the\n"
+       "Trolls, Hibliminos."))
+
+(define (angriss-join knpc kpc)
+  (say knpc "Do lips join a cup\n"
+       "but to drain it dry? My kind\n"
+       "to Men join the same."))
+
+(define (angriss-job knpc kpc)
+  (say knpc "Hunger."))
+
+(define (angriss-bye knpc kpc)
+  (say knpc "The empire of light\n"
+       "Calls you back. Ascend the stair\n"
+       "if you can reach it.\n"))
+
+
+(define (angriss-soft knpc kpc)
+  (say knpc "To drink the dark wine\n"
+       "Men crush the grape. I drink the\n"
+       "wine that's crushed from Men."))
+
+(define (angriss-hung knpc kpc)
+  (say knpc "A river of blood\n"
+       "flows down to my lair, a pile\n"
+       "of bones waxes there."))
+
+(define (angriss-men knpc kpc)
+  (say knpc "So proud in armor\n"
+       "so soft in hidden aspect\n"
+       "so sweet in folly."))
+
+(define (angriss-gobl knpc kpc)
+  (say knpc "A stealthy hunt, a\n"
+       "terrible struggle, in the\n"
+       "end the longest rest."))
+
+(define (angriss-trol knpc kpc)
+  (say knpc "Stone-thrower and rock\n"
+       "beater, your fearsome bellow\n"
+       "will become a scream."))
+
+(define (angriss-choose knpc kpc)
+  (say knpc "Choose whom you will give to me.")
+  (let ((kchar (kern-ui-select-party-member))
+        (quest (angriss-quest (kobj-gob-data knpc))))
+    (if (null? kchar)
+        (begin
+          (say knpc "You toy with a monster, now flee.")
+          (harm-relations knpc kpc)
+          (harm-relations knpc kpc)
+          (kern-conv-end))
+        (if (is-dead? kchar)
+            (begin
+              (say knpc "FRESH meat I require!\n"
+                   "Poison! Foul, is that dead blood!\n"
+                   "Bring me another.")
+              (kern-conv-end))
+            (begin
+              (say knpc "Honor is satisfied.\n")
+              (if (not (quest-done? quest))
+                  (quest-done! quest #t))
+              (kern-char-leave-player kchar)
+              (kern-being-set-base-faction kchar faction-none)
+              (improve-relations knpc kpc)
+              (kern-conv-end))))))
+
+
+(define (angriss-rune knpc kpc)
+  (let ((quest (angriss-quest (kobj-gob-data knpc))))
+    (if (quest-done? quest)
+        (begin
+          (say knpc "The ancient secret,\n"
+               "The key to a lock of hell.\n"
+               "Take it, it is thine.")
+          (kern-obj-remove-from-inventory knpc t_rune_f 1)
+          (kern-obj-add-to-inventory kpc t_rune_f 1)
+          (rune-basic-quest 'questentry-rune-f s_runestone_f)
+         )
+        (say knpc "I know what you seek.\n"
+             "But I wonder, do you? First,\n"
+             "satisfy honor."))))
+
+(define (angriss-sacr knpc kpc)
+
+  (define (player-alone?)
+    (< (num-player-party-members) 
+       2))
+
+  (let ((quest (angriss-quest (kobj-gob-data knpc))))
+
+    (define (refused)
+      (say knpc "Flee from my presence.\n"
+           "You may escape my wrath, but\n"
+           "You will not return.")
+      (harm-relations knpc kpc)
+      (harm-relations knpc kpc)
+      (kern-conv-end))
+
+    (define (offer-quest)
+      (display "offer-quest")(newline)
+      (if (player-alone?)
+          (begin
+            (say knpc "You will find, if you\n"
+                 "seek, a fool to join you. Bring\n"
+                 "that fool unto me.\n"
+                 "...Agreed?")
+            (if (kern-conv-get-yes-no? kpc)
+                (begin
+                  (quest-accepted! quest)
+                  (improve-relations knpc kpc)
+                  (improve-relations knpc kpc))
+                (refused)))
+          (begin
+            (say knpc "Among your party\n"
+                 "Choose one as a sacrifice\n"
+                 "and you will go free.\n"
+                 "...Agreed?")
+            (if (kern-conv-get-yes-no? kpc)
+                (angriss-choose knpc kpc)
+                (refused)))))
+            
+    (if (quest-done? quest)
+        (say knpc "It is done.")
+        (if (quest-accepted? quest)
+            (if (player-alone?)
+                (say knpc "Alone you come back.\n"
+                     "Where is the sacrifice that\n"
+                     "will keep you from doom?")
+                (choose-victim))
+            (offer-quest)))))
+
+
+(define (angriss-hono knpc kpc)
+  (say knpc "I demand honor\n"
+       "and sacrifice. Give them to\n"
+       "me, or flee, or die."))
+
+(define angriss-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default angriss-default)
+       (method 'hail angriss-hail)
+       (method 'bye angriss-bye)
+       (method 'job angriss-job)
+       (method 'name angriss-name)
+       (method 'join angriss-join)
+       
+       (method 'soft angriss-soft)
+       (method 'hung angriss-hung)
+       (method 'rune angriss-rune)
+       (method 'men angriss-men)
+       (method 'gobl angriss-gobl)
+       (method 'trol angriss-trol)
+       (method 'sacr angriss-sacr)
+       (method 'hono angriss-hono)
+       ))
+
+(define (angriss-ai kchar)
+  (if (angriss-spoke? (kobj-gob-data kchar))
+      (spider-ai kchar)
+      (begin
+        (angriss-spoke! (kobj-gob-data kchar))
+        (kern-conv-begin kchar))))
+
+(define (mk-angriss)
+  (bind 
+   (kern-char-force-drop
+    (kern-mk-char 
+     'ch_angriss         ; tag
+     "Angriss"           ; name
+     sp_queen_spider     ; species
+     nil                 ; occ
+     s_purple_spider     ; sprite
+     faction-spider ; starting alignment
+     20 0 20             ; str/int/dex
+     10 5                ; hp mod/mult
+     10 5                ; mp mod/mult
+     max-health ;;..current hit points
+     -1 ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     angriss-lvl
+     #f                  ; dead
+     'angriss-conv       ; conv
+     nil                 ; sched
+     'angriss-ai          ; special ai
+     
+     ;;..........container (and contents)
+     (mk-inventory (list (list 1 t_rune_f)))
+     nil                 ; readied
+     )
+    #t)
+    (angriss-mk)))
diff --git a/worlds/haxima-1.002/ankh-shrine.scm b/worlds/haxima-1.002/ankh-shrine.scm
new file mode 100644 (file)
index 0000000..0bcba20
--- /dev/null
@@ -0,0 +1,114 @@
+(kern-mk-map 
+ 'm_ankh_shrine 19 19 pal_expanded
+ (list
+       "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn  "
+       "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn  "
+       "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn  "
+       "rn rn rn rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn rn rn rn  "
+       "rn rn rn rn rc *3 *1 *1 *1 *1 *1 *1 *1 *5 ra rn rn rn rn  "
+       "rn rn rn r4 *3 ** *. *8 *8 *8 *8 *8 ** *. *5 r2 rn rn rn  "
+       "rn rn rn r4 *2 ** xx xx xx xx xx xx xx ** *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *4 xx pp ,, ,, ,, pp xx *2 *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *4 xx ,, cc cc cc ,, xx *2 *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *4 xx ,, cc cc cc ,, xx *2 *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *4 xx ,, cc cc cc ,, xx *2 *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *4 xx pp ,, cc ,, pp xx *2 *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *. xx xx ,, cc ,, xx xx *. *4 r2 rn rn rn  "
+       "rn rn rn r4 *a *. ** *5 ,, cc ,, *3 ** *. *c r2 rn rn rn  "
+       "rn rn rn rn r5 *a ** *4 ,, cc ,, *2 *. *c r3 rn rn rn rn  "
+       "rn rn rn rn rn r5 ** *4 ,, cc ,, *2 *. r3 rn rn rn rn rn  "
+       "rn rn rn rn rn r4 *2 *4 ,, cc ,, *2 *4 r2 rn rn rn rn rn  "
+       "rn rn rn rn rn r4 *2 *4 ,, cc ,, *2 *4 r2 rn rn rn rn rn  "
+       "rn rn rn rn rn r4 ** ** ,, cc ,, ** *. r2 rn rn rn rn rn  "
+  ))
+
+
+;;----------------------------------------------------------------------------
+;; Include files
+;;----------------------------------------------------------------------------
+(kern-load "talking-ankh.scm")
+(kern-load "demon-gate.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_ankh_shrine     ; tag
+ "Ankh Shrine"      ; name
+ s_shrine      ; sprite
+ m_ankh_shrine      ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+  (put (mk-talking-ankh) 9 9)
+  )
+  nil ; hooks
+ (list  ;; edge entrances
+  (list east  9 18)
+  (list south 9 18) 
+  (list north 9 18)
+  (list west  9 18)
+  )
+ )
+
+(mk-place-music p_ankh_shrine 'ml-outdoor-adventure)
+
+;; Make the actual get location to the west
+(kern-mk-map
+ 'm_demon_gate 19 19 pal_expanded
+ (list
+                "*2 ** ** *. *. *. dd .. tb || || || td .. %% .. tt || || "
+                "*2 ** *. *. ** *. *5 dd t% ta || tc t# %3 %% %5 t% ta || "
+                "*2 *. *. *. *. *. ** *d dd tD te t# %3 %% _7 %% %5 t% tt "
+                "*2 *. *. *c dd dd *e dd .. t7 t# %3 %% _b __ _d %% %5 .. "
+                "*2 *c dd dd .. .. dd .. t. tt .. %a %% %% _e %% %% %c .. "
+                "*2 dd .. .. ar t. .. t. ar t. t. .. %a %% %% %% %c tC tt "
+                "*6 dd .. t. t. .. tf .. t. |. t. t. .. %a %% %c tC t3 || "
+                "*. dd ar .. tt .. bb .. .. t. ar t. t. .. %% .. t3 || || "
+                "*. dd .. tf bb t. .. t. .. .. t. |. t. .. %% .. te .. t. "
+                "*. *d dd .. t. .. {f .. t. .. .. tt .. %b gg %d .. t. .. "
+                "*. dd .. tf .. t. .. t. .. .. t. |. t. .. %% .. .. .. t. "
+                "*. dd ar tD t7 .. t. bb .. t. ar t. t. .. gg .. tb || || "
+                "*6 dd .. t3 tc tA .. .. t. |. t. tt t. .. gg %5 tD tt || "
+                "*6 dd .. tt ar t7 .. t. ar t. tt t& tt t. tt gg t3 tt || "
+                "*6 dd .. te .. te tA .. t. tt t# dd .. t. tt gg tt tt || "
+                "*6 dd dd .. dd t% tb tt tt t# dd *7 dd .. te .. ta || || "
+                "*2 dd dd dd *7 dd .. .. .. dd *b ** *d dd .. dd t% ta || "
+                "*2 *5 dd *3 ** *5 dd dd .. .. dd *e dd .. dd *7 dd t% tt "
+                "*2 *. *. *. *. ** *. *d dd .. .. dd .. dd *b *8 *d dd .. "
+  )
+ )
+
+(kern-mk-place 
+ 'p_demon_gate  ; tag
+ "Demon Gate"   ; name
+ nil     ; sprite
+ m_demon_gate  ; map
+ #f               ; wraps
+ #f                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ ;; neighbors
+ nil
+ ;; objects
+ (list
+  (put (mk-demon-gate) 0 0)
+  )
+
+ nil ; hooks
+ nil ; edge entrances
+ )
+
+(mk-dungeon-level 
+ (list p_demon_gate p_ankh_shrine)
+ )
+
+(mk-place-music p_demon_gate 'ml-battle-music)
diff --git a/worlds/haxima-1.002/anne.scm b/worlds/haxima-1.002/anne.scm
new file mode 100644 (file)
index 0000000..8e27e49
--- /dev/null
@@ -0,0 +1,113 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define anne-lvl 4)
+(define anne-species sp_human)
+(define anne-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Paladin's Hold, in the Keep guarding Kurpolis.
+;;----------------------------------------------------------------------------
+(define anne-bed ph-bed2)
+(define anne-mealplace ph-tbl2)
+(define anne-workplace ph-medik)
+(define anne-leisureplace ph-dine)
+(kern-mk-sched 'sch_anne
+               (list 0  0 anne-bed          "sleeping")
+               (list 7  0 anne-mealplace    "eating")
+               (list 8  0 anne-workplace    "working")
+               (list 12 0 anne-mealplace    "eating")
+               (list 13 0 anne-workplace    "working")
+               (list 18 0 anne-mealplace    "eating")
+               (list 19 0 anne-leisureplace "idle")
+               (list 22 0 anne-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (anne-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Anne is a female White Magick mage serving as a medik 
+;; in the service of Glasdrin.  
+;; She currently serves in the Paladin's Hold of the Keep guarding Kurpolis.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (anne-name knpc kpc)
+  (say knpc "I am called Anne."))
+
+(define (anne-job knpc kpc)
+  (say knpc "I am a medik in the service of Glasdrin. Are you in need of healing?")
+  (if (yes? kpc)
+      (anne-trade knpc kpc)))
+
+(define (anne-trade knpc kpc)
+  (if (trade-services knpc kpc
+                      (list
+                       (svc-mk "Heal" 30 heal-service)
+                       (svc-mk "Cure" 30 cure-service)
+                       (svc-mk "Resurrect" 100 resurrect-service)))
+      (begin
+        (say knpc "What else can I do for you?")
+        (anne-trade knpc kpc))
+      (begin
+        (say knpc "Will there be anything else?")
+        (if (kern-conv-get-yes-no? kpc)
+            (anne-trade knpc kpc)
+            (say knpc "Very well.")))))
+
+(define (anne-medik knpc kpc)
+  (say knpc "I heal paladins who are wounded in combat. I will heal others, too, for a price."))
+
+(define (anne-kurp knpc kpc)
+  (say knpc "This is a savage place, not for the inexperienced. It gets worse the deeper you go."))
+
+(define anne-conv
+  (ifc kurpolis-conv
+
+       ;; basics
+       (method 'job anne-job)
+       (method 'name anne-name)
+       
+       ;; trade
+       (method 'trad anne-trade)
+       (method 'heal anne-trade)
+       (method 'pric anne-trade)
+
+       (method 'medik anne-medik)
+       (method 'kurp anne-kurp)
+       ))
+
+(define (mk-anne)
+  (bind 
+   (kern-mk-char 
+    'ch_anne           ; tag
+    "Anne"             ; name
+    anne-species         ; species
+    anne-occ              ; occ
+    s_companion_wizard     ; sprite
+    faction-men      ; starting alignment
+    1 3 2            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    anne-lvl
+    #f               ; dead
+    'anne-conv         ; conv
+    sch_anne           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_sword
+                                                t_armor_leather
+                                                )               ; readied
+    )
+   (anne-mk)))
diff --git a/worlds/haxima-1.002/arms.png b/worlds/haxima-1.002/arms.png
new file mode 100644 (file)
index 0000000..c3fcf28
Binary files /dev/null and b/worlds/haxima-1.002/arms.png differ
diff --git a/worlds/haxima-1.002/arms.scm b/worlds/haxima-1.002/arms.scm
new file mode 100644 (file)
index 0000000..81b53b9
--- /dev/null
@@ -0,0 +1,851 @@
+;;----------------------------------------------------------------------------
+;; arms.scm - armament types
+;;
+;; The basic primitive for creating an armament type is the kern-mk-arms-type
+;; procedure. This procedure takes a lot of parameters (listed below in
+;; order). A lot of the parameters are boiler-plate for whole classes of
+;; weapons, so I added some "curried" wrapper calls below.
+;;
+;;          tag : the symbol for the type in the script (variable-name)
+;;         name : the string name used by the game
+;;       sprite : sprite for the type
+;;       to-hit : to-hit attack bonus (dice expr)
+;;       damage : attack damage (dice expr)
+;;        armor : damage reduced when hit (dice expr)
+;;      deflect : bonus to deflect attack (dice expr)
+;;        slots : slots it will fit in (e.g., hands)
+;;        hands : number of slots required to ready it
+;;        range : range it will fire
+;;          rap : required action points to attack with it
+;;       AP_mod : modifier to max AP per round for the wielder
+;;      missile : nil or the armament type it fires
+;;       thrown : true or false
+;;         ubiq : true if it needs ammo in inventory, false otherwise
+;;       weight : weight of arms
+;;   fire-sound : string name of sound file to play when it's fired
+;;     gifc-cap :
+;;         gifc :
+;;   stratt_mod : percentage of str based attack bonus used
+;;   dexatt_mod : percentage of dex based attack bonus used
+;;   damage_mod : percentage of damage bonus used
+;;    avoid_mod : multiplier for avoidance bonus (1.0 = no effect)
+;;
+;;
+;;----------------------------------------------------------------------------
+
+;; This keeps weapons proportional to the default cost, for a one line change between turn systems
+(define (weap-ap mult)
+       (floor (* mult default-weapon-rap)))
+       
+(define (armour-ap mult)
+       (floor (* mult default-armour-apmod)))
+
+(kern-mk-sprite-set 'ss_arms 32 32 9 8 0 0 "arms.png")
+
+;;-------------------------------------------------------------------------
+;; Temp ifc for mutable attack types
+;;-------------------------------------------------------------------------
+
+(define temp-ifc-state (list 0))
+
+(define (temp-ifc-set tempifc)
+       (set-car! temp-ifc-state tempifc))
+       
+(define temp-ifc
+  (ifc '()
+       (method 'hit-loc
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                                ((car temp-ifc-state) kmissile kuser ktarget kplace x y dam)
+                 ))))
+
+(define temp-cannonball-state (list -1 -1))
+
+(define (temp-cannonball-init x y)
+       (set-car! temp-cannonball-state x)
+       (set-car! (cdr temp-cannonball-state) y)
+               )
+                 
+;;--------------------------------------------------------------------------
+;; Curried constructors
+;;
+;; These are for creating the standard classes of armaments. They simplify
+;; things by filling in the blanks for all the boilerplate parameters of
+;; the primitive kern-mk-arms-type procedure.
+;;--------------------------------------------------------------------------
+
+(define obj-ifc-cap (ifc-cap obj-ifc))    
+
+(define (mk-melee-arms-type tag name sprite to-hit-bonus damage deflect AP_cost AP_mod slots 
+                            num-hands range weight
+                                                       stratt_mod dexatt_mod
+                                                       damage_mod avoid_mod)
+  (kern-mk-arms-type tag name sprite to-hit-bonus damage "0" deflect slots 
+                     num-hands range AP_cost AP_mod nil nil #f #f weight nil
+                                        obj-ifc-cap obj-ifc stratt_mod dexatt_mod damage_mod avoid_mod mmode-smallobj))
+
+;; Curried constructor: missile weapon (add missile, ubiq flag to melee)
+(define (mk-projectile-arms-type tag name sprite to-hit-bonus damage deflect AP_cost AP_mod
+                                 slots num-hands range projectile ammo ubiq weight
+                                                                stratt_mod dexatt_mod damage_mod avoid_mod ifc)
+  (kern-mk-arms-type tag name sprite to-hit-bonus damage "0" deflect slots 
+                     num-hands range AP_cost AP_mod projectile ammo #f ubiq weight nil (ifc-cap ifc) ifc stratt_mod dexatt_mod damage_mod avoid_mod mmode-smallobj))
+
+;; Curried constructor: thrown weapon (add field to melee)
+(define (mk-thrown-arms-type tag name sprite to-hit-bonus damage deflect AP_cost AP_mod slots 
+                             num-hands range missile ubiq ifc weight
+                                                        stratt_mod dexatt_mod damage_mod avoid_mod)
+  (kern-mk-arms-type tag name sprite to-hit-bonus damage "0" deflect slots 
+                     num-hands range AP_cost AP_mod missile nil #t ubiq weight nil (ifc-cap ifc) ifc stratt_mod dexatt_mod damage_mod avoid_mod mmode-smallobj))
+
+(define (mk-ammo-arms-type tag name sprite ifc mmode)
+  (kern-mk-arms-type tag name sprite "0" "0" "0" "0" slot-nil 0 0 0 0 nil nil #f #f 
+                     0 nil (ifc-cap ifc) ifc 20 60 20 1.0 mmode))
+
+(define (mk-missile-arms-type tag name sprite ifc mmode beam)
+  (kern-mk-missile-type tag name sprite (ifc-cap ifc) ifc mmode beam beam))
+                     
+(define (mk-armor-type tag name sprite to-hit armor slots equiptime AP_mod weight avoid_mod)
+  (kern-mk-arms-type tag name sprite to-hit "0" armor "0" slots 1 0 equiptime AP_mod nil nil #f #f 
+                     weight nil obj-ifc-cap obj-ifc 20 60 20 avoid_mod mmode-largeobj))
+
+(define (mk-shield-type tag name sprite to-hit deflect AP_mod slots weight avoid_mod) 
+  (kern-mk-arms-type tag name sprite to-hit "0" "0" deflect slots 1 0 default-weapon-rap AP_mod nil nil #f #f 
+                     weight nil obj-ifc-cap obj-ifc 20 60 20 avoid_mod mmode-largeobj))
+
+;; ============================================================================
+;; Missiles for Projectile Weapons & Spells
+;; ============================================================================
+
+(kern-mk-sprite 's_sling_stone               ss_arms 1  0  #f   0 )
+(kern-mk-sprite 's_warhead                   ss_arms 1  1  #f   0 )
+(kern-mk-sprite 's_cannonball                ss_arms 1  2  #f   0 )
+(kern-mk-sprite 's_fireball                  ss_arms 1  3  #f   0 )
+(kern-mk-sprite 's_deathball                 ss_arms 1  4  #f   0 )
+(kern-mk-sprite 's_arrow                     ss_arms 1  8  #f 495 )
+(kern-mk-sprite 's_bolt                      ss_arms 1 80  #f 495 )
+(kern-mk-sprite 's_arrowobj                  ss_arms 1 68  #f   0 )
+(kern-mk-sprite 's_arrowstack                ss_arms 1 69  #f   0 )
+(kern-mk-sprite 's_boltobj                   ss_arms 1 70  #f   0 )
+(kern-mk-sprite 's_boltstack                 ss_arms 1 71  #f   0 )
+(kern-mk-sprite 's_poison_bolt               ss_arms 1 16  #f 170 )
+(kern-mk-sprite 's_acid_bolt                 ss_arms 1 20  #f 170 )
+(kern-mk-sprite 's_thrownweb                 ss_arms 1 31  #f   0 )
+(kern-mk-sprite 's_prismatic_bolt            ss_arms 4 100  #f   0 )
+(kern-mk-sprite 's_squat_bubbly_green_potion ss_arms 1 30  #f   0 )
+(kern-mk-sprite 's_thrown_green_potion       ss_arms 4 104  #f   0 )
+
+;; ----------------------------------------------------------------------------
+;; mk-missile-ifc -- automate missile ifc creation. 'pred?' takes an object as
+;; a parameter and returns true iff the 'hit' proc should be applied to it.
+;; ----------------------------------------------------------------------------
+(define (mk-missile-ifc hit)
+  (ifc '()
+       (method 'hit-loc (lambda (kmissile kuser ktarget kplace x y dam)
+                          (let ((targets (filter obj-is-char? 
+                                                 (kern-get-objects-at (mk-loc kplace 
+                                                                              x 
+                                                                              y)))))
+                            (if (notnull? targets)
+                                (hit (car targets))))))))
+
+
+(define poison-bolt-ifc (mk-missile-ifc apply-poison))
+(define deathball-ifc   (mk-missile-ifc magical-kill))
+(define stunball-ifc (mk-missile-ifc paralyze))
+(define acid-bolt-ifc (mk-missile-ifc apply-acid))
+
+(define lightningbolt-ifc 
+       (ifc '()
+               (method 'enter
+                       (lambda (kmissile kplace x y)
+                               ((car temp-ifc-state) kmissile nil nil kplace x y 0)
+                               ))
+               ))
+
+(define (on-hit-nontarget ktarget loc dam proc)
+       (for-each proc
+               (if (> dam -1)
+               (filter (lambda (obj) (not (equal? obj ktarget)))
+               (kern-get-objects-at loc))
+       (kern-get-objects-at loc)
+               ))
+)
+
+(define (on-hit-target ktarget dam proc)
+       (if (> dam -1)
+               (proc ktarget)
+       ))
+
+;; fireball-hit -- when a fireball hits it burns all characters and leaves a
+;; fire 
+(define fireball-ifc
+  (ifc '()
+       (method 'hit-loc
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                       (let* (
+                                       (havemana (> (kern-char-get-mana kuser) 0))
+                                       (usedmana (if (and havemana (equal? (kern-dice-roll "1d15") 1))
+                                                               (
+                                                                       begin
+                                                                       (kern-char-set-mana kuser (- (kern-char-get-mana kuser) 1))
+                                                                       #t
+                                                               )
+                                                               #f))
+                                       (setfire (and usedmana (equal? (kern-dice-roll "1d3") 1)))
+                                       (loc (mk-loc kplace x y))
+                                       (hurt (> dam 0))
+                                       (targdamage (cond
+                                                                               (usedmana (if hurt "2d5+3" "2d4+2"))
+                                                                               (havemana (if hurt "2d4+2" "2d3+2"))
+                                                                               (else (if hurt "1d4-1" "1d2-1"))
+                                                                               ))
+                                       (othdamage (cond
+                                                                               (usedmana "2d3+2")
+                                                                               (havemana "1d4")
+                                                                               (else "0")
+                                                                               ))
+                                       )
+                               (if (and setfire (terrain-ok-for-field? loc))
+                                       (kern-obj-put-at (kern-mk-field F_fire (kern-dice-roll "1d5")) loc))
+                               (if (not havemana)
+                                               (kern-log-msg "Attack fizzles!"))
+                               (on-hit-target ktarget dam 
+                                       (lambda (obj) (generic-burn obj targdamage))
+                               )
+                               (if havemana
+                                       (on-hit-nontarget ktarget loc dam 
+                                               (lambda (obj) (generic-burn obj othdamage)))
+                                       )                         
+               ))
+                       )))
+                       
+(define (prismatic-acid ktarget power)
+       (if (and (kern-obj-is-char? ktarget)
+                       (contest-of-skill power
+                               (occ-ability-dexdefend ktarget)))
+               (apply-acid ktarget)))
+               
+(define (prismatic-slip ktarget power)
+       (if (and (kern-obj-is-char? ktarget)
+                       (contest-of-skill power
+                       (occ-ability-dexdefend ktarget)))
+               (slip ktarget)))
+               
+(define prismatic-bolt-ifc
+       (ifc '()
+       (method 'hit-loc
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                       (let* (
+                                       (havemana (> (kern-char-get-mana kuser) 0))
+                                       (usedmana (if (and havemana (equal? (kern-dice-roll "1d15") 1))
+                                                               (
+                                                                       begin
+                                                                       (kern-char-set-mana kuser (- (kern-char-get-mana kuser) 1))
+                                                                       #t
+                                                               )
+                                                               #f))
+                                       (magpower (if havemana
+                                                       (if usedmana (max 7 (occ-ability-blackmagic kuser)) 5)
+                                                       0))
+                                       (loc (mk-loc kplace x y))
+                                       (hit (> dam -1))
+                                       (hurt (> dam 0))
+                                       (havetarget (not (eqv? ktarget '())))
+                                       (pristype (kern-dice-roll "1d100"))
+                                       (proclist
+                                       
+                                               (cond ((< pristype 10)
+                                                               (list nil
+                                                       (lambda (obj) (powers-paralyse kuser obj magpower))
+                                                       (lambda (obj) (powers-paralyse kuser obj (- magpower 3)))))
+                                                                                       
+                                                       ((< pristype 20)
+                                                               (list nil
+                                                       (lambda (obj) (prismatic-acid obj magpower))
+                                                       (lambda (obj) (prismatic-acid obj (- magpower 3)))))
+                                                                                                               
+                                                               ((< pristype 30)
+                                                                       (list nil
+                                                       (lambda (obj) (powers-poison-effect kuser obj (+ magpower 3)))
+                                                       (lambda (obj) (powers-poison-effect kuser obj (- magpower 2)))))
+                                                       
+                                                       ((< pristype 40)
+                                                                       (list nil
+                                                       (lambda (obj) (generic-burn obj "2d3+2"))
+                                                       (lambda (obj) (generic-burn obj "1d5"))))
+                                                               
+                                                       ((< pristype 50)
+                                                                       (list nil
+                                                       (lambda (obj) (apply-lightning obj))
+                                                       (lambda (obj) (apply-lightning obj))))
+                                               
+                                                                               ((< pristype 60)
+                                                                       (list nil
+                                                       (lambda (obj) (prismatic-slip obj (+ magpower 5)))
+                                                       (lambda (obj) (prismatic-slip obj (+ magpower 2)))))
+                                                               
+                                                                       ((< pristype 70)
+                                                                       (list
+                                                               (lambda (loc) (powers-field-energy-weak kuser loc magpower))
+                                                               nil nil))
+
+                                                                       ((< pristype 80)
+                                                                       (list
+                                                               (lambda (loc) (powers-field-fire-weak kuser loc magpower))
+                                                               nil nil))
+                                                               
+                                                                       ((< pristype 90)
+                                                                       (list
+                                                               (lambda (loc) (powers-field-poison-weak kuser loc magpower))
+                                                               nil nil))
+                                                               
+                                                                       ((< pristype 101) 
+                                                                       (list
+                                                               (lambda (loc) (powers-field-sleep-weak kuser loc magpower))
+                                                               nil nil))
+                                       )))
+                               (if (not havemana)
+                                               (kern-log-msg "Attack fizzles!")
+                                               (begin
+                                                       (if (not (null? (car proclist)))
+                                                               ((car proclist) loc))
+                                                       (if (not (null? (cadr proclist)))
+                                                               (on-hit-target ktarget dam (cadr proclist)))
+                                                       (if (not (null? (caddr proclist)))
+                                                               (on-hit-nontarget ktarget loc dam (caddr proclist)))
+                                               )
+                                       )
+                       ))
+                       )))
+                       
+(define warhead-ifc
+  (ifc nil
+       (method 'hit-loc 
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                 (kern-obj-put-at (kern-mk-obj F_fire 1) 
+                                  (mk-loc kplace x y))))))
+                                  
+(kern-mk-sprite 's_flaming_oil    ss_arms 4 96 #f 0)
+(kern-mk-sprite 's_oil_potion     ss_arms 1 5 #f 0)
+(kern-mk-sprite 's_spear          ss_arms 1 88 #f 495 )
+(kern-mk-sprite 's_spearobj       ss_arms 1 6 #f 0)
+(kern-mk-sprite 's_throwing_axe   ss_arms 1 29 #f 0)
+(kern-mk-sprite 's_thrown_axe     ss_arms 8 72 #f 0)
+(kern-mk-sprite 's_thrown_boulder ss_arms 1 7 #f 0)
+(kern-mk-sprite 's_smoke_bomb     ss_arms 4 112 #f 0)
+(kern-mk-sprite 's_smoke_potion   ss_arms 1 108 #f 0)
+
+(define flaming-oil-ifc
+  (ifc obj-ifc
+       (method 'hit-loc 
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                 (kern-obj-put-at (kern-mk-obj F_fire 1) 
+                                  (mk-loc kplace x y))))))
+
+(define vial-of-slime-ifc
+  (ifc obj-ifc
+       (method 'hit-loc 
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                 (let* ((lvl (kern-dice-roll "1d3+5"))
+                        (knpc (spawn-npc 'green-slime lvl))
+                        (loc (pick-loc (mk-loc kplace x y) knpc)))
+                   (cond ((null? loc) 
+                          (kern-obj-dec-ref knpc)
+                          0)
+                         (else
+                          (kern-being-set-base-faction knpc (kern-being-get-base-faction kuser))
+                          (kern-obj-set-temporary knpc #t)
+                          (kern-obj-put-at knpc loc))))))))
+
+(define smoke-bomb-ifc
+       (ifc obj-ifc
+               (method 'hit-loc
+                       (lambda (kmissile kuser ktarget kplace x y dam)
+                               (fields-smoke-apply kplace x y 10)
+               ))))
+                          
+(define (mk-drop-proj-ifc type-tag prob)
+       (ifc obj-ifc
+       (method 'hit-loc 
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                       (if (< (kern-dice-roll "1d100") prob)
+                               (let ((dropobj (kern-mk-obj (eval type-tag) 1))
+                                               (loc (mk-loc kplace x y)))
+                                       (if (can-be-dropped? dropobj loc cant)
+                                               (kern-obj-put-at dropobj loc)
+                       ))))
+      )))
+            
+;; todo: handle possibility that magicaxe doesnt have a wielder?
+(define magicaxe-ifc
+       (ifc obj-ifc
+               (method 'hit-loc 
+                       (lambda (kmissile kuser ktarget kplace x y dam)
+                               (kern-fire-missile (eval 't_returning_axe_p) (mk-loc kplace x y) (kern-obj-get-location kuser))
+                               (kern-log-msg "Magic axe returns!")
+                       )
+       ))
+)
+                   
+                          
+(define missile-arms-types
+  (list
+   ;;    ==================================================================================================
+   ;;    tag                 | name          | sprite          | gifc              | movement_mode | beam
+   ;;    ====================================================================================================
+   (list 't_slingstone        "sling stone"    s_sling_stone     obj-ifc             mmode-missile     #f)
+   (list 't_arrow_p           "arrow"          s_arrow           (mk-drop-proj-ifc 't_arrow 5)
+                                                                                     mmode-missile     #f  )
+   (list 't_bolt_p            "bolt"           s_bolt            (mk-drop-proj-ifc 't_bolt 5)             
+                                                                                     mmode-missile     #f  )
+   (list 't_warhead_p         "warhead"        s_warhead         warhead-ifc         mmode-missile     #f  )
+   (list 't_cannonball_p      "cannonball"     s_cannonball      obj-ifc             mmode-missile     #f  )
+
+   
+   (list 't_poison_bolt       "poison bolt"    s_poison_bolt     poison-bolt-ifc     mmode-missile     #f  )
+   (list 't_acid_bolt         "acid bolt"      s_acid_bolt       acid-bolt-ifc       mmode-missile     #f  )
+   (list 't_fireball          "fireball"       s_fireball        fireball-ifc        mmode-missile     #f  )
+   (list 't_deathball         "deathball"      s_deathball       deathball-ifc       mmode-missile     #f  )
+   (list 't_slimeglob         "slime glob"     s_acid_bolt       obj-ifc             mmode-missile     #f  )
+   (list 't_mfireball         "fireball"       s_fireball        temp-ifc            mmode-missile     #f  )
+   (list 't_mpoison_bolt      "poison bolt"    s_poison_bolt     temp-ifc            mmode-missile     #f  )
+   (list 't_prismatic_bolt    "prismatic bolt" s_prismatic_bolt  prismatic-bolt-ifc  mmode-missile     #f  )
+   (list 't_stunball                           "stun ball"       s_lightning    stunball-ifc            mmode-missile          #f  )
+   (list 't_lightning_bolt     "lightning bolt"        s_lightning      lightningbolt-ifc   mmode-missile      #t  )  
+   (list 't_magicarrow_p      "arrow"          s_arrow           obj-ifc             mmode-missile     #f  )
+   
+   
+   (list 't_mweb              "web"            s_thrownweb       temp-ifc            mmode-missile     #f  )
+   (list 't_oil_p             "flaming oil"    s_flaming_oil     flaming-oil-ifc     mmode-missile     #f  )
+   (list 't_smoke_bomb_p      "smoke bomb"     s_smoke_bomb      smoke-bomb-ifc      mmode-missile     #f  )
+   (list 't_spear_p           "spear"          s_spear           (mk-drop-proj-ifc 't_spear 25)             
+                                                                                     mmode-missile     #f  )
+   (list 't_thrown_axe_p      "thrown axe"     s_thrown_axe      magicaxe-ifc        mmode-missile     #f  )
+   (list 't_returning_axe_p   "thrown axe"     s_thrown_axe      obj-ifc              mmode-return     #f  )
+   (list 't_thrown_rock_p     "thrown rock"    s_cannonball      (mk-drop-proj-ifc 't_thrown_rock 80)             
+                                                                                     mmode-missile     #f  )
+   (list 't_thrown_boulder_p  "hurled boulder" s_thrown_boulder  (mk-drop-proj-ifc 't_thrown_boulder 80)             
+                                                                                     mmode-missile     #f  )
+
+   (list 't_slime_vial_p      "vial of slime"  s_thrown_green_potion vial-of-slime-ifc  mmode-missile          #f  )
+
+   ))
+
+(map (lambda (type) (apply mk-missile-arms-type type)) missile-arms-types)  
+         
+                          
+(define ammo-arms-types
+  (list
+   ;;    ===========================================================================================
+   ;;    tag                 | name          | sprite          | gifc              | movement_mode 
+   ;;    ===========================================================================================
+
+   (list 't_arrow             "arrow"          s_arrowobj        obj-ifc             mmode-smallobj )
+   (list 't_bolt              "bolt"           s_boltobj         obj-ifc             mmode-smallobj )
+   (list 't_warhead           "warhead"        s_warhead         warhead-ifc         mmode-smallobj )
+   (list 't_cannonball        "cannonball"     s_cannonball      obj-ifc             mmode-smallobj )
+   ))
+   
+   
+;; If we don't create these missile types now, we won't be able to refer to
+;; them below in the projectile-arms-types table. For example, t_bow needs to
+;; refer to t_arrow. But the interpreter won't recognize t_arrow as a variable
+;; name until we call this procedure to create the t_arrow type.
+(map (lambda (type) (apply mk-ammo-arms-type type)) ammo-arms-types)
+
+;; ============================================================================
+;; Projectile Weapons
+;; ============================================================================
+
+(kern-mk-sprite 's_sling      ss_arms 1 24 #f 0)
+(kern-mk-sprite 's_bow        ss_arms 1 25 #f 0)
+(kern-mk-sprite 's_crossbow   ss_arms 1 26 #f 0)
+(kern-mk-sprite 's_doom_staff ss_arms 1 27 #f 0)
+(kern-mk-sprite 's_stun_wand  ss_arms 1 28 #f 0)
+
+(define proj-ifc
+       (ifc obj-ifc
+               (method 'on-attack
+                       (lambda (kuser)
+                               (println "oa")
+                               (kern-sound-play-at sound-missile (kern-obj-get-location kuser))
+                       )
+       ))
+)
+
+(define projectile-arms-types
+  (list
+   ;;     =========================================================================================================================================================================================
+   ;;     tag            | name           |  sprite     | to-hit | damage | to-def | AP_cost | AP_mod       | slots       | hnds | rng | missile        | ammo  | ubiq | weight | stratt | dexatt | dammod | avoid | ifc
+   ;;     =========================================================================================================================================================================================
+   (list 't_sling          "sling"           s_sling      "1d2-2"  "1d4"    "-1"      (weap-ap 1) 0   slot-weapon   1      4     t_slingstone     nil     #t     0        10       60       30       0.9       proj-ifc)
+   (list 't_sling_4        "+4 sling"        s_sling      "+3"     "1d4+4"  "+0"      (weap-ap 1) 0   slot-weapon   1      6     t_slingstone     nil     #t     0        10       60       30       0.9       proj-ifc)
+
+   (list 't_self_bow       "self bow"        s_bow        "+1"     "1d6"    "-2"      (weap-ap 0.8) 0   slot-weapon   2      4     t_arrow_p        t_arrow #f     2        10       70       20       0.9  proj-ifc)
+   (list 't_bow            "bow"             s_bow        "1d3-2"  "2d4"    "-2"     (weap-ap 1) 0   slot-weapon   2      5     t_arrow_p        t_arrow #f     2        10       70       20       0.9  proj-ifc)
+   (list 't_long_bow       "longbow"         s_bow        "1d3-2"  "2d6+1"  "-2"     (weap-ap 1.2) 0   slot-weapon   2      6     t_arrow_p        t_arrow #f     2        10       70       20       0.9  proj-ifc)
+   (list 't_great_bow      "great bow"       s_bow        "1d3-2"  "2d6+3"  "-2"     (weap-ap 1.34) 0   slot-weapon   2      7     t_arrow_p        t_arrow #f     2        10       70       20       0.9  proj-ifc)
+
+   (list 't_lt_crossbow    "light crossbow"  s_crossbow   "1d4-2"  "2d5"    "-1"     (weap-ap 1) 0   slot-weapon   2      5     t_bolt_p         t_bolt  #f     3         0       80        0       0.95 proj-ifc)
+   (list 't_crossbow       "crossbow"        s_crossbow   "1d4-2"  "4d4"    "-1"     (weap-ap 1) 0   slot-weapon   2      6     t_bolt_p         t_bolt  #f     3         0       80        0       0.95 proj-ifc)
+   (list 't_hvy_crossbow   "heavy crossbow"  s_crossbow   "1d4-2"  "4d6+2"  "-1"     (weap-ap 2) 0   slot-weapon   2      7     t_bolt_p         t_bolt  #f     3         0       80        0       0.95 proj-ifc)
+   (list 't_trpl_crossbow  "triple crossbow" s_crossbow   "1d4-2"  "2d5"    "-1"      (weap-ap 0.67) 0   slot-weapon   2      5     t_bolt_p         t_bolt  #f     3         0       80        0       0.95 proj-ifc)
+
+   (list 't_doom_staff     "doom staff"      s_doom_staff "1d4"    "1d2"    "+2"     (weap-ap 1) 0    slot-weapon   2      5     t_fireball       nil     #t     2         0       50        0       1.0  proj-ifc)
+   (list 't_acid_spray     "acid spray"      nil          "-7"     "1d6"    "+0"     (weap-ap 1) 0    slot-nil      2      2     t_slimeglob      nil     #t     0        10       50       20       1.0  proj-ifc)
+   (list 't_fire_glob      "fire glob"       nil          "-8"     "1d6"    "+0"     (weap-ap 1) 0    slot-nil      2      2     t_fireball       nil     #t     0        10       50       20       1.0  proj-ifc)
+   (list 't_stun_wand      "stun wand"       s_stun_wand  "-2"     "1d4"    "-1"     (weap-ap 1) 0    slot-weapon   1      6     t_stunball       nil     #t     2         0       80        0       1.0  proj-ifc)
+   (list 't_acid_wand      "acid wand"       s_stun_wand  "-2"     "1d4"    "-1"     (weap-ap 1) 0    slot-weapon   1      6     t_acid_bolt      nil     #t     2         0       80        0       1.0  proj-ifc)
+   (list 't_prismatic_gaze "prismatic gaze"  nil          "1d4"    "0"      "+0"     (weap-ap 1) 0    slot-nil      1      3     t_prismatic_bolt nil     #t     0         0        0        0       0.85 proj-ifc)
+   ))
+
+;; ============================================================================
+;; Thrown Weapons
+;; ============================================================================
+
+   
+(define thrown-arms-types
+  (list
+   ;;     =================================================================================================================================================================================================================
+   ;;     tag              | name          | sprite                   | to-hit | dmg | to-def | AP_cost | AP_mod        | slots       | hnds | rng | missile          | ubiq | ifc              | weight | stratt | dexatt | dammod | avoid
+   ;;     =================================================================================================================================================================================================================
+   (list  't_thrown_rock    "small rock"    s_cannonball                "-2"     "1d2"    "-2"   (weap-ap 1.33) 0  slot-weapon   1      4     t_thrown_rock_p    #t     obj-ifc             1       20       20         0      0.9 )
+   (list  't_thrown_boulder "loose boulder" s_thrown_boulder            "-2"     "3d4+1"  "-2"  (weap-ap 2) 0  slot-weapon   2      5     t_thrown_boulder_p #f     obj-ifc            10       40       20        60      0.9 )
+
+   (list  't_spear          "spear"         s_spearobj                  "+1"     "1d8+1"  "+1"  (weap-ap 1) 0  slot-weapon   1      4     t_spear_p          #f     obj-ifc             2       30       60        40      1.0 )
+   (list  't_magic_axe      "magical axe"   s_throwing_axe              "+2"     "2d4+2"  "+0"  (weap-ap 1) 0  slot-weapon   1      4     t_thrown_axe_p     #t     obj-ifc             2       30       60        40      1.0 )
+
+   (list  't_oil            "flaming oil"   s_oil_potion                "-1"     "1d6"    "-2"  (weap-ap 1.2) 0  slot-weapon   1      4     t_oil_p            #f     flaming-oil-ifc     1       20       30         0      0.9 )
+   (list  't_slime_vial     "vial of slime" s_squat_bubbly_green_potion "-1"     "1d2"    "-2"  (weap-ap 1.2) 0  slot-weapon   1      4     t_slime_vial_p     #f     vial-of-slime-ifc   1       20       30         0      1.0 )
+   (list  't_smoke_bomb     "smoke bomb"    s_smoke_potion                "-1"     "1"      "-2"  (weap-ap 1.2) 0  slot-weapon   1      6     t_smoke_bomb_p     #f     smoke-bomb-ifc      1       20       30         0      0.9 )
+   ))
+
+(map (lambda (type) (apply mk-thrown-arms-type type)) thrown-arms-types)  
+   
+;; Inventory sprites
+(kern-mk-sprite 's_axe            ss_arms 1 29 #f 0)
+(kern-mk-sprite 's_dagger         ss_arms 1 32 #f 0)
+(kern-mk-sprite 's_mace           ss_arms 1 33 #f 0)
+(kern-mk-sprite 's_sword          ss_arms 1 34 #f 0)
+(kern-mk-sprite 's_2h_axe         ss_arms 1 35 #f 0)
+(kern-mk-sprite 's_2h_sword       ss_arms 1 36 #f 0)
+(kern-mk-sprite 's_morning_star   ss_arms 1 37 #f 0)
+(kern-mk-sprite 's_halberd        ss_arms 1 38 #f 0)
+(kern-mk-sprite 's_staff          ss_arms 1 39 #f 0)
+(kern-mk-sprite 's_eldritch_blade ss_arms 2 40 #f 0)
+(kern-mk-sprite 's_mystic_sword   ss_arms 2 42 #f 0)
+(kern-mk-sprite 's_flaming_sword  ss_arms 2 44 #f 0)
+
+;; Paper-doll sprites
+(kern-mk-sprite 's_hum_staff_gold     ss_arms 4 56 #f 0)
+(kern-mk-sprite 's_hum_staffglo_blue  ss_arms 4 60 #f 0)
+(kern-sprite-apply-matrix (kern-sprite-clone s_hum_staffglo_blue 
+                                             's_hum_staffglo_green) 
+                          mat_blue_to_green)
+(kern-mk-sprite 's_hum_halberd ss_arms 4 64 #f 0)
+
+(define melee-arms-types
+  (list
+   ;;     ===================================================================================================================================================
+   ;;     tag          |    name           | sprite         | to-hit | damage | to-def | AP_cost | AP_mod | slots | hnds | rng | weight | dxmod | stmod | dammod | avoid
+   ;;     ===================================================================================================================================================
+   (list  't_hands          "bare hands"     nil              "1d2"    "1d2"    "1d2"    (weap-ap 0.67) 0 slot-nil      1      1     0        50      20       10      1.0  )
+   (list  't_F_fangs        "fangs"          nil              "1d2"    "1d4"    "+0"     (weap-ap 0.67) 0 slot-nil      1      1     0        50      20       30      1.0  )
+   (list  't_fangs          "fangs"          nil              "1d2"    "1d6"    "+0"      (weap-ap 1)   0 slot-nil      1      1     0        50      20       30      1.0  )
+   (list  't_G_fangs        "great fangs"    nil              "1d2"    "1d10"   "+0"     (weap-ap 1.34) 0 slot-nil      1      1     0        50      20       30      1.0  )
+   (list  't_horns          "horns"          nil              "1d2"    "1d8"    "1d2"    (weap-ap 0.67) 0 slot-nil      1      1     0        30      40       60      1.0  )
+   (list  't_stinger        "stinger"        nil              "1d2"    "1d2"    "+0"     (weap-ap 0.67) 0 slot-nil      1      1     0        50      20       10      1.0  )
+   (list  't_tentacles      "tentacles"      nil              "1d3"    "4d4"    "4d2"     (weap-ap 1)   0 slot-nil      1      1     0        70      20       60      1.0  )
+   (list  't_beak           "beak"           nil              "+0"     "2d4"    "+0"      (weap-ap 1)   0 slot-nil      1      1     0        50      30       30      1.0  )
+   (list  't_pincers        "pincers"        nil              "-1"     "4d4"    "4d2"     (weap-ap 1.2) 0 slot-nil      1      1     0        50      30       30      1.0  )
+
+   (list  't_dagger         "dagger"         s_dagger         "1d4"    "1d4"    "1d2"     (weap-ap 0.8) 0 slot-weapon   1      1     0        80      10       10      1.0  )
+   (list  't_dagger_4       "+4 dagger"      s_dagger         "1d4+4"  "1d4+4"  "1d2+4"   (weap-ap 0.8) 0 slot-weapon   1      1     0        80      10       10      1.0  )
+   (list  't_mace           "mace"           s_mace           "1d4"    "1d6+2"  "+0"      (weap-ap 1)   0 slot-weapon   1      1     3        20      60       80      0.95 )
+   (list  't_axe            "axe"            s_axe            "1d2"    "2d4+2"  "+0"      (weap-ap 1.2) 0 slot-weapon   1      1     3        30      50       90      0.95 )
+   (list  't_sword          "sword"          s_sword          "1d2"    "1d8+1"  "1d2"     (weap-ap 1)   0 slot-weapon   1      1     2        50      20       70      1.0  )
+   (list  't_sword_2        "+2 sword"       s_sword          "1d2+2"  "1d8+3"  "1d2+2"   (weap-ap 1)   0 slot-weapon   1      1     2        50      20       70      1.0  )
+   (list  't_sword_4        "+4 sword"       s_sword          "1d2+4"  "1d8+5"  "1d2+4"   (weap-ap 1)   0 slot-weapon   1      1     2        50      20       70      1.0  )
+   (list  't_2H_axe         "2H axe"         s_2h_axe         "+0"     "4d4+4"  "-2"     (weap-ap 1.34) 0 slot-weapon   2      1     4        20      60      100      0.9  )
+   (list  't_2H_sword       "2H sword"       s_2h_sword       "+0"     "2d8+2"  "+1"      (weap-ap 1.2) 0 slot-weapon   2      1     4        40      40       90      0.95 )
+   (list  't_morning_star   "morning star"   s_morning_star   "1d2+2"  "1d6+1"  "-1"      (weap-ap 1)   0 slot-weapon   1      2     3        20      40       70      0.9  )
+   (list  't_morning_star_2 "+2 morning star" s_morning_star  "1d2+4"  "1d6+3"  "+2"      (weap-ap 1)   0 slot-weapon   1      2     3        20      40       70      0.9  )
+   (list  't_halberd        "halberd"        s_halberd        "1d3+1"  "2d8-2"  "1d2"     (weap-ap 1)   0 slot-weapon   2      2     4        30      30      100      0.9  )
+   (list  't_staff          "staff"          s_staff          "1d3"    "1d4"    "1d3"     (weap-ap 0.8) 0 slot-weapon   2      2     2        60      30       40      1.0  )
+   (list  't_eldritch_blade "eldritch blade" s_eldritch_blade "+2"     "3d7+5"  "+0"     (weap-ap 1.34) 0 slot-weapon   2      1     2        50      20       70      1.0  )
+   (list  't_mystic_sword   "mystic sword"   s_mystic_sword   "+3"     "1d10+5" "+2"      (weap-ap 1)   0 slot-weapon   1      1     1        60      20       70      1.0  )
+   ))
+   
+(kern-mk-sprite 's_leather_helm  ss_arms 1 48 #f 0)
+(kern-mk-sprite 's_chain_coif    ss_arms 1 49 #f 0)
+(kern-mk-sprite 's_iron_helm     ss_arms 1 50 #f 0)
+(kern-mk-sprite 's_leather_armor ss_arms 1 51 #f 0)
+(kern-mk-sprite 's_chain_armor   ss_arms 1 52 #f 0)
+(kern-mk-sprite 's_plate_armor   ss_arms 1 53 #f 0)
+
+(define armor-types
+  (list
+   ;;     ===============================================================================================================
+   ;;     tag               | name            |  sprite        |  to-hit | armor  | slots     | equip_AP | AP_mod | weight | avoid 
+   ;;     ===============================================================================================================
+   (list   't_leather_helm    "leather helm"     s_leather_helm   "-1"     "1d2"    slot-helm    (weap-ap 1) -0  0  1.0  )
+   (list   't_leather_helm_2  "+2 leather helm"  s_leather_helm   "+0"     "1d2+2"  slot-helm    (weap-ap 1) -0  0  1.0  )
+   (list   't_leather_helm_4  "+4 leather helm"  s_leather_helm   "+0"     "1d2+4"  slot-helm    (weap-ap 1) -0  0  1.0  )
+
+   (list   't_chain_coif      "chain coif"       s_chain_coif     "-1"     "1d3"    slot-helm    (weap-ap 1) (armour-ap -1)  1  0.9  )
+   (list   't_chain_coif_4    "+4 chain coif"    s_chain_coif     "+0"     "1d3+4"  slot-helm    (weap-ap 1) (armour-ap -1)  1  0.9  )
+
+   (list   't_iron_helm       "iron helm"        s_iron_helm      "-1"     "1d4"    slot-helm    (weap-ap 1) (armour-ap -2)  2  0.9  )
+   (list   't_iron_helm_4     "+4 iron helm"     s_iron_helm      "+0"     "1d4+4"  slot-helm    (weap-ap 1) (armour-ap -2)  2  0.9  )
+
+   (list   't_armor_leather   "leather armor"    s_leather_armor  "-1"     "1d4"    slot-armor   (weap-ap 2) (armour-ap -1)  2  0.85 )
+   (list   't_armor_leather_2 "+2 leather armor" s_leather_armor  "+0"     "1d4+2"  slot-armor   (weap-ap 2) (armour-ap -1)  2  0.85 )
+   (list   't_armor_leather_4 "+4 leather armor" s_leather_armor  "+0"     "1d4+4"  slot-armor   (weap-ap 2) (armour-ap -1)  2  0.9  )
+
+   (list   't_armor_chain     "chain armor"      s_chain_armor    "-2"     "2d4"    slot-armor   (weap-ap 2) (armour-ap -5)  4  0.7  )
+   (list   't_armor_chain_4   "+4 chain armor"   s_chain_armor    "+0"     "2d4+4"  slot-armor   (weap-ap 2) (armour-ap -5)  4  0.8  )
+
+   (list   't_armor_plate     "plate armor"      s_plate_armor    "-4"     "4d4"    slot-armor   (weap-ap 5) (armour-ap -10) 8  0.6  )
+   (list   't_armor_plate_4   "+4 plate armor"   s_plate_armor    "+0"     "4d4+4"  slot-armor   (weap-ap 5) (armour-ap -10) 8  0.7  )
+   ))  
+
+(kern-mk-sprite 's_shield            ss_arms 1 54 #f 0)
+(kern-mk-sprite 's_scratched_shield  ss_arms 1 55 #f 0)
+
+(define shield-types
+  (list
+   ;;     ============================================================================================================
+   ;;     tag                 | name             | sprite           | to-hit | deflect | AP_mod | slots      | weight | avoid  
+   ;;     ============================================================================================================
+   (list   't_shield           "small shield"     s_shield            "-1"     "5"    -0  slot-shield  2         0.9  )
+   (list   't_shield_4         "+4 small shield"  s_shield            "+0"     "9"    -0  slot-shield  2         0.95 )
+   (list   't_scratched_shield "scratched shield" s_scratched_shield  "+0"     "7"    -0  slot-shield  2         0.9  )
+   ))
+
+
+(map (lambda (type) (apply mk-projectile-arms-type type)) projectile-arms-types)
+(map (lambda (type) (apply mk-melee-arms-type      type)) melee-arms-types)
+(map (lambda (type) (apply mk-armor-type           type)) armor-types)
+(map (lambda (type) (apply mk-shield-type          type)) shield-types)
+
+;;----------------------------------------------------------------------------
+;; Spiked Armor
+;;----------------------------------------------------------------------------
+(kern-mk-sprite 's_spiked_helm    ss_arms 1 46 #f 0)
+(kern-mk-sprite 's_spiked_shield  ss_arms 1 47 #f 0)
+
+(kern-mk-arms-type 't_spiked_helm "spiked helm" s_spiked_helm
+                   "0" "1d4" "3" "0"
+                   slot-helm 1 1 (weap-ap 2) -0
+                   nil nil #f #f
+                   2 ;; weight
+                   nil obj-ifc-cap obj-ifc
+                                  30 10 20 0.9 mmode-smallobj)
+
+(kern-mk-arms-type 't_spiked_shield "spiked shield" s_spiked_shield
+                   "0" "1d5" "0" "5"
+                   slot-shield 1 1 (weap-ap 2) -0
+                   nil nil #f #f
+                   3 ;; weight
+                   nil obj-ifc-cap obj-ifc
+                                  40 20 20 0.8 mmode-largeobj)
+
+;;--------------------------------------------------------------------------
+;; Special arms types
+;;
+;; These don't fit into the mold for any standard arms type.
+;;--------------------------------------------------------------------------
+
+(define flaming-sword-ifc
+  (ifc obj-ifc
+       (method 'hit-loc 
+               (lambda (kmissile kuser ktarget kplace x y dam)
+                       (cond ((equal? dam 0)
+                                               (generic-burn ktarget "1d5-2"))
+                                       ((> dam 0)
+                                               (generic-burn ktarget "2d4"))
+                       ))
+         )))          
+                                                       
+(kern-mk-arms-type 't_flaming_sword "flaming sword" s_flaming_sword "1d2" "1d8+2" "0" "1d2" slot-weapon 1 1 (weap-ap 1) 0 nil nil #f #f 2 nil
+                                        (ifc-cap flaming-sword-ifc) flaming-sword-ifc 50 20 70 1.0 mmode-smallobj)
+
+
+(kern-mk-arms-type 't_cannon         ; tag
+                   "cannon"          ; name
+                   nil               ; sprite
+                   "+1"              ;;       to-hit : to-hit attack bonus (dice expr)
+                   "1d10+4"          ;;       damage : attack damage (dice expr)
+                   "0"               ;;        armor : added to armor class (dice expr)
+                   "0"               ;;      deflect : damage deflected when hit (dice expr)
+                   slot-nil          ;;        slots : slots it will fit in (e.g., hands)
+                   0                 ;;        hands : number of slots required to ready it
+                   6                 ;;        range : range it will fire
+                   (weap-ap 2.0)     ;;          rap : required action points to attack with it
+                   0                 ;;       AP_mod : modifier to max AP per round for the wielder
+                   t_cannonball_p    ;;
+                   nil              ;;      missile : nil or the armament type it fires
+                   #f                ;;       thrown : true or false
+                   #t                ;;         ubiq : true if it needs ammo in inventory, false otherwise
+                   0                 ;;       weight : unused
+                   sound-cannon-fire ;;   fire-sound : string name of sound file to play when it's fired
+                   0                 ;;      ifc-cap : integer bitmap describing interface slots
+                   nil               ;;  get-handler : script ifc
+                                  0 0 0 1.0
+                                  mmode-largeobj
+                   )
+
+;;----------------------------------------------------------------------------
+;; This list of "blockable" arms types is used by combat ai. An arms type is
+;; "blockable" if an adjacent enemy can interfere with its usage.
+;;----------------------------------------------------------------------------
+(define blockable-arms-types
+  (list t_sling t_sling_4
+        t_self_bow t_bow t_long_bow t_great_bow
+        t_hvy_crossbow t_trpl_crossbow
+        t_spear
+        t_thrown_rock t_thrown_boulder ))
+; t_lt_crossbow is quick to load, and can be used in melee
+
+(define arms-types-needing-ammo
+  (list t_self_bow t_bow t_long_bow t_great_bow
+        t_lt_crossbow t_crossbow t_hvy_crossbow t_trpl_crossbow ))
+
+(define (arms-type-is-blockable? karms)
+  (display "arms-type-is-bloackable?")(newline)
+  (in-list? karms blockable-arms-types))
+
+(define (arms-type-needs-ammo? karms)
+  (in-list? karms arms-types-needing-ammo))
+
+;;----------------------------------------------------------------------------
+;; Test paper doll sprites: add a gob to the staff arms type with a "readied"
+;; sprite.
+;;----------------------------------------------------------------------------
+(kern-type-set-gob t_staff 
+                   (kern-sprite-blit-over s_hum_staff_gold 
+                                          s_hum_staffglo_blue))
+
+(kern-type-set-gob t_halberd s_hum_halberd)
+
+;;--------------------------------------------------------------------------
+;; Cannon mounting for shipboard combat (and maybe anywhere else we can think of later)
+;;--------------------------------------------------------------------------
+
+;; uglyhack find target location or set up 'safe' location to simulate cannonball leaving play area
+(define (arms-searchline place x y dx dy)
+       (let* ((wid (kern-place-get-width place))
+               (hgt (kern-place-get-height place)))
+               (define (arms-searchline-iter ix iy)
+                       (cond ((< ix 0) (list 0 iy #f))
+                               ((< iy 0) (list ix 0 #f))
+                               ((>= ix wid) (list (- wid 1) iy #f))
+                               ((>= iy hgt) (list ix (- wid 1) #f))
+                               ((not (null? (get-being-at (mk-loc place ix iy))))
+                                       (list ix iy #t))
+                               (else (arms-searchline-iter (+ ix dx) (+ iy dy)))
+                       ))
+               (let* ((target (arms-searchline-iter (+ x dx) (+ y dy)))
+                               (tx (car target))
+                               (ty (cadr target))
+                               (havet (caddr target))
+                               )
+                       (if havet
+                               (temp-cannonball-init -1 -1)
+                               (temp-cannonball-init tx ty)
+                       )
+                       (list tx ty)
+                       )))
+                       
+(define localcannonball-ifc
+       (ifc '()
+               (method 'hit-loc 
+                       (lambda (kmissile kuser ktarget kplace x y dam)
+                               (let ((ktarget (get-being-at (mk-loc kplace x y))))
+                                       (if (not (null? ktarget))
+                                               (
+                                                       begin
+                                                       (kern-log-msg (kern-obj-get-name ktarget) " hit by cannonball!")
+                                                       (kern-obj-apply-damage ktarget "cannon" (kern-dice-roll "1d10+4"))
+                                               )
+                                       )
+                               ))
+               )))
+                               
+(mk-missile-arms-type 't_localcannonball "cannonball" s_cannonball localcannonball-ifc mmode-cannon #f)
+               
+(define cannon-ifc
+       (ifc '()
+               (method 'xamine 
+                       (lambda (kcannon kuser)
+                               (let ((ready (cadr (gob kcannon))))
+                                       (kern-log-msg "The cannon is "
+                                               (cond ((equal? ready 2) 
+                                                        "ready to fire")
+                                                        ((equal? ready 1) 
+                                                        "loaded but unready")
+                                                        (else "unloaded")))
+                                       result-ok
+                       ))
+               )
+               (method 'handle
+                       (lambda (kcannon kuser)
+                               (let ((ready (cadr (gob kcannon)))
+                                               (facing (car (gob kcannon))))
+                                       (kern-obj-dec-ap kuser speed-human)
+                                       (cond
+                                               ((equal? ready 2)
+                                                       (let* ((loc (kern-obj-get-location kcannon))
+                                                               (aimdir (direction-to-lvect facing))
+                                                               (targetloc (arms-searchline (car loc)
+                                                                       (cadr loc) (caddr loc)
+                                                                       (car aimdir) (cadr aimdir))))
+                                                               (kern-sound-play sound-cannon-fire)
+                                                               (kern-log-msg "BOOOM")
+                                                               (kern-fire-missile t_localcannonball loc (mk-loc (car loc) (car targetloc) (cadr targetloc)))
+                                                               )
+                                                       (bind kcannon (list facing 0)))
+                                               ((equal? ready 1)
+                                                       (kern-log-msg "Cannon ready to fire")
+                                                       (bind kcannon (list facing 2)))
+                                               (else
+                                                       (kern-log-msg "Cannon loaded")
+                                                       (bind kcannon (list facing 1)))
+                                       )
+                       ))
+               )
+               (method 'init
+                       (lambda (kcannon)
+                               (kern-obj-set-facing kcannon (car (gob kcannon)))
+                               (kern-obj-set-pclass kcannon pclass-boulder)
+               ))      
+       ))
+
+(mk-obj-type 't_cannonobj "cannon" s_cannon layer-mechanism cannon-ifc)     
+         
+(define  (arms-mk-cannon facing)
+       (let ((kcannon (kern-mk-obj t_cannonobj 1)))
+          (kern-obj-set-facing kcannon facing) 
+          (bind kcannon (list facing 0))
+          kcannon))
+
+;; Weapons that aren't affected by acid       
+(define arms-immune-to-acid
+  (list t_flaming_sword
+        t_shield_4
+        t_armor_plate_4
+        t_armor_chain_4
+        t_armor_leather_2
+        t_armor_leather_4
+        t_iron_helm_4
+        t_chain_coif_4
+        t_leather_helm_2
+        t_leather_helm_4
+        t_sword_2
+        t_sword_4
+        t_eldritch_blade
+        t_mystic_sword
+        t_magic_axe
+        t_doom_staff
+        t_stun_wand))
diff --git a/worlds/haxima-1.002/bakup.scm b/worlds/haxima-1.002/bakup.scm
new file mode 100644 (file)
index 0000000..1feb5e3
--- /dev/null
@@ -0,0 +1,32977 @@
+;; save.scm -- a nazghul session file
+;; Load the standard definitions file
+(load "naz.scm")
+
+(kern-load "game.scm")
+
+(kern-load "camping-map.scm")
+
+(kern-load "zones.scm")
+
+(kern-load "runes.scm")
+
+(kern-load "prices.scm")
+
+(kern-load "special.scm")
+
+(kern-load "town-entry.scm")
+
+(kern-load "endless-deeps-mech.scm")
+
+(kern-load "gregor.scm")
+
+(kern-load "kalcifax.scm")
+
+(kern-load "ilya.scm")
+
+(kern-mk-place 'p_gregors_hut "Gregor's Hut"
+  s_hamlet ;; sprite
+  (kern-mk-map
+    nil     32 32 pal_expanded
+    (list
+      "|| || || || tt tc .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. tC tt tt tt tt "
+      "|| || || || tt tB .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. t3 tt tt tt tt tt tt "
+      "|| || tt tt tt t5 .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. tC tt || || || tt tt tt "
+      "|| tt tt tt tt tt .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. tC t3 tt || || || tt tt tt "
+      "tt tt tt tt tt tt .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. tC t3 tt || || tt || || tt t# "
+      "tc t# .. t% tt tt tA .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. tb tt tt || tt tt tt || tt .. "
+      ".. .. .. .. ta tt tt td .. .. .. .. .. .. .. .. /7 .. .. .. .. .. t% ta tt || || tt || || tt .. "
+      ".. .. .. .. /0 /d /d /d /d /d /d /d /d /d /d /d /9 /d /d /d /d /d /d /2 ta tt || || || tt tc .. "
+      ".. .. .. /0 /a t3 tt t5 tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. /8 /d /d /2 ta tt tt t# .. "
+      ".. .. .. /7 t3 tt tt tt t5 rr rr ws rr rr rr ws rr rr rr rr rr bb bb bb bb bb /8 /d /2 te .. .. "
+      ".. .. .. /7 ta tt tt tt tt rr cc cc cc cc cc cc cc rr cc cc rr .. .. .. .. .. bb .. /7 .. .. .. "
+      ".. .. .. /7 t% ta tt tt tt rr cc cc cc cc cc cc cc rr cc cc rr t7 tA .. .. .. bb .. /7 .. .. .. "
+      ".. .. .. /7 .. t% tt || || rr cc cc [[ @@ ]] cc cc rr cc cc rr tt t5 tA .. .. bb .. /7 .. .. .. "
+      ".. .. .. /7 .. .. ta || |C rr cc cc cc cc cc cc cc rr cc cc rr tt tt t5 tA .. bb .. /7 .. .. .. "
+      ".. .. .. /7 .. .. rr rr rr rr cc cc cc cc cc cc cc cc cc cc rr tt tt || td .. bb .. /7 .. .. .. "
+      ".. .. .. /7 .. .. ws cc cc rr rr cc rr && rr rr rr rr rr rr rr ta tt tc t# .. bb .. /7 .. .. .. "
+      "/d /d /d /6 .. .. rr cc cc cc cc cc cc cc cc cc cc rr .. .. rr .. .. .. .. .. bb .. /4 /d /d /d "
+      ".. .. .. /7 .. .. rr rr rr rr cc cc cc cc cc cc cc rr .. .. rr .. .. .. .. .. bb .. /7 t3 tt tt "
+      ".. .. .. /7 .. .. rr cc cc rr cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. bb t7 /7 tt tt tt "
+      ".. .. .. /7 .. .. ws cc cc cc cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. bb te /7 tt tc %3 "
+      ".. .. .. /7 .. .. rr rr rr rr rr ws rr cc rr ws rr rr .. rr rr bb bb bb bb bb /0 /d /a te %3 %% "
+      ".. .. .. /7 .. .. .. .. .. .. .. tb td /7 .. tb tt td /4 /d /d /d /d /d /d /d /a t3 td %3 %% %% "
+      ".. .. .. /7 .. .. .. .. .. .. .. .. .. /7 .. .. .. .. /7 .. .. .. .. .. tC t3 tt tc %3 %% ~3 ~9 "
+      ".. .. .. /8 /d /d /d /d /d /d /d /d /d /9 /d /1 /d /d /a .. .. .. .. tC t3 tt tt %3 ~3 ~9 ~c %% "
+      ".. .. .. .. .. .. .. t3 tt t5 .. .. .. .. .. /7 .. .. t7 tA .. .. tb tt tt tt tc %% ~6 %% %% %% "
+      "tt t5 tA .. .. .. .. tt tt tt tA .. .. .. .. /7 .. .. tt tt t5 tA .. t% te ~3 ~9 ~9 ~c %% %% %% "
+      "|| tt t5 tA .. .. .. ta tt tt t5 .. .. .. .. /7 .. .. ta tt tt tt t5 .. .. ~6 .. tf %a %c t7 .. "
+      "|| || tt t5 tA .. .. t% ta tt tc .. .. .. .. /7 .. .. t% tt tt tt tc ~3 ~~ -4 .. .. .. t3 tt .. "
+      "|| || tt tt t5 tA .. .. .. .. .. .. .. .. .. /8 /2 .. .. tt tt tt ~3 ~8 ~8 ~c t3 t5 .. ta |C .. "
+      "|| || || tt tt t5 tA .. .. .. .. .. .. .. .. .. /7 .. .. tt tt tc ~6 t3 tt tt tt tt tA .. .. .. "
+      "|| || || || || tt t5 tA .. .. .. .. .. .. .. .. /7 .. .. tt tt ~3 ~c tt t# tD tt tt |% .. .. .. "
+      "|| || || || || || tt t5 .. .. .. .. .. .. .. .. /7 .. .. tt tt ~6 t3 tt .. t3 tt || || .. .. .. "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_gregors_hut
+    (list
+      (bind
+        (kern-mk-char
+          'ch_ilya
+          "Ilya"
+          sp_human
+          nil
+          s_child
+          2
+          0 10 5
+          0 0
+          0 0
+          19 0
+          9 9
+          #f ;; dead?
+          'ilya-conv
+          sch_ilya
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          #f
+        )
+      ) ;; bind
+    7 18)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    13 20)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 19)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 16)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_gregor
+          "Gregor"
+          sp_human
+          nil
+          s_townsman
+          2
+          0 10 5
+          0 0
+          0 0
+          19 0
+          9 9
+          #f ;; dead?
+          'gregor-conv
+          sch_gregor
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    7 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 15)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    17 14)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    18 20)
+    (list
+      (bind
+        (kern-mk-obj tf_ew_bridge 1
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    25 26)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    7 18)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    7 16)
+  ) ;; end of objects in p_gregors_hut
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 31 31) ;; Northwest
+    (list 1 16 31) ;; North
+    (list 2 0 31) ;; Northeast
+    (list 3 31 16) ;; West
+    (list 4 16 16) ;; Here
+    (list 5 0 16) ;; East
+    (list 6 31 0) ;; Southwest
+    (list 7 16 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_gregors_hut
+
+(kern-mk-place 'p_moongate_clearing "Moongate Clearing"
+  s_shrine ;; sprite
+  (kern-mk-map
+    nil     23 28 pal_expanded
+    (list
+      "^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^d t3 tt tt tt td ^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^5 "
+      "^^ {{ {{ {{ ^^ ^^ ^^ ^c t3 tt tt || || ^b ^^ ^^ {{ {{ {{ ^^ {{ {{ ^^ "
+      "^^ {{ {{ {{ {{ ^^ t3 tt tt || tt tt || |% ^a ^^ {C t7 {{ ^^ ^^ {{ ^^ "
+      "^^ {{ {{ {{ {{ {C tt || || || || tt || || |% ^e t3 tt {A {{ ^^ {{ ^^ "
+      "^^ ^^ {{ {{ {C t3 || || || || tt tt tt || || tt tt tt t5 {A {{ {{ ^^ "
+      "^^ ^^ ^^ ^^ t3 tt || || || tt tt tt tt tt tt tt tt tt tt td {{ ^^ ^^ "
+      "^^ ^^ ^^ ^^ || || || || tt tt tc bb ta tt tt tt tt tt || ^b ^^ ^^ ^c "
+      "^^ ^^ ^^ ^^ || || || tt tt bb .. .. .. bb tt tt tt || || |% ^a ^c |& "
+      "^^ ^^ ^^ ^c || || tt tt tt td .. .. .. tb tt tt tt tt || || || || || "
+      "^^ ^c |# || || || tt tt bb .. .. .. .. .. bb tt tt tt tt tt tt tt tt "
+      "^^ |# || || || || tt tc .. .. .. .. .. .. .. ta tt tt tt tt tt tt tc "
+      "{{ |A || || || || tt bb .. .. .. .. .. .. .. bb tt tt tt tt tt tc {& "
+      "{{ {% |A || || tt tt t5 .. .. .. .. .. .. .. t3 tt tc {# {% te {# {{ "
+      "^^ {{ {{ {{ {% ta tt tt bb .. .. .. .. .. bb tt tc {# {{ {{ {{ {{ {{ "
+      "^^ ^^ ^^ {{ {{ {% ta tt tt td .. .. .. tb tt tt {# ^^ ^^ {{ {{ ^^ ^^ "
+      "^^ ^^ ^^ ^^ {{ {{ {% ta tt bb .. .. .. bb tt tt {A ^^ ^^ ^^ {{ {{ ^^ "
+      "^^ ^^ {7 ^^ ^^ ^^ {{ {% tt td .. .. .. tb tt tt td {{ ^^ ^^ {{ {{ ^^ "
+      "^^ {3 .. {1 {5 ^^ {{ {{ tt bb .. .. .. bb tt tt {B {{ {{ {{ {{ ^^ ^^ "
+      "^^ {2 .. .. {4 ^^ {{ {{ tt td .. .. .. tb tt tt tt tt t5 {A ^^ ^^ ^^ "
+      "^^ {a .. {8 {c ^^ {{ {{ tt bb .. .. .. bb te bb te bb tt t5 ^^ ^^ ^^ "
+      "^^ ^^ {e ^^ ^^ ^^ {{ {{ tt td .. .. .. .. .. .. .. .. ta tt ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tt bb .. .. .. .. .. .. .. .. bb tt ^^ ^^ ^^ "
+      "^^ ^^ ,H ,A ,I ,L ^^ ^^ tt t5 .. .. .. .. .. .. .. .. tb tt ^a ^^ ^^ "
+      "^^ {3 .. .. .. .. {5 ^^ ta tc bb .. bb t7 bb .. .. .. bb tt t5 ^a ^^ "
+      "^^ {2 .. .. .. .. .. {9 .. .. .. tC t3 tt td .. .. .. tb tt tt t5 ^e "
+      "^^ {2 .. .. .. .. {4 ^^ t3 || tt tt tt tt bb .. .. .. bb tt tt tt t5 "
+      "^^ ,S ,E ,E ,K ,E ,R ^^ || || || tt tt tc .. .. .. .. .. ta tt tt tt "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ta || tt tt tc bb .. .. .. .. .. bb ta tt tc "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_moongate_clearing
+    (list
+      (kern-tag 'black-gate
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            '()
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    11 11)
+  ) ;; end of objects in p_moongate_clearing
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 22 27) ;; Northwest
+    (list 1 16 27) ;; North
+    (list 2 0 27) ;; Northeast
+    (list 3 22 10) ;; West
+    (list 4 11 14) ;; Here
+    (list 5 0 11) ;; East
+    (list 6 22 0) ;; Southwest
+    (list 7 11 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_moongate_clearing
+
+(kern-mk-place 'p_abandoned_cellar "Musty Cellar"
+  nil ;; sprite
+  (kern-mk-map
+    nil     32 32 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr rr {{ {{ {{ rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. {{ {{ {{ {{ .. {{ {{ rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. .. .. .. .. .. .. .. {{ {{ rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ .. .. .. .. .. .. .. .. .. .. {{ rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ .. {{ {{ {{ .. .. .. .. {{ rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr {{ {{ .. .. .. {{ rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ {{ {{ {{ {{ rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ .. {{ {{ rr rr rr "
+      "rr rr rr rr rr x! .. x! rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ {{ rr rr rr "
+      "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr x! .. x! rr rr rr rr rr rr rr rr rr rr {{ {{ {{ .. {{ {{ rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. .. .. .. {{ {{ rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ .. .. .. .. .. {{ {{ rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ .. {{ {{ {{ rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr {{ {{ {{ rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_abandoned_farm "Abandoned Farm"
+        s_hamlet ;; sprite
+        (kern-mk-map
+          nil           32 32 pal_expanded
+          (list
+            "tt tt || || || || || || || || || || || tt tt .. .. .. tt || || || || || || || || tt tt tt tt tt "
+            "tt tt || || || || || || || || || || || || tt .. .. .. ta || || || || tt || || || || tt tt bb tt "
+            "|| || || || || || || || || || tt || || || tt tA .. .. t% tt || || tt tt tt || || || || tt tt tt "
+            "|| || || || || || || || || tt tt tt || || tt t5 .. .. .. tt || tt tt tt tt tt || || || tt tt tt "
+            "|| || || || || || || || || || tt || || || tt tc .. .. .. tt || || tt tt tt tt || || || || || tt "
+            "|| || || || || || || || || || || || || || tt t# .. .. tC tt || || || tt || tt tt tt || || || || "
+            "|| || || || || || || || || || || || || tt tt .. .. .. t3 tt tt || || || || tt || tt tt tt tt || "
+            "|| || || tt tt || || || || || tt tt tt tt tc .. .. tC tt tt tt tt tt || tt tt || || || tt tt tt "
+            "|| || || tt tt tt tt tt tt tt tc t# .. .. .. .. .. tb tt tt tt tt tt tt tt || || || tt tt bb tt "
+            "|| || || tt tt tt tt tt tt tc t# .. bb bb bb bb bb bb bb bb tD ta tt tt tt tt tt || || tt tt tt "
+            "|| || tt tt t# .. .. .. .. .. .. bb .. .. .. .. .. .. tb tt td t& te bb ta tt tt tt || || tt || "
+            "|| || tt tt .. bb rr rr ws rr rr rr .. .. .. .. .. .. .. .. .. .. t% tf bb tt tt tt || || || || "
+            "|| || tt tt .. rr .. cc cc cc cc rr .. .. .. .. .. .. .. .. .. && .. .. bb tt tt tt || || || || "
+            "|| tt tt tt .. rr cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. .. .. .. bb tt bb ta || || || || "
+            "tt tt tt tc .. ws cc cc cc cc cc ws .. .. .. .. .. .. .. .. .. bb .. tf bb tt td t# .. t% |A || "
+            "t% ta tc t# .. rr cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. .. .. .. bb te t# .. .. .. t% |A "
+            ".. .. .. .. .. rr cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. .. .. .. bb .. .. tC tf tA .. .. "
+            ".. .. .. .. .. rr rr rr cc rr rr bb rr cc rr .. .. .. .. .. .. .. .. .. bb .. tC t7 bb t7 tA .. "
+            "t5 tA .. .. .. rr cc cc cc cc cc cc .. cc rr .. .. .. .. .. .. .. .. .. bb .. t3 tt tt tt tt tt "
+            "tt t5 tA .. .. ws cc cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. .. bb .. tt tt tt tt tt bb "
+            "tt tt t5 .. .. rr cc cc cc cc cc .. cc cc rr rr rr rr ws rr rr bb rr bb .. tC tt tt tt tt tt tt "
+            "tt tt tt tA .. rr cc cc cc [[ @@ ]] cc cc rr cc cc cc cc cc .. .. rr .. tC t3 tt || || || tt tt "
+            "|| || tt t5 .. ws cc cc cc cc cc cc cc cc rr cc cc cc cc cc cc cc rr .. t3 tt || || || || || tt "
+            "|| || tt tt .. rr cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ws tC tt || || || || || || tt "
+            "|| || || tt .. rr rr rr cc cc cc cc cc cc rr cc cc cc cc cc cc .. rr t3 tt || || || tt || || || "
+            "|| || || tt .. rr cc cc cc cc cc [[ @@ ]] rr cc cc cc cc cc .. .. bb tt tt || || || || || || || "
+            "|| || || tt .. rr rr rr rr ws rr rr rr rr rr rr rr rr ws rr rr rr rr tt tt || || || || || || tt "
+            "|| || || tt tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. tC t3 tt tt tt || || || || || tt tt "
+            "|| || tt tt tt tt tt tt tt tt tt tt tt t5 tA .. .. .. tC t3 tt tt tt tt tt tt || || || || tt tt "
+            "|| || tt tt || || || || || || || || tt tt t5 tA .. tC t3 tt tt || || || tt tt || || || || tt tt "
+            "|| || || || || || || || || || || || || tt tt t5 .. t3 tt tt || || || || || || || || || tt tt tt "
+            "|| || || || || || || || || || || || || || tt tt .. tt tt || || || tt || || || || || tt tt tt tt "
+          )
+        )
+        #f #f #f #f
+        ;; subplaces
+        nil
+        nil ;; neighbors
+        (list ;; objects in p_abandoned_farm
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'troll
+              )
+            ) ;; bind
+          19 14)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          13 17)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          7 25)
+          (list
+            (bind
+              (kern-mk-obj t_ladder_down 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'p_abandoned_cellar
+                6
+                25
+              )
+            ) ;; bind
+          6 25)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'queen-spider
+              )
+            ) ;; bind
+          9 23)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'troll
+              )
+            ) ;; bind
+          19 13)
+        ) ;; end of objects in p_abandoned_farm
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 31 31) ;; Northwest
+          (list 1 16 31) ;; North
+          (list 2 0 31) ;; Northeast
+          (list 3 31 16) ;; West
+          (list 4 16 16) ;; Here
+          (list 5 0 16) ;; East
+          (list 6 31 0) ;; Southwest
+          (list 7 16 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_abandoned_farm
+
+    9)
+  ) ;; end neighbors of p_abandoned_cellar
+  (list ;; objects in p_abandoned_cellar
+    (list
+      (kern-mk-field web-type 20)    7 13)
+    (list
+      (kern-mk-field web-type 20)    7 14)
+    (list
+      (kern-mk-field web-type 20)    7 15)
+    (list
+      (kern-mk-field web-type 20)    7 16)
+    (list
+      (kern-mk-field web-type 20)    8 13)
+    (list
+      (kern-mk-field web-type 20)    9 12)
+    (list
+      (kern-mk-field web-type 20)    9 13)
+    (list
+      (kern-mk-field web-type 20)    9 14)
+    (list
+      (kern-mk-field web-type 20)    10 12)
+    (list
+      (kern-mk-field web-type 20)    10 13)
+    (list
+      (kern-mk-field web-type 20)    10 14)
+    (list
+      (kern-mk-field web-type 20)    11 12)
+    (list
+      (kern-mk-field web-type 20)    11 13)
+    (list
+      (kern-mk-field web-type 20)    11 14)
+    (list
+      (kern-mk-field web-type 20)    9 16)
+    (list
+      (kern-mk-field web-type 20)    10 16)
+    (list
+      (kern-mk-field web-type 20)    10 17)
+    (list
+      (kern-mk-field web-type 20)    10 16)
+    (list
+      (kern-mk-field web-type 20)    11 17)
+    (list
+      (kern-mk-field web-type 20)    11 18)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    5 13)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    6 15)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    7 12)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    9 14)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    11 14)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    10 16)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    11 18)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          6
+          0 0 0
+          0 0
+          0 0
+          26 512
+          5 3
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 1 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    11 12)
+    (list
+      (kern-mk-obj t_puska 1
+        ;; hooks
+        (list
+        )
+      )
+    10 18)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_abandoned_farm
+          6
+          25
+        )
+      ) ;; bind
+    6 25)
+    (list
+      (kern-mk-field web-type 20)    5 12)
+    (list
+      (kern-mk-field web-type 20)    5 13)
+    (list
+      (kern-mk-field web-type 20)    5 14)
+    (list
+      (kern-mk-field web-type 20)    6 11)
+    (list
+      (kern-mk-field web-type 20)    6 12)
+    (list
+      (kern-mk-field web-type 20)    6 13)
+    (list
+      (kern-mk-field web-type 20)    6 14)
+    (list
+      (kern-mk-field web-type 20)    6 15)
+    (list
+      (kern-mk-field web-type 20)    7 12)
+  ) ;; end of objects in p_abandoned_cellar
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 31 31) ;; Northwest
+    (list 1 16 31) ;; North
+    (list 2 0 31) ;; Northeast
+    (list 3 31 16) ;; West
+    (list 4 16 16) ;; Here
+    (list 5 0 16) ;; East
+    (list 6 31 0) ;; Southwest
+    (list 7 16 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_abandoned_cellar
+
+p_abandoned_farm
+(kern-load "slimy-cavern-zones.scm")
+
+(kern-load "roland.scm")
+
+(kern-mk-place 'p_slimy_cavern "Slimy Cavern"
+  nil ;; sprite
+  (kern-mk-map
+    nil     16 32 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr .. .. .. rr "
+      "rr rr rr rr rr .. .. && .. .. rr rr .. .. .. rr "
+      "rr rr rr rr bb .. .. .. .. .. bb rr rr .. rr rr "
+      "rr bb .. .. bb .. .. .. .. .. bb .. .. .. rr rr "
+      "rr bb .. .. .. bb bb .. bb bb .. .. .. .. .. rr "
+      "rr .. .. .. .. .. .. .. .. .. .. .. .. .. .. rr "
+      "rr bb .. .. .. .. .. .. .. .. .. .. .. .. rr rr "
+      "rr rr bb .. .. .. .. .. .. .. .. .. rr rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. rr .. .. rr "
+      "rr .. .. .. .. .. .. rr rr .. .. rr rr .. .. rr "
+      "rr .. rr .. rr bb rr rr rr rr .. rr rr .. rr rr "
+      "rr %7 rr .. .. .. rr .. .. rr .. rr rr .. rr rr "
+      "~~ b~ b~ rr .. .. rr .. .. .. .. .. .. .. rr rr "
+      "rr ~a b~ ~4 .. .. rr rr .. rr rr .. rr rr rr rr "
+      "rr rr %a ~a ~9 ~1 b~ rr rr rr rr .. rr rr rr rr "
+      "rr .. .. .. .. ~a b~ b~ rr rr .. .. .. rr rr rr "
+      "rr .. rr .. %f rr b~ ~~ bb %7 .. .. .. rr rr rr "
+      "rr .. rr rr rr rr rr b~ ~~ ~5 %5 .. .. %7 rr rr "
+      "rr .. rr rr rr .. .. rr %% ~a b~ ~9 b~ ~1 ~5 rr "
+      "rr .. .. .. rr .. %b %% %% %% %c .. %% b~ ~8 ~~ "
+      "rr rr rr .. rr .. .. rr rr .. .. .. %e rr rr rr "
+      "rr rr rr .. rr rr rr rr rr .. .. .. .. .. bb rr "
+      "rr rr .. .. .. rr rr .. .. .. rr .. .. .. .. rr "
+      "rr .. .. .. .. .. .. .. rr rr rr .. .. .. .. rr "
+      "rr .. .. .. .. rr rr rr rr rr rr rr .. .. rr rr "
+      "rr rr .. .. rr rr rr .. .. .. rr rr rr .. rr rr "
+      "rr rr rr .. rr rr .. .. .. .. .. rr rr .. rr rr "
+      "rr .. .. .. .. .. .. .. .. .. .. .. .. .. .. rr "
+      "rr .. rr rr rr rr .. .. .. .. .. rr .. rr .. rr "
+      "rr .. rr rr rr rr rr .. .. .. rr rr .. .. .. rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_slimy_cavern
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    10 18)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    13 18)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_roland
+          "Roland"
+          sp_human
+          oc_warrior
+          s_human_knight
+          2
+          16 10 16
+          25 5
+          0 0
+          53 512
+          5 3
+          #f ;; dead?
+          'roland-conv
+          nil
+          'roland-ai
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          #f
+          #f
+        )
+      ) ;; bind
+    14 1)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 2 t_food)
+          (list 1 t_2h_sword)
+          (list 1 t_armor_chain)
+          (list 1 t_iron_helm)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    9 2)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_shard
+          13
+          8
+        )
+      ) ;; bind
+    8 30)
+    (list
+      (bind
+        (kern-mk-obj tf_ns_bridge 1
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    4 15)
+    (list
+      (bind
+        (kern-mk-obj tf_ns_bridge 1
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    11 19)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    13 3)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "blackguard"
+          sp_human
+          oc_wrogue
+          s_brigand
+          8
+          0 0 0
+          0 0
+          0 0
+          12 256
+          4 2
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'self-destruct-trap
+            ;; contents
+            (list
+              (list 8 t_bolt)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_sword
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "2d6-2"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_picklock
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      50
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_ex_por_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_wis_quas_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_sanct_lor_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_an_tym_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_vas_rel_por_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_mana_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_torch
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'blackguard
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    5 4)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "blackguard"
+          sp_human
+          oc_wrogue
+          s_brigand
+          8
+          0 0 0
+          0 0
+          0 0
+          12 256
+          4 2
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'sleep-trap
+            ;; contents
+            (list
+              (list 1 t_sword)
+              (list 4 t_bolt)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_crossbow
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "2d6-2"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_picklock
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      50
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_ex_por_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_wis_quas_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_sanct_lor_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_an_tym_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_vas_rel_por_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_mana_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_torch
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'blackguard
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    9 4)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "blackguard"
+          sp_human
+          oc_wrogue
+          s_brigand
+          8
+          0 0 0
+          0 0
+          0 0
+          12 256
+          4 2
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'sleep-trap
+            ;; contents
+            (list
+              (list 1 t_sword)
+              (list 7 t_bolt)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_crossbow
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "2d6-2"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_picklock
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      50
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_ex_por_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_wis_quas_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_sanct_lor_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_an_tym_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_vas_rel_por_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_mana_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_torch
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'blackguard
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    9 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    9 17)
+  ) ;; end of objects in p_slimy_cavern
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 15 31) ;; Northwest
+    (list 1 8 31) ;; North
+    (list 2 0 31) ;; Northeast
+    (list 3 15 16) ;; West
+    (list 4 8 16) ;; Here
+    (list 5 0 16) ;; East
+    (list 6 15 0) ;; Southwest
+    (list 7 8 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_slimy_cavern
+
+(kern-load "jim.scm")
+
+(kern-load "gwen.scm")
+
+(kern-load "chanticleer.scm")
+
+(kern-load "earl.scm")
+
+(kern-load "miggs.scm")
+
+(kern-mk-place 'p_trigrave "Trigrave"
+  s_town ;; sprite
+  (kern-mk-map
+    nil     32 32 pal_expanded
+    (list
+      "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt "
+      "tt xx xx xx xx xx xx xx xx xx xx xx xx xx tt tt td .. .. .. tb tt tt tt xx xx xx xx xx xx xx tt "
+      "tt xx cc cc x! .G .R .A .Y @@ x! cc cc xx tt tt bb .. .. .. bb tt tt tt xx .I .R .O .N @@ xx tt "
+      "tt xx cc cc x! @@ .D .O .V .E x! cc cc xx tt tt td .. .. .. tb tt tt tt xx .W .O .R .K .S xx tt "
+      "tt cc cc cc cc cc cc cc cc cc cc cc cc xx tt tt bb .. .. .. bb ta tt tt ws cc cc cc cc cc xx tt "
+      "tt xx xx xx x! @@ .I .N .N @@ x! xx xx xx tt tt td .. .. .. .. .. bb ta sA cc cc cc cc cc xx tt "
+      "tt xx cc cc xx cc cc cc cc cc xx cc cc xx tt tt bb .. .. .. .. .. .. tD cc cc cc cc cc __ xx tt "
+      "tt xx cc cc cc cc cc cc cc cc cc cc cc xx tt tt td .. .. .. .. .. bb t3 xx cc cc cc cc !! xx tt "
+      "tt xx xx xx x! cc cc cc cc cc x! xx xx xx tt tt bb .. .. .. bb t3 tt tt ws cc cc cc cc cc xx tt "
+      "tt xx cc cc cc cc cc cc cc cc cc cc cc xx tt tt td .. .. .. tb tt tt tt xx xx cc xx cc xx xx tt "
+      "tt xx cc cc xx cc cc cc cc cc xx cc cc xx tt tt bb .. .. .. bb tt tt tt xx cc cc x! cc cc xx tt "
+      "tt xx xx xx xx ws x! cc x! ws xx xx xx xx tt tt td .. .. .. tb tt tt tt xx cc cc xx cc cc xx tt "
+      "tt tt tt tt tt tc bb .. bb tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt xx xx xx xx xx xx xx tt "
+      "tt tt tt tt tc sI .. .. .. ta tt tt tt tt tt tc .. .. .. .. .. ta tt tt tt tt tt tt tt tt tt tt "
+      "bb te bb te bb .. .. .. .. .. bb te bb te bb .. .. .. .. .. .. .. bb te bb te bb te bb te bb ta "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      "bb t7 bb t7 bb t7 bb t7 bb .. .. .. .. .. .. .. bb t7 bb t7 bb t7 bb t7 bb t7 bb t7 bb t7 bb t3 "
+      "tt tt tt tt tt tt tt tt tt t5 .. .. .. .. .. t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+      "tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+      "tt xx xx xx xx xx xx xx tt tt td .. .. .. tb tt tt xx xx xx xx xx xx xx xx xx xx xx xx xx xx tt "
+      "tt xx @@ .D .R .Y @@ xx tt tt bb .. .. .. bb tt tt xx x! @@ .L .U .S .T .Y x! xx cc cc cc xx tt "
+      "tt xx .G .O .O .D .S xx tt tt td .. .. .. .. ta tt ws cc cc 00 cc cc 00 cc cc xx cc cc cc xx tt "
+      "tt cc cc cc cc cc cc ws tt tt bb .. .. .. .. .. bb sT cc cc 00 cc cc 00 cc cc x! xx cc xx xx tt "
+      "tt xx @@ @@ @@ @@ @@ xx tt tt td .. .. .. .. .. .. cc cc cc cc cc cc cc cc cc cc cc cc cc xx tt "
+      "tt xx cc cc cc cc cc sE bb .. .. .. .. .. .. .. .. cc cc cc cc cc cc cc cc cc cc cc cc && xx tt "
+      "tt xx cc cc cc cc cc cc .. .. .. .. .. .. .. .. bb xx cc cc 00 cc cc 00 cc cc x! cc cc && xx tt "
+      "tt xx cc cc cc cc cc xx bb .. .. .. .. .. .. t3 tt ws cc cc 00 cc cc 00 cc cc xx cc cc cc xx tt "
+      "tt xx cc cc cc cc cc ws tt tt td .. .. .. bb tt tt xx x! @@ .J .U .G .S @@ x! xx cc cc cc xx tt "
+      "tt xx xx xx xx xx xx xx tt tt bb .. .. .. tb tt tt xx xx xx xx xx xx xx xx xx xx xx ws xx xx tt "
+      "tt tt tt tt tt tt tt tt tt tt t5 .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_trigrave
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    1 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    10 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 11)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    2 6)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    12 6)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    12 9)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    12 2)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    2 9)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_stun_wand)
+          (list 3 t_xen_corp_scroll)
+          (list 3 t_in_vas_por_ylem_scroll)
+          (list 5 t_vas_mani_scroll)
+        )
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    2 10)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    1 24)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 27)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 6)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    26 9)
+    (list
+      (kern-tag 'tiw-portcullis
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    28 9)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tiw-portcullis
+          #f
+          '()
+        )
+      ) ;; bind
+    25 11)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    25 10)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_scratched_shield)
+          (list 1 t_armor_plate)
+          (list 1 t_iron_helm)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    28 11)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 100 t_gold_coins)
+          (list 3 t_dagger)
+          (list 3 t_mace)
+          (list 3 t_sword)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    29 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    28 24)
+    (list
+      (kern-tag 'tlj-d-1
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            'tlj-d-2
+            #f
+            #f
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    17 25)
+    (list
+      (kern-tag 'tlj-d-2
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            'tlj-d-1
+            #f
+            #f
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    17 26)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    27 22)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_jim
+          "Jim"
+          sp_human
+          nil
+          s_townsman
+          2
+          0 10 5
+          0 0
+          0 0
+          19 0
+          9 9
+          #f ;; dead?
+          'jim-conv
+          sch_jim
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    18 23)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_gwen
+          "Gwen"
+          sp_human
+          nil
+          s_gwen
+          2
+          0 10 5
+          0 0
+          0 0
+          19 0
+          9 9
+          #f ;; dead?
+          'gwen-conv
+          sch_gwen
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    5 4)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_chant
+          "Chanticleer"
+          sp_human
+          nil
+          s_chanticleer
+          2
+          0 10 5
+          0 0
+          0 0
+          19 0
+          9 9
+          #f ;; dead?
+          'chant-conv
+          sch_chant
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+        )
+      ) ;; bind
+    18 23)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_earl
+          "Earl"
+          sp_human
+          nil
+          s_townsman
+          2
+          0 10 5
+          0 0
+          0 0
+          19 0
+          9 9
+          #f ;; dead?
+          'earl-conv
+          sch_earl
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    2 9)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_miggs
+          "Miggs"
+          sp_human
+          nil
+          s_fat_townswoman
+          2
+          12 10 8
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'miggs-conv
+          sch_miggs
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    27 25)
+    (list
+      (kern-tag 'trigrave-inn-room-1-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    4 7)
+    (list
+      (kern-tag 'trigrave-inn-room-2-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    4 9)
+    (list
+      (kern-tag 'trigrave-inn-room-3-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    10 9)
+    (list
+      (kern-tag 'trigrave-inn-room-4-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    10 7)
+  ) ;; end of objects in p_trigrave
+  (list ;; on-entry-hooks
+    'lock-inn-room-doors
+  )
+  (list ;; edge entrances
+    (list 0 31 31) ;; Northwest
+    (list 1 12 31) ;; North
+    (list 2 0 31) ;; Northeast
+    (list 3 31 16) ;; West
+    (list 4 16 16) ;; Here
+    (list 5 0 16) ;; East
+    (list 6 31 0) ;; Southwest
+    (list 7 18 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_trigrave
+
+(kern-load "warritrix.scm")
+
+(kern-mk-place 'p_lost_halls_4 "Lost Halls South"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr .. .. .. ,, .. rr ,, .. ,, rr rr "
+      "rr rr rr rr .. .. .. rr .. .. .. ,, .. ,, ,, ,, ,, ,, rr "
+      "rr rr .. .. .. .. .. .. .. .. xx ,, ,, .. ,, ,, ,, ,, rr "
+      "rr rr .. .. .. .. .. .. .. .. .. xx rr ,, ,, ,, ,, ,, rr "
+      "rr .. .. .. bb .. .. .. .. .. .. xx rr rr rr ,, ,, ,, rr "
+      "rr .. .. .. .. .. .. .. bb .. .. rr xx rr rr ,, bb ,, rr "
+      "rr rr .. .. .. .. .. .. .. .. .. rr xx rr rr ,, ,, ,, rr "
+      "rr rr .. .. .. .. .. .. .. .. rr rr rr xx rr rr ,, ,, ,, "
+      "rr rr rr .. .. .. .. .. rr rr rr rr rr rr xx ,, ,, ,, ,, "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr xx xx ,, ,, "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr ,, .. "
+      "rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr rr .. .. .. "
+      "rr rr rr .. .. .. .. .. .. .. rr rr .. rr .. .. .. .. rr "
+      "rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr .. rr "
+      "rr rr .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr .. .. .. .. .. rr rr rr .. .. rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_lost_halls_1 "Lost Halls Entrance"
+        nil ;; sprite
+        (kern-mk-map
+          nil           19 19 pal_expanded
+          (list
+            "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+            "rr xx xx rr .. rr rr .. .. rr rr rr rr rr rr rr rr rr rr "
+            "rr xx cc cc .. .. .. .. .. .. [[ @@ ]] rr rr rr rr rr rr "
+            "rr rr cc cc .. .. .. .. .. .. .. .. .. .. .. rr rr rr rr "
+            "rr .. .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr rr "
+            "rr .. .. .. .. .. .. .. .. .. .. && .. .. .. rr .. .. rr "
+            "rr .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. rr "
+            "rr .. .. .. .. .. .. .. .. .. bb .. bb .. .. .. .. .. .. "
+            "rr rr .. .. .. .. && .. .. .. .. .. .. .. .. .. .. .. ,, "
+            "rr rr rr .. .. .. .. .. .. .. .. %3 %d rr rr xx .. ,, ,, "
+            "rr rr rr .. .. .. .. .. .. %b %% %% rr rr xx rr rr ,, ,, "
+            "rr rr rr .. .. .. .. .. rr rr ~1 ~~ rr xx rr ,, ,, ,, ,, "
+            "rr rr rr rr .. .. rr rr rr rr -- -- xx rr ,, ,, ,, ,, rr "
+            "rr rr rr rr .. .. rr rr rr rr rr rr xx ,, ,, ,, ,, rr rr "
+            "rr rr rr .. .. .. rr rr rr rr rr xx rr ,, ,, ,, ,, rr rr "
+            "rr rr rr .. .. .. .. .. .. .. rr xx rr ,, ,, ,, ,, rr rr "
+            "rr rr rr .. .. .. .. .. .. .. rr xx rr rr rr && rr rr rr "
+            "rr rr rr rr .. .. rr rr .. .. .. rr rr rr rr rr rr rr rr "
+            "rr rr rr rr rr rr rr rr .. .. .. ,, rr ,, ,, ,, rr rr rr "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        (list
+          (list
+            (kern-mk-place 'p_lost_halls_2 "Lost Halls East"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                  "rr rr rr rr rr rr rr rr rr rr rr rr .. .. .. rr rr rr rr "
+                  "rr rr rr rr rr rr rr rr rr rr .. .. .. .. .. rr rr rr rr "
+                  "rr .. rr rr rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr "
+                  "rr .. .. .. rr rr rr .. .. .. .. .. .. rr .. .. .. .. rr "
+                  "rr .. .. .. .. .. .. .. .. .. .. .. .. rr .. .. .. .. rr "
+                  "rr .. .. .. .. .. .. .. .. .. .. .. .. rr .. .. .. .. rr "
+                  ".. .. xx xx .. .. .. .. .. .. .. .. rr rr .. rr rr .. rr "
+                  ".. .. .X .. .O .. xx xx xx .. .. rr rr rr .. rr rr .. rr "
+                  ",, ,, ,, ,, ,, ,, xx ,, ,, xx xx .. rr rr .. rr rr .. .. "
+                  ".. ,, ,, ,, ,, ,, xx ,, ,, ,, ,, xx .. .. .. .. .. ,, rr "
+                  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, ,, rr "
+                  "rr rr ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx .. rr .. rr rr "
+                  "rr rr rr ,, ,, ,, rr rr rr ,, ,, ,, rr xx rr .. .. .. rr "
+                  "rr rr rr rr ,, ,, rr rr rr rr ,, ,, rr rr xx .. .. .. rr "
+                  "rr rr tb td ,, ,, rr rr rr rr ,, ,, rr rr xx rr .. .. rr "
+                  "rr tf t# .. .. ,, rr rr rr rr ,, ,, ,, rr xx rr rr .. rr "
+                  "rr xx xx xx .. .. .. ,, ,, ,, ,, ,, ,, ,, ,, xx rr .. rr "
+                  "rr xx rr rr rr rr bb ,, ,, ,, ,, ,, rr rr rr xx xx rr rr "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              (list
+                (list
+                  (kern-mk-place 'p_lost_halls_3 "Lost Halls Keep"
+                    nil ;; sprite
+                    (kern-mk-map
+                      nil                       19 19 pal_expanded
+                      (list
+                        "rr rr rr rr rr rr rr rr rr rr xx xx xx xx xx xx xx xx rr "
+                        "rr rr rr rr rr .. .. rr rr rr xx ,L ,A ,R ,D ,E ,R xx rr "
+                        "rr rr rr .. .. .. .. .. rr rr xx ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr .. .. .. .. .. .. rr rr xx ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr rr .. .. .. .. bb rr rr xx ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr rr rr rr .. rr rr rr rr xx xx xx ,, ,, xx xx xx rr "
+                        "rr rr rr ,, ,, ,, ,, ,, rr xx xx xx xx ,, ,, xx xx xx rr "
+                        "rr rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr ,, ,, pp ,, pp ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr "
+                        ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr .. ,, pp ,, pp ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr "
+                        "rr rr rr rr rr rr rr rr xx xx xx ,, ,, xx xx xx xx xx rr "
+                        "rr rr rr rr rr rr rr rr xx xx xx ,, ,, xx xx xx xx rr rr "
+                        "rr rr xx xx xx xx rr rr xx ,, ,, ,, ,, ,, ,, xx xx rr rr "
+                        "xx xx xx xx xx xx xx xx xx ,, ,, ,, ,, ,, ,, xx xx rr rr "
+                        "xx xx xx xx xx xx xx xx xx ,, ,, ,, ,, ,, ,, xx xx rr rr "
+                        "xx xx xx xx xx xx xx xx ,, ,, ,, xx xx xx xx xx xx rr rr "
+                      )
+                    )
+                    #f #t #f #f
+                    ;; subplaces
+                    nil
+                    (list
+                      (list
+                        (kern-mk-place 'p_lost_halls_6 "Lost Halls End"
+                          nil ;; sprite
+                          (kern-mk-map
+                            nil                             19 19 pal_expanded
+                            (list
+                              "rr rr rr rr rr rr rr rr .. .. .. bb bb bb bb bb bb rr rr "
+                              "rr rr rr rr rr rr rr t3 tt t5 .. bb .. .. .. bb t3 t5 rr "
+                              "rr rr rr rr rr rr rr ta tt tc .. .. tf bb .. tC tt tc rr "
+                              "rr rr rr rr rr rr rr rr te tB bb .. .. .. tC t3 tc rr rr "
+                              "rr rr rr rr rr rr rr rr rr tb td tA .. bb tb tc rr rr rr "
+                              "rr rr bb rr rr rr rr rr rr rr rr tf .. .. rr rr rr rr rr "
+                              "rr rr rr rr rr rr rr rr rr rr rr .. bb .. rr rr rr rr rr "
+                              "rr rr rr rr bb rr rr rr rr rr rr .. .. .. rr rr rr rr rr "
+                              "rr rr rr rr rr bb rr rr ,R rr .. .. .. .. rr rr rr rr rr "
+                              "rr rr rr rr rr rr rr rr bb tf .. bb .. .. %7 bb rr rr rr "
+                              "rr rr rr rr rr rr rr rr .. .. .. .. bb .. %% %d bb rr rr "
+                              "rr rr rr rr rr rr rr bb .. .. bb .. .. %3 %% tf %3 ,T rr "
+                              "rr rr ,, xx xx rr rr bb .. bb tb t5 .. _b _1 _1 __ rr rr "
+                              "rr ,, ,, ,, xx rr ,A %d .. .. t% te .. ~% __ __ __ _5 rr "
+                              "rr ,, ,, ,, xx rr rr rr bb .. bb .. .. .. __ ~B ~D _4 rr "
+                              "bb ,, ,, ,, xx rr rr rr rr tf %3 __ _1 bb __ __ __ _c rr "
+                              "xx bb xx xx xx rr rr rr ,Q %% _3 __ __ __ __ __ bb rr rr "
+                              "rr rr rr rr rr rr rr rr rr rr bb _8 _8 _8 _8 bb ,P rr rr "
+                              "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                            )
+                          )
+                          #f #t #f #f
+                          ;; subplaces
+                          nil
+                          (list
+                            (list
+                              (kern-mk-place 'p_lost_halls_5 "Lost Halls Feast Room"
+                                nil ;; sprite
+                                (kern-mk-map
+                                  nil                                   19 19 pal_expanded
+                                  (list
+                                    "rr rr rr rr rr rr rr .. .. .. .. .. rr rr rr rr rr rr rr "
+                                    "rr .. .. .. .. rr rr .. .. .. .. .. rr rr rr rr rr rr rr "
+                                    "rr .. rr bb .. .. rr .. .. .. .. rr rr rr rr rr rr rr rr "
+                                    "rr .. rr rr .. .. rr .. .. .. .. rr rr rr rr rr rr rr rr "
+                                    "rr .. .. .. .. rr rr .. .. .. rr rr rr rr cc cc rr rr rr "
+                                    "rr rr .. rr rr rr rr .. .. .. rr ,, cc cc cc cc cc cc rr "
+                                    "rr .. .. .. rr rr rr .. .. .. .. ,, cc cc cc cc cc cc rr "
+                                    ".. .. bb .. rr rr bb .. .. .. .. pp cc cc 00 00 cc cc rr "
+                                    ".. .. .. .. rr bb && .. .. .. .. ,, cc cc 00 00 cc cc rr "
+                                    ".. .. .. .. rr bb && .. .. .. .. ,, cc cc 00 00 cc cc rr "
+                                    ".. .. bb .. rr bb && .. .. .. .. ,, cc cc 00 00 cc cc rr "
+                                    ".. .. .. .. rr rr bb .. .. .. .. ,, cc cc 00 00 cc cc rr "
+                                    "rr .. .. rr rr rr rr .. .. .. .. pp cc cc 00 00 cc cc rr "
+                                    "rr rr .. .. .. .. rr rr .. .. .. ,, cc cc cc cc cc cc rr "
+                                    "rr rr .. rr rr .. rr rr rr .. rr ,, cc cc cc cc cc cc rr "
+                                    "rr rr .. rr bb .. rr rr rr rr rr rr rr bb cc cc rr rr rr "
+                                    "rr rr .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                                    "rr rr rr .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                                    "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                                  )
+                                )
+                                #f #t #f #f
+                                ;; subplaces
+                                nil
+                                nil ;; neighbors
+                                (list ;; objects in p_lost_halls_5
+                                  (list
+                                    (bind
+                                      (kern-mk-obj t_monman 1
+                                        ;; hooks
+                                        (list
+                                        )
+                                      )
+                                      (list
+                                        'monman
+                                        (list
+                                          0
+                                          0
+                                          0
+                                          -1
+                                          6
+                                          -1
+                                        )
+                                      )
+                                    ) ;; bind
+                                  0 0)
+                                  (list
+                                    (bind
+                                      (kern-mk-obj t_spawn_pt 1
+                                        ;; hooks
+                                        (list
+                                        )
+                                      )
+                                      (list
+                                        'spawn-pt
+                                        'giant-spider
+                                      )
+                                    ) ;; bind
+                                  0 9)
+                                  (list
+                                    (bind
+                                      (kern-mk-obj t_spawn_pt 1
+                                        ;; hooks
+                                        (list
+                                        )
+                                      )
+                                      (list
+                                        'spawn-pt
+                                        'gint-warrior
+                                      )
+                                    ) ;; bind
+                                  13 8)
+                                  (list
+                                    (bind
+                                      (kern-mk-obj t_spawn_pt 1
+                                        ;; hooks
+                                        (list
+                                        )
+                                      )
+                                      (list
+                                        'spawn-pt
+                                        'gint-warrior
+                                      )
+                                    ) ;; bind
+                                  16 10)
+                                  (list
+                                    (bind
+                                      (kern-mk-obj t_spawn_pt 1
+                                        ;; hooks
+                                        (list
+                                        )
+                                      )
+                                      (list
+                                        'spawn-pt
+                                        'gint-mage
+                                      )
+                                    ) ;; bind
+                                  14 13)
+                                ) ;; end of objects in p_lost_halls_5
+                                (list ;; on-entry-hooks
+                                  'on-entry-to-dungeon-room
+                                )
+                                (list ;; edge entrances
+                                  (list 0 18 18) ;; Northwest
+                                  (list 1 9 18) ;; North
+                                  (list 2 0 18) ;; Northeast
+                                  (list 3 18 9) ;; West
+                                  (list 4 9 9) ;; Here
+                                  (list 5 0 9) ;; East
+                                  (list 6 18 0) ;; Southwest
+                                  (list 7 9 0) ;; South
+                                  (list 8 0 0) ;; SoutheastUp
+                                )
+                              ) ;; end of place p_lost_halls_5
+
+                            3)
+                          ) ;; end neighbors of p_lost_halls_6
+                          (list ;; objects in p_lost_halls_6
+                            (list
+                              (bind
+                                (kern-mk-obj t_corpse 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  (list
+                                    (list
+                                      1
+                                      't_rune_l
+                                    )
+                                    (list
+                                      1
+                                      't_armor_chain_4
+                                    )
+                                    (list
+                                      1
+                                      't_chain_coif_4
+                                    )
+                                    (list
+                                      1
+                                      't_sword_4
+                                    )
+                                    (list
+                                      1
+                                      't_shield_4
+                                    )
+                                    (list
+                                      1
+                                      't_warritrix_orders
+                                    )
+                                  )
+                                )
+                              ) ;; bind
+                            12 12)
+                            (list
+                              (bind
+                                (kern-mk-obj t_corpse 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  (list
+                                    (list
+                                      4
+                                      't_bolt
+                                    )
+                                    (list
+                                      1
+                                      't_food
+                                    )
+                                  )
+                                )
+                              ) ;; bind
+                            14 2)
+                            (list
+                              (bind
+                                (kern-mk-obj t_corpse 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  (list
+                                    (list
+                                      5
+                                      't_bolt
+                                    )
+                                    (list
+                                      1
+                                      't_torch
+                                    )
+                                  )
+                                )
+                              ) ;; bind
+                            13 10)
+                            (list
+                              (bind
+                                (kern-mk-obj t_corpse 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  (list
+                                    (list
+                                      1
+                                      't_food
+                                    )
+                                    (list
+                                      4
+                                      't_arrow
+                                    )
+                                  )
+                                )
+                              ) ;; bind
+                            11 7)
+                            (list
+                              (bind
+                                (kern-mk-obj t_corpse 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  (list
+                                    (list
+                                      1
+                                      't_gold_coins
+                                    )
+                                    (list
+                                      4
+                                      't_arrow
+                                    )
+                                    (list
+                                      2
+                                      't_bolt
+                                    )
+                                  )
+                                )
+                              ) ;; bind
+                            12 8)
+                            (list
+                              (bind
+                                (kern-mk-obj t_corpse 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  (list
+                                    (list
+                                      1
+                                      't_heal_potion
+                                    )
+                                  )
+                                )
+                              ) ;; bind
+                            8 10)
+                            (list
+                              (bind
+                                (kern-mk-obj t_monman 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  'monman
+                                  (list
+                                    0
+                                    0
+                                    0
+                                    -1
+                                    6
+                                    -1
+                                  )
+                                )
+                              ) ;; bind
+                            0 0)
+                            (list
+                              (bind
+                                (kern-mk-obj t_spawn_pt 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  'spawn-pt
+                                  'yellow-slime
+                                )
+                              ) ;; bind
+                            16 11)
+                          ) ;; end of objects in p_lost_halls_6
+                          (list ;; on-entry-hooks
+                            'on-entry-to-dungeon-room
+                          )
+                          (list ;; edge entrances
+                            (list 0 18 18) ;; Northwest
+                            (list 1 9 18) ;; North
+                            (list 2 0 18) ;; Northeast
+                            (list 3 18 9) ;; West
+                            (list 4 9 9) ;; Here
+                            (list 5 0 9) ;; East
+                            (list 6 18 0) ;; Southwest
+                            (list 7 9 0) ;; South
+                            (list 8 0 0) ;; SoutheastUp
+                          )
+                        ) ;; end of place p_lost_halls_6
+
+                      7)
+                    ) ;; end neighbors of p_lost_halls_3
+                    (list ;; objects in p_lost_halls_3
+                      (list
+                        (bind
+                          (kern-mk-obj t_corpse 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            (list
+                              (list
+                                1
+                                't_mana_potion
+                              )
+                              (list
+                                1
+                                't_food
+                              )
+                            )
+                          )
+                        ) ;; bind
+                      5 2)
+                      (list
+                        (bind
+                          (kern-mk-obj t_corpse 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            (list
+                              (list
+                                1
+                                't_torch
+                              )
+                              (list
+                                3
+                                't_arrow
+                              )
+                            )
+                          )
+                        ) ;; bind
+                      7 3)
+                      (list
+                        (bind
+                          (kern-mk-obj t_monman 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'monman
+                            (list
+                              0
+                              0
+                              0
+                              -1
+                              6
+                              -1
+                            )
+                          )
+                        ) ;; bind
+                      0 0)
+                      (list
+                        (bind
+                          (kern-mk-obj t_spawn_pt 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'spawn-pt
+                            'green-slime
+                          )
+                        ) ;; bind
+                      9 18)
+                      (list
+                        (bind
+                          (kern-mk-obj t_spawn_pt 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'spawn-pt
+                            'gint-warrior
+                          )
+                        ) ;; bind
+                      13 9)
+                      (list
+                        (bind
+                          (kern-mk-obj t_spawn_pt 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'spawn-pt
+                            'gint-mage
+                          )
+                        ) ;; bind
+                      14 10)
+                    ) ;; end of objects in p_lost_halls_3
+                    (list ;; on-entry-hooks
+                      'on-entry-to-dungeon-room
+                    )
+                    (list ;; edge entrances
+                      (list 0 18 18) ;; Northwest
+                      (list 1 9 18) ;; North
+                      (list 2 0 18) ;; Northeast
+                      (list 3 18 9) ;; West
+                      (list 4 9 9) ;; Here
+                      (list 5 0 9) ;; East
+                      (list 6 18 0) ;; Southwest
+                      (list 7 9 0) ;; South
+                      (list 8 0 0) ;; SoutheastUp
+                    )
+                  ) ;; end of place p_lost_halls_3
+
+                5)
+                (list
+                  p_lost_halls_5
+                7)
+              ) ;; end neighbors of p_lost_halls_2
+              (list ;; objects in p_lost_halls_2
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                0 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'gint-warrior
+                    )
+                  ) ;; bind
+                9 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_corpse 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      (list
+                        (list
+                          3
+                          't_gold_coins
+                        )
+                        (list
+                          1
+                          't_torch
+                        )
+                      )
+                    )
+                  ) ;; bind
+                12 1)
+                (list
+                  (bind
+                    (kern-mk-obj t_corpse 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      (list
+                        (list
+                          5
+                          't_arrow
+                        )
+                        (list
+                          1
+                          't_bolt
+                        )
+                        (list
+                          2
+                          't_gold_coins
+                        )
+                      )
+                    )
+                  ) ;; bind
+                14 2)
+              ) ;; end of objects in p_lost_halls_2
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_lost_halls_2
+
+          5)
+        ) ;; end neighbors of p_lost_halls_1
+        (list ;; objects in p_lost_halls_1
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'giant-spider
+              )
+            ) ;; bind
+          9 18)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'troll
+              )
+            ) ;; bind
+          7 8)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'cave-goblin-slinger
+              )
+            ) ;; bind
+          18 8)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'green-slime
+              )
+            ) ;; bind
+          2 2)
+          (list
+            (bind
+              (kern-mk-obj t_ladder_up 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'p_shard
+                39
+                75
+              )
+            ) ;; bind
+          2 2)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          5 17)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          9 10)
+        ) ;; end of objects in p_lost_halls_1
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 18 18) ;; Northwest
+          (list 1 9 18) ;; North
+          (list 2 0 18) ;; Northeast
+          (list 3 18 9) ;; West
+          (list 4 9 9) ;; Here
+          (list 5 0 9) ;; East
+          (list 6 18 0) ;; Southwest
+          (list 7 9 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_lost_halls_1
+
+    1)
+    (list
+      p_lost_halls_5
+    5)
+  ) ;; end neighbors of p_lost_halls_4
+  (list ;; objects in p_lost_halls_4
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    5 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    5 13)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'troll
+        )
+      ) ;; bind
+    9 0)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+            (list
+              5
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    7 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+            (list
+              1
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    7 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              3
+              't_bolt
+            )
+            (list
+              1
+              't_gem
+            )
+          )
+        )
+      ) ;; bind
+    8 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_torch
+            )
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    5 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    4 11)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_lost_halls_4
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_lost_halls_4
+
+p_lost_halls_1
+p_lost_halls_6
+p_lost_halls_3
+p_lost_halls_2
+p_lost_halls_5
+(kern-load "zane.scm")
+
+(kern-load "enchanter.scm")
+
+(kern-mk-place 'p_enchanters_tower "Enchanters Tower"
+  s_keep ;; sprite
+  (kern-mk-map
+    nil     31 31 pal_expanded
+    (list
+      "tt tt bb te bb || || tt %a %% %% %% %% %c .. .. .. %a %% %% %% %% %% %% %% %% %% %% %% %% %% "
+      "bb te .. t% tb tt || || tt t5 %% %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. bb .. %a %% "
+      "td t# .. .. .. .. bb || || tt %% %% %% .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. %% "
+      "bb .. .. .. .. .. .. ta || || %a %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. .. .. bb %% "
+      "|| .. .. .. .. .. .. .. bb || t5 %% %% %d .. .. .. %b %% %% %% %% %% %% %% %% %5 .. .. .. %% "
+      "|| bb .. .. .. .. .. .. .. || || %a %c xx w+ cc w+ xx %e tb tt tt tt tt t5 %a %% bb .. bb %% "
+      "|| || .. .. .. .. && .. .. ta || xx xx xx ,, cc ,, xx xx xx || || || tt tt t5 %% .. .. .. %% "
+      "tc bb .. .. bb .. .. .. .. xx w+ xx && xx ,, cc ,, xx && xx xx xx || || || tt %% bb .. bb %% "
+      "%5 .. .. || || tA .. .. xx xx ,, ,, ,, xx x! cc x! xx ,, ,, xx xx ?? xx || tt %% .. .. .. %% "
+      "%% bb .. bb || t5 tA xx xx ,, ,, ,, ,, xx ,, cc ,, ,, ,, ,, xx ,, ,, xx || tt %% bb .. bb %% "
+      "%% .. .. || || tt td xx ,, ,, 00 ,, ,, xx ,, cc ,, xx xx xx xx xx xx xx || tc %% .. .. .. %% "
+      "%% bb .. bb || || xx xx ,, ,, 00 ,, ,, xx ,, cc ,, xx ,, ,, ,, ,, ,, xx xx %3 %% bb .. bb %% "
+      "%% .. .. %f ta || xx ,, ,, ,, ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, ,, ,, && xx %a %% .. .. .. %% "
+      "%c bb .. bb %f xx xx xx xx xx xx xx xx xx ,, cc ,, xx xx xx xx xx xx xx xx xx %e bb .. bb %a "
+      ".. .. .. .. .. w+ ,, ,, ,, ,, xx ,, ,, x! ,, cc ,, x! ,, ,, xx ,, ,, ,, ,, w+ .. .. .. .. .. "
+      ".. .. .. .. .. cc cc cc cc ,, xx ,, ,, ,, ,, cc ,, xx ,, ,, xx ,, cc cc cc cc .. .. .. .. .. "
+      ".. .. .. .. .. w+ ,, ,, cc ,, xx ,, ,, xx ,, cc ,, xx ,, ,, xx ,, cc ,, ,, w+ .. .. .. .. .. "
+      "%5 bb .. bb %7 xx xx x! cc x! xx xx xx xx ,, cc ,, xx xx xx xx x! cc x! xx xx %7 bb .. bb %3 "
+      "%% %% %% %% %% %5 w+ ,, cc ,, ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, ,, cc ,, w+ t7 %a %% %% %% %% "
+      "%% %c .. %a %% %% xx xx cc ,, pp ,, ,, pp ,, cc ,, pp ,, ,, pp ,, cc xx xx tt tt tt tt tt tt "
+      "%% .. .. .. %% %% %5 w+ cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx t3 || || || || || tt "
+      "%% %5 .. %3 %% %% %% xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx || || bb te bb || || "
+      "%% %% %% %% %% %% %% %5 xx xx x! ,, ,, pp ,, cc ,, pp ,, ,, x! xx xx || || tt td t& tb tt || "
+      "%% %c t3 tt tt t5 tA %a %5 xx xx xx ,, ,, ,, cc ,, ,, ,, xx xx xx tb || || bb .. .. .. bb || "
+      "%c t3 tL ~3 ~5 tJ t5 tA %a %% %5 xx w+ xx xx cc xx xx w+ xx %3 %% ~5 ta || td .. ++ .. tb || "
+      "tt tL ~3 -- -- ~5 tJ t5 .. %% %% %% %5 xx ,, cc ,, xx %3 %% %% ~b ~~ -d || bb .. .. .. bb || "
+      "tt ~3 -- __ __ -- ~5 tt .. %% %% %% %% xx ,, cc ,, xx %a %% %% %% ~c %% || || td .. tb || || "
+      "tt ~a -- __ __ -- ~c tt .. %% %% %% %% xx w+ cc w+ xx .. bb .. bb %% %c || || bb .. bb || || "
+      "tt tH ~a -- -- ~c tG tc .. %e .. %a %% .. .. .. .. .. .. .. .. .. == .. tt tc tA .. t3 || || "
+      "%5 ta tH ~a ~c tG tc t# %7 .. .. .. %% bb .. .. .. bb .. bb .. bb %% %5 || bb t7 bb || || || "
+      "%% %5 tt tt tt tt t# %3 %% %5 .. %3 %% %5 .. .. .. %3 %% %% %% %% %% %% || || || || || || || "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_enchanters_tower
+    (list
+      (kern-mk-obj t_doom_staff 1
+        ;; hooks
+        (list
+        )
+      )
+    19 14)
+    (list
+      (kern-mk-obj t_xen_corp_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    19 15)
+    (list
+      (kern-mk-obj t_an_tym_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    19 16)
+    (list
+      (kern-mk-obj t_vas_rel_por_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    18 14)
+    (list
+      (kern-mk-obj t_in_vas_por_ylem_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    18 15)
+    (list
+      (kern-mk-obj t_gold_coins 500
+        ;; hooks
+        (list
+        )
+      )
+    18 16)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    21 11)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    19 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 24)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    22 17)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    8 17)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    13 12)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    17 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    17 12)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_enchanter
+          "Enchanter"
+          sp_human
+          oc_wizard
+          s_companion_wizard
+          2
+          0 5 0
+          10 2
+          20 5
+          18 0
+          10 8
+          #f ;; dead?
+          'enchanter-conv
+          sch_enchanter
+          nil
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 10 t_food)
+              (list 100 t_arrow)
+              (list 1 t_dagger)
+              (list 1 t_sword)
+              (list 5 t_torch)
+              (list 5 t_cure_potion)
+              (list 5 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_bow
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          (list
+            #f
+            #f
+            #f
+          )
+          (list
+            #f
+            #f
+            #f
+          )
+          (list
+            #f
+            #f
+            #f
+          )
+          (list
+            #f
+            #f
+            #f
+          )
+        )
+      ) ;; bind
+    18 11)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_zane
+          "Zane"
+          sp_human
+          oc_ranger
+          s_companion_ranger
+          2
+          1 0 1
+          1 1
+          0 0
+          18 0
+          10 8
+          #f ;; dead?
+          'zane-conv
+          sch_zane
+          nil
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 10 t_food)
+              (list 100 t_arrow)
+              (list 1 t_dagger)
+              (list 1 t_sword)
+              (list 5 t_torch)
+              (list 5 t_cure_potion)
+              (list 5 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_bow
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    4 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 15)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    25 15)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 27)
+    (list
+      (kern-tag 'enchtwr-port-4
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    13 15)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'enchtwr-port-4
+          #f
+          '()
+        )
+      ) ;; bind
+    21 9)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 10 sulphorous_ash)
+          (list 10 ginseng)
+          (list 10 garlic)
+          (list 10 spider_silk)
+          (list 10 blood_moss)
+          (list 10 black_pearl)
+          (list 10 nightshade)
+          (list 10 mandrake)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    11 14)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'spike-trap
+        ;; contents
+        (list
+          (list 10 t_heal_potion)
+          (list 10 t_mana_potion)
+          (list 5 t_cure_potion)
+          (list 5 t_poison_immunity_potion)
+          (list 1 t_inv_potion)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    11 15)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'lightning-trap
+        ;; contents
+        (list
+          (list 100 t_gold_coins)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    11 16)
+  ) ;; end of objects in p_enchanters_tower
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 30 30) ;; Northwest
+    (list 1 15 30) ;; North
+    (list 2 0 30) ;; Northeast
+    (list 3 30 15) ;; West
+    (list 4 15 15) ;; Here
+    (list 5 0 15) ;; East
+    (list 6 30 0) ;; Southwest
+    (list 7 15 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_enchanters_tower
+
+(kern-load "shroom.scm")
+
+(kern-load "gen.scm")
+
+(kern-load "doris.scm")
+
+(kern-load "deric.scm")
+
+(kern-load "jorn.scm")
+
+(kern-load "abe.scm")
+
+(kern-load "kama.scm")
+
+(kern-load "abigail.scm")
+
+(kern-mk-place 'p_green_tower_lower "Beneath Green Tower"
+  nil ;; sprite
+  (kern-mk-map
+    nil     22 38 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr cc cc rr cc cc cc rr cc cc rr rr x! rr rr rr .. .. .. rr rr rr "
+      "rr cc cc cc cc cc cc cc cc cc rr rr rr rr rr .. .. .. .. .. rr rr "
+      "rr cc cc rr cc cc cc rr cc cc rr rr rr rr .. .. .. rr .. .. .. rr "
+      "rr rr rr rr cc cc cc rr rr rr rr rr rr rr rr .. rr rr rr .. rr rr "
+      "rr cc cc rr cc cc cc rr cc cc rr rr x! rr .. .. .. rr .. .. .. rr "
+      "rr cc cc cc cc cc cc cc cc cc rr rr rr rr rr .. rr rr rr .. rr rr "
+      "rr cc cc rr cc cc cc rr cc cc rr rr rr rr .. .. .. rr .. .. .. rr "
+      "rr rr rr rr cc cc cc rr rr rr rr rr rr rr rr .. rr rr rr .. rr rr "
+      "rr cc cc rr cc cc cc rr cc cc rr rr x! rr .. .. .. rr .. .. .. rr "
+      "rr cc cc cc cc cc cc cc cc cc rr rr rr rr rr .. rr rr rr .. rr rr "
+      "rr cc cc rr cc cc cc rr cc cc rr rr rr rr .. .. .. rr .. .. .. rr "
+      "rr rr rr rr cc cc cc rr rr rr rr rr rr rr rr .. rr rr rr .. rr rr "
+      "rr rr rr rr cc cc cc cc cc cc cc rr rr rr .. .. .. rr .. .. .. rr "
+      "rr rr rr rr cc cc cc cc cc cc cc cc rr rr rr .. .. .. .. .. rr rr "
+      "rr rr rr rr rr cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. rr "
+      "rr rr rr rr rr rr rr rr xx x! cc x! xx .. rr ,C ,R ,Y ,P ,T rr rr "
+      "xx xx xx xx xx xx xx xx xx cc cc cc xx ?? xx xx xx xx xx xx xx rr "
+      "xx xx ,T ,A ,L ,O ,S xx xx cc cc cc xx cc cc _! x! _! cc cc xx rr "
+      "xx x! cc cc cc cc cc x! xx cc cc cc xx cc cc -- _! -- cc cc xx rr "
+      "xx cc cc cc cc cc cc cc xx cc cc cc cc cc cc -- -- -- cc cc xx rr "
+      "xx cc cc cc aa cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc xx rr "
+      "xx cc cc cc cc cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc xx rr "
+      "xx x! cc cc cc cc cc x! xx cc cc cc xx ,C ,I ,S ,T ,E ,R ,N xx rr "
+      "xx xx xx xx cc xx xx xx x! cc cc cc x! xx xx xx xx xx xx xx xx xx "
+      "xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+      "xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+      "xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+      "xx xx xx xx cc xx xx xx x! cc cc cc x! xx xx xx cc xx xx xx xx xx "
+      "xx cc cc cc cc cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc xx rr "
+      "xx cc cc cc cc cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc ?? rr "
+      "xx xx cc cc cc x! cc cc xx cc cc cc xx cc cc x! cc cc cc xx xx rr "
+      "rr xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx rr rr "
+      "rr xx xx xx cc cc cc cc xx cc cc cc xx cc cc cc cc xx xx xx rr rr "
+      "rr rr rr xx xx xx cc cc xx cc cc cc xx cc cc xx xx xx rr rr rr rr "
+      "rr rr rr rr rr xx xx xx xx cc cc cc xx xx xx xx rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr xx xx xx xx xx rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_green_tower "Green Tower"
+        s_town ;; sprite
+        (kern-mk-map
+          nil           64 64 pal_expanded
+          (list
+            "|| || || || || || || || || || || || || || || || || || || || || || || || || || || || || tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || || || || || || || || || || || || || || "
+            "|| || || || || || || || || || || |C rr rr rr rr rr rr rr || || || || || || || || || || tt td .. /7 .. tb tt || || || || || || || || || || || || || || || || || || || || || || || || || || || || "
+            "|| || rr rr rr rr rr || || || rr rr rr && cc cc cc cc rr || || || || || || || || || || tt bb .. /7 .. bb tt || || || || || || || || || || || || xx xx xx xx xx xx xx xx xx tt tt || || || || || "
+            "|| || rr cc cc cc rr || || || rr cc rr cc cc cc cc cc rr || || || || || || || || || tt tt td .. /7 .. tb tt || || || || || || || || || || || |C xx .. .. .. .. .. .. .. xx tt tt tt || || || || "
+            "|| || rr cc cc cc rr || || || rr cc cc cc cc cc cc cc rr || || || || || || || || || tt tt bb .. /4 /d /d /d /d /d /d /d /d /d /d /d /d /d /1 /d .. .. .. .. .. .. .. .. ws tt tt tt || || || || "
+            "|| || rr cc cc cc rr || || || rr cc rr cc cc cc rr rr rr || || || || || || || || tt tt tt td .. /7 .. bb t3 || || || || || || || || || |% /7 tf sR @@ @@ @@ @@ @@ @@ @@ xx tt tt tt || || || || "
+            "|| || rr rr cc rr rr || || || rr cc rr cc cc cc cc cc rr || || || || || || || || tt tt tt bb .. /7 .. t3 tt || || || || || || || || || || /7 .. .. .. .. .. .. .. .. .. xx tt tt || || || || || "
+            "|| || || |% /7 |B || || || || |D /7 rr rr rr rr rr rr rr || || || || || || || tt tt tt tt td .. /7 .. ta tt || || || || || || || || || || /7 t7 xx .S .H .R .O .O .M .S xx || || || || || || || "
+            "|| || || || /8 /d /d /d /1 /d /d /a |# || || || || || || || || || || || || || tt tt tt tt bb .. /7 .. bb tt || || || || || || || || || tt /7 tt xx xx xx xx xx xx xx xx xx || || || || || || || "
+            "|| || || || || || || |% /7 |# || || || || || || || || || || || || || || || tt tt tt tt tt td .. /7 .. tb tt || || || || || || || || tt tt /7 te xx .. .. .. xx .. .. .. xx || || || || || || || "
+            "|| || |C rr rr rr |A || /7 |A || || || || || || || || || || || || || || || tt tt tt tt tt bb .. /7 .. bb tt || || || || || || || || tt tt /8 /d .. .. .. .. ?? .. .. .. ?? tt tt tt tt tt tt tt "
+            "|| rr rr rr cc rr rr |E /4 /d /d /d /d /d /d /d /d /d /d /2 || || || || tt tt tt tt tt tt td .. /7 .. tb tt || || || || tt tt tt tt tt tt tt t5 xx .. .. tf xx .. .. .. xx || || || || || || || "
+            "|| rr cc cc cc cc rr rr /7 |# || || || || || || || || |% /7 || || || || tt tt tt tt tt tt bb .. /7 .. bb tt || || || || tt t& ta tt tt || || || xx xx ws xx xx xx .. xx xx || || || || || || || "
+            "|| rr cc cc cc cc cc cc /a || || || || || || || || tt || /7 || || || tt tt tt tt tt tt tt td .. /7 .. tb tt || tt tt tt tt tA tD tt || || || || || || || || || || || || || || || || || || || || "
+            "|| rr rr cc cc cc rr rr |# || || || || tt || || tt tt tt /7 || || || tt tt tt tt tt tt tt bb .. /7 .. bb tt || tt || || tt tt tt tt || || || || || || || || || || || || || || || || || || || || "
+            "|| |% rr rr && rr rr |# tt || || || tt tc bb || || tt || /7 || tt tt tt tt tt tt tt tt tt td .. /7 .. tb tt || tt || || || || || || || || || || || || || || || || || || || || || || || || || || "
+            "|| || |% rr rr rr |# tt tt tt || tt tc t& tb || || tt bb /7 bb .. bb te bb te bb te bb te t# .. /7 .. t% te bb te bb ta tc bb te bb te bb ta tt || || || || || || || || || || || || || || || || "
+            "|| || || tt || || || || tt || tt tt tB .. tD tt || tc .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. bb tt || || || || || || || || || || || || || || || "
+            "|| || tt tt tt || || || || || || tt t5 tE t3 || || bb .. /4 /d /d /d /d /d /d /d /d /d /d /d /d /5 /d /d /d /d /d /d /d /d /d /d /d /d /2 .. || tt || || || || || || || || || || || || || || || "
+            "|| || || tt || || || || || tt tt tt tt tt tt || || td .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. ta tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || tt tt tt tt tt tt tt || || || bb .. /7 .. .. .. bb t7 bb t7 bb t7 .. .. .. /7 .. .. .. bb t3 t5 bb t7 bb tf tA .. /7 .. bb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || tt tt tc t& ta tt tt || || || || td .. /7 .. .. t3 tt tt tt tt tt tt bb .. .. /7 .. .. bb t3 tt tt tt tt t5 bb t7 .. /7 .. tb tt || || || || || || || || || || || || || || || "
+            "|| || || || || bb tt tc t# .. t% ta tt tt || || || bb .. /7 .. bb tt || || || || || tc xx w+ xx cc xx w+ xx ta || || || || || tt tc .. /7 .. bb tt || || || || || || || || || || || || || || || "
+            "|| || || || || tt tt tB .. .. .. tD tt tt || || || || .. /7 .. tb tt || || || |C xx w+ xx cc cc cc cc cc xx xx xx |A || || || tt bb .. /7 .. tb tt || || || || || || || || || || || || || || || "
+            "|| || || || || tt tt t5 tA .. tC t3 tt tt || || || bb .. /7 .. bb tt || |C xx xx xx cc cc cc cc cc cc cc cc cc xx xx xx |A || tt td .. /7 .. bb tt || || || || || || || || || || || || || || || "
+            "|| || || || || tt tt tt t5 tE t3 tt tt || || || || || .. /7 .. tb tt || xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx || tt bb .. /7 .. t3 tt || || || || || || || || || || || || || || || "
+            "|| || tt tt tt tt || tt tt tt tt bb || || tt tt || bb .. /7 .. bb tt |C xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx |A tt td .. /7 .. ta tt || || || || || || || || || || || || || || || "
+            "|| || tt || || || || || tt tt tt || || || || || || td .. /7 .. tb tt xx xx cc cc cc xx x! xx xx cc xx xx x! xx cc cc cc xx xx tt bb .. /7 .. bb tt || || || || || || || || || || || || || || tt "
+            "tt tt tt || || || || || || || || || || || || || tt bb .. /7 .. bb te xx cc cc cc xx xx xx || .. cc .. tb || xx xx cc cc cc xx ta td .. /7 .. tb tt || || || || || || || || || || || || || || tt "
+            "bb ta tt tt tt tt tt tt tt tt tt tt tt tt tt tt tc .. .. /7 .. tf bb xx cc cc cc x! || || || .. cc .. t% ta || x! cc cc cc xx bb .. .. /7 .. bb tt || || || || || || || || || || || || || || tt "
+            ".. .. bb te bb te bb te bb te bb te bb te bb bb .. .. .. /7 .. .. .. w+ cc cc cc xx te t# bb .. cc .. bb t% te xx cc cc cc w+ .. .. .. /7 .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+            ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. xx cc cc cc xx .. .. .. .. cc .. .. .. .. xx cc cc cc xx .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+            "/d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /5 /d /d /d cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc /d /d /d /5 /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d "
+            ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. xx cc cc cc xx .. .. .. .. cc .. .. .. .. xx cc cc cc xx .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+            ".. .. bb t7 bb t7 bb t7 bb t7 bb t7 bb t3 tt t5 bb .. .. /7 .. .. .. w+ cc cc cc xx t7 tA bb .. cc .. bb tC t7 xx cc cc cc w+ .. .. .. /7 .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+            "bb t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt t5 .. /7 .. .. bb xx cc cc cc x! || t5 tA .. cc .. tC t3 || x! cc cc cc xx bb .. .. /7 .. bb tt || || || || || || || || || || || tt tt tt tt "
+            "tt tt || || || || tt tt tt tt tt tt tt tt || || tt tc .. /7 .. .. t7 xx cc cc cc xx xx || td .. cc .. tb || xx xx cc cc cc xx t7 .. .. /7 .. tb tt || || || || || || || || || || || || || || tt "
+            "tt tt || || || || tt tt tt tt tt tt tt tt || || tt bb .. /7 .. bb tt xx xx cc cc cc xx x! xx xx cc xx xx x! xx cc cc cc xx xx tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || tt tt tt tt tt tt tt || || tt td .. /7 .. tb tt |% xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx |# tt td .. /7 .. tb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || || tt tt tt tt tt tt || || tt bb .. /7 .. bb tt || xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx || tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || || || || || || || || || || tt td .. /7 .. tb tt || |% xx xx xx cc cc cc cc cc cc cc cc cc xx xx xx |# || tt td .. /7 .. tb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || || || || || || || || || || tt bb .. /7 .. bb tt || || || |% xx w+ xx cc cc cc cc cc xx xx xx |# || || || tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || || || || || || || || rr rr tt td .. /7 .. tb tt || || || || || t5 xx w+ xx cc xx w+ xx t3 || || || || tt tt td .. /7 .. tb tt || || || || || || || || || || || || || || || "
+            "|| || || || || || || || || || || || || || || || tt bb .. /7 .. bb tt tt tt tt tt tt tc bb .. .. /7 .. .. bb ta tt tt tt tt tt tt bb .. /7 .. bb tt tt tt tt tt tt tt || || || || || || || || || "
+            "|| || || || || || || tt tt tt tt || || || || || tt td .. /7 .. .. te bb te bb te bb .. .. .. .. /7 .. .. .. .. bb te bb te bb te .. .. /7 .. .. te bb te bb te bb tt || || || || || || || || || "
+            "|| || || || || tt rr tt rr rr tt rr rr |A || || tt bb .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. t% tb tt || || || || || || || || || "
+            "|| || || rr rr tt tt tt || || tt t5 rr rr rr || tt td .. /8 /d /d /d /d /d /d /d /d /d /d /d /d /5 /d /d /d /d /d /d /d /d /d /d /d /d /9 /d /d /d /d /d /2 .. bb tt || || || || || || || || || "
+            "|| || || rr |# || || tt tt tt || tt tt |% rr || || bb .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. tb tt || || || || || || || || || "
+            "|| || || || tt tt tt tc t# t% ta || tt tt || rr rr || || t5 bb t7 bb t7 bb t7 bb t7 bb t7 bb .. /7 .. t7 bb t7 bb t7 bb t7 bb t7 bb t7 bb tf bb tb td bb /4 /2 bb ta || || || || || || || || || "
+            "|| rr rr || tt tt |C t# .. bb t% tt tt tt tt |% rr rr || tt tt tt tt tt tt tt tt tt tt tt t5 .. /7 .. tt tt tt tt tt tt tt tt tt tt tt xx xx xx xx ws sT cc cc sI ws xx xx xx xx || || || || || "
+            "|| || || || tt tc t# .. .. .. .. te t& ta tt || |% rr || || || || || || || || || || || || tt .. /7 .. tt || || || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc xx || || || || || "
+            "|| tt tt tt tc t# .. .. .. .. .. .. .. t% ta tt || tt tt || || || || || || || || || || || tt .. /7 .. tt || || || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc xx || || || || || "
+            "|| tt tt tt t# bb .. .. .. .. .. .. .. bb t% tt tF ta tt tt tt tt tt || || || || || || || tt .. /7 .. tt || || || || || || || || || || xx cc cc 00 cc cc cc cc cc cc 00 cc cc xx || || || || || "
+            "|| || || tt tA .. .. .. .. aa .. .. .. .. tC tt || rr || || || || tt || || || || || || || tt .. /7 .. tt || || || || || || || || || |C xx cc cc 00 cc cc && && cc cc 00 cc cc xx |A || || || || "
+            "|| rr || tt tt tt t5 .. .. .. .. .. .. t3 tt || || rr || || || || tt || || || || || || || tt .. /7 .. tt || || || || || || || || xx xx xx cc cc 00 cc cc cc cc cc cc 00 cc cc xx xx xx || || || "
+            "|| rr |A || || tF tt .. .. .. .. .. .. tt tt || rr || || |C rr rr tt rr rr |A || || || tt tt .. /7 .. tt || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx || || || "
+            "|| rr rr || tt tt tt bb .. .. .. bb .. tt tt |C rr || || rr rr tb tt td rr rr || || || tt tt .. /7 .. tt || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx || || || "
+            "|| |% rr || tt tt tt tt t5 tA .. .. tC tt || rr rr || || rr tf .! .! .! tf rr || || || tt tt .. /7 .. tt || || || || || || || |C xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx |A || || "
+            "|| || || || || || || || tt tt tt tt tt || tt rr |# || || rr .! .! && .! .! rr || || || tt tt .. /7 .. || || || || || || || || xx xx cc xx xx @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ xx xx cc xx xx || || "
+            "|| || || rr rr |A || || tt tt tt || tt tt || rr || || || rr tf .! .! .! .! rr || || || tt tt .. /7 .. tt || || || || || || || xx cc cc cc xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx || || "
+            "|| || || |% rr rr || rr rr rr || rr rr rr rr || || || || rr rr .! .! tb t5 rr || || || tt tt .. /7 .. tt || || || || || || || xx cc cc cc xx .W .H .I .T .E @@ .S .T .A .G xx cc cc cc xx || || "
+            "|| || || || || || || || || || || || || || || || || || || |% rr rr rr rr tt || || || tt tt tt .. /7 .. tt || || || || || || || xx cc cc cc xx xx xx xx xx xx xx xx xx xx xx xx cc cc cc xx || || "
+            "|| || || || || || || || || || || || || || || || || || || || || || || || || || || || tt tt tc .. /7 .. ta tt || || || || || || xx xx xx xx xx |# || || || || || || || || |% xx xx xx xx xx || || "
+            "|| || || || || || || || || || || || || || || || || || || || || || || || || || || || tt tt t# .. /7 .. t% tt tt || || || || || || || || || || || || || || || || || || || || || || || || || || || "
+          )
+        )
+        #f #f #f #f
+        ;; subplaces
+        nil
+        nil ;; neighbors
+        (list ;; objects in p_green_tower
+          (list
+            (bind
+              (kern-char-force-drop                (kern-mk-char
+                  'ch_jorn
+                  "Jorn"
+                  sp_human
+                  oc_wrogue
+                  s_brigand
+                  2
+                  0 0 0
+                  0 0
+                  0 0
+                  15 0
+                  7 5
+                  #f ;; dead?
+                  'jorn-conv
+                  sch_jorn
+                  'spell-sword-ai
+                  (kern-mk-container
+                    t_chest
+                    ;; trap
+                    nil
+                    ;; contents
+                    (list
+                      (list 1 t_skull_ring)
+                      (list 67 t_gold_coins)
+                      (list 3 t_picklock)
+                      (list 3 t_heal_potion)
+                    )
+                    ;; hooks
+                    (list
+                    )
+                  )
+                  (list
+                    t_leather_helm_2
+                    t_dagger_4
+                    t_sword_2
+                    t_armor_leather_2
+                  )
+                  ;; hooks
+                  (list
+                  )
+                )
+              #t) ;; kern-char-force-drop
+              '()
+            ) ;; bind
+          46 50)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_abe
+                "Abe"
+                sp_human
+                nil
+                s_companion_wizard
+                2
+                0 0 0
+                0 0
+                0 0
+                13 0
+                5 3
+                #f ;; dead?
+                'abe-conv
+                sch_abe
+                nil
+                nil ;; inventory
+                nil
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+              )
+            ) ;; bind
+          46 50)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #t
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          48 10)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          48 6)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          48 4)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #t
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          54 12)
+          (list
+            (kern-mk-obj t_bed 1
+              ;; hooks
+              (list
+              )
+            )
+          51 9)
+          (list
+            (kern-mk-container
+              t_chest
+              ;; trap
+              'burn-trap
+              ;; contents
+              (list
+                (list 50 sulphorous_ash)
+                (list 50 garlic)
+                (list 50 ginseng)
+                (list 50 blood_moss)
+                (list 50 black_pearl)
+                (list 50 spider_silk)
+                (list 50 mandrake)
+                (list 50 nightshade)
+              )
+              ;; hooks
+              (list
+              )
+            )
+          53 9)
+          (list
+            (kern-mk-container
+              t_chest
+              ;; trap
+              'poison-trap
+              ;; contents
+              (list
+                (list 10 t_cure_potion)
+                (list 10 t_heal_potion)
+                (list 10 t_mana_potion)
+                (list 10 t_poison_immunity_potion)
+                (list 1 t_inv_potion)
+              )
+              ;; hooks
+              (list
+              )
+            )
+          54 9)
+          (list
+            (kern-mk-container
+              t_chest
+              ;; trap
+              'sleep-trap
+              ;; contents
+              (list
+                (list 1 t_armor_leather)
+                (list 1 t_sword)
+                (list 1 t_shield)
+                (list 1 t_leather_helm)
+              )
+              ;; hooks
+              (list
+              )
+            )
+          55 9)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          7 13)
+          (list
+            (kern-mk-obj t_bed 1
+              ;; hooks
+              (list
+              )
+            )
+          2 13)
+          (list
+            (kern-mk-container
+              t_chest
+              ;; trap
+              nil
+              ;; contents
+              (list
+                (list 100 t_arrow)
+                (list 1 t_bow)
+              )
+              ;; hooks
+              (list
+              )
+            )
+          4 11)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          11 6)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          16 6)
+          (list
+            (kern-mk-obj t_bed 1
+              ;; hooks
+              (list
+              )
+            )
+          17 4)
+          (list
+            (kern-mk-container
+              t_chest
+              ;; trap
+              'burn-trap
+              ;; contents
+              (list
+                (list 100 t_bolt)
+                (list 1 t_crossbow)
+                (list 1 t_shield)
+                (list 2 t_cure_potion)
+                (list 5 t_heal_potion)
+              )
+              ;; hooks
+              (list
+              )
+            )
+          17 6)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          51 49)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          52 49)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          57 59)
+          (list
+            (kern-tag 'white-stag-door
+              (bind
+                (kern-mk-obj t_door 1
+                  ;; hooks
+                  (list
+                  )
+                )
+                (list
+                  #f
+                  0
+                  '()
+                  #f
+                  #t
+                  #f
+                  (list
+                    (list
+                      's_closed_solid_wood_door_in_stone
+                      #t
+                      5
+                    )
+                    (list
+                      's_open_door_in_stone
+                      #f
+                      0
+                    )
+                    (list
+                      's_locked_solid_wood_door_in_stone
+                      #t
+                      5
+                    )
+                    (list
+                      's_magically_locked_solid_wood_door_in_stone
+                      #t
+                      5
+                    )
+                  )
+                )
+              ) ;; bind
+            ) ;; kern-tag
+          44 58)
+          (list
+            (kern-mk-obj t_bed 1
+              ;; hooks
+              (list
+              )
+            )
+          43 61)
+          (list
+            (kern-mk-obj t_bed 1
+              ;; hooks
+              (list
+              )
+            )
+          58 61)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #t
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          59 58)
+          (list
+            (bind
+              (kern-mk-obj t_lever 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                'gtl-portcullis-1
+                #f
+                '()
+              )
+            ) ;; bind
+          29 28)
+          (list
+            (bind
+              (kern-mk-obj t_ladder_down 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'p_green_tower_lower
+                10
+                26
+              )
+            ) ;; bind
+          32 32)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          32 22)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          41 32)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          32 42)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          23 32)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_shroom
+                "Shroom"
+                sp_human
+                nil
+                s_companion_druid
+                2
+                8 14 8
+                0 0
+                0 0
+                13 0
+                5 3
+                #f ;; dead?
+                'shroom-conv
+                sch_shroom
+                nil
+                nil ;; inventory
+                nil
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                #f
+              )
+            ) ;; bind
+          51 9)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_gen
+                "Gen"
+                sp_human
+                oc_ranger
+                s_companion_ranger
+                2
+                12 10 12
+                25 5
+                0 0
+                53 812
+                5 3
+                #f ;; dead?
+                'gen-conv
+                sch_gen
+                nil
+                nil ;; inventory
+                nil
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                #f
+              )
+            ) ;; bind
+          2 13)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_doris
+                "Doris"
+                sp_human
+                nil
+                s_townswoman
+                2
+                0 0 0
+                0 0
+                0 0
+                11 0
+                0 1
+                #f ;; dead?
+                'doris-conv
+                sch_doris
+                nil
+                nil ;; inventory
+                nil
+                ;; hooks
+                (list
+                )
+              )
+              '()
+            ) ;; bind
+          47 59)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_abigail
+                "Abigail"
+                sp_forest_goblin
+                oc_wrogue
+                s_goblin_child
+                2
+                0 0 0
+                0 0
+                0 1
+                9 128
+                7 1
+                #f ;; dead?
+                'abigail-conv
+                sch_abigail
+                nil
+                nil ;; inventory
+                nil
+                ;; hooks
+                (list
+                )
+              )
+              '()
+            ) ;; bind
+          60 61)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_kalc
+                "Kalcifax"
+                sp_human
+                oc_wizard
+                s_companion_wizard
+                2
+                0 5 0
+                12 2
+                1 1
+                40 4096
+                15 6
+                #f ;; dead?
+                'kalc-conv
+                sch_kalc
+                nil
+                nil ;; inventory
+                (list
+                  t_staff
+                )
+                ;; hooks
+                (list
+                )
+              )
+              '()
+            ) ;; bind
+          46 50)
+          (list
+            (bind
+              (kern-mk-char
+                'ch_deric
+                "Deric"
+                sp_human
+                nil
+                s_companion_ranger
+                2
+                0 0 0
+                0 0
+                0 0
+                3 0
+                6 4
+                #f ;; dead?
+                'deric-conv
+                sch_deric
+                nil
+                nil ;; inventory
+                nil
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+              )
+            ) ;; bind
+          13 2)
+        ) ;; end of objects in p_green_tower
+        (list ;; on-entry-hooks
+          'lock-inn-room-doors
+        )
+        (list ;; edge entrances
+          (list 0 63 63) ;; Northwest
+          (list 1 32 63) ;; North
+          (list 2 0 63) ;; Northeast
+          (list 3 63 32) ;; West
+          (list 4 32 32) ;; Here
+          (list 5 0 32) ;; East
+          (list 6 63 0) ;; Southwest
+          (list 7 32 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_green_tower
+
+    9)
+  ) ;; end neighbors of p_green_tower_lower
+  (list ;; objects in p_green_tower_lower
+    (list
+      (bind
+        (kern-mk-char
+          'ch_amy
+          "Amy"
+          sp_human
+          oc_wright
+          s_companion_tinker
+          1
+          2 4 4
+          25 5
+          1 1
+          17 55
+          5 1
+          #f ;; dead?
+          'amy-conv
+          nil
+          nil
+          nil ;; inventory
+          (list
+            t_leather_helm
+            t_sling
+            t_sword
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    11 25)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_kama
+          "Kama"
+          sp_forest_goblin
+          oc_wrogue
+          s_fgob_civilian
+          2
+          2 0 10
+          25 5
+          0 0
+          57 1024
+          12 4
+          #f ;; dead?
+          'kama-conv
+          sch_kama
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          #f
+        )
+      ) ;; bind
+    8 1)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_crypt
+          9
+          3
+        )
+      ) ;; bind
+    17 1)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              3
+              't_arrow
+            )
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    14 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    14 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_gold_coins
+            )
+            (list
+              1
+              't_gold_coins
+            )
+            (list
+              2
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    14 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              3
+              't_gold_coins
+            )
+            (list
+              2
+              't_bolt
+            )
+            (list
+              1
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    14 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              5
+              't_arrow
+            )
+            (list
+              1
+              't_cure_potion
+            )
+            (list
+              3
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    16 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    16 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_torch
+            )
+          )
+        )
+      ) ;; bind
+    16 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    16 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              2
+              't_arrow
+            )
+            (list
+              1
+              't_mana_potion
+            )
+            (list
+              3
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    18 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              2
+              't_arrow
+            )
+            (list
+              1
+              't_food
+            )
+            (list
+              1
+              't_gem
+            )
+          )
+        )
+      ) ;; bind
+    18 7)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    18 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+            (list
+              1
+              't_food
+            )
+            (list
+              4
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    18 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_mana_potion
+            )
+          )
+        )
+      ) ;; bind
+    20 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_food
+            )
+            (list
+              1
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    20 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_bolt
+            )
+            (list
+              1
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    20 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    20 11)
+    (list
+      (kern-tag 'gtl-portcullis-1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    10 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    12 20)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 24)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 28)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    8 32)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    12 32)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    16 28)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    15 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    7 29)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    2 32)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    13 29)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    19 29)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            0
+            21
+            21
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_green_tower
+          32
+          32
+        )
+      ) ;; bind
+    10 26)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 2)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 6)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 10)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 2)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 6)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 10)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "rat"
+          sp_rat
+          nil
+          s_rat
+          5
+          0 0 0
+          0 0
+          0 0
+          7 128
+          1 1
+          #f ;; dead?
+          nil
+          nil
+          'rat-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      25
+                      "1"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'rat
+          #f
+          #t
+          '()
+        )
+      ) ;; bind
+    16 3)
+    (list
+      (kern-mk-char
+        'ch_wanderer
+        "The Wanderer"
+        sp_human
+        oc_wanderer
+        s_wanderer
+        1
+        5 5 5
+        25 5
+        1 1
+        25 217
+        5 1
+        #f ;; dead?
+        nil
+        nil
+        nil
+        nil ;; inventory
+        (list
+          t_shield
+          t_sword
+        )
+        ;; hooks
+        (list
+        )
+      )
+    10 26)
+  ) ;; end of objects in p_green_tower_lower
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 21 37) ;; Northwest
+    (list 1 11 37) ;; North
+    (list 2 0 37) ;; Northeast
+    (list 3 21 19) ;; West
+    (list 4 11 19) ;; Here
+    (list 5 0 19) ;; East
+    (list 6 21 0) ;; Southwest
+    (list 7 11 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_green_tower_lower
+
+p_green_tower
+(kern-mk-place 'p_mushroom_cave "Mushroom Cave"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr %3 %d rr rr tf .. .. .. tf rr rr rr {{ rr rr rr rr rr "
+      "rr %% rr rr || t# .. .. .. t% || rr rr tf {A rr rr rr rr "
+      "rr %% rr tf %7 bb .. .. .. bb %7 |% rr t% t7 rr rr rr rr "
+      "rr %e rr %b %% %% %5 .. .. %b %% te rr .. te rr rr rr rr "
+      "rr rr rr t7 %% bb %e .. .. bb %% %5 rr {c {{ rr rr rr rr "
+      "rr .. |B || %% %d .. .. .. %b %% %% rr {{ {{ rr rr rr rr "
+      "rr .. rr || %% bb .. %b %5 bb %a %c rr {{ {{ rr rr rr rr "
+      "rr t7 rr te %% .. .. .. %a %d t3 t5 rr {5 {{ rr rr rr rr "
+      "rr tt rr %b %c bb .. .. .. bb || |C rr {4 {{ rr rr rr rr "
+      "rr te rr rr tf %f .. .. .. tb || rr rr .. t7 rr rr rr rr "
+      "rr t% tf rr rr rr .. .. .. rr rr rr .. tC tt rr rr rr rr "
+      "rr .. .. .. && rr rr .. rr rr .. .. tC t3 |C rr rr rr rr "
+      "rr .. .. .. .. .. rr rr rr {{ {2 tC t3 |C rr rr rr rr rr "
+      "rr rr tf .. .. rr rr rr rr rr tb tt |C rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_mushroom_cave
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_shard
+          78
+          74
+        )
+      ) ;; bind
+    7 12)
+    (list
+      (kern-mk-obj t_royal_cape 1
+        ;; hooks
+        (list
+        )
+      )
+    4 14)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'yellow-slime
+        )
+      ) ;; bind
+    7 7)
+  ) ;; end of objects in p_mushroom_cave
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_mushroom_cave
+
+(kern-load "douglas.scm")
+
+(kern-mk-place 'p_shamans_grove "Shaman's Grove"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr t7 bb t7 rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr tb tt tt tt td rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr t7 bb te t& te bb t7 rr rr rr rr rr rr "
+      "rr rr rr rr rr rr tt t5 tB aa tD t3 tt rr rr rr rr rr rr "
+      "rr rr rr rr rr rr ta tt td tE tb tt tc rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr te bb t7 bb te rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr t3 tt t5 rr rr rr rr rr rr rr rr "
+      "rr rr rr t3 tt t5 rr rr || || || rr rr |# || |% rr rr rr "
+      "rr rr t3 tc t& ta t5 rr || || || rr |# || || || |% rr rr "
+      "rr t3 tc t# .. t% te bb || || || || || || || || || |% rr "
+      "rr tt tB .. && .. tD tb || || || || || || tt || || || rr "
+      "rr ta t5 tA .. tC t7 bb || || || || || || || || || |C rr "
+      "rr rr ta t5 tE t3 tc rr || || || rr |A || || || |C rr rr "
+      "rr rr rr ta tt tc rr rr || || || rr rr |A || |C rr rr rr "
+      "rr rr rr rr rr rr rr rr || tt || rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr tt tt tt rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr ta tt tc rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_goblin_crossroads "Goblin Crossroads"
+        nil ;; sprite
+        (kern-mk-map
+          nil           19 19 pal_expanded
+          (list
+            "rr rr rr rr rr rr rr {{ {{ ,, ,, {{ rr rr rr rr rr rr rr "
+            "rr rr rr rr rr rr rr rr {{ ,, {# {{ {{ {{ {{ rr rr rr rr "
+            "rr rr rr rr rr rr rr rr {{ {{ ,, {5 {{ rr {{ {{ {{ rr rr "
+            "rr rr rr rr rr rr rr rr rr {{ ,, bb {5 {{ {{ {{ {{ rr rr "
+            "rr rr rr rr rr rr rr rr rr ,, {{ {a {8 {1 {5 {{ {{ rr rr "
+            "rr rr rr rr rr rr rr rr rr rr {{ {{ {{ {a bb {d {{ {{ rr "
+            "rr rr rr rr rr rr rr rr rr rr bb {{ {{ {{ {e {{ {{ {{ rr "
+            "{{ {{ {{ rr rr rr rr rr rr rr rr {{ {{ {{ {{ {{ {{ {{ {{ "
+            ",, {{ {{ {a bb rr rr rr rr rr rr {{ {{ {{ {{ {{ ,, {C ,, "
+            ",, {E ,, {{ {6 {{ rr rr rr rr rr {{ {{ ,, ,, ,, {A ,, ,, "
+            ",, ,, ,, {1 ,, ,, {{ rr rr rr {{ {{ {{ {% ,, ,, ,, {% ,, "
+            "{{ {{ {{ {a bb .. {5 {{ {{ {{ {{ {{ {7 {{ {{ {{ {{ {{ {{ "
+            "rr {{ {{ {{ {2 {8 bb {5 {{ {{ {{ {3 bb {d {{ {{ {{ rr rr "
+            "rr rr {{ rr rr {{ {a .. {5 {{ {{ {2 {c {{ {{ {{ rr rr rr "
+            "rr rr rr rr {{ {{ {{ {a {8 {1 {1 {4 {{ {{ {{ {{ rr rr rr "
+            "rr rr rr rr {{ {{ {{ {{ {{ {2 bb {4 {{ {{ rr rr rr rr rr "
+            "rr rr rr rr rr {{ {{ {{ {{ ,, .. {c {{ {{ {{ rr rr rr rr "
+            "rr rr rr rr rr rr rr {{ {{ {2 {4 {{ rr rr rr rr rr rr rr "
+            "rr rr rr rr rr rr rr {{ ,, .. .. rr rr rr rr rr rr rr rr "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        (list
+          (list
+            (kern-mk-place 'p_kurpolis_entrance "Entrance to Kurpolis"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "rr rr rr rr xx xx x! xx xx && xx xx x! xx xx rr rr rr rr "
+                  "rr .. .. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "xx xx x! xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "xx xx ,, ,, ,, ,, ,, [[ @@ @@ @@ ]] ,, ,, x! rr rr rr rr "
+                  "xx xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "xx xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "xx xx ,, xx xx xx xx xx xx x! xx xx xx xx xx rr bb ,, rr "
+                  "xx xx ,, xx xx .K .U .R .P .O .L .I .S xx ,, bb bb bb ,, "
+                  "xx xx ,, xx x! ,, ,, ,, ,, ,, ,, ,, ,, x! bb bb ,, bb ,, "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, bb ,, ,, ,, "
+                  "x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb ,, "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ bb bb bb bb ,, "
+                  "xx xx ,, xx x! ,, ,, ,, ,, ,, ,, ,, ,, x! bb bb ,, bb rr "
+                  "xx xx ,, xx xx xx xx xx xx xx xx xx xx xx xx ,, bb rr rr "
+                  "xx xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "xx xx x! xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "rr rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr "
+                  "rr rr rr rr xx xx xx xx xx xx xx xx xx xx xx rr rr rr rr "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              nil ;; neighbors
+              (list ;; objects in p_kurpolis_entrance
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                7 17)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                9 17)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                11 17)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                13 17)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                18 7)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                18 11)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-berserker
+                    )
+                  ) ;; bind
+                15 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'crossbowman
+                    )
+                  ) ;; bind
+                12 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'crossbowman
+                    )
+                  ) ;; bind
+                12 11)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'halberdier
+                    )
+                  ) ;; bind
+                10 10)
+                (list
+                  (bind
+                    (kern-mk-char
+                      'ch_douglas
+                      "Douglas"
+                      sp_human
+                      oc_warrior
+                      s_companion_paladin
+                      2
+                      0 0 0
+                      0 0
+                      0 0
+                      14 0
+                      0 4
+                      #f ;; dead?
+                      'doug-conv
+                      sch_doug
+                      nil
+                      nil ;; inventory
+                      (list
+                        t_chain_coif
+                        t_sword
+                        t_armor_chain
+                      )
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    '()
+                  ) ;; bind
+                5 1)
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (bind
+                    (kern-mk-obj t_ladder_up 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'p_shard
+                      53
+                      18
+                    )
+                  ) ;; bind
+                9 10)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                2 8)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                2 12)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                4 15)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                4 3)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #t
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                4 1)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_windowed_wood_door_in_rock
+                          #f
+                          5
+                        )
+                        (list
+                          's_open_door_in_rock
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_windowed_wood_door_in_rock
+                          #f
+                          5
+                        )
+                        (list
+                          's_magically_locked_windowed_wood_door_in_rock
+                          #f
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                13 10)
+                (list
+                  (kern-mk-container
+                    t_chest
+                    ;; trap
+                    nil
+                    ;; contents
+                    (list
+                      (list 10 t_food)
+                    )
+                    ;; hooks
+                    (list
+                    )
+                  )
+                1 1)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                5 17)
+              ) ;; end of objects in p_kurpolis_entrance
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_kurpolis_entrance
+
+          3)
+          (list
+            (kern-mk-place 'p_cave_goblin_village "Cave Goblin Village"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                  "rr rr rr rr rr rr {{ {{ {{ {{ {{ {{ rr rr rr rr rr rr rr "
+                  "rr rr rr rr rr {{ ,, ,, ,, ,, {A {{ {{ rr {{ {{ {{ rr rr "
+                  "rr rr rr rr rr {{ ,, ,, && ,, ,, bb {{ rr {{ ,, {A {{ rr "
+                  "rr rr rr rr rr {{ ,, ,, ,, ,, ,, ,, {1 .. {9 ,, ,, {{ rr "
+                  "rr rr rr rr rr {{ {a {8 ,, ,, {# {{ ,, rr {{ ,, ,, {{ rr "
+                  "rr rr rr rr rr {{ {{ {{ {6 {{ bb {C ,, rr {{ {{ {{ {{ rr "
+                  "{{ {{ {{ {{ bb {{ bb {{ {2 {5 {C ,, ,, rr rr {{ {{ rr rr "
+                  "{{ {{ {{ {{ bb {{ {{ {3 ,, ,, ,, ,, {# rr rr rr rr rr rr "
+                  ",, {A ,, {9 .. {9 {1 ,, .. ,, ,, ,, {{ {{ rr rr rr rr rr "
+                  ",, ,, {c {{ bb {{ {a ,, ,, ,, ,, {4 {{ {{ {{ rr rr rr rr "
+                  "{{ {{ {{ {{ bb {{ {{ ,, ,, ,, ,, ,, {1 {5 {{ rr rr rr rr "
+                  "rr rr rr rr rr {{ bb {% ,, ,, ,, {# ,, .. ~C ~~ ~~ rr rr "
+                  "rr rr rr rr rr {{ {{ {{ {D ,, {B {{ {{ {a ~3 -- -- ~~ rr "
+                  "rr rr rr rr rr rr rr bb bb .. bb bb rr {{ ~a -- -- ~~ rr "
+                  "rr rr rr rr rr rr rr {{ {{ {6 {{ {{ rr {{ {H ~a ~c {G rr "
+                  "rr rr rr rr rr rr rr {{ {{ {a {5 {{ rr rr {{ {{ {{ {{ rr "
+                  "rr rr rr rr rr rr rr {{ {{ {{ {6 {{ rr rr {{ {{ {{ rr rr "
+                  "rr rr rr rr rr rr rr {{ {{ {3 {4 {{ rr rr rr rr rr rr rr "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              (list
+                (list
+                  (kern-mk-place 'p_trolls_den "Troll's Den"
+                    nil ;; sprite
+                    (kern-mk-map
+                      nil                       19 19 pal_expanded
+                      (list
+                        "rr rr rr rr rr rr rr {{ {2 ,, ,, {{ rr rr rr rr rr rr rr "
+                        "rr {{ {{ {{ rr rr rr {{ {2 ,, {B {{ rr rr rr rr rr rr rr "
+                        "rr {{ {{ {{ {{ rr rr {{ {a .. ,, {A rr rr rr rr rr rr rr "
+                        "rr {{ {{ {{ {{ {{ rr rr {{ {2 ,, bb rr rr rr rr rr rr rr "
+                        "rr rr {{ {{ rr {{ {{ rr {{ ,, {c {{ rr rr rr rr rr rr rr "
+                        "rr rr {{ rr rr rr {{ {{ {{ {6 {{ {{ rr rr rr rr rr rr rr "
+                        "rr rr {{ {{ rr {{ {{ rr {{ {a {5 {{ rr {{ {{ rr rr rr rr "
+                        "rr {{ {{ {{ {6 {{ rr rr rr {{ {2 {1 {8 {5 {{ {{ {{ rr rr "
+                        "rr {{ {{ {b bb {d {{ rr {{ {3 .. rr {{ {a {5 {{ {3 .. rr "
+                        "rr {{ {{ {{ {e {{ {{ {{ {{ {2 rr rr rr {{ {2 {1 .. .. rr "
+                        "rr rr {{ {{ {{ {{ rr {{ {3 {c {{ rr {{ {{ {2 .. .. && rr "
+                        "rr rr rr {{ {{ rr rr rr {4 {{ {{ {{ {3 {1 .. {8 .. .. rr "
+                        "rr rr rr {{ {7 {{ rr {{ {2 rr rr {1 bb {8 {c {{ {a .. rr "
+                        "rr rr {{ bb .. {5 {{ {3 {8 rr rr rr {4 {{ {{ {{ {{ rr rr "
+                        "rr {{ {3 .. .. .. {9 {c {{ {{ rr rr rr rr {{ {{ {{ rr rr "
+                        "rr {{ {a .. .. bb {{ {{ {{ {{ rr rr rr rr rr rr rr rr rr "
+                        "rr {{ {{ {a {8 bb {{ {{ rr rr rr rr rr rr rr rr rr rr rr "
+                        "rr rr {{ {{ {{ rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                        "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                      )
+                    )
+                    #f #t #f #f
+                    ;; subplaces
+                    nil
+                    (list
+                      (list
+                        (kern-mk-place 'p_watchpoint "Watchpoint"
+                          nil ;; sprite
+                          (kern-mk-map
+                            nil                             19 19 pal_expanded
+                            (list
+                              "rr rr rr rr rr rr rr {{ {C ,, ,, {{ rr rr rr rr rr rr rr "
+                              "rr rr rr rr rr rr rr {{ ,, ,, {4 {{ rr rr rr rr rr rr rr "
+                              "rr rr rr rr rr rr bb {{ ,, .. ,, {5 {{ rr rr rr rr rr rr "
+                              "rr rr rr rr rr rr {{ {{ ,, .. ,, bb {{ rr rr rr rr rr rr "
+                              "rr rr rr rr rr bb {{ {{ {2 ,, ,, {c {{ rr rr rr rr rr rr "
+                              "rr rr rr rr rr {{ {{ {{ ,, .. ,, {{ {{ {{ rr rr rr rr rr "
+                              "rr rr rr rr bb {A {{ {C oo ee oo {{ ~~ -- rr rr rr rr rr "
+                              "rr rr rr rr bb bb ~1 ~9 ~~ ee ee ~9 ~~ _! rr rr rr rr rr "
+                              "rr rr rr -- -- ~~ ~c {& oo ee ~c {{ ~~ -- rr rr rr rr rr "
+                              "rr rr rr _! -- -c {G {{ {{ ,, {{ {{ {{ {{ {{ rr rr rr rr "
+                              "rr rr rr -- -- {G {{ bb ,, ,, ,, bb {{ {{ {{ rr rr rr rr "
+                              "rr rr rr rr {{ {{ x. x. w+ d, w+ x. x. {{ {{ rr rr rr rr "
+                              "rr rr rr rr {{ {{ x. .. ,, ,, ,, ,, rr {d {{ rr rr rr rr "
+                              "rr rr rr rr rr {{ x. ,, ,, ,, ,, ,, x. {{ {{ rr rr rr rr "
+                              "rr rr rr rr {{ {{ x. ,, ,, ,, ,, ,, x. {{ {{ rr rr rr rr "
+                              "rr rr rr rr {{ {{ bb ,, ,, ,, ,, .. x. {{ rr rr rr rr rr "
+                              "rr rr rr rr rr {{ x. ,, ,, ,, .. bb x. rr rr rr rr rr rr "
+                              "rr rr rr rr rr rr rr x. x. && x. x. x. rr rr rr rr rr rr "
+                              "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                            )
+                          )
+                          #f #t #f #f
+                          ;; subplaces
+                          nil
+                          nil ;; neighbors
+                          (list ;; objects in p_watchpoint
+                            (list
+                              (bind
+                                (kern-mk-obj t_guard_pt 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  'spawn-pt
+                                  'halberdier
+                                )
+                              ) ;; bind
+                            8 12)
+                            (list
+                              (bind
+                                (kern-mk-obj t_guard_pt 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  'spawn-pt
+                                  'crossbowman
+                                )
+                              ) ;; bind
+                            10 12)
+                            (list
+                              (bind
+                                (kern-mk-obj t_monman 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  'monman
+                                  (list
+                                    0
+                                    0
+                                    0
+                                    -1
+                                    6
+                                    -1
+                                  )
+                                )
+                              ) ;; bind
+                            0 0)
+                            (list
+                              (bind
+                                (kern-mk-obj t_ladder_down 1
+                                  ;; hooks
+                                  (list
+                                  )
+                                )
+                                (list
+                                  'p_paladins_hold
+                                  3
+                                  9
+                                )
+                              ) ;; bind
+                            9 14)
+                          ) ;; end of objects in p_watchpoint
+                          (list ;; on-entry-hooks
+                            'on-entry-to-dungeon-room
+                          )
+                          (list ;; edge entrances
+                            (list 0 18 18) ;; Northwest
+                            (list 1 9 18) ;; North
+                            (list 2 0 18) ;; Northeast
+                            (list 3 18 9) ;; West
+                            (list 4 9 9) ;; Here
+                            (list 5 0 9) ;; East
+                            (list 6 18 0) ;; Southwest
+                            (list 7 9 0) ;; South
+                            (list 8 0 0) ;; SoutheastUp
+                          )
+                        ) ;; end of place p_watchpoint
+
+                      3)
+                    ) ;; end neighbors of p_trolls_den
+                    (list ;; objects in p_trolls_den
+                      (list
+                        (bind
+                          (kern-mk-obj t_ladder_up 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'p_old_mine
+                            17
+                            17
+                          )
+                        ) ;; bind
+                      3 15)
+                      (list
+                        (bind
+                          (kern-mk-obj t_spawn_pt 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'spawn-pt
+                            'troll
+                          )
+                        ) ;; bind
+                      16 10)
+                      (list
+                        (bind
+                          (kern-mk-obj t_spawn_pt 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'spawn-pt
+                            'troll-geomancer
+                          )
+                        ) ;; bind
+                      17 9)
+                      (list
+                        (bind
+                          (kern-mk-obj t_spawn_pt 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'spawn-pt
+                            'troll
+                          )
+                        ) ;; bind
+                      17 11)
+                      (list
+                        (kern-mk-obj t_food 1
+                          ;; hooks
+                          (list
+                          )
+                        )
+                      17 8)
+                      (list
+                        (kern-mk-obj t_beer 1
+                          ;; hooks
+                          (list
+                          )
+                        )
+                      16 8)
+                      (list
+                        (kern-mk-obj t_food 1
+                          ;; hooks
+                          (list
+                          )
+                        )
+                      16 12)
+                      (list
+                        (kern-mk-obj t_beer 1
+                          ;; hooks
+                          (list
+                          )
+                        )
+                      15 11)
+                      (list
+                        (bind
+                          (kern-mk-obj t_monman 1
+                            ;; hooks
+                            (list
+                            )
+                          )
+                          (list
+                            'monman
+                            (list
+                              0
+                              0
+                              0
+                              -1
+                              6
+                              -1
+                            )
+                          )
+                        ) ;; bind
+                      0 0)
+                    ) ;; end of objects in p_trolls_den
+                    (list ;; on-entry-hooks
+                      'on-entry-to-dungeon-room
+                    )
+                    (list ;; edge entrances
+                      (list 0 18 18) ;; Northwest
+                      (list 1 9 18) ;; North
+                      (list 2 0 18) ;; Northeast
+                      (list 3 18 9) ;; West
+                      (list 4 9 9) ;; Here
+                      (list 5 0 9) ;; East
+                      (list 6 18 0) ;; Southwest
+                      (list 7 9 0) ;; South
+                      (list 8 0 0) ;; SoutheastUp
+                    )
+                  ) ;; end of place p_trolls_den
+
+                7)
+              ) ;; end neighbors of p_cave_goblin_village
+              (list ;; objects in p_cave_goblin_village
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-priest
+                    )
+                  ) ;; bind
+                9 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-berserker
+                    )
+                  ) ;; bind
+                14 4)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-priest
+                    )
+                  ) ;; bind
+                16 4)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #t
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                13 4)
+                (list
+                  (kern-mk-container
+                    t_chest
+                    ;; trap
+                    nil
+                    ;; contents
+                    (list
+                      (list 1 t_bolt)
+                      (list 2 t_food)
+                      (list 5 t_gold_coins)
+                      (list 1 t_mana_potion)
+                      (list 9 t_arrow)
+                    )
+                    ;; hooks
+                    (list
+                    )
+                  )
+                16 4)
+                (list
+                  (kern-mk-container
+                    t_chest
+                    ;; trap
+                    nil
+                    ;; contents
+                    (list
+                      (list 1 t_heal_potion)
+                      (list 2 t_food)
+                      (list 2 t_cure_potion)
+                      (list 4 t_gold_coins)
+                      (list 1 t_bolt)
+                    )
+                    ;; hooks
+                    (list
+                    )
+                  )
+                16 5)
+                (list
+                  (kern-mk-container
+                    t_chest
+                    ;; trap
+                    nil
+                    ;; contents
+                    (list
+                      (list 5 t_gold_coins)
+                    )
+                    ;; hooks
+                    (list
+                    )
+                  )
+                15 3)
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                5 8)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                8 2)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                9 3)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-slinger
+                    )
+                  ) ;; bind
+                10 13)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-berserker
+                    )
+                  ) ;; bind
+                6 10)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-berserker
+                    )
+                  ) ;; bind
+                8 4)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-berserker
+                    )
+                  ) ;; bind
+                7 3)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-berserker
+                    )
+                  ) ;; bind
+                8 13)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'cave-goblin-priest
+                    )
+                  ) ;; bind
+                15 4)
+              ) ;; end of objects in p_cave_goblin_village
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_cave_goblin_village
+
+          5)
+          (list
+            p_watchpoint
+          7)
+        ) ;; end neighbors of p_goblin_crossroads
+        (list ;; objects in p_goblin_crossroads
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'cave-goblin-slinger
+              )
+            ) ;; bind
+          14 11)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'cave-goblin-berserker
+              )
+            ) ;; bind
+          15 9)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'forest-goblin-hunter
+              )
+            ) ;; bind
+          15 5)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'forest-goblin-hunter
+              )
+            ) ;; bind
+          12 7)
+        ) ;; end of objects in p_goblin_crossroads
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 18 18) ;; Northwest
+          (list 1 9 18) ;; North
+          (list 2 0 18) ;; Northeast
+          (list 3 18 9) ;; West
+          (list 4 9 9) ;; Here
+          (list 5 0 9) ;; East
+          (list 6 18 0) ;; Southwest
+          (list 7 9 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_goblin_crossroads
+
+    7)
+  ) ;; end neighbors of p_shamans_grove
+  (list ;; objects in p_shamans_grove
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-hunter
+        )
+      ) ;; bind
+    4 10)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-stalker
+        )
+      ) ;; bind
+    5 11)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_dank_cave
+          9
+          1
+        )
+      ) ;; bind
+    14 11)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-shaman
+        )
+      ) ;; bind
+    9 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-hunter
+        )
+      ) ;; bind
+    3 11)
+  ) ;; end of objects in p_shamans_grove
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_shamans_grove
+
+p_watchpoint
+p_trolls_den
+p_cave_goblin_village
+p_goblin_crossroads
+p_kurpolis_entrance
+(kern-mk-place 'p_treasury2 "Lost Treasury of Luximene"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx ,T ,R ,E ,A ,S ,U ,R ,Y @@ xx xx xx xx xx "
+      "xx xx xx xx xx @@ @@ @@ ,O @@ ,F @@ @@ @@ xx xx xx xx xx "
+      "xx xx xx xx xx @@ ,L ,U ,X ,I ,M ,E ,N ,E xx xx xx xx xx "
+      "xx xx xx xx xx cc cc cc ,, cc ,, cc cc cc xx xx xx xx xx "
+      "xx xx xx xx xx cc pp ,, ,, ,, ,, ,, pp cc xx xx xx xx xx "
+      "xx xx xx xx xx cc ,, ,, ,, cc ,, ,, ,, cc xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, cc cc cc ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, cc cc ,, cc cc ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, cc cc cc ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx ,, ,, ,, cc ,, ,, ,, xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx ,, ,, ,, xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_treasury2
+    (list
+      (kern-mk-obj t_gold_coins 63
+        ;; hooks
+        (list
+        )
+      )
+    9 13)
+    (list
+      (kern-mk-obj t_gold_coins 45
+        ;; hooks
+        (list
+        )
+      )
+    13 5)
+    (list
+      (kern-mk-obj t_gold_coins 62
+        ;; hooks
+        (list
+        )
+      )
+    12 11)
+    (list
+      (kern-mk-obj t_gold_coins 27
+        ;; hooks
+        (list
+        )
+      )
+    10 8)
+    (list
+      (kern-mk-obj t_gold_coins 54
+        ;; hooks
+        (list
+        )
+      )
+    7 11)
+    (list
+      (kern-mk-obj t_gold_coins 48
+        ;; hooks
+        (list
+        )
+      )
+    5 8)
+    (list
+      (kern-mk-obj t_gold_coins 47
+        ;; hooks
+        (list
+        )
+      )
+    13 8)
+    (list
+      (kern-mk-obj t_gold_coins 64
+        ;; hooks
+        (list
+        )
+      )
+    11 11)
+    (list
+      (kern-mk-obj t_gold_coins 45
+        ;; hooks
+        (list
+        )
+      )
+    8 13)
+    (list
+      (kern-mk-obj t_gold_coins 60
+        ;; hooks
+        (list
+        )
+      )
+    8 9)
+    (list
+      (kern-mk-obj t_gold_coins 62
+        ;; hooks
+        (list
+        )
+      )
+    13 10)
+    (list
+      (kern-mk-obj t_gold_coins 81
+        ;; hooks
+        (list
+        )
+      )
+    8 10)
+    (list
+      (kern-mk-obj t_gold_coins 49
+        ;; hooks
+        (list
+        )
+      )
+    7 9)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_torch)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    8 11)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_food)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    10 13)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 9 t_gold_coins)
+          (list 1 t_mana_potion)
+          (list 3 t_arrow)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    10 10)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_torch)
+          (list 5 t_bolt)
+          (list 1 t_gold_coins)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    11 9)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 4 t_food)
+          (list 4 t_gold_coins)
+          (list 4 t_arrow)
+          (list 3 t_bolt)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    6 9)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    9 8)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    10 11)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    10 5)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    10 6)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    12 7)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    10 9)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    5 10)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    12 9)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    11 6)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    7 8)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_arrow
+            )
+            (list
+              2
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    11 7)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              5
+              't_bolt
+            )
+            (list
+              5
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    9 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    5 7)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_treasury
+          9
+          9
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 1 t_eldritch_blade)
+          (list 1 t_armor_plate_4)
+          (list 1 t_iron_helm_4)
+          (list 1 t_doom_staff)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    9 5)
+    (list
+      (kern-mk-obj t_gold_coins 44
+        ;; hooks
+        (list
+        )
+      )
+    11 5)
+    (list
+      (kern-mk-obj t_gold_coins 32
+        ;; hooks
+        (list
+        )
+      )
+    9 11)
+    (list
+      (kern-mk-obj t_gold_coins 56
+        ;; hooks
+        (list
+        )
+      )
+    12 8)
+    (list
+      (kern-mk-obj t_gold_coins 29
+        ;; hooks
+        (list
+        )
+      )
+    11 12)
+    (list
+      (kern-mk-obj t_gold_coins 51
+        ;; hooks
+        (list
+        )
+      )
+    9 10)
+    (list
+      (kern-mk-obj t_gold_coins 61
+        ;; hooks
+        (list
+        )
+      )
+    7 10)
+    (list
+      (kern-mk-obj t_gold_coins 49
+        ;; hooks
+        (list
+        )
+      )
+    7 6)
+  ) ;; end of objects in p_treasury2
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_treasury2
+
+(kern-load "may.scm")
+
+(kern-load "kathryn.scm")
+
+(kern-load "thud.scm")
+
+(kern-load "bill.scm")
+
+(kern-load "melvin.scm")
+
+(kern-load "hackle.scm")
+
+(kern-mk-place 'p_bole "Bole"
+  s_hamlet ;; sprite
+  (kern-mk-map
+    nil     48 39 pal_expanded
+    (list
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~6 ^a ^^ ^c ~6 ^a ^^ ^^ ~6 || || || || || || || || || ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^c t7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~6 |B || |% ~6 |# |% ^e ~6 || || || || || || || || || ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^c t3 tt tc {5 ^^ ^^ ^^ ^^ ^^ ^^ ~a ~5 |A |C ~6 |A |C ~3 ~c || || || || || || || || || |% ^a ^^ ^^ ^^ ^^ ^c |& ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ t3 tt tc t# .. {1 {5 ^^ ^^ ^^ ^c |& ~a ~1 ~~ ~~ ~~ ~1 ~c |# || || || || || || || || || || |% ^^ ^^ ^c |# || || |% ^e t3 tt tt tt t5 ^^ ^^ "
+      "^^ ^c tt t# .. .. .. .. .. {5 ^c tb tt || |% ~a ~~ bb ~~ ~c |# || || || tt tt tt tt tt tt tt tt || ^a ^c |# || || || || tt tc bb .. bb te ^a ^^ "
+      "^^ t3 tc .. .. .. .. .. .. .. bb .. t% tt || tH ~a ~~ ~c tG || || || tc t# .. .. .. t% ta tt tt || || || || || || |C ^7 tt bb .. .. .. bb t7 ^^ "
+      "^^ tt t# .. .. .. .. .. .. bb .. .. .. ta tt tt td ~6 tb tt || || tt t# tC t3 tt t5 tA .. t% ta tt tt tt || || || ^3 ^^ tt .. .. .. .. tb tt ^^ "
+      "^^ tt .. .. rr rr rr rr rr rr rr .. .. .. .. .. .. == .. t% ta tt tc .. t3 || || || || t5 .. .. .. t% tt || || |C ^^ ^^ tt bb .. .. .. bb tt ^^ "
+      "^^ tt .. .. rr .. .. .. .. .. rr .. .. tC t3 tt td ~6 t7 tA .. .. .. tC tt || || || || tt tA .. .. tC tt || |C ^3 ^^ ^^ ta t5 bb .. bb t3 tc ^^ "
+      "^^ tt .. .. rr .. .. .. .. .. rr .. .. t3 || || ~3 ~c || tt tt tt tt tt || || || || || tt t5 .. .. t3 tt || ^3 ^^ ^^ ^^ ^5 ta tt tt tt tc ^3 ^^ "
+      "^^ tt .. .. rr .. .. && .. .. .. .. .. tt || || ~6 |# || || || || || || || || || || || || tt .. tC tt || |C ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ tt .. .. rr .. .. .. .. .. rr .. .. tt || |C ~6 || || || || || || || || || || tt tt tt tc .. t3 || |C ^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ tt .. .. rr .. .. .. .. .. rr .. .. tt || ~3 ~c tt tt tt tt tt tt tt tt || || tt t# .. .. tC tt || ^b ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ tt .. .. rr rr rr .. rr rr rr .. .. || |C ~6 t3 tt tt tt tt tt tt tt tt tt || tt .. t3 tt tt || || |% ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ tt tA .. .. .. .. .. .. bb .. .. tC || ~3 ~c tt xx xx xx xx xx xx xx xx tt tt tc .. tt tt tt tt tt tt t5 ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ tt t5 tA .. .. .. .. bb {8 tC t3 tt || ~6 t3 tt xx cc cc cc cc cc cc xx te bb .. tC tt tt tt tt tt tt tt tt td ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ta tt t5 .. .. .. {c ^^ ^c t3 tt || || ~6 tt tt xx cc xx cc cc cc cc xx .. .. .. t3 tt xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ^^ ^^ "
+      "^^ ^5 tt tt tA .. {c ^^ ^^ t3 tt || tt tc ~6 tt tt xx xx xx cc cc cc cc cc .. .. bb tt tt xx cc cc cc cc cc cc cc cc xx cc cc cc cc cc xx ^^ ^^ "
+      "^^ ^^ ta tt tt td ^^ ^^ ^c tt tt || tt ~3 ~c tt tt tt t5 xx cc cc cc cc xx .. .. tb tt tt xx cc cc x! cc cc x! cc cc xx cc cc cc cc cc xx ^^ ^^ "
+      "^^ ^^ ^5 ta tc ^3 ^^ ^^ t3 tt tt || tt ~6 t3 tt tt tt tt xx cc cc cc cc xx .. .. bb tt tt xx xx xx xx cc cc xx xx xx xx cc cc cc cc cc xx ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c tt || || tt tc ~6 tt || || tt tt xx xx xx && xx xx .. .. .. ta tt xx cc cc cc cc cc cc cc cc xx cc cc cc cc cc xx ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^c t3 tt || tt tc ~3 ~c tt || || tt tt tt t5 xx xx xx t7 bb .. .. bb tt xx cc cc x! cc cc x! cc cc xx cc cc cc cc cc xx ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ t3 tt tt tt tt tc ~3 ~c t3 tt || || || tt tt tt tt tt tt tt td .. .. tb tt xx xx xx xx cc cc xx xx xx xx xx xx xx cc cc xx ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ tt || || || tt ~3 ~c t3 tt || || || || || || tt tt tt tt tt bb .. .. bb tt xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ tt || || tt tc ~6 t3 tt || || || || || || || || || tt tt tt td .. .. tb tt xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+      "^^ |& ^a ^^ ^^ ta tt tt tc ~3 ~c tt || || || || || || || || || || || tt bb .. .. .. bb te xx cc cc 00 cc cc xx xx xx cc cc cc cc cc cc xx ^^ ^^ "
+      "^^ || |% ^a ^^ ^5 ta tL ~3 ~4 t3 tt || || || || || || || || || || || tc .. .. .. .. .. .. sI cc cc 00 cc cc && xx && cc cc cc xx cc cc xx ^^ ^^ "
+      "^^ || tt td ^a ^L ~3 ~~ ~~ ~4 tt || || || || || || || || || || || || bb .. .. .. .. .. .. cc cc cc 00 cc cc && xx && cc cc cc xx xx xx xx ^^ ^^ "
+      "^^ tt tL ~3 ~1 ~~ ~~ ~~ ~~ ~4 tt || || || || || || tt tt tt || || || t5 .. .. .. .. .. .. xx cc cc 00 cc cc xx xx xx cc cc cc cc cc cc xx ^^ ^^ "
+      "^c tL ~3 ~~ ~~ bb ~~ ~~ ~~ ~c tt || || || || || tt tc ^7 ta tt || || tt bb .. .. .. bb t7 xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+      "~~ ~~ ~~ ~~ ~~ ~~ ~~ bb ~~ tG tt || || || || tt tc ^3 ^^ ^5 ta tt || || tt td .. .. tb tt xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+      "bb ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~c tt || || || || || tt ^b ^^ ^^ ^^ ^d tt || || || bb .. .. bb tt xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ^^ ^^ "
+      "~~ ~~ ~~ bb ~~ ~~ ~8 ~c tG tt || || || || || tt t5 ^a ^^ ^c t3 tt || || || td .. .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt t5 ^^ ^^ ^^ "
+      "~~ ~~ ~~ ~~ ~c tG tt tt tt || || || || || || || tt tt tt tt tt || || || tt bb .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt t5 ^a ^^ "
+      "~~ bb ~c tG tt tt tt tt || || || || || || || || || || || || || || || || tc .. .. .. tb tt tt || || || || || || || || || || || tt tt tt tt td ^^ "
+      "~~ ~~ || tt tt tt tt tt tt || || || || || || || || || || || || || || || bb .. .. .. bb || || || || || || || || || || || || || || || tt tc ^3 ^^ "
+      "~~ ~c || || tt tt tt tt tt || || || || || || || || || || || || || || || td .. .. tb tt || || || || || || || || || || || || || || || tt ^b ^^ ^^ "
+      "~c tG || || tt tt || || || || || || || || || || || || || || || || || || bb .. .. bb || || || || || || || || || || || || || || || || tt t5 ^a ^^ "
+      "|| || || || || || || || || || || || || || || || || || || || || || || || t5 .. .. t3 || || || || || || || || || || || || || || || || || tt t5 ^^ "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_bole
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    38 21)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    40 17)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    44 17)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 17)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    19 15)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    23 19)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    5 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 13)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    10 10)
+    (list
+      (bind
+        (kern-mk-obj t_thief_door 1
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        (list
+          'p_traps_1
+          4
+          16
+        )
+      ) ;; bind
+    43 6)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_may
+          "May"
+          sp_human
+          nil
+          s_townswoman
+          2
+          0 0 0
+          0 0
+          0 0
+          16 0
+          8 6
+          #f ;; dead?
+          'may-conv
+          sch_may
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    31 23)
+    (list
+      (bind
+        (kern-char-force-drop          (kern-mk-char
+            'ch_kathryn
+            "Kathryn"
+            sp_human
+            oc_wizard
+            s_wizard
+            2
+            0 4 0
+            2 1
+            4 2
+            16 0
+            8 6
+            #f ;; dead?
+            'kathryn-conv
+            sch_kathryn
+            'spell-sword-ai
+            (kern-mk-container
+              t_chest
+              ;; trap
+              nil
+              ;; contents
+              (list
+                (list 1 t_kathryns_letter)
+                (list 100 t_gold_coins)
+                (list 5 sulphorous_ash)
+                (list 5 ginseng)
+                (list 5 garlic)
+                (list 3 spider_silk)
+                (list 3 blood_moss)
+                (list 2 black_pearl)
+                (list 1 nightshade)
+                (list 1 mandrake)
+                (list 1 t_wis_quas_scroll)
+              )
+              ;; hooks
+              (list
+              )
+            )
+            (list
+              t_staff
+            )
+            ;; hooks
+            (list
+            )
+          )
+        #t) ;; kern-char-force-drop
+        '()
+      ) ;; bind
+    31 23)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_thud
+          "Thud"
+          sp_troll
+          oc_warrior
+          s_troll
+          2
+          4 0 2
+          2 1
+          0 0
+          40 4096
+          8 6
+          #f ;; dead?
+          'thud-conv
+          sch_thud
+          nil
+          nil ;; inventory
+          (list
+            t_iron_helm
+            t_2h_axe
+            t_armor_plate
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    31 23)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_bill
+          "Bill"
+          sp_human
+          nil
+          s_townsman
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          5 3
+          #f ;; dead?
+          'bill-conv
+          sch_bill
+          nil
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 10 t_torch)
+              (list 100 t_arrow)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_2h_axe
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    20 15)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_melvin
+          "Melvin"
+          sp_human
+          nil
+          s_townsman
+          2
+          10 10 10
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'melvin-conv
+          sch_melvin
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    40 18)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_hackle
+          "Hackle"
+          sp_human
+          nil
+          s_beggar
+          2
+          10 10 10
+          0 0
+          0 0
+          16 0
+          0 6
+          #f ;; dead?
+          'hackle-conv
+          sch_hackle
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    2 3)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bull"
+          sp_bull
+          nil
+          s_bull
+          0
+          0 0 0
+          0 0
+          0 0
+          22 128
+          1 1
+          #f ;; dead?
+          nil
+          nil
+          'animal-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'npcg
+          'bull
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    6 4)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "dryad"
+          sp_dryad
+          nil
+          s_reaper
+          5
+          0 0 0
+          0 0
+          0 0
+          20 16384
+          30 8
+          #f ;; dead?
+          nil
+          nil
+          'dryad-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d5"
+                      't_torch
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'dryad
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    6 35)
+    (list
+      (kern-tag 'bole-inn-room-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    33 17)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    36 17)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    33 20)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    36 20)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    42 25)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    42 28)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    30 27)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    31 18)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    38 18)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    31 21)
+  ) ;; end of objects in p_bole
+  (list ;; on-entry-hooks
+    'lock-inn-room-doors
+  )
+  (list ;; edge entrances
+    (list 0 47 38) ;; Northwest
+    (list 1 26 38) ;; North
+    (list 2 0 38) ;; Northeast
+    (list 3 47 19) ;; West
+    (list 4 24 19) ;; Here
+    (list 5 0 19) ;; East
+    (list 6 47 0) ;; Southwest
+    (list 7 24 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_bole
+
+(kern-load "patch.scm")
+
+(kern-load "angela.scm")
+
+(kern-load "jess.scm")
+
+(kern-load "chester.scm")
+
+(kern-load "steward.scm")
+
+(kern-load "ini.scm")
+
+(kern-load "jeffreys.scm")
+
+(kern-mk-place 'p_glasdrin "Glasdrin"
+  s_keep ;; sprite
+  (kern-mk-map
+    nil     31 31 pal_expanded
+    (list
+      "xx xx xx xx xx .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. xx xx xx xx xx "
+      "xx ,, ,, ,, xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx cc ++ cc xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, cc cc cc xx "
+      "xx ,, ,, ,, xx xx xx xx xx xx xx xx xx xx xx x! xx xx xx xx xx xx xx xx xx xx xx cc cc cc xx "
+      "xx xx ,, xx xx xx .A .R .M .S ]] xx ,, ,, ,, ,, ,, ,, ,, xx .M .E .D .I .C .K xx xx ,, xx xx "
+      ".. xx ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, pp ,, ,, ,, pp ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+      ".. xx ,, xx ,, xx @@ @@ @@ @@ @@ xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+      ".. xx ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, pp ,, ,, ,, pp ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+      ".. xx ,, xx xx xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+      ".. xx ,, xx xx xx xx xx ,, sA xx xx ,, pp ,, ,, ,, pp ,, xx xx xx ,, sH xx xx xx xx ,, xx .. "
+      ".. xx ,, xx ,, ,, xx .. cc .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx cc .. xx ,, ,, xx ,, xx .. "
+      ".. xx ,, xx ,, ,, ,, cc cc xx xx ,, xx xx ,, ,, ,, xx xx ,, xx xx cc cc ,, ,, ,, xx ,, xx .. "
+      ".. xx ,, xx xx xx xx .. cc xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx cc .. xx xx xx xx ,, xx .. "
+      ".. xx ,, xx ,, ,, xx .. cc xx ,, ,, ,, xx w+ ,, w+ xx ,, ,, ,, xx cc .. xx ,, ,, xx ,, xx .. "
+      ".. xx ,, xx ,, ,, ,, cc cc xx ,, ,, ,, xx cc cc cc xx ,, ,, ,, xx cc cc ,, ,, ,, xx ,, xx .. "
+      ".. xx ,, xx xx xx xx .. cc xx xx xx xx x! cc cc cc x! xx xx xx xx cc .. xx xx xx xx ,, xx .. "
+      ".. xx ,, ,, cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ,, ,, xx .. "
+      ".. xx ,, xx xx xx xx xx xx xx .. .. .. .. cc cc cc t3 tt tt t5 xx xx xx xx xx xx xx ,, xx .. "
+      ".. xx ,, xx .H .O .T .E .L xx .. .. .. .. cc cc cc tt ~3 ~5 tt xx .H .O .L .Y ]] xx ,, xx .. "
+      ".. xx ,, xx ,, ,, ,, ,, ,, ,, .. .. .. .. cc cc cc tt ~a ~c tt xx .G .R .A .I .L xx ,, xx .. "
+      ".. xx ,, xx @@ @@ @@ @@ @@ sI .. .. .. .. cc cc cc ta tt tt tc ws ,, ,, ,, ,, ,, xx ,, xx .. "
+      ".. xx ,, xx ,, ,, ,, ,, ,, ,, cc cc cc cc cc cc cc cc cc cc cc ,, ,, ,, ,, ,, ,, xx ,, xx .. "
+      ".. xx ,, xx x! ,, ,, ,, ,, ws bb .. .. bb cc cc cc bb bb bb bb ws ,, ,, 00 ,, && xx ,, xx .. "
+      ".. xx ,, xx xx ,, xx ,, xx xx .. .. .. .. cc cc cc bb .. .. .. sT ,, ,, 00 ,, ,, xx ,, xx .. "
+      ".. xx ,, xx ,, ,, xx ,, ,, xx .. .. .. .. cc cc cc bb .. tC t7 xx ,, ,, ,, ,, ,, xx ,, xx .. "
+      ".. xx ,, xx ,, ,, xx ,, ,, xx .. .. .. bb cc cc cc bb .. tb tc xx xx [[ @@ ]] xx xx ,, xx .. "
+      "xx xx ,, xx xx xx xx xx xx xx xx xx xx x! cc w+ cc x! xx xx xx xx xx ,, ,, ,, xx xx ,, xx xx "
+      "xx ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, w+ cc cc cc w+ ,, ,, ,, xx xx xx ,, xx xx ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ cc cc cc w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, w+ cc cc cc w+ ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, xx "
+      "xx xx xx xx xx .. .. .. .. xx xx xx xx xx cc cc cc xx xx xx xx xx .. .. .. .. xx xx xx xx xx "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_glasdrin
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'halberdier
+        )
+      ) ;; bind
+    14 12)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'halberdier
+        )
+      ) ;; bind
+    16 12)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'crossbowman
+        )
+      ) ;; bind
+    12 28)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'crossbowman
+        )
+      ) ;; bind
+    18 28)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    21 21)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 14)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 14)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    19 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    8 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 7)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 13)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 27)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    22 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    27 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    2 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 2)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    26 28)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    28 26)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 21)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 19)
+    (list
+      (kern-tag 'glasdrin-inn-room-1-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    5 23)
+    (list
+      (kern-tag 'glasdrin-inn-room-2-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    7 23)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 25)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 25)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    26 10)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 13)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    26 13)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 10)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    11 14)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    29 28)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    19 14)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_prison
+          6
+          4
+        )
+      ) ;; bind
+    2 2)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_patch
+          "Patch"
+          sp_human
+          oc_wizard
+          s_companion_wizard
+          2
+          0 0 0
+          0 0
+          0 0
+          16 0
+          0 6
+          #f ;; dead?
+          'patch-conv
+          sch_patch
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    25 10)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_angela
+          "Angela"
+          sp_human
+          nil
+          s_townswoman
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'ange-conv
+          sch_ange
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    4 19)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_jess
+          "Jess"
+          sp_human
+          nil
+          s_townswoman
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'jess-conv
+          sch_jess
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    23 26)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_chester
+          "Chester"
+          sp_human
+          oc_warrior
+          s_townsman
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'ches-conv
+          sch_ches
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    4 10)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_steward
+          "Victoria"
+          sp_human
+          nil
+          s_lady
+          2
+          0 0 0
+          0 0
+          0 0
+          16 0
+          0 6
+          #f ;; dead?
+          'stew-conv
+          sch_stew
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+        )
+      ) ;; bind
+    11 14)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_ini
+          "Ini"
+          sp_human
+          oc_warrior
+          s_companion_paladin
+          2
+          5 0 5
+          25 5
+          0 0
+          30 612
+          0 3
+          #f ;; dead?
+          'ini-conv
+          sch_ini
+          nil
+          nil ;; inventory
+          (list
+            t_chain_coif
+            t_halberd
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+        )
+      ) ;; bind
+    29 28)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_jeffreys
+          "Jeff"
+          sp_human
+          oc_warrior
+          s_companion_paladin
+          2
+          0 0 0
+          0 0
+          0 0
+          15 0
+          0 5
+          #f ;; dead?
+          'jeff-conv
+          sch_jeff
+          nil
+          nil ;; inventory
+          (list
+            t_chain_coif
+            t_sword
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    19 14)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bull"
+          sp_bull
+          nil
+          s_bull
+          0
+          0 0 0
+          0 0
+          0 0
+          36 16384
+          8 8
+          #f ;; dead?
+          nil
+          nil
+          'animal-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'npcg
+          'bull
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    19 24)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'halberdier
+        )
+      ) ;; bind
+    15 25)
+  ) ;; end of objects in p_glasdrin
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+    'lock-inn-room-doors
+  )
+  (list ;; edge entrances
+    (list 0 30 30) ;; Northwest
+    (list 1 15 30) ;; North
+    (list 2 0 30) ;; Northeast
+    (list 3 30 15) ;; West
+    (list 4 15 15) ;; Here
+    (list 5 0 15) ;; East
+    (list 6 30 0) ;; Southwest
+    (list 7 15 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_glasdrin
+
+(kern-load "alchemist.scm")
+
+(kern-load "oscar.scm")
+
+(kern-load "henry.scm")
+
+(kern-load "bart.scm")
+
+(kern-load "lia.scm")
+
+(kern-load "fing.scm")
+
+(kern-load "ghertie.scm")
+
+(kern-mk-place 'p_oparine "Oparine"
+  s_town ;; sprite
+  (kern-mk-map
+    nil     31 55 pal_expanded
+    (list
+      ".. .. .. .. .. .. .. .. .. .. .. .. cc cc cc cc cc cc .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. xx xx xx xx xx xx xx xx xx xx cc cc cc cc cc cc xx xx xx xx xx xx xx xx xx xx xx xx .. "
+      ".. .. xx .C .H .E .E .R .F .U .L xx cc cc cc cc cc cc xx ,, xx .B .I .L .G .E xx ,, ,, xx .. "
+      ".. .. xx .B .U .N .K .M .A .T .E xx cc cc cc cc cc cc xx ,, xx .W .A .T .E .R xx ,, ,, xx .. "
+      ".. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, xx cc cc cc cc cc cc xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. "
+      ".. .. xx [[ @@ @@ @@ @@ @@ @@ ]] xx cc cc cc cc cc cc xx ,, xx [[ @@ @@ @@ ]] xx xx xx xx .. "
+      ".. .. xx ,, ,, ,, ,, ,, ,, ,, ,, ws cc cc cc cc cc cc xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+      ".. .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, cc cc cc cc cc cc ws ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+      ".. .. xx xx xx xx ,, ,, xx xx xx sI cc cc cc cc cc xx xx [[ @@ ]] ,, ,, ,, [[ @@ ]] xx xx .. "
+      ".. .. xx ,, ,, xx ,, ,, ,, ,, ,, xx cc cc cc cc cc xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx .. "
+      ".. .. xx ,, ,, ,, ,, ,, xx ,, ,, ws cc cc cc cc cc xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx .. "
+      ".. .. xx xx xx xx ,, ,, xx xx xx xx cc cc cc cc cc xx xx [[ @@ ]] ,, ,, ,, [[ @@ ]] xx xx .. "
+      ".. .. xx ,, ,, xx ,, ,, ,, ,, ,, xx cc cc cc cc cc cc ws ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+      ".. .. xx ,, ,, ,, ,, ,, xx ,, ,, ws cc cc cc cc cc cc xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+      ".. .. xx xx xx xx xx ,, xx xx xx xx cc cc cc cc cc cc xx xx xx xx sT ,, xx xx xx xx xx .. .. "
+      ".. .. xx ,, ,, xx ,, ,, xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc .. .. "
+      ".. .. xx ,, ,, xx ,, ,, xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc .. .. "
+      ".. .. xx ,, ws xx xx xx xx cc cc cc cc cc cc ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## "
+      "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ## _3 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 __ "
+      "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc oo __ __ __ __ __ oo __ __ __ __ __ oo __ __ "
+      "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee "
+      ".. .. .. .. xx xx xx xx xx cc cc cc cc cc cc cc ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee "
+      ".. .. .. .. xx ,, ,, ,, xx cc cc cc cc cc cc cc ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee "
+      ".. .. .. .. xx ,, ,, ,, ,, cc cc cc cc cc cc cc oo __ __ ee ee ee oo __ __ __ __ __ oo __ __ "
+      ".. .. .. .. xx ,, ,, ,, xx cc cc cc ## ## ## ## __ __ __ ee ee ee __ __ __ __ _8 __ __ __ __ "
+      ".. xx xx xx xx xx xx xx xx cc cc cc ## _3 _1 __ __ __ __ ee ee ee __ __ _c ## ## ## _a __ __ "
+      ".. xx ,A ,L ,K ,E ,M ,Y xx cc cc cc ## _2 __ __ __ __ __ ee ee ee __ __ ## ## ee ## ## __ __ "
+      ".. xx ,, ,, ,, ,, ,, ,, ws cc cc cc ## _2 xx xx xx xx oo ee ee ee oo _c ## ee ee ee ## _a __ "
+      ".. xx ,, ,, ,, ,, ,, ,, sP cc cc cc ## _2 xx ee ee xx ~~ ee ee ee __ ## ## ee ee ee ## ## __ "
+      ".. xx ,, ,, aa && ,, ,, ,, cc cc cc ## _2 xx ee ee ee ee ee ee ee __ ## ee ee ee ee ee ## _2 "
+      ".. xx ,, ,, ,, ,, ,, ,, xx cc cc cc ## _2 xx ee ee xx __ ee ee ee ee ee ee ee ee ee ee ## _2 "
+      ".. xx ,, ,, ,, ,, ,, ,, ws cc cc cc ## _2 xx xx xx xx __ ee ee ee __ ## vv vv ee ee vv ## _2 "
+      ".. xx [[ @@ @@ @@ @@ ]] xx cc cc cc ## _2 __ __ __ __ __ ee ee ee _c ## ee ee ee ee ee ## _2 "
+      ".. xx xx xx xx xx xx xx xx cc cc cc ## ~a ~~ ~~ __ __ oo ee ee ee oo ## vv vv vv vv vv ## _2 "
+      ".. .. .. .. .. .. .. .. bb .. .. .. bb .. ~% ~~ -- __ __ ee ee ee _5 ## ee ee ee ee ee ## _2 "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ~a ~~ -- __ __ __ __ __ ## ## vv vv vv ## ## __ "
+      ".. .. .. .. .. .. .. .. bb .. .. .. bb .. .. ~% ~~ ~~ -- __ __ __ __ _5 ## ee ee ee ## _3 __ "
+      ".. xx xx xx xx xx xx xx .. .. .. .. .. .. .. .. ~a ~~ -- -- __ __ __ __ ## ## vv ## ## __ __ "
+      ".. xx [[ .S .E .A ]] xx bb .. .. .. bb .. .. .. ~% ~~ ~~ -- __ __ __ __ _5 ## ## ## _3 __ __ "
+      ".. xx .W .I .T .C .H sR .. .. .. .. .. .. .. .. ~C ~~ ~~ -- -- __ __ __ __ __ _1 __ __ __ __ "
+      ".. xx ,, ,, ,, ,, ,, ws bb .. .. .. bb .. .. .. ~3 ~~ ~~ -- -- __ __ __ __ __ __ __ __ __ __ "
+      ".. xx ,, ,, ,, ,, ,, ,, .. .. .. .. .. .. .. ~C ~~ ~~ ~~ -- -- __ __ __ __ __ __ __ __ __ __ "
+      ".. xx ,, [[ @@ ]] ,, ws bb .. .. .. bb .. .. ~3 ~~ ~~ -- -- -- -- __ __ __ __ __ __ __ __ __ "
+      ".. xx xx ,, ,, ,, xx xx .. .. .. .. .. .. .. ~2 ~~ ~~ ~~ ~~ -- -- -- __ __ __ __ __ __ __ __ "
+      ".. .. xx xx ,, xx xx .. bb .. .. .. oo .. oo ~8 ~8 ~~ ~~ ~~ -- -- -- __ __ __ __ __ __ __ __ "
+      ".. .. xx ,, ,, ,, xx .. .. .. .. .. ee ee ee .. .. bb ~~ ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+      ".. .. xx ,, ,, ,, ws .. bb .. .. .. ee ee ee .. .. .. ~a ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+      ".. .. xx xx ,, xx xx .. .. .. .. .. ee ee ee .. .. .. bb ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+      ".. .. .. bb .. bb .. .. .. .. bb .. oo ~~ oo .. .. .. ~3 ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. ~6 .. .. .. .. ~~ ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+      ".. .. bb ~3 ~1 ~5 bb .. .. .. .. ~C ~3 ~~ oo ee ee ee oo ~~ ~~ -- -- -- __ __ __ __ __ __ __ "
+      "~C ~3 ~~ ~~ ~~ ~~ ~~ ~5 ~A .. ~C ~3 ~~ ~~ ~~ ee ee ee ~~ ~~ ~~ -- -- -- -- __ __ __ __ __ __ "
+      "~~ ~~ -- -- -- -- -- ~~ ~~ ~1 ~~ ~~ ~~ ~c oo ee ee ee oo ~a ~~ ~~ -- -- -- __ __ __ __ __ __ "
+      "-- -- -- __ __ __ -- -- -- -- -- ~~ ~c ~# .. .. .. .. .. ~% ~a ~~ ~~ -- -- __ __ __ __ __ __ "
+      "-- -- -- __ __ __ -- -- -- -- -- ~~ ~# .. .. .. .. .. .. .. ~% ~~ ~~ -- -- -- __ __ __ __ __ "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_oparine
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    3 9)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    3 12)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    6 15)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    10 12)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    10 9)
+    (list
+      (kern-tag 'oparine-inn-room-1-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    5 10)
+    (list
+      (kern-tag 'oparine-inn-room-2-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    5 13)
+    (list
+      (kern-tag 'oparine-inn-room-3-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #t
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    7 14)
+    (list
+      (kern-tag 'oparine-inn-room-4-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    8 12)
+    (list
+      (kern-tag 'oparine-inn-room-5-door
+        (bind
+          (kern-mk-obj t_door 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            0
+            '()
+            #f
+            #t
+            #f
+            (list
+              (list
+                's_closed_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_open_door_in_stone
+                #f
+                0
+              )
+              (list
+                's_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+              (list
+                's_magically_locked_solid_wood_door_in_stone
+                #t
+                5
+              )
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    8 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 17)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 15)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    17 29)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 41)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 47)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 44)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    3 45)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    8 29)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    8 23)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    5 22)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    19 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    23 14)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    20 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    26 4)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    27 2)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_alchemist
+          "Alchemist"
+          sp_human
+          oc_wright
+          s_companion_tinker
+          2
+          0 0 0
+          0 0
+          0 0
+          18 0
+          10 8
+          #f ;; dead?
+          'alch-conv
+          sch_alch
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            #f
+            #f
+            #f
+          )
+          #f
+          #f
+        )
+      ) ;; bind
+    3 28)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_oscar
+          "Oscar"
+          sp_human
+          nil
+          s_townsman
+          2
+          0 0 0
+          0 0
+          0 0
+          11 0
+          0 1
+          #f ;; dead?
+          'oscar-conv
+          sch_oscar
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    21 7)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_henry
+          "Henry"
+          sp_human
+          nil
+          s_townsman
+          2
+          0 0 0
+          0 0
+          0 0
+          16 0
+          0 6
+          #f ;; dead?
+          'henry-conv
+          sch_henry
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    21 4)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_bart
+          "Bart"
+          sp_forest_goblin
+          nil
+          s_orc
+          2
+          0 0 0
+          0 0
+          0 0
+          9 0
+          0 1
+          #f ;; dead?
+          'bart-conv
+          sch_bart
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    22 6)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_lia
+          "Lia"
+          sp_human
+          oc_wizard
+          s_townswoman
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'lia-conv
+          sch_lia
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    3 49)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_fing
+          "Fing"
+          sp_nixie
+          oc_warrior
+          s_nixie
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          0 3
+          #f ;; dead?
+          'fing-conv
+          sch_fing
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    3 50)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_ghertie
+          "Ghertie"
+          sp_ghast
+          oc_warrior
+          s_ghost
+          2
+          0 0 0
+          0 0
+          0 0
+          16 0
+          0 6
+          #f ;; dead?
+          'ghertie-conv
+          sch_ghertie
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            #f
+            #f
+            #f
+          )
+        )
+      ) ;; bind
+    6 15)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    2 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 7)
+  ) ;; end of objects in p_oparine
+  (list ;; on-entry-hooks
+    'lock-inn-room-doors
+  )
+  (list ;; edge entrances
+    (list 0 30 54) ;; Northwest
+    (list 1 16 54) ;; North
+    (list 2 0 54) ;; Northeast
+    (list 3 30 21) ;; West
+    (list 4 15 27) ;; Here
+    (list 5 0 19) ;; East
+    (list 6 30 0) ;; Southwest
+    (list 7 15 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_oparine
+
+(kern-mk-place 'p_traps_1 "Riddles"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr xx xx xx xx xx xx xx xx xx xx rr rr "
+      "rr rr rr xx xx xx xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, x! rr rr "
+      "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx rr rr "
+      "rr rr xx xx ,, xx xx xx xx ,, xx xx xx xx ,, xx xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+      "rr rr xx xx ,, xx xx xx xx ,, xx xx xx xx ,, xx xx rr rr "
+      "rr rr xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr x! ,, ,, ,, x! ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx xx xx xx rr rr rr "
+      "rr rr xx xx xx xx xx xx xx xx xx xx rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_traps_1
+    (list
+      (bind
+        (kern-mk-obj t_step_riddle 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'egg
+          't_lava
+          3
+          5
+          3
+          9
+          (list
+            "All who would pass must answer the riddle:
+
+"
+            "  In a marble hall white as milk
+"
+            "  Lined with skin soft as silk
+"
+            "  Within a fountain crystal clear
+"
+            "  A golden apple doth appear
+"
+            "  No doors there are to this stronghold
+"
+            "  Yet thieves break in to steal its gold.
+"
+          )
+        )
+      ) ;; bind
+    4 14)
+    (list
+      (bind
+        (kern-mk-obj t_step_riddle 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'few
+          't_lava
+          8
+          5
+          3
+          9
+          (list
+            "All who would pass must answer the riddle:
+
+"
+            "  I know a word of letters three.
+"
+            "  Add two, and fewer there will be."
+          )
+        )
+      ) ;; bind
+    9 4)
+    (list
+      (bind
+        (kern-mk-obj t_step_riddle 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'eye
+          't_lava
+          13
+          5
+          3
+          9
+          (list
+            "All who would pass must answer the riddle:
+
+"
+            "  Pronounced as one letter,
+"
+            "  but written with three.
+"
+            "  Two letters there are
+"
+            "  and two only in me.
+"
+            "  I'm double, and single,
+"
+            "  and black, blue and gray.
+"
+            "  When read from both ends
+"
+            "  I'm the same either way."
+          )
+        )
+      ) ;; bind
+    14 14)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_2
+          9
+          15
+        )
+      ) ;; bind
+    14 2)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_bole
+          43
+          6
+        )
+      ) ;; bind
+    4 16)
+  ) ;; end of objects in p_traps_1
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_traps_1
+
+(kern-mk-place 'p_traps_2 "The Choice"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx ,, ,, ,, ,, ,, xx xx xx xx xx ,, ,, ,, ,, ,, xx xx "
+      "xx xx xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx xx xx "
+      "xx xx xx xx ,, xx xx ,, ,, ,, ,, ,, xx xx ,, xx xx xx xx "
+      "xx xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx xx xx "
+      "xx xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx xx xx "
+      "xx xx xx xx ,, xx xx xx xx ~x xx xx xx xx ,, xx xx xx xx "
+      "xx xx xx xx ,, xx xx .C .H ~O .O .S .E xx ,, xx xx xx xx "
+      "xx xx xx xx ,, xx xx !! !! ~! !! !! !! xx ,, xx xx xx xx "
+      "xx xx xx xx ,, xx xx ,, ,, ,, ,, ,, ,, xx ,, xx xx xx xx "
+      "xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, ,, xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx !! !! !! !! !! !! xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx .W .I .S .E .L .Y xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_traps_2
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'mk-bandit
+        )
+      ) ;; bind
+    4 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    14 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    14 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 8)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_3
+          9
+          9
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_1
+          14
+          2
+        )
+      ) ;; bind
+    9 15)
+    (list
+      (bind
+        (kern-mk-obj t_step_clue 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          "Doesn't the other way look better?"
+        )
+      ) ;; bind
+    13 15)
+    (list
+      (bind
+        (kern-mk-obj t_step_clue 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          "Doesn't the other way look better?"
+        )
+      ) ;; bind
+    6 15)
+    (list
+      (kern-mk-obj t_secret_path 1
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    9 14)
+    (list
+      (kern-mk-obj t_secret_path 1
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    9 13)
+    (list
+      (kern-mk-obj t_secret_path 1
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    9 12)
+    (list
+      (kern-mk-obj t_secret_path 1
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    9 11)
+    (list
+      (kern-mk-obj t_secret_path 1
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    9 10)
+    (list
+      (kern-mk-obj t_secret_path 1
+        ;; hooks
+        (list
+          (list
+            ef_permanent_invisibility
+            '()
+            2
+            0
+          )
+        )
+      )
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_2
+          14
+          3
+        )
+      ) ;; bind
+    4 3)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_2
+          4
+          3
+        )
+      ) ;; bind
+    14 3)
+  ) ;; end of objects in p_traps_2
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_traps_2
+
+(kern-load "traps_3_mechs.scm")
+
+(kern-mk-place 'p_traps_3 "Fun with Levers"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx xx xx ,, x! xx xx xx x! ,, x! xx xx xx x! ,, xx xx xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx xx xx ,, x! xx xx xx x! ,, x! xx xx xx x! ,, xx xx xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_traps_3
+    (list
+      (kern-tag 't3_pc6
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    12 15)
+    (list
+      (kern-tag 't3_pc7
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    3 6)
+    (list
+      (kern-tag 't3_pc8
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 6)
+    (list
+      (kern-tag 't3_pc9
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    15 6)
+    (list
+      (kern-tag 't3_pc10
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    3 12)
+    (list
+      (kern-tag 't3_pc11
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 12)
+    (list
+      (kern-tag 't3_pc12
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    15 12)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          0
+        )
+      ) ;; bind
+    3 3)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          1
+        )
+      ) ;; bind
+    15 3)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          2
+        )
+      ) ;; bind
+    3 9)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          3
+        )
+      ) ;; bind
+    15 9)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          4
+        )
+      ) ;; bind
+    3 15)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          5
+        )
+      ) ;; bind
+    9 15)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          't3_ctrl
+          #f
+          6
+        )
+      ) ;; bind
+    15 15)
+    (list
+      (kern-tag 't3_ctrl
+        (bind
+          (kern-mk-obj t_t3_ctrl 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            (list
+              't3_pc1
+              't3_pc2
+              't3_pc3
+              't3_pc4
+              't3_pc5
+              't3_pc6
+              't3_pc7
+              't3_pc8
+              't3_pc9
+              't3_pc10
+              't3_pc11
+              't3_pc12
+            )
+            (list
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+            )
+            (list
+              #t
+              #t
+              #t
+              #t
+              #t
+              #t
+              #f
+              #f
+              #f
+              #f
+              #f
+              #f
+            )
+            (list
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+            )
+            (list
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+            )
+            (list
+              #f
+              #f
+              #f
+              #f
+              #f
+              #f
+              #t
+              #t
+              #t
+              #t
+              #t
+              #t
+            )
+            (list
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+              #t
+              #f
+            )
+            (list
+              #f
+              #f
+              #t
+              #t
+              #t
+              #t
+              #t
+              #t
+              #t
+              #t
+              #f
+              #f
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_2
+          9
+          9
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_4
+          9
+          9
+        )
+      ) ;; bind
+    9 3)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'queen-spider
+        )
+      ) ;; bind
+    6 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    6 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'yellow-slime
+        )
+      ) ;; bind
+    15 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bandit
+        )
+      ) ;; bind
+    15 3)
+    (list
+      (kern-tag 't3_pc1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    6 3)
+    (list
+      (kern-tag 't3_pc2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    6 9)
+    (list
+      (kern-tag 't3_pc3
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    6 15)
+    (list
+      (kern-tag 't3_pc4
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    12 3)
+    (list
+      (kern-tag 't3_pc5
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    12 9)
+  ) ;; end of objects in p_traps_3
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_traps_3
+
+(kern-mk-place 'p_traps_4 "Labyrinth of Burning Glass"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ~, ,, ,, ,, ,, ,, xx "
+      "xx ,, pp ~, pp ~, pp ~, pp ~, pp ~, pp ,, pp ~, pp ,, xx "
+      "xx ,, ~, ,, ,, ,, ,, ,, ,, ,, ,, ,, ~, ,, ,, ,, ~, ,, xx "
+      "xx ,, pp ,, pp ~, pp ~, pp ~, pp ,, pp ~, pp ,, pp ,, xx "
+      "xx ,, ~, ,, ~, ,, ,, ,, ~, ,, ,, ,, ~, ,, ,, ,, ~, ,, xx "
+      "xx ,, pp ,, pp ~, pp ,, pp ~, ~p ~, pp ,, pp ~, pp ,, xx "
+      "xx ,, ~, ,, ,, ,, ~, ,, ~, ,, ,, ,, ~, ,, ~, ,, ~, ,, xx "
+      "xx ,, pp ~, pp ,, pp ,, pp ~, pp ~, pp ~, pp ,, pp ,, xx "
+      "xx ,, ~, ,, ,, ,, ~, ,, ,, ,, ,, ,, ,, ,, ~, ,, ~, ,, xx "
+      "xx ,, pp ,, pp ~, pp ~, pp ~, pp ~, pp ,, pp ,, pp ,, xx "
+      "xx ,, ~, ,, ~, ,, ~, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, pp ,, pp ,, pp ,, pp ~, pp ~, pp ,, pp ~, pp ,, xx "
+      "xx ,, ~, ,, ~, ,, ~, ,, ~, ,, ,, ,, ~, ,, ,, ,, ~, ,, xx "
+      "xx ,, pp ,, pp ,, pp ,, pp ,, pp ,, pp ~, pp ~, pp ,, xx "
+      "xx ,, ~, ,, ~, ,, ,, ,, ~, ,, ~, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, pp ,, pp ~, pp ~, pp ~, pp ~, pp ~, pp ~, pp ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_traps_4
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_3
+          9
+          3
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_thiefs_den
+          9
+          9
+        )
+      ) ;; bind
+    9 7)
+  ) ;; end of objects in p_traps_4
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_traps_4
+
+(kern-load "mouse.scm")
+
+(kern-mk-place 'p_thiefs_den "Thief's Den"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, pp ,, ,, ,, ,, ,, ,, ,, ,, ,, pp ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_thiefs_den
+    (list
+      (kern-mk-obj t_picklock 1
+        ;; hooks
+        (list
+        )
+      )
+    8 6)
+    (list
+      (kern-mk-obj t_gem 1
+        ;; hooks
+        (list
+        )
+      )
+    8 7)
+    (list
+      (kern-mk-obj t_an_tym_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    9 7)
+    (list
+      (kern-mk-obj t_in_mani_corp_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    10 7)
+    (list
+      (kern-mk-obj t_vas_rel_por_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    10 8)
+    (list
+      (kern-mk-obj t_sanct_lor_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    10 10)
+    (list
+      (kern-mk-obj t_in_quas_xen_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    9 10)
+    (list
+      (kern-mk-obj t_an_xen_exe_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    8 9)
+    (list
+      (kern-mk-obj t_in_an_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    7 9)
+    (list
+      (kern-mk-obj t_in_ex_por_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    6 9)
+    (list
+      (kern-mk-obj t_vas_mani_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    6 8)
+    (list
+      (kern-mk-obj t_wis_quas_scroll 1
+        ;; hooks
+        (list
+        )
+      )
+    6 7)
+    (list
+      (kern-mk-obj t_gold_coins 74
+        ;; hooks
+        (list
+        )
+      )
+    6 2)
+    (list
+      (kern-mk-obj t_gold_coins 112
+        ;; hooks
+        (list
+        )
+      )
+    2 9)
+    (list
+      (kern-mk-obj t_gold_coins 243
+        ;; hooks
+        (list
+        )
+      )
+    1 17)
+    (list
+      (kern-mk-obj t_gold_coins 30
+        ;; hooks
+        (list
+        )
+      )
+    7 3)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    3 1)
+    (list
+      (bind
+        (kern-char-force-drop          (kern-mk-char
+            'ch_mouse
+            "Mouse"
+            sp_human
+            nil
+            s_brigand
+            2
+            0 0 10
+            2 2
+            1 1
+            18 0
+            10 8
+            #f ;; dead?
+            'mouse-conv
+            nil
+            nil
+            (kern-mk-container
+              t_chest
+              ;; trap
+              nil
+              ;; contents
+              (list
+                (list 1 t_rune_k)
+                (list 1 t_sword)
+                (list 50 t_arrow)
+              )
+              ;; hooks
+              (list
+              )
+            )
+            (list
+              t_leather_helm
+              t_bow
+              t_armor_leather
+            )
+            ;; hooks
+            (list
+            )
+          )
+        #t) ;; kern-char-force-drop
+        (list
+          #t
+        )
+      ) ;; bind
+    3 3)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_traps_4
+          9
+          7
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (kern-mk-obj t_food 10
+        ;; hooks
+        (list
+        )
+      )
+    4 1)
+    (list
+      (kern-mk-obj t_wine 1
+        ;; hooks
+        (list
+        )
+      )
+    4 2)
+    (list
+      (kern-mk-obj t_cure_potion 1
+        ;; hooks
+        (list
+        )
+      )
+    3 4)
+    (list
+      (kern-mk-obj t_mana_potion 1
+        ;; hooks
+        (list
+        )
+      )
+    4 5)
+    (list
+      (kern-mk-obj t_heal_potion 1
+        ;; hooks
+        (list
+        )
+      )
+    5 5)
+    (list
+      (kern-mk-obj t_poison_immunity_potion 1
+        ;; hooks
+        (list
+        )
+      )
+    6 5)
+    (list
+      (kern-mk-obj t_inv_potion 1
+        ;; hooks
+        (list
+        )
+      )
+    7 5)
+    (list
+      (kern-mk-obj t_torch 1
+        ;; hooks
+        (list
+        )
+      )
+    8 5)
+  ) ;; end of objects in p_thiefs_den
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_thiefs_den
+
+(kern-load "anne.scm")
+
+(kern-load "jones.scm")
+
+(kern-load "alex.scm")
+
+(kern-mk-place 'p_treasury "Treasury"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+      "xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx "
+      "xx xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx ,, ,, ,, ,, ,, w+ xx w+ ,, ,, ,, ,, ,, xx xx xx "
+      "xx xx xx ,, ,, ,, ,, ,, w+ xx w+ ,, ,, ,, ,, ,, xx xx xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, w+ xx w+ ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, xx xx xx x! xx x! xx xx xx ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, xx xx xx xx ,, xx xx xx xx ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, xx xx xx x! xx x! xx xx xx ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx "
+      "xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+      "xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_great_hall "Great Hall"
+        nil ;; sprite
+        (kern-mk-map
+          nil           19 19 pal_expanded
+          (list
+            "xx xx xx xx xx xx xx xx xx xx xx xx xx x! xx xx xx xx xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, xx xx ,, cc cc cc ,, xx xx ,, ,, ,, ,, xx "
+            "x! ,, ,, ,, ,, xx x! ,, cc cc cc ,, x! xx ,, ,, ,, ,, x! "
+            ",, ,, ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, ,, ,, "
+            "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+            "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+            "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+            ",, ,, ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, ,, ,, "
+            "x! ,, ,, ,, ,, xx x! ,, cc cc cc ,, x! xx ,, ,, ,, ,, x! "
+            "xx ,, ,, ,, ,, xx xx ,, cc cc cc ,, xx xx ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+            "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        (list
+          (list
+            (kern-mk-place 'p_paladins_hold "Paladin's Hold"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "xx xx xx xx xx xx xx xx xx xx xx xx xx && xx xx xx xx xx "
+                  "xx xx xx xx xx xx xx xx xx x! ,, ,, ,, ,, ,, ,, ,, x! xx "
+                  "xx xx ,, ,, ,, xx x! xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+                  "xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, [[ @@ @@ @@ ]] ,, ,, xx "
+                  "xx xx ,, ,, ,, xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+                  "xx xx xx xx xx xx ,, xx xx x! ,, ,, ,, ,, ,, ,, ,, x! xx "
+                  "xx xx xx xx xx xx ,, xx xx xx xx xx xx xx xx xx xx xx xx "
+                  "xx xx xx x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, "
+                  "xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, "
+                  "xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+                  "xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, "
+                  "xx xx xx x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! .. ,, ,, ,, "
+                  "xx xx xx xx xx xx xx xx ,, xx xx xx xx xx xx xx xx xx xx "
+                  "xx .A .R .M .S xx xx xx ,, xx xx xx xx .M .E .D .I .K xx "
+                  "xx ,, ,, ,, ,, x! ,, ,, ,, ,, ,, ,, sH ,, ,, ,, ,, ,, xx "
+                  "x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! "
+                  "xx ,, ,, ,, ,, sA ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+                  "xx ,, ,, ,, ,, xx xx xx ,, xx xx xx xx ,, ,, ,, ,, ,, xx "
+                  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              nil ;; neighbors
+              (list ;; objects in p_paladins_hold
+                (list
+                  (bind
+                    (kern-mk-char
+                      'ch_anne
+                      "Anne"
+                      sp_human
+                      oc_wizard
+                      s_companion_wizard
+                      2
+                      0 0 0
+                      0 0
+                      0 0
+                      14 0
+                      6 4
+                      #f ;; dead?
+                      'anne-conv
+                      sch_anne
+                      nil
+                      nil ;; inventory
+                      nil
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    '()
+                  ) ;; bind
+                10 1)
+                (list
+                  (bind
+                    (kern-mk-char
+                      'ch_jones
+                      "Jones"
+                      sp_human
+                      nil
+                      s_townsman
+                      2
+                      0 0 0
+                      0 0
+                      0 0
+                      16 0
+                      8 6
+                      #f ;; dead?
+                      'jones-conv
+                      sch_jones
+                      nil
+                      nil ;; inventory
+                      nil
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    '()
+                  ) ;; bind
+                4 7)
+                (list
+                  (bind
+                    (kern-mk-char
+                      'ch_alex
+                      "Alex"
+                      sp_human
+                      oc_wizard
+                      s_companion_wizard
+                      2
+                      0 0 0
+                      0 0
+                      0 0
+                      18 0
+                      10 8
+                      #f ;; dead?
+                      'alex-conv
+                      sch_alex
+                      nil
+                      nil ;; inventory
+                      nil
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    '()
+                  ) ;; bind
+                10 1)
+                (list
+                  (bind
+                    (kern-mk-obj t_custom_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'put-gate-guard
+                      'php1
+                      'deep
+                    )
+                  ) ;; bind
+                11 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'crossbowman
+                    )
+                  ) ;; bind
+                13 8)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'crossbowman
+                    )
+                  ) ;; bind
+                13 10)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'halberdier
+                    )
+                  ) ;; bind
+                15 10)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'halberdier
+                    )
+                  ) ;; bind
+                15 8)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                17 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'skeletal-spear-thrower
+                    )
+                  ) ;; bind
+                18 7)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'skeletal-spear-thrower
+                    )
+                  ) ;; bind
+                18 11)
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (kern-tag 'php1
+                    (bind
+                      (kern-mk-obj t_portcullis 1
+                        ;; hooks
+                        (list
+                        )
+                      )
+                      (list
+                        #f
+                        '()
+                        #f
+                        '()
+                      )
+                    ) ;; bind
+                  ) ;; kern-tag
+                14 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                5 15)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                12 15)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                13 17)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                15 17)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                17 17)
+                (list
+                  (kern-mk-obj t_bed 1
+                    ;; hooks
+                    (list
+                    )
+                  )
+                17 15)
+                (list
+                  (bind
+                    (kern-mk-obj t_ladder_down 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'p_forsaken_prison
+                      9
+                      9
+                    )
+                  ) ;; bind
+                8 17)
+                (list
+                  (bind
+                    (kern-mk-obj t_ladder_up 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'p_watchpoint
+                      9
+                      14
+                    )
+                  ) ;; bind
+                3 9)
+              ) ;; end of objects in p_paladins_hold
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_paladins_hold
+
+          3)
+          (list
+            (kern-mk-place 'p_death_knights_hold "Death Knight's Hold"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "xx xx xx xx xx xx xx xx xx xx xx rr rr rr rr rr rr rr rr "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. .. bb bb rr rr rr "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, .. .. .. .. bb rr rr "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, .. .. .. .. .. bb rr "
+                  "xx xx xx xx ,, ,, ,, xx xx xx xx ,, ,, ,, ,, .. .. .. rr "
+                  ",, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, xx xx ,, xx xx xx xx "
+                  ",, ,, ,, xx w+ w+ w+ xx ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, xx w+ w+ w+ xx ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+                  ",, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, xx xx ,, xx xx xx xx "
+                  "xx xx xx xx ,, ,, ,, xx xx xx xx ,, ,, ,, ,, .. .. .. rr "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, .. .. .. .. .. bb rr "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, .. .. .. .. bb rr rr "
+                  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. .. bb bb .. bb rr "
+                  "xx xx xx xx xx xx xx xx xx xx xx rr rr rr rr rr rr rr rr "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              nil ;; neighbors
+              (list ;; objects in p_death_knights_hold
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                14 16)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                7 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                9 2)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                9 16)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                14 6)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                14 12)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'warlock
+                    )
+                  ) ;; bind
+                14 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #t
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                10 2)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #t
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                14 5)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #f
+                      #t
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                14 13)
+                (list
+                  (bind
+                    (kern-mk-obj t_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      #f
+                      0
+                      '()
+                      #f
+                      #t
+                      #f
+                      (list
+                        (list
+                          's_closed_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_open_door_in_stone
+                          #f
+                          0
+                        )
+                        (list
+                          's_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                        (list
+                          's_magically_locked_solid_wood_door_in_stone
+                          #t
+                          5
+                        )
+                      )
+                    )
+                  ) ;; bind
+                10 16)
+                (list
+                  (bind
+                    (kern-mk-obj t_ladder_down 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'p_altar_room
+                      17
+                      17
+                    )
+                  ) ;; bind
+                17 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'craven-archer
+                    )
+                  ) ;; bind
+                5 5)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'craven-archer
+                    )
+                  ) ;; bind
+                5 13)
+                (list
+                  (bind
+                    (kern-mk-obj t_guard_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'craven-archer
+                    )
+                  ) ;; bind
+                11 9)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'death-knight
+                    )
+                  ) ;; bind
+                14 2)
+              ) ;; end of objects in p_death_knights_hold
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_death_knights_hold
+
+          5)
+        ) ;; end neighbors of p_great_hall
+        (list ;; objects in p_great_hall
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'death-knight
+              )
+            ) ;; bind
+          10 8)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'death-knight
+              )
+            ) ;; bind
+          10 9)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'death-knight
+              )
+            ) ;; bind
+          10 10)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'warlock
+              )
+            ) ;; bind
+          12 9)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'skeletal-warrior
+              )
+            ) ;; bind
+          9 13)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'skeletal-spear-thrower
+              )
+            ) ;; bind
+          10 14)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (bind
+              (kern-mk-obj t_ladder_down 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'p_pools
+                9
+                9
+              )
+            ) ;; bind
+          9 6)
+          (list
+            (bind
+              (kern-mk-obj t_hidden 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                't_hidden_mech
+                1
+              )
+            ) ;; bind
+          13 0)
+          (list
+            (bind
+              (kern-mk-obj t_disg_lvr 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                'gh_wall
+                #f
+                's_wall_torch
+              )
+            ) ;; bind
+          13 0)
+          (list
+            (kern-tag 'gh_wall
+              (bind
+                (kern-mk-obj t_terrain_blitter 1
+                  ;; hooks
+                  (list
+                  )
+                )
+                (list
+                  'p_great_hall
+                  8
+                  0
+                  3
+                  1
+                  'm_hall_section
+                )
+              ) ;; bind
+            ) ;; kern-tag
+          0 0)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'halberdier
+              )
+            ) ;; bind
+          8 8)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'halberdier
+              )
+            ) ;; bind
+          8 10)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'crossbowman
+              )
+            ) ;; bind
+          6 8)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'medik
+              )
+            ) ;; bind
+          7 9)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'crossbowman
+              )
+            ) ;; bind
+          6 10)
+        ) ;; end of objects in p_great_hall
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 18 18) ;; Northwest
+          (list 1 9 18) ;; North
+          (list 2 0 18) ;; Northeast
+          (list 3 18 9) ;; West
+          (list 4 9 9) ;; Here
+          (list 5 0 9) ;; East
+          (list 6 18 0) ;; Southwest
+          (list 7 9 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_great_hall
+
+    7)
+  ) ;; end neighbors of p_treasury
+  (list ;; objects in p_treasury
+    (list
+      (kern-tag 'tr-be2
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            9
+            6
+            1
+            1
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 6)
+    (list
+      (kern-tag 'tr-be3
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            9
+            7
+            1
+            1
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 7)
+    (list
+      (kern-tag 'tr-be4
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            9
+            8
+            1
+            1
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 8)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-be1
+          #f
+          '()
+        )
+      ) ;; bind
+    1 1)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-be2
+          #f
+          '()
+        )
+      ) ;; bind
+    17 1)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-be3
+          #f
+          '()
+        )
+      ) ;; bind
+    17 17)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-be4
+          #f
+          '()
+        )
+      ) ;; bind
+    1 17)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_treasury2
+          9
+          9
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    15 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    16 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    17 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    15 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    16 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    17 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    15 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    16 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'green-slime
+        )
+      ) ;; bind
+    17 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    15 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    16 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    17 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    15 16)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    16 16)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    17 16)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    15 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    16 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    17 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    1 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    2 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    3 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    1 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    2 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    3 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    1 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    2 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    3 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    1 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    2 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    3 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    1 16)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    2 16)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    3 16)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    1 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    2 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    3 17)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (kern-tag 'tr-ba
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            2
+            2
+            3
+            3
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    2 2)
+    (list
+      (kern-tag 'tr-bb
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            14
+            2
+            3
+            3
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    14 2)
+    (list
+      (kern-tag 'tr-bc
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            14
+            14
+            3
+            3
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    14 14)
+    (list
+      (kern-tag 'tr-bd
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            2
+            14
+            3
+            3
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    2 14)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-ba
+          #f
+          '()
+        )
+      ) ;; bind
+    11 11)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-bb
+          #f
+          '()
+        )
+      ) ;; bind
+    7 11)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-bc
+          #f
+          '()
+        )
+      ) ;; bind
+    7 7)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'tr-bd
+          #f
+          '()
+        )
+      ) ;; bind
+    11 7)
+    (list
+      (kern-tag 'tr-be1
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_treasury
+            9
+            5
+            1
+            1
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 5)
+  ) ;; end of objects in p_treasury
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_treasury
+
+p_death_knights_hold
+p_great_hall
+p_paladins_hold
+(kern-mk-place 'p_absalot "Absalot"
+  s_ruin ;; sprite
+  (kern-mk-map
+    nil     41 36 pal_expanded
+    (list
+      "tt tt tt tt tc .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. cc .. .. .. .. .. .. .. .. .. .. .. .. .. ta tt tt tt tt tt "
+      "tt xx xx xx xx xx xx xx xx xx xx xx xx .. .. .. xx xx xx xx .. cc .. xx xx xx xx .. .. %7 .. .. .. .. .. t% ta tt tt tt tt "
+      "tt xx ,, xx xx xx xx xx xx xx xx xx xx .. .. .. xx ,, ,, xx .. cc .. xx ,, ,, xx .. %b %% %d .. .. .. .. .. .. .. t% ta tt "
+      "tt xx ?? xx .L .I .B .R .A .R .Y xx xx xx .. .. xx ,, .. .. .. cc .. ,, ,, ,, xx .. .. %e .. .. .. .. .. .. .. .. .. t% ta "
+      "tc rr ,, ,, ,, ,, tt ,, ,, .. ,, ,, ,, xx .. .. xx xx xx .. .. cc .. xx xx xx xx .. .. .. xx xx xx xx xx xx xx xx xx .. .. "
+      ".. xx ,, ,, ,, t3 tt td ,, ,, ,, ,, ,, rr .. .. .. .. .. .. .. cc .. .. .. .. .. .. .. xx bb .A .C .A .D .E .M .Y xx xx .. "
+      ".. xx .. ,, 00 te ,, 00 ,, .. 00 ,, ,, xx .. .. xx xx rr rr .. cc .. xx xx xx .. .. .. bb ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. "
+      ".. xx ,, ,, 00 ,, ,, 00 ,, ,, 00 ,, ,, xx .. .. xx ,, ,, rr .. cc .. ,, ,, ,, xx .. .. xx rr ,, ,, ,, ,, .. ,, ,, ,, xx .. "
+      ".. xx ,, ,, 00 ,, ,, 00 ,, .. 00 ,, ,, xx .. .. xx ,, ,, ,, .. cc .. xx ,, ,, xx .. .. xx ,, ,, 00 ,, ,, ,, 00 ,, ,, xx .. "
+      ".. rr ,, ,, .. ,, ,, 00 ,, ,, 00 ,, ,, rr .. .. xx xx .. xx .. cc .. bb xx xx xx .. .. xx ,, .. .. ,, ,, ,, 00 ,, ,, xx .. "
+      ".. xx ,, ,, 00 ,, ,, 00 ,, ,, 00 ,, ,, rr .. .. .. .. .. .. .. cc .. .. .. .. .. %7 .. xx ,, ,, 00 00 00 00 00 ,, ,, xx .. "
+      ".. tC t7 ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx tC t7 pp ,, pp ,, ,, cc ,, ,, pp .. %3 %% %% rr ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. "
+      ".. tb tt bb ,, ,, ,, ,, ,, ,, ,, .. ,, xx tb tt td ,, .. ,, ,, cc ,, ,, ,, .. %a %% .. rr .. ,, ,, .. ,, ,, rr ,, ,, xx .. "
+      ".. t% ta td xx xx xx ,, .. xx xx xx rr xx t% te pp ,, ,, ,, ,, cc ,, ,, ,, ,, .. %e .. rr rr xx xx xx ,, rr xx xx xx xx .. "
+      ".. .. .. .. .. .. .. cc .. .. .. .. .. .. .. .. .. .. ,, ,, .. cc cc ,, ,, ,, ,, .. .. .. .. .. .. .. cc .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ,, ,, cc cc cc cc cc cc cc ,, ,, .. .. .. .. .. .. .. cc .. .. .. .. .. .. "
+      "cc cc cc cc cc .. cc cc cc cc cc cc .. cc cc cc cc cc cc .F .O .R .U .M cc cc cc cc cc cc cc .. cc cc .. cc cc cc cc cc cc "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ,, ,, cc cc .. cc cc cc cc ,, ,, .. .. .. .. cc .. .. .. .. .. bb .. .. bb "
+      "%5 .. .. .. xx xx ,, xx .. .. xx xx ,, xx .. .. ,, ,, ,, .. cc cc cc ,, ,, ,, ,, .. .. .. xx ,, rr xx ,, xx .. .. .. .. .. "
+      "%% %5 .. .. xx ,, ,, xx .. .. xx .. ,, xx .. .. pp ,, ,, .. .. cc ,, .. ,, ,, pp .. .. xx ,, ,, xx ,, .. xx tC t7 tA .. bb "
+      "%% %% .. .. xx ,, ,, rr %5 .. xx ,, ,, xx .. .. ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, .. .. xx .. ,, xx ,, .. .. tb tt td .. .. "
+      "%% %% .. .. xx xx rr rr %% .. xx xx xx xx t7 tA .. ,, pp ,, ,, cc ,, ,, pp ,, pp .. .. rr xx xx .. .. .. xx .. bb .. .. bb "
+      "%% %% %5 .. .. .. .. %% %c .. .. .. .. tb tt td .. .. .. .. .. cc .. .. .. .. .. tC t7 tA .. .. .. .. .. .. .. .. .. .. .. "
+      "%% %% %c .. %3 %% %% %% .. .. .. .. .. t% te t# .. .. .. .. .. cc tC t7 tA .. .. tb tt td .. .. .. .. .. .. .. bb .. .. bb "
+      "%% %c .. .. %a %% %% %% .. .. .. xx xx xx xx bb xx rr .. .. .. cc tb tt td tA .. bb tt bb .. bb .. bb .. .. .. .. .. .. .. "
+      "%% .. .. .. .. %a %% %c .. .. xx .. ,, ,, ,, ,, ,, xx xx .. .. cc t% te tF t7 bb .G .A .R .. .E .N .S bb .. .. bb .. .. bb "
+      "%% .. %3 %5 .. .. %% .. .. .. xx .M .. .G .I .C .K .S xx .. .. cc .. t% tb tt td .. .. tt tt tt .. .. .. .. .. .. .. .. .. "
+      "%% %% %% %% %5 .. %% %5 .. .. xx ,, ,, ,, ,, ,, ,, ,, sA .. .. bb .. .. bb te bb .. t3 tt tt tt t5 .. bb .. bb .. .. .. bb "
+      "%% %% %% bb %% %% %% %% %5 .. xx ,, ,, ,, .. ,, ,, ,, ,, cc cc .. .. .. .. .. .. .. ta tt tt tt tt tA .. .. .. .. .. .. .. "
+      "%% %% %% %% ~5 %% %% %% %c .. xx ,, ,, ,, ,, ,, .. .. xx .. .. cc .. .. .. .. .. .. t% tt tt tt tt tt tt t5 tA .. .. bb .. "
+      "%% bb %% ~3 ~~ %% %% bb .. .. .. .F .U .T .U .R .E .S xx .. .. cc .. .. .. %3 %% %5 .. ta tt tt tt tt tt tt tt t5 .. .. .. "
+      "%% .. %% ~2 ~~ ~5 %% %% .. .. xx xx ,, ,, ,, ,, ,, xx xx .. .. cc bb .. bb %% bb %% %5 .. t% ta tt tt bb tt bb tt bb tC t3 "
+      "%% bb %% ~a ~8 ~c %% bb .. .. %a xx xx .. aa ,, xx xx .. %7 .. cc .. %3 %% %% %% %% %% %5 .. t% tt tt tt tt tt tt tt tt tt "
+      "%% %% %% %% %% %% %% %c .. %7 .. %% xx ,, ,, ,, xx %% %% %% .. .. .. %% %% %% %% %% %% %% %5 .. tt bb tt tt tt tt || || || "
+      "%% %% %% bb %% bb %% .. .. %% .. %% xx xx xx xx xx %% %% %c .. cc .. %a %% %% %% %% %% %% %% bb ta tt tt tt tt || || || || "
+      "%% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% %% .. .. cc .. .. %% %% %% %% %% %% %% .. .. t% tt || || || || || || "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_absalot
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    23 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    12 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    31 20)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    35 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    3 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    23 19)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    28 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    36 30)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    12 19)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_old_absalot
+          11
+          27
+        )
+      ) ;; bind
+    2 2)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    38 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 32)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    21 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    39 25)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    25 26)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    34 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    24 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    37 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 31)
+  ) ;; end of objects in p_absalot
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 40 35) ;; Northwest
+    (list 1 21 35) ;; North
+    (list 2 0 35) ;; Northeast
+    (list 3 40 16) ;; West
+    (list 4 20 18) ;; Here
+    (list 5 0 16) ;; East
+    (list 6 40 0) ;; Southwest
+    (list 7 21 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_absalot
+
+(kern-load "silas.scm")
+
+(kern-load "dennis.scm")
+
+(kern-load "selene.scm")
+
+(kern-mk-place 'p_old_absalot "Old Absalot"
+  nil ;; sprite
+  (kern-mk-map
+    nil     31 31 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr xx xx xx xx xx xx rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr xx xx ,T ,E ,M ,P ,L ,E xx xx rr rr rr ,, ,, ,, rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr xx !! cc cc cc cc cc cc !! xx xx rr rr ,, ,, ,, rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr !! !! cc aa cc cc aa cc !! !! xx xx rr ,, ,, ,, rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr xx !! !! !! cc cc cc cc cc cc !! !! !! xx rr ,, ,, ,, rr rr rr rr rr rr rr "
+      "rr rr rr rr ,, rr xx ,, ,, pp ,, ,, ,, ,, ,, ,, pp ,, ,, xx rr ,, ,, ,, rr rr rr rr rr rr rr "
+      "rr rr rr rr ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr rr ,, rr rr rr rr rr rr rr rr rr "
+      "rr rr rr ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb rr ,, rr ,M ,E ,A ,T rr rr rr rr "
+      "rr rr rr ,, ,, ,, ,, ,, ,, pp ,, ,, ,, ,, ,, ,, pp ,, ,, ,, ,, ,, rr ,, ,, ,, ,, rr rr rr rr "
+      "rr rr xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr ,, ,, ,, ,, rr rr rr rr "
+      "xx xx xx rr xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr ,, ,, ,, ,, ,, ,, rr rr rr rr "
+      "rr ,S ,L ,A ,V ,E ,S xx rr xx ,, pp ,, ,, pp ,, rr xx xx rr rr ,, xx xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, ,, ,, ,, xx rr xx ,, ,, ,, ,, ,, ,, xx rr rr rr rr ,, xx ,F ,L ,E ,S ,H ,L ,Y xx "
+      "xx ,, ,, ,, ,, ,, ,, xx rr xx ,, ,, ,, ,, ,, ,, xx rr rr rr rr ,, rr ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, xx rr xx ,, pp ,, ,, pp ,, xx rr rr rr rr ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx rr ,, ,, xx xx xx rr xx ,, ,, ,, ,, ,, ,, xx rr rr rr rr rr xx ,, ,, ,, aa ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, rr rr xx xx xx ,, ,, xx xx xx rr rr rr rr rr xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx ,, ,, xx rr rr rr rr rr xx ,, ,, rr rr rr rr rr xx xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, xx rr rr rr xx ,, ,, xx rr rr rr xx ,, ,, ,, xx ,, ,, [[ @@ ]] ,, ,, xx "
+      "xx xx xx ,, ,, xx xx xx xx xx xx rr ,, ,, xx xx rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx ,F ,E ,A ,S ,T xx xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr xx xx xx xx rr rr xx "
+      "xx xx xx ,, xx xx xx xx xx xx ,, ,, ,, xx xx ,, ,, ,, xx xx xx xx xx xx rr cc cc cc cc cc rr "
+      "xx xx xx ,, xx xx xx xx rr xx ,, ,, ,, xx xx ,, ,, ,, xx ,B ,L ,O ,O ,D xx cc cc ~~ ~~ cc rr "
+      "xx ,, xx ,, xx xx xx xx rr xx ,, ,, ,, rr xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, cc ~~ ~~ ~~ cc rr "
+      "xx xx xx ,, xx xx xx xx rr ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, cc ~~ aa cc cc rr "
+      "xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, cc ~~ ~~ ~~ cc xx "
+      "xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx rr rr xx ,B ,A ,T ,H ,S xx cc cc ~~ ~~ cc xx "
+      "xx ,, ,, ,, ,, ,, xx xx xx xx ,, ,, ,, xx rr rr rr rr xx xx xx xx xx xx xx cc cc cc cc cc xx "
+      "xx xx xx rr rr rr xx xx rr rr xx xx xx xx rr rr rr rr rr rr rr rr rr rr rr xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_old_absalot
+    (list
+      (kern-tag 'oa-ps2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            'oa-ps1
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    4 19)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'oa-ps2
+          #f
+          '()
+        )
+      ) ;; bind
+    2 20)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'oa-cp1
+          #f
+          '()
+        )
+      ) ;; bind
+    1 14)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'oa-cp2
+          #f
+          '()
+        )
+      ) ;; bind
+    2 14)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'oa-cp3
+          #f
+          '()
+        )
+      ) ;; bind
+    5 14)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'oa-cp4
+          #f
+          '()
+        )
+      ) ;; bind
+    6 14)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 23)
+    (list
+      (kern-mk-field f_poison_perm -1)    3 24)
+    (list
+      (kern-mk-field f_sleep_perm -1)    3 25)
+    (list
+      (kern-mk-field f_energy_perm -1)    3 26)
+    (list
+      (kern-mk-field f_fire_perm -1)    3 27)
+    (list
+      (kern-mk-field f_poison_perm -1)    3 28)
+    (list
+      (kern-mk-field f_poison_perm -1)    2 27)
+    (list
+      (kern-mk-field f_poison_perm -1)    4 27)
+    (list
+      (kern-mk-field f_sleep_perm -1)    1 27)
+    (list
+      (kern-mk-field f_sleep_perm -1)    2 28)
+    (list
+      (kern-mk-field f_sleep_perm -1)    3 29)
+    (list
+      (kern-mk-field f_sleep_perm -1)    4 28)
+    (list
+      (kern-mk-field f_sleep_perm -1)    5 27)
+    (list
+      (kern-mk-field f_energy_perm -1)    1 28)
+    (list
+      (kern-mk-field f_energy_perm -1)    2 29)
+    (list
+      (kern-mk-field f_energy_perm -1)    4 29)
+    (list
+      (kern-mk-field f_energy_perm -1)    5 28)
+    (list
+      (kern-mk-field f_fire_perm -1)    1 29)
+    (list
+      (kern-mk-field f_fire_perm -1)    5 29)
+    (list
+      (bind
+        (kern-mk-obj t_hidden 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          't_rune_s
+          1
+        )
+      ) ;; bind
+    4 29)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    22 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    26 8)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    26 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    26 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    25 8)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    25 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    24 8)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    4 6)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 1 t_demon_gate_book)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    4 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    19 8)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    21 6)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    21 1)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    23 1)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    23 3)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    23 5)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_absalot
+          2
+          2
+        )
+      ) ;; bind
+    11 27)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_silas
+          "Silas"
+          sp_human
+          oc_wizard
+          s_companion_shepherd
+          2
+          0 5 0
+          2 1
+          2 1
+          28 16384
+          20 8
+          #f ;; dead?
+          'silas-conv
+          sch_silas
+          'spell-sword-ai
+          nil ;; inventory
+          (list
+            t_stun_wand
+          )
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          (list
+            #f
+            #f
+            #f
+          )
+          #f
+        )
+      ) ;; bind
+    25 23)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_dennis
+          "Dennis"
+          sp_human
+          oc_wright
+          s_townsman
+          2
+          0 0 0
+          0 0
+          0 0
+          13 512
+          5 3
+          #f ;; dead?
+          'dennis-conv
+          sch_dennis
+          'spell-sword-ai
+          nil ;; inventory
+          (list
+            t_staff
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    23 13)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_selene
+          "Selene"
+          sp_human
+          nil
+          s_townswoman
+          2
+          0 0 0
+          0 0
+          0 0
+          15 2048
+          7 5
+          #f ;; dead?
+          'selene-conv
+          sch_selene
+          nil
+          nil ;; inventory
+          (list
+            t_dagger
+          )
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    10 5)
+    (list
+      (kern-tag 'oa-cp1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    2 16)
+    (list
+      (kern-tag 'oa-cp2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    2 18)
+    (list
+      (kern-tag 'oa-cp3
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    5 16)
+    (list
+      (kern-tag 'oa-cp4
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    5 18)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 16)
+    (list
+      (kern-tag 'oa-ps1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    3 19)
+  ) ;; end of objects in p_old_absalot
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 30 30) ;; Northwest
+    (list 1 15 30) ;; North
+    (list 2 0 30) ;; Northeast
+    (list 3 30 15) ;; West
+    (list 4 15 15) ;; Here
+    (list 5 0 15) ;; East
+    (list 6 30 0) ;; Southwest
+    (list 7 15 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_old_absalot
+
+(kern-load "engineer.scm")
+
+(kern-mk-place 'p_engineers_hut "Engineers Hut"
+  s_hamlet ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "** *. *8 *8 *8 *8 *8 *8 *8 ** ** ee ee *. ** *8 ** ** ** "
+      "*c rr rr rr rr ws rr rr rr rr *4 ee ee *2 rr rr rr ** ** "
+      ".. rr rr [[ @@ @@ @@ ]] rr rr *6 ee ee *e rr ,, *b rr *. "
+      "|| rr 00 ,, ,, ,, ,, ,, ,, rr *e /0 /d /d ,, ,, ,, *a ** "
+      "*d rr 00 ,, ,, ,, ,, ,, ,, rr .. /7 .. .. rr ,, ,, rr *a "
+      ".. rr 00 ,, ,, [[ ]] ,, ,, ,, /d /6 .. .. rr ,, bb rr .. "
+      "~~ rr ,, ,, ,, ,, ,, ,, ,, rr .. /7 .. .. rr .. ,, rr .. "
+      "~~ bb ~~ ,, ,, ,, ,, ,, ,, rr .. /7 .. .. rr ,, ,, rr .. "
+      "bb ~~ ~~ ,, ,, ,, [[ @@ ]] rr .. /7 .. .. rr rr rr rr .. "
+      "~~ rr ,, ,, ,, ,, rr rr rr rr .. /7 .. bb .. .. .. tC t3 "
+      ".. rr ,, ,, ,, ,, 00 rr .. .. .. /7 .. .. .. .. .. t3 tt "
+      ".. rr ,, ,, ,, ,, 00 rr .. /0 /d /9 /d /d /d /2 .. ta tt "
+      ".. rr ,, rr && rr rr rr .. /7 .. .. .. .. .. /7 .. t% ta "
+      "bb .. .. rr rr rr ~~ .. .. /7 .. .. .. rr rr ,, rr rr .. "
+      "bb .. .. .. .. .. ~2 bb .. /7 .. .. rr rr ,, ,, ,, rr .. "
+      "bb .. .. .. .. .. ~a ~~ ~9 =| ~9 ~~ rr && ,, ,, ,, rr .. "
+      "bb .. .. .. .. .. .. bb .. /7 .. ~~ rr rr ,, ,, ,, rr .. "
+      "bb .. .. .. .. .. bb .. .. /7 .. ~a ~~ rr rr rr rr rr .. "
+      "t5 bb bb bb bb bb t7 .. .. /7 .. .. ~6 .. .. .. .. .. .. "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_engineers_hut
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bull"
+          sp_bull
+          nil
+          s_bull
+          0
+          0 0 0
+          0 0
+          0 0
+          36 16384
+          8 8
+          #f ;; dead?
+          nil
+          nil
+          'animal-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'npcg
+          'bull
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    3 15)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 13)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    16 15)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 5 t_food)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    14 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    14 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    2 12)
+    (list
+      (kern-mk-obj t_voidship_plans 1
+        ;; hooks
+        (list
+        )
+      )
+    16 7)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_engineer
+          "Engineer"
+          sp_human
+          oc_wright
+          s_companion_tinker
+          2
+          2 10 2
+          10 2
+          20 5
+          18 0
+          10 8
+          #f ;; dead?
+          'engineer-conv
+          sch_engineer
+          nil
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'bomb-trap
+            ;; contents
+            (list
+              (list 1 t_dagger)
+              (list 5 t_cure_potion)
+              (list 5 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_doom_staff
+          )
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          (list
+            #f
+            #f
+            #f
+          )
+        )
+      ) ;; bind
+    3 3)
+  ) ;; end of objects in p_engineers_hut
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 11 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_engineers_hut
+
+(kern-load "the-man.scm")
+
+(kern-mk-place 'p_mans_hideout "The MAN's Hideout"
+  s_mountains ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx x! xx xx xx rr rr rr rr rr xx xx xx xx xx xx xx "
+      "xx pp cc cc cc pp xx xx xx rr rr rr xx .T .O .O .L .S xx "
+      "xx cc ,, ,, ,, cc ,, ,, xx xx xx xx xx ,, ,, ,, ,, ,, xx "
+      "x! cc ,, ,, ,, cc x! ,, ?? ,, ?? ?? ?? ,, ,, ,, ,, ,, xx "
+      "xx cc ,, ,, ,, cc xx xx xx x! ?? xx xx ,, ,, ,, ,, ,, xx "
+      "xx pp cc cc cc pp xx xx ,, ,, ,, xx xx xx x! ,, x! xx xx "
+      "xx xx xx ,, xx xx x! cc ,, ,, ,, cc x! xx xx ,, xx rr rr "
+      "rr rr xx ,, xx xx cc pp cc ,, cc pp cc xx xx ,, xx rr rr "
+      "rr rr xx ,, xx ,, ,, cc ,, ,, ,, cc ,, ,, xx ,, xx rr rr "
+      "rr rr x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! rr rr "
+      "rr rr xx ,, xx ,, ,, cc ,, ,, ,, cc ,, ,, xx ,, xx ~~ ~~ "
+      "rr rr xx ,, xx xx cc pp cc ,, cc pp cc xx xx ,, xx ~~ rr "
+      "rr xx x! ,, x! xx x! cc ,, ,, ,, cc x! xx ~~ ,, ~~ ~c rr "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ~~ ee ~~ rr rr "
+      "xx ,, ,, ,, ,, ,, rr rr rr rr rr rr rr ~~ ~~ ~8 ~c rr rr "
+      "x! ,, ,, 00 ,, ,, rr rr .. .. .. rr rr ~2 rr rr rr rr rr "
+      "xx ,, ,, ,, ,, ,, rr .. .. .. .. .. rr ~4 rr ,, ,, rr rr "
+      "xx xx xx && xx xx rr .. .. .. .. ~3 ~~ ~c rr ,, ,, rr rr "
+      "rr rr xx xx xx rr rr rr .. .. .. ~~ rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_mans_hideout
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 1 t_sling_4)
+          (list 1 t_dagger_4)
+          (list 1 t_leather_helm_4)
+          (list 1 t_armor_leather_4)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    13 3)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 10 t_cure_potion)
+          (list 10 t_poison_immunity_potion)
+          (list 10 t_inv_potion)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    13 4)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 10 t_heal_potion)
+          (list 10 t_mana_potion)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    17 2)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 10 t_in_ex_por_scroll)
+          (list 10 t_wis_quas_scroll)
+          (list 10 t_vas_mani_scroll)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    17 3)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 10 t_an_tym_scroll)
+          (list 10 t_sanct_lor_scroll)
+          (list 10 t_in_quas_xen_scroll)
+          (list 10 t_an_xen_exe_scroll)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    17 4)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_forsaken_prison
+          2
+          16
+        )
+      ) ;; bind
+    9 3)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_man
+          "The MAN"
+          sp_human
+          oc_wrogue
+          s_brigandess
+          2
+          0 0 0
+          0 0
+          0 0
+          19 0
+          11 9
+          #f ;; dead?
+          'man-conv
+          sch_man
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    15 13)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 10 t_food)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    5 16)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    3 3)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 100 t_gold_coins)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    7 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 2)
+    (list
+      (bind
+        (kern-mk-obj t_disg_lvr 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'mh-b1
+          #f
+          's_wall_rock
+        )
+      ) ;; bind
+    7 18)
+    (list
+      (bind
+        (kern-mk-obj t_hidden 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          't_hidden_mech
+          1
+        )
+      ) ;; bind
+    7 18)
+    (list
+      (kern-tag 'mh-b1
+        (bind
+          (kern-mk-obj t_terrain_blitter 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'p_mans_hideout
+            8
+            14
+            3
+            1
+            'm_hall_section
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 5)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'bomb-trap
+        ;; contents
+        (list
+          (list 10 t_gem)
+          (list 10 t_torch)
+          (list 10 t_picklock)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    13 2)
+  ) ;; end of objects in p_mans_hideout
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_mans_hideout
+
+(kern-load "luximene.scm")
+
+(kern-load "necromancer.scm")
+
+(kern-mk-place 'p_necromancers_lair "Necromancers Lair"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx && xx xx xx xx xx x! xx xx xx "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, x! ,, ,, ,, ,, [[ @@ ]] ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx xx xx xx xx xx xx xx x! ,, x! xx xx xx x! ,, x! xx xx "
+      "xx xx .. .. .. xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx .. .. .. ,, .. xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx .. ,, ,, .. .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx .. .. ,, .. .. xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx xx .. .. .. xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx xx xx ,, xx xx xx xx x! ,, x! xx xx xx x! ,, x! xx xx "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ~~ ee ~~ ~~ xx 00 ,, ,, ,, 00 xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ee ee ~~ ~~ xx 00 ,, ,, ,, 00 xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ~~ ~~ ~~ ~~ xx 00 ,, ,, ,, 00 xx "
+      "xx x! [[ @@ ]] x! xx xx ~~ ~~ ~~ xx xx x! 00 00 00 x! xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_necromancers_lair
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 7)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    3 7)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 7)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 8)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 8)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 8)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 3)
+    (list
+      (kern-mk-obj mandrake 6
+        ;; hooks
+        (list
+        )
+      )
+    2 1)
+    (list
+      (kern-mk-obj nightshade 4
+        ;; hooks
+        (list
+        )
+      )
+    3 1)
+    (list
+      (kern-mk-obj blood_moss 12
+        ;; hooks
+        (list
+        )
+      )
+    4 1)
+    (list
+      (kern-mk-obj black_pearl 14
+        ;; hooks
+        (list
+        )
+      )
+    2 5)
+    (list
+      (kern-mk-obj spider_silk 21
+        ;; hooks
+        (list
+        )
+      )
+    3 5)
+    (list
+      (kern-mk-obj garlic 18
+        ;; hooks
+        (list
+        )
+      )
+    4 5)
+    (list
+      (kern-mk-obj ginseng 17
+        ;; hooks
+        (list
+        )
+      )
+    1 4)
+    (list
+      (kern-mk-obj sulphorous_ash 26
+        ;; hooks
+        (list
+        )
+      )
+    1 3)
+    (list
+      (kern-mk-obj t_mana_potion 8
+        ;; hooks
+        (list
+        )
+      )
+    1 2)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_shard
+          40
+          70
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_necr
+          "Necromancer"
+          sp_human
+          oc_wizard
+          s_companion_wizard
+          2
+          0 0 0
+          0 0
+          0 0
+          18 0
+          10 8
+          #f ;; dead?
+          'necr-conv
+          sch_necr
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          #f
+          #f
+        )
+      ) ;; bind
+    15 13)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    15 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 6)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 5 t_food)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    10 1)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 12)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 12)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 6)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    12 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 15)
+  ) ;; end of objects in p_necromancers_lair
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_necromancers_lair
+
+(kern-mk-place 'p_smoldering_cave "Smoldering Cave"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr {8 .. {8 rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr !_ !_ rr {{ {6 {{ rr !_ !_ rr rr rr rr rr "
+      "rr rr rr rr !_ !_ !_ !! {{ {6 {{ !! !_ !_ !_ rr rr rr rr "
+      "rr rr rr !_ !_ !_ !_ !_ !! =| !! !_ !_ !_ !_ !_ rr rr rr "
+      "rr rr rr !_ !_ !_ !_ !c {{ {6 {{ !a !_ !_ !_ !_ rr rr rr "
+      "rr rr !_ !_ !_ !_ !c bb {{ {6 {{ bb !a !_ !_ !_ !_ rr rr "
+      "rr rr !_ !_ !_ !! bb {{ {{ {6 {{ {{ bb !! !_ !_ !_ rr rr "
+      "rr rr !_ !_ !_ !! {{ {{ {3 .. {5 {{ {{ !! !_ !_ !_ rr rr "
+      "rr rr !_ !_ !_ !! {{ {{ {2 .. {4 {{ {{ !! !_ !_ !_ rr rr "
+      "rr rr !_ !_ !_ !! {{ {{ {a {8 {c {{ {{ !! !_ !_ !_ rr rr "
+      "rr rr !_ !_ !_ !! bb {{ {{ {{ {{ {{ bb !! !_ !_ !_ rr rr "
+      "rr rr !_ !_ !_ !_ !5 bb {{ {{ {{ bb !3 !_ !_ !_ !_ rr rr "
+      "rr rr rr !_ !_ !_ !_ !! !! !! !! !! !_ !_ !_ !_ rr rr rr "
+      "rr rr rr !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ rr rr rr "
+      "rr rr rr rr !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ rr rr rr rr "
+      "rr rr rr rr rr rr !_ !_ !_ !_ !_ !_ !_ rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_fire_sea "Fire Sea"
+        nil ;; sprite
+        (kern-mk-map
+          nil           19 19 pal_expanded
+          (list
+            "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+            "rr !_ !_ !! {A {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ rr rr rr "
+            "rr !_ !_ !_ !5 {A {{ {{ {3 {9 {9 {9 {9 {5 {{ {C ~! rr rr "
+            "rr !! !_ !! !! !5 {{ {3 {c {{ {{ {{ {{ {6 {{ ~! !_ ~! rr "
+            "rr {% !e {# {{ !! {{ {6 {{ {C !3 !5 {{ {6 {{ {% ~! {# rr "
+            "rr {{ {{ {3 {9 == {9 {c {C !3 !_ !! {{ {6 {{ !7 {{ {{ rr "
+            "rr {{ {3 {c {{ !! {{ {{ !_ !_ !_ !_ {{ {a {9 == {9 {1 rr "
+            "rr {{ {6 {{ {{ !_ !_ !_ rr rr rr rr !5 {{ {{ !! {{ {2 rr "
+            "rr {{ {6 {{ {{ {% !a !_ rr .. .. rr rr !! !! !c {{ {2 rr "
+            "rr {{ {a {9 {9 {5 {{ rr rr .. .. .. rr {{ !! {{ {{ {2 rr "
+            "rr {{ {{ {{ {{ {6 {{ rr rr .. bb .. .. {9 == {9 {9 {8 rr "
+            "rr {C !3 !! !! =| !! !_ rr .. .. .. rr {{ !! {{ {{ {{ rr "
+            "rr !! !_ !c {{ {6 {{ !_ rr rr rr .. rr rr !_ !! !5 {A rr "
+            "rr {% !e {# {{ {6 {{ !! !_ !_ rr rr rr rr !_ !_ !_ !! rr "
+            "rr rr {{ {{ {{ {6 {{ !a !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ rr "
+            "rr rr rr {{ {{ {6 {{ {% !a !! !! !_ !_ !_ !_ !_ !_ !_ rr "
+            "rr rr rr bb {{ {a {5 {{ {{ {{ {% !a !! !! !_ !_ !_ !_ rr "
+            "rr rr rr rr bb {{ {2 {1 {1 {5 {{ {{ {{ {{ !! !_ !_ !_ rr "
+            "rr rr rr rr rr rr rr rr .. .. {5 {{ {{ {3 bb !! !! ~! rr "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        nil ;; neighbors
+        (list ;; objects in p_fire_sea
+          (list
+            (kern-mk-obj t_gold_coins 140
+              ;; hooks
+              (list
+              )
+            )
+          11 10)
+          (list
+            (kern-mk-obj t_armor_plate_4 1
+              ;; hooks
+              (list
+              )
+            )
+          11 11)
+          (list
+            (kern-mk-obj t_gem 14
+              ;; hooks
+              (list
+              )
+            )
+          9 11)
+          (list
+            (kern-mk-obj t_gold_coins 104
+              ;; hooks
+              (list
+              )
+            )
+          10 11)
+          (list
+            (kern-mk-obj t_shield_4 1
+              ;; hooks
+              (list
+              )
+            )
+          10 11)
+          (list
+            (kern-mk-obj t_gem 10
+              ;; hooks
+              (list
+              )
+            )
+          11 11)
+          (list
+            (kern-mk-obj t_gold_coins 96
+              ;; hooks
+              (list
+              )
+            )
+          11 12)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'dragon
+              )
+            ) ;; bind
+          11 10)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (kern-mk-obj t_rune_w 1
+              ;; hooks
+              (list
+              )
+            )
+          11 12)
+          (list
+            (kern-mk-obj t_gold_coins 181
+              ;; hooks
+              (list
+              )
+            )
+          9 8)
+          (list
+            (kern-mk-obj t_gold_coins 157
+              ;; hooks
+              (list
+              )
+            )
+          10 8)
+          (list
+            (kern-mk-obj t_iron_helm_4 1
+              ;; hooks
+              (list
+              )
+            )
+          10 8)
+          (list
+            (kern-mk-obj t_gold_coins 94
+              ;; hooks
+              (list
+              )
+            )
+          9 9)
+          (list
+            (kern-mk-obj t_gem 13
+              ;; hooks
+              (list
+              )
+            )
+          10 9)
+          (list
+            (kern-mk-obj t_gold_coins 135
+              ;; hooks
+              (list
+              )
+            )
+          11 9)
+          (list
+            (kern-mk-obj t_gold_coins 113
+              ;; hooks
+              (list
+              )
+            )
+          9 10)
+          (list
+            (kern-mk-obj t_sword_4 1
+              ;; hooks
+              (list
+              )
+            )
+          9 10)
+        ) ;; end of objects in p_fire_sea
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 18 18) ;; Northwest
+          (list 1 9 18) ;; North
+          (list 2 0 18) ;; Northeast
+          (list 3 18 9) ;; West
+          (list 4 9 9) ;; Here
+          (list 5 0 9) ;; East
+          (list 6 18 0) ;; Southwest
+          (list 7 9 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_fire_sea
+
+    1)
+  ) ;; end neighbors of p_smoldering_cave
+  (list ;; objects in p_smoldering_cave
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_shard
+          118
+          46
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'fire-slime
+        )
+      ) ;; bind
+    9 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'fire-slime
+        )
+      ) ;; bind
+    7 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'fire-slime
+        )
+      ) ;; bind
+    10 4)
+  ) ;; end of objects in p_smoldering_cave
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_smoldering_cave
+
+p_fire_sea
+(kern-mk-place 'p_void_temple "Void Temple"
+  s_shrine ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "cc cc cc cc cc cc cc .. .. .. .. .. cc cc cc cc cc cc cc "
+      "cc cc cc cc cc cc cc cc .. .. .. cc cc cc cc cc cc cc cc "
+      "cc cc t3 tt tt *3 *1 *5 bb .. bb *3 *1 *5 tt tt t5 cc cc "
+      "cc cc tt tt *3 ** *. ** *5 cc *3 ** ** ** *5 tt tt cc cc "
+      "cc cc tt *3 *. ** ** ** *4 cc *2 ** ** *. *. *5 tt cc cc "
+      "cc cc *3 ** ** *. ** ** *c cc *a ** ** ** ** *. *5 cc cc "
+      "cc cc *2 *. *. ** *. *c bb .. bb *a *. ** *. ** *4 cc cc "
+      ".. cc *a ** *. ** *c .g .. .. .. .h *a ** ** ** *c cc .. "
+      ".. .. bb *a *8 *c bb .. .. .. .. .. bb *a *8 *c bb .. .. "
+      ".. .. .. cc cc cc .. .. .. .. .. .. .. cc cc cc .. .. .. "
+      ".. .. bb *3 *1 *5 bb .. .. .. .. .. bb *3 *1 *5 bb .. .. "
+      ".. cc *3 ** ** ** *5 .j .. .. .. .l *3 ** *. ** *5 cc .. "
+      "cc cc *2 *. *. ** ** *5 bb .. bb *3 ** *. *. *. *4 cc cc "
+      "cc cc *a *. *. ** ** *. *5 cc *3 ** ** *. ** ** *c cc cc "
+      "cc cc tt *a ** *. ** *. *4 cc *2 *. *. *. *. *c tt cc cc "
+      "cc cc tt tt *a *. *. ** *c cc *a ** *. *. *c tt tt cc cc "
+      "cc cc ta tt tt *a *8 *c bb .. bb *a *8 *c tt tt tc cc cc "
+      "cc cc cc cc cc cc cc cc .. .. .. cc cc cc cc cc cc cc cc "
+      "cc cc cc cc cc cc cc .. .. .. .. .. cc cc cc cc cc cc cc "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_void_temple
+    (list
+      (kern-mk-field f_energy_perm -1)    9 5)
+    (list
+      (kern-mk-field f_sleep_perm -1)    9 15)
+    (list
+      (kern-mk-field f_fire_perm -1)    9 14)
+    (list
+      (kern-mk-field f_energy_perm -1)    9 13)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'wisp
+        )
+      ) ;; bind
+    7 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'wisp
+        )
+      ) ;; bind
+    9 7)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'wisp
+        )
+      ) ;; bind
+    11 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'wisp
+        )
+      ) ;; bind
+    9 11)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (kern-mk-obj t_rune_d 1
+        ;; hooks
+        (list
+        )
+      )
+    9 9)
+    (list
+      (kern-mk-field f_sleep_perm -1)    15 9)
+    (list
+      (kern-mk-field f_fire_perm -1)    14 9)
+    (list
+      (kern-mk-field f_energy_perm -1)    13 9)
+    (list
+      (kern-mk-field f_sleep_perm -1)    3 9)
+    (list
+      (kern-mk-field f_fire_perm -1)    4 9)
+    (list
+      (kern-mk-field f_energy_perm -1)    5 9)
+    (list
+      (kern-mk-field f_sleep_perm -1)    9 3)
+    (list
+      (kern-mk-field f_fire_perm -1)    9 4)
+  ) ;; end of objects in p_void_temple
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_void_temple
+
+(kern-mk-place 'p_merciful_death "Wreck of the Merciful Death (abovedecks)"
+  s_ship ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. ~C ~3 ~1 ~1 ~1 ~5 ~A .. .. .. ~C ~3 ~1 ~1 ~1 ~5 ~A .. "
+      "~~ ~~ ~~ bb -- -- ~~ ~~ ~1 ee ~1 ~~ ~~ -- -- -- ~~ ~5 ~A "
+      "-- -- -- ~~ -- -- -- -- -- ee -- -- -- -- -- bb -- ~~ ~~ "
+      "-- ## ## ## ## ## ## ## ## ee ## ## ## -- -- ~~ -- -- -- "
+      "-- ## ee ee ee ee ee ee ee ee ee ee ## ## ## ## -- -- -- "
+      "-- ## ee ee ee ee ee ee ee ee ee ee ee ee ee ## ## -- -- "
+      "-- ## ee ee ee ee ee ee ee ee ee ee ee ee ee ee ## ## -- "
+      "-- ## ee ee oo ee ee ee ee oo ee ee ee WW ee ee ee ## -- "
+      "-- ## ee ee ee ee ee ee ee ee ee ee ee ee ee ee ## ## -- "
+      "-- ## ee ee ee ee ee ee ee ee ee ee ee ee ~~ ~~ ~~ ~~ -- "
+      "-- ## ee ~~ ~~ ~~ ee ee ~~ ~~ ee ee ## ## ## ~~ ~~ ~~ -- "
+      "-- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ bb -- "
+      "-- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ bb ~~ ~~ ~~ ~~ -- -- bb ~~ -- "
+      "-- -- bb -- -- -- -- -- -- ~~ -- -- -- -- -- -- ~~ -- -- "
+      "-- -- ~~ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- -- -- __ __ __ __ -- -- -- -- __ __ __ -- -- -- -- "
+      "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_merciful_death
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    7 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-spear-thrower
+        )
+      ) ;; bind
+    10 9)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_merciful_death_l2
+          6
+          9
+        )
+      ) ;; bind
+    6 9)
+  ) ;; end of objects in p_merciful_death
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_merciful_death
+
+(kern-mk-place 'p_merciful_death_l2 "Wreck of the Merciful Death (belowdecks)"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr -- -- -- -- -- rr rr rr rr rr -- -- -- -- -- rr rr "
+      "-- -- -- bb -- -- -- -- -- -- -- -- -- -- -- -- -- -- rr "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- bb -- -- -- "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- #> #> #> #> #> #> #> #> #> #> -- -- -- -- -- -- -- "
+      "-- -- #> ee ee ee ee ee ee ee ee #> #> #> #> -- -- -- -- "
+      "-- -- #> ee ee ee ee ee ee ee ee ee ee ee #> #> -- -- -- "
+      "-- -- #> ee ee ee ee ee ee ee ee ee ee ee ee #> -- -- -- "
+      "-- -- #> ee ee ee ee ee ee ee ee ee ee ee #> #> -- -- -- "
+      "-- -- #> ee ee ee ee ee ee ee ee #> #> #> #> -- -- -- -- "
+      "-- -- #> #> #> #> #> #> #> #> #> #> -- -- -- -- -- -- -- "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- bb -- "
+      "-- -- -- -- -- -- -- -- -- bb -- -- -- -- -- -- bb -- -- "
+      "-- -- bb -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- -- -- __ __ __ __ -- -- -- -- __ __ __ -- -- -- -- "
+      "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_merciful_death_l2
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_merciful_death
+          6
+          9
+        )
+      ) ;; bind
+    6 9)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'poison-trap
+        ;; contents
+        (list
+          (list 1 t_rune_c)
+          (list 342 t_gold_coins)
+          (list 4 t_gem)
+          (list 1 t_sextant)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    14 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    7 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-spear-thrower
+        )
+      ) ;; bind
+    10 9)
+  ) ;; end of objects in p_merciful_death_l2
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_merciful_death_l2
+
+(kern-mk-place 'p_angriss_lair "Entrance to Angriss's Lair"
+  s_spider_web ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "|| || || || || || || || tt tt tt || || || tt || || || || "
+      "|| || || || || || || || || tt || || || tt tt tt || || || "
+      "|| || || || || || bb bb bb bb || || || bb .. bb || || || "
+      "|| || || || bb bb bb t3 t5 bb bb || bb .. .. .. bb || || "
+      "|| || || bb .. .. t3 || || t5 bb .. .. .. .. .. bb || || "
+      "|| || || bb .. .. ta || || tc .. .. .. .. .. bb || || || "
+      "|| || || bb bb bb .. .. .. .. .. .. .. bb bb || || || || "
+      "|| || || || bb bb .. bb .. .. tC t3 tt t5 bb || || || || "
+      "tt || || || bb || || || bb .. tb || || tt td bb || || tt "
+      "tt tt || || bb || tF || bb .. t% |A || tc t# bb || tt tt "
+      "tt || || || bb || || || bb bb .. .. .. .. bb || || || tt "
+      "|| || || || bb bb bb bb .. .. .. bb .. bb bb bb || || || "
+      "|| || || bb .. tC t3 t5 tA .. .. bb .. || || bb || || || "
+      "|| || || bb .. t3 || || td .. bb .. .. t% || bb || || || "
+      "|| || || bb .. ta || |C t# .. bb .. .. .. .. bb || || || "
+      "|| || || || bb .. .. .. .. bb || bb bb .. bb || || || || "
+      "|| || || || || bb .. bb bb || || || tt tt tt || || || || "
+      "|| || || || || tt tt tt || tt || || || tt || || || || || "
+      "|| || || || || || tt || tt tt tt || || || || || || || || "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_angriss_lair
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_spider_cave
+          15
+          4
+        )
+      ) ;; bind
+    15 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    6 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    15 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    7 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    6 13)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    14 12)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_spider_cave
+          6
+          9
+        )
+      ) ;; bind
+    6 9)
+  ) ;; end of objects in p_angriss_lair
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_angriss_lair
+
+(kern-load "angriss.scm")
+
+(kern-mk-place 'p_spider_cave "Spider Cave"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr .. .. .. .. .. rr rr rr rr rr rr rr "
+      "rr bb .. .. .. .. .. .. .. .. .. .. rr rr bb .. bb bb rr "
+      "rr rr .. .. .. .. .. .. .. .. .. rr rr bb .. .. .. bb rr "
+      "rr rr rr .. rr .. .. .. tC t7 tA rr .. .. .. .! .. bb rr "
+      "rr rr rr rr rr rr .. tC t3 tt t5 rr .. .. .! .! .! .. rr "
+      "rr rr rr bb rr t3 tt tt tt tt tc rr bb .. .. .! .. .. rr "
+      "rr rr .. tC t3 tt tt tt tt tt t# rr rr bb bb .. .. bb rr "
+      "rr .. tC t3 tt tt tt tt tt tt tA .. rr rr rr rr rr rr rr "
+      "rr .. t3 tt tt .! .! .! tt tt t5 tA .. .. bb .. .. .. rr "
+      "rr .. tt tt tt .! .! .! tt tt tt td .. .. .. .. .. rr rr "
+      "rr .. tt tt tt .! .! .! tt tt tc t# .. .. bb .. .. .. rr "
+      "rr .. ta tt tt tt tt tt tt tc rr .. .. .. .. bb .. .. rr "
+      "rr .. t% ta tt tc bb ta tc rr rr bb .. rr rr .. .. rr rr "
+      "rr .. .. t% te rr rr rr rr rr rr rr rr rr bb rr .. .. rr "
+      "rr bb .. rr .. .. rr rr .. .. bb .. .. bb .. .. .. .. rr "
+      "rr rr bb .. .. .. .. .. .. .. .. bb .. .. .. .. .. .. rr "
+      "rr rr .. .. .. bb .. .. .. .. bb .. .. .. .. bb .. bb rr "
+      "rr .. .. .. .. .. .. .. rr rr rr rr rr .. .. .. .. rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_angriss_throne_room "Angriss's Throne Room"
+        nil ;; sprite
+        (kern-mk-map
+          nil           19 19 pal_expanded
+          (list
+            "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+            "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+            "rr rr .. .. .. .. bb .. .. .. .. .. .. .. .. .. .. rr rr "
+            "rr .. .. .. .. .. bb bb .. bb bb bb .. .. .. .. .. .. rr "
+            "rr .. .. .. .. bb .. bb bb bb .. bb bb .. .. .. .. .. rr "
+            "rr .. .. .. bb bb .. .. .. .. bb bb bb bb .. .. .. .. rr "
+            "rr .. .. .. bb .. .. bb bb .. .. bb bb .. bb .. .. .. rr "
+            "rr .. .. bb .. .. bb .. .. .. .. .. bb .. bb bb .. .. rr "
+            "rr .. .. bb .. bb .. .. .. .. .. bb .. .. bb .. .. .. rr "
+            "rr .. .. bb .. .. bb .. .. .. .. .. bb .. bb .. .. .. rr "
+            "rr .. .. bb bb .. bb .. .. .. .. .. bb bb .. bb .. .. rr "
+            "rr .. .. .. .. .. bb bb .. .. .. bb bb .. .. bb .. .. rr "
+            "rr .. .. .. bb bb bb .. bb .. bb .. .. bb bb .. .. .. rr "
+            "rr .. .. .. bb bb bb bb bb bb bb .. bb bb bb .. .. .. rr "
+            "rr bb .. .. .. bb .. bb bb .. bb .. .. bb .. .. .. .. rr "
+            "rr bb bb .. .. .. bb bb bb bb .. bb .. .. .. .. .. .. rr "
+            "rr bb .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. bb rr "
+            "rr bb bb .. bb .. .. .. .. .. .. .. .. .. .. .. bb bb rr "
+            "rr rr rr rr rr rr rr .. .. .. .. .. rr rr rr rr rr rr rr "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        nil ;; neighbors
+        (list ;; objects in p_angriss_throne_room
+          (list
+            (kern-mk-field f_web_perm -1)          7 8)
+          (list
+            (kern-mk-field f_web_perm -1)          8 8)
+          (list
+            (kern-mk-field f_web_perm -1)          9 8)
+          (list
+            (kern-mk-field f_web_perm -1)          10 8)
+          (list
+            (kern-mk-field f_web_perm -1)          7 9)
+          (list
+            (kern-mk-field f_web_perm -1)          8 9)
+          (list
+            (kern-mk-field f_web_perm -1)          9 9)
+          (list
+            (kern-mk-field f_web_perm -1)          10 9)
+          (list
+            (kern-mk-field f_web_perm -1)          11 9)
+          (list
+            (kern-mk-field f_web_perm -1)          7 10)
+          (list
+            (kern-mk-field f_web_perm -1)          8 10)
+          (list
+            (kern-mk-field f_web_perm -1)          9 10)
+          (list
+            (kern-mk-field f_web_perm -1)          10 10)
+          (list
+            (kern-mk-field f_web_perm -1)          11 10)
+          (list
+            (kern-mk-field f_web_perm -1)          8 11)
+          (list
+            (kern-mk-field f_web_perm -1)          9 11)
+          (list
+            (kern-mk-field f_web_perm -1)          10 11)
+          (list
+            (kern-mk-field f_web_perm -1)          9 12)
+          (list
+            (kern-mk-field f_web_perm -1)          11 12)
+          (list
+            (kern-mk-field f_web_perm -1)          11 13)
+          (list
+            (kern-mk-field f_web_perm -1)          11 14)
+          (list
+            (kern-mk-field f_web_perm -1)          12 14)
+          (list
+            (kern-mk-field f_web_perm -1)          5 6)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          5 3)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_torch
+                  )
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                  (list
+                    2
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          17 5)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                  (list
+                    1
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          3 16)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                  (list
+                    2
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          17 11)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_arrow
+                  )
+                  (list
+                    3
+                    't_gold_coins
+                  )
+                  (list
+                    3
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          3 4)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          9 17)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    2
+                    't_gold_coins
+                  )
+                  (list
+                    4
+                    't_bolt
+                  )
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          13 8)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_arrow
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    1
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          16 15)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_bolt
+                  )
+                  (list
+                    2
+                    't_bolt
+                  )
+                  (list
+                    2
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          16 13)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    2
+                    't_arrow
+                  )
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                )
+              )
+            ) ;; bind
+          3 12)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                  (list
+                    5
+                    't_bolt
+                  )
+                  (list
+                    5
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          8 3)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          9 12)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    3
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          13 3)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    1
+                    't_arrow
+                  )
+                  (list
+                    3
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          3 13)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_gold_coins
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                )
+              )
+            ) ;; bind
+          3 11)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                )
+              )
+            ) ;; bind
+          4 4)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_cure_potion
+                  )
+                  (list
+                    3
+                    't_arrow
+                  )
+                  (list
+                    1
+                    't_torch
+                  )
+                )
+              )
+            ) ;; bind
+          10 9)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_bolt
+                  )
+                  (list
+                    3
+                    't_bolt
+                  )
+                  (list
+                    4
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          13 9)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          5 3)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_cure_potion
+                  )
+                )
+              )
+            ) ;; bind
+          1 9)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_torch
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          9 7)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    2
+                    't_arrow
+                  )
+                  (list
+                    4
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          2 12)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    2
+                    't_gold_coins
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          1 11)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_bolt
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          16 13)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          3 13)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          1 4)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          15 13)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          8 11)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                  (list
+                    2
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          1 8)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_arrow
+                  )
+                  (list
+                    3
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          16 8)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_bolt
+                  )
+                  (list
+                    1
+                    't_cure_potion
+                  )
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                )
+              )
+            ) ;; bind
+          7 7)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                )
+              )
+            ) ;; bind
+          9 2)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_cure_potion
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          14 17)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    2
+                    't_gold_coins
+                  )
+                  (list
+                    4
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          14 15)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_gold_coins
+                  )
+                  (list
+                    3
+                    't_gold_coins
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          16 13)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    2
+                    't_bolt
+                  )
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    1
+                    't_cure_potion
+                  )
+                )
+              )
+            ) ;; bind
+          5 1)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    5
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          5 1)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                  (list
+                    2
+                    't_bolt
+                  )
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                )
+              )
+            ) ;; bind
+          8 5)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_bolt
+                  )
+                  (list
+                    3
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          7 18)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    3
+                    't_arrow
+                  )
+                  (list
+                    1
+                    't_mana_potion
+                  )
+                  (list
+                    2
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          14 4)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_heal_potion
+                  )
+                )
+              )
+            ) ;; bind
+          3 17)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_picklock
+                  )
+                )
+              )
+            ) ;; bind
+          9 10)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          10 8)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          12 16)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    5
+                    't_gold_coins
+                  )
+                  (list
+                    1
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          1 9)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    4
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          5 11)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_food
+                  )
+                )
+              )
+            ) ;; bind
+          5 11)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_gold_coins
+                  )
+                )
+              )
+            ) ;; bind
+          15 9)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_arrow
+                  )
+                )
+              )
+            ) ;; bind
+          1 3)
+          (list
+            (bind
+              (kern-mk-obj t_corpse 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                (list
+                  (list
+                    1
+                    't_bolt
+                  )
+                )
+              )
+            ) ;; bind
+          3 17)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          6 12)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          12 6)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          10 10)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          7 10)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          10 11)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          9 6)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          6 8)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          12 10)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          11 9)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          7 8)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          7 7)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          12 11)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          11 6)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          6 7)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          8 10)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          6 8)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          8 8)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          6 10)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          9 9)
+          (list
+            (bind
+              (kern-mk-obj spider-egg-type 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                10
+              )
+            ) ;; bind
+          10 6)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (bind
+              (kern-char-force-drop                (kern-mk-char
+                  'ch_angriss
+                  "Angriss"
+                  sp_queen_spider
+                  nil
+                  s_purple_spider
+                  7
+                  20 0 20
+                  10 5
+                  10 5
+                  138 0
+                  132 20
+                  #f ;; dead?
+                  'angriss-conv
+                  nil
+                  'angriss-ai
+                  (kern-mk-container
+                    t_chest
+                    ;; trap
+                    nil
+                    ;; contents
+                    (list
+                      (list 1 t_rune_f)
+                    )
+                    ;; hooks
+                    (list
+                    )
+                  )
+                  nil
+                  ;; hooks
+                  (list
+                  )
+                )
+              #t) ;; kern-char-force-drop
+              (list
+                #f
+                (list
+                  #f
+                  #f
+                  #f
+                )
+              )
+            ) ;; bind
+          9 9)
+          (list
+            (kern-mk-field f_web_perm -1)          9 6)
+          (list
+            (kern-mk-field f_web_perm -1)          10 6)
+          (list
+            (kern-mk-field f_web_perm -1)          7 7)
+          (list
+            (kern-mk-field f_web_perm -1)          8 7)
+          (list
+            (kern-mk-field f_web_perm -1)          9 7)
+          (list
+            (kern-mk-field f_web_perm -1)          10 7)
+          (list
+            (kern-mk-field f_web_perm -1)          11 7)
+          (list
+            (kern-mk-field f_web_perm -1)          6 8)
+        ) ;; end of objects in p_angriss_throne_room
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 18 18) ;; Northwest
+          (list 1 9 18) ;; North
+          (list 2 0 18) ;; Northeast
+          (list 3 18 9) ;; West
+          (list 4 9 9) ;; Here
+          (list 5 0 9) ;; East
+          (list 6 18 0) ;; Southwest
+          (list 7 9 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_angriss_throne_room
+
+    1)
+  ) ;; end neighbors of p_spider_cave
+  (list ;; objects in p_spider_cave
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 4)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    15 1)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    12 3)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    12 4)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    16 6)
+    (list
+      (bind
+        (kern-mk-obj spider-egg-type 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          10
+        )
+      ) ;; bind
+    17 4)
+    (list
+      (kern-mk-field web-type 20)    15 1)
+    (list
+      (kern-mk-field web-type 20)    12 3)
+    (list
+      (kern-mk-field web-type 20)    12 4)
+    (list
+      (kern-mk-field web-type 20)    16 6)
+    (list
+      (kern-mk-field web-type 20)    17 4)
+    (list
+      (kern-mk-field web-type 20)    17 5)
+    (list
+      (kern-mk-field web-type 20)    15 6)
+    (list
+      (kern-mk-field web-type 20)    13 5)
+    (list
+      (kern-mk-obj t_gold_coins 52
+        ;; hooks
+        (list
+        )
+      )
+    14 2)
+    (list
+      (kern-mk-obj t_gold_coins 34
+        ;; hooks
+        (list
+        )
+      )
+    17 5)
+    (list
+      (kern-mk-obj t_bow 1
+        ;; hooks
+        (list
+        )
+      )
+    15 6)
+    (list
+      (kern-mk-obj t_arrow 34
+        ;; hooks
+        (list
+        )
+      )
+    13 5)
+    (list
+      (kern-mk-obj t_leather_helm 1
+        ;; hooks
+        (list
+        )
+      )
+    16 2)
+    (list
+      (kern-mk-obj t_halberd 1
+        ;; hooks
+        (list
+        )
+      )
+    12 3)
+    (list
+      (kern-mk-obj t_heal_potion 3
+        ;; hooks
+        (list
+        )
+      )
+    15 1)
+    (list
+      (kern-mk-obj t_mana_potion 5
+        ;; hooks
+        (list
+        )
+      )
+    16 6)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_angriss_lair
+          6
+          9
+        )
+      ) ;; bind
+    6 9)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_angriss_lair
+          15
+          4
+        )
+      ) ;; bind
+    15 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'queen-spider
+        )
+      ) ;; bind
+    9 0)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'queen-spider
+        )
+      ) ;; bind
+    15 15)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'queen-spider
+        )
+      ) ;; bind
+    1 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    15 1)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    12 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    12 4)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 6)
+  ) ;; end of objects in p_spider_cave
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_spider_cave
+
+p_angriss_throne_room
+(kern-load "meaney.scm")
+
+(kern-load "amy.scm")
+
+(kern-mk-place 'p_poor_house "The Poor House"
+  s_hamlet ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      ".. .. .. .. .. .. .. .. .. /7 .. bb bb bb bb bb bb bb ta "
+      ".. /0 /d /d /d /d /d /d /d /a bb .. .. .. .. t3 tt t5 bb "
+      ".. /7 .. .. .. .. .. .. .. .. bb .. .. .. .. te bb tt bb "
+      ".. /7 .. rr rr rr rr rr rr bb rr .. .. .. .. t% tb tc bb "
+      ".. /7 .. rr .P .O .O .R ]] rr .. .. .. .. .. .. .. .. bb "
+      ".. /7 .. rr .H .O .U .S .E rr .. .. .. .. .. .. .. .. bb "
+      ".. /7 .. ,, ,, ,, ,, ,, ,, rr rr rr ,, rr bb rr .. .. bb "
+      ".. /7 .. bb ,, ,, ,, ,, ,, rr ,, ,, ,, ,, .. rr .. .. bb "
+      ".. /7 .. rr ,, ,, ,, ,, ,, d, ,, ,, ,, ,, ,, rr bb bb .. "
+      "/d /6 .. rr rr rr d, rr rr bb ,, ,, 00 ,, ,, ws .. /0 /d "
+      ".. /7 .. rr ,, ,, ,, ,, ,, rr ,, ,, 00 ,, ,, rr .. /7 .. "
+      ".. /7 .. rr ,, ,, ,, ,, ,, rr ,, ,, 00 ,, ,, rr .. /7 .. "
+      ".. /7 .. ws ,, ,, ,, ,, ,, rr ,, ,, ,, ,, ,, rr .. /7 .. "
+      ".. /7 .. rr ,, .. ,, ,, ,, rr ,, ,, ,, ,, ,, ws .. /7 .. "
+      ".. /7 .. rr ,, ,, .. ,, ,, rr ,, bb && bb ,, rr .. /7 .. "
+      ".. /7 .. rr rr rr bb rr rr rr rr rr rr rr rr rr .. /7 .. "
+      ".. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. "
+      ".. /8 /d /d /d /d /d /d /d /1 /d /d /d /d /d /d /d /a .. "
+      ".. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_poor_house
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+          4
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 6)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+          4
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    12 6)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_food)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    10 14)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        nil
+        ;; contents
+        (list
+          (list 1 t_gold_coins)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    14 14)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bull"
+          sp_bull
+          nil
+          s_bull
+          0
+          0 0 0
+          0 0
+          0 0
+          32 4096
+          6 6
+          #f ;; dead?
+          nil
+          nil
+          'animal-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'npcg
+          'bull
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    16 3)
+    (list
+      (bind
+        (kern-char-force-drop          (kern-mk-char
+            'ch_meaney
+            "Meaney"
+            sp_human
+            nil
+            s_companion_shepherd
+            2
+            0 0 0
+            0 0
+            0 0
+            16 0
+            8 6
+            #f ;; dead?
+            'meaney-conv
+            sch_meaney
+            nil
+            (kern-mk-container
+              t_chest
+              ;; trap
+              nil
+              ;; contents
+              (list
+                (list 1 t_skull_ring)
+                (list 1 t_dagger)
+              )
+              ;; hooks
+              (list
+              )
+            )
+            nil
+            ;; hooks
+            (list
+            )
+          )
+        #t) ;; kern-char-force-drop
+        (list
+          0
+        )
+      ) ;; bind
+    4 10)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 10)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 12)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 14)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 10)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 12)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 14)
+  ) ;; end of objects in p_poor_house
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_poor_house
+
+(kern-load "gholet.scm")
+
+(kern-mk-place 'p_prison "Prison"
+  s_hamlet ;; sprite
+  (kern-mk-map
+    nil     32 9 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, xx xx xx xx xx ,, xx ,, xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx xx xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx xx xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx ee xx xx ,, xx xx xx ,, xx xx xx ,, xx xx xx ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx ,, ,, ,, x! ,, ,, ,, ee ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx ee xx xx ,, xx xx xx ,, xx xx xx ,, xx xx xx ,, ,, ,, xx "
+      "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx xx xx "
+      "xx ,, ,, ,, xx xx xx xx xx ,, xx ,, xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_prison
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    1 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    2 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    3 7)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    1 6)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    4 2)
+    (list
+      (kern-tag 'pp1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    12 4)
+    (list
+      (kern-tag 'pp2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    14 4)
+    (list
+      (kern-mk-field f_energy_perm -1)    26 4)
+    (list
+      (kern-mk-field f_energy_perm -1)    28 3)
+    (list
+      (kern-mk-field f_energy_perm -1)    28 4)
+    (list
+      (kern-mk-field f_energy_perm -1)    28 5)
+    (list
+      (kern-mk-field f_energy_perm -1)    29 3)
+    (list
+      (kern-mk-field f_energy_perm -1)    29 5)
+    (list
+      (kern-mk-field f_energy_perm -1)    30 3)
+    (list
+      (kern-mk-field f_energy_perm -1)    30 4)
+    (list
+      (kern-mk-field f_energy_perm -1)    30 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    16 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    20 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    16 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    20 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    24 5)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    27 4)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'pp1
+          #f
+          '()
+        )
+      ) ;; bind
+    11 1)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'pp2
+          #f
+          '()
+        )
+      ) ;; bind
+    11 7)
+    (list
+      (bind
+        (kern-char-force-drop          (kern-mk-char
+            'ch_my
+            "Gholet"
+            sp_human
+            nil
+            s_brigand
+            2
+            0 0 0
+            0 0
+            0 0
+            14 0
+            6 4
+            #f ;; dead?
+            'gholet-conv
+            nil
+            nil
+            (kern-mk-container
+              t_chest
+              ;; trap
+              nil
+              ;; contents
+              (list
+                (list 1 t_skull_ring)
+              )
+              ;; hooks
+              (list
+              )
+            )
+            nil
+            ;; hooks
+            (list
+            )
+          )
+        #t) ;; kern-char-force-drop
+        '()
+      ) ;; bind
+    24 1)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "zorn"
+          sp_zorn
+          oc_wrogue
+          s_zorn
+          5
+          0 0 0
+          0 0
+          0 0
+          18 16384
+          10 8
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'poison-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d20+9"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'zorn
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    29 4)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "footpad"
+          sp_human
+          oc_wrogue
+          s_brigand
+          8
+          0 0 0
+          0 0
+          0 0
+          18 16384
+          10 8
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'self-destruct-trap
+            ;; contents
+            (list
+              (list 5 t_gold_coins)
+              (list 2 t_food)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_dagger
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "2d6-2"
+                      't_gold_coins
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_torch
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'footpad
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    16 7)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'halberdier
+        )
+      ) ;; bind
+    9 1)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'halberdier
+        )
+      ) ;; bind
+    9 7)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_glasdrin
+          2
+          2
+        )
+      ) ;; bind
+    6 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 2)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 10 t_food)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    1 1)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 1 t_cure_potion)
+          (list 1 t_heal_potion)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    2 1)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 10 t_arrow)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    1 2)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 10 t_bolt)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    2 7)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 1 t_vas_mani_scroll)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    3 7)
+    (list
+      (kern-mk-container
+        t_chest
+        ;; trap
+        'burn-trap
+        ;; contents
+        (list
+          (list 10 sulphorous_ash)
+          (list 5 garlic)
+          (list 5 ginseng)
+        )
+        ;; hooks
+        (list
+        )
+      )
+    3 6)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    1 1)
+  ) ;; end of objects in p_prison
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 31 8) ;; Northwest
+    (list 1 16 8) ;; North
+    (list 2 0 8) ;; Northeast
+    (list 3 31 4) ;; West
+    (list 4 16 4) ;; Here
+    (list 5 0 4) ;; East
+    (list 6 31 0) ;; Southwest
+    (list 7 16 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_prison
+
+(kern-load "talking-ankh.scm")
+
+(kern-load "demon-gate.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-load "nossifer.scm")
+
+(kern-mk-place 'p_ankh_shrine "Ankh Shrine"
+  s_shrine ;; sprite
+  (kern-mk-map
+    nil     31 31 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr ** ** ** ** ** ** ** ** ** rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** ** ** ** ** ** ** ** ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx xx xx xx xx xx xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx pp ,, ,, ,, pp xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx ,, cc cc cc ,, xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx ,, cc cc cc ,, xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx ,, cc cc cc ,, xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx pp ,, cc ,, pp xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** xx xx ,, cc ,, xx xx ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr ** ** ** ** ,, cc ,, ** ** ** ** rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr ** ** ** ,, cc ,, ** ** ** rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr ** ** ,, cc ,, ** ** rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr ** ** ,, cc ,, ** ** rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr ** ** ,, cc ,, ** ** rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr ** ** ,, cc ,, ** ** rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_ankh_shrine
+    (list
+      (bind
+        (kern-mk-char
+          'ch_ankh
+          "Ankh"
+          sp_statue
+          nil
+          s_ankh
+          2
+          0 0 0
+          0 0
+          0 0
+          189 0
+          9 9
+          #f ;; dead?
+          'ankh-conv
+          nil
+          'ankh-ai
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+        )
+      ) ;; bind
+    14 21)
+    (list
+      (kern-tag 'demon-gate
+        (bind
+          (kern-mk-obj t_demon_gate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            8
+            #f
+            #f
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    0 0)
+  ) ;; end of objects in p_ankh_shrine
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 30 30) ;; Northwest
+    (list 1 14 30) ;; North
+    (list 2 0 30) ;; Northeast
+    (list 3 14 30) ;; West
+    (list 4 15 15) ;; Here
+    (list 5 14 30) ;; East
+    (list 6 30 0) ;; Southwest
+    (list 7 14 30) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_ankh_shrine
+
+(kern-mk-place 'p_pools "Pools"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr "
+      "rr -- -- rr rr .. .. .. .. .. .. .. %3 %% %% %5 .. .. rr "
+      "rr -- -- rr rr .. .. .. .. .. .. %b %% ~3 ~5 %% %5 .. rr "
+      "rr -- -- ~~ %5 .. .. .. .. .. .. ~C ~3 -- -- ~5 %% %5 rr "
+      "rr rr ~~ ~c %% .. .. .. .. .. .. ~3 -- -- -- -- ~5 %% rr "
+      "rr rr %a %% %c .. .. .. .. .. .. ~~ -- -- -- -- ~4 %% rr "
+      "rr rr .. .. .. .. .. xx w+ d, ,, xx ~~ -- -- -- ~c %% rr "
+      "rr .. .. .. .. .. .. rr ,, ,, ,, xx ~~ -- -- ~c %% %c rr "
+      "rr .. %3 %% %% %5 .. w+ .. ,, ,, rr ~% ~a ~c %% %c rr rr "
+      "rr %3 %% ~3 ~5 %% .. ,, ,, ,, ,, ,, .. %% %% %% .. .. rr "
+      "rr %% ~3 -- ~c %% .. rr xx .. ,, rr .. %% ~7 %% %5 .. rr "
+      "rr %% ~a ~c %% %c .. .. .. .. .. .. %3 ~3 -- ~5 %% .. rr "
+      "rr %a %% %% %c .. .. .. .. .. %3 %% ~3 -- -- ~4 %% .. rr "
+      "rr rr .. rr rr .. .. .. .. .. %% ~3 -- -- -- ~c %% .. rr "
+      "rr rr rr rr rr .. .. .. .. .. %% ~a -- -- ~c %% %c .. rr "
+      "rr rr rr rr .. .. .. .. .. .. %a %% ~a ~c %% %c .. rr rr "
+      "rr rr rr rr rr .. .. rr rr .. .. %a %% %% %c .. .. rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_deepness "The Deepness"
+        nil ;; sprite
+        (kern-mk-map
+          nil           38 38 pal_expanded
+          (list
+            "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr bb .. .. .. bb rr rr rr rr rr rr "
+            "rr rr _3 _1 _1 _5 {{ {{ {{ {{ {{ {{ {{ {{ rr {{ rr rr rr bb %3 %% %% ~7 %% %% %5 .. .. .. .. .. %3 %% %% %% %5 rr "
+            "rr _3 __ __ __ __ =| _1 _1 _5 rr rr rr {{ {{ {{ {{ {{ {{ {% %e bb %a ~e %% %% %% bb .. .. .. bb %% %% %% %% %% rr "
+            "rr _a _8 _c rr _e {{ __ __ __ __ _5 rr rr rr {{ rr rr rr {{ {2 == .. bb %e bb %% %5 .. .. .. %3 %% bb %% bb %% rr "
+            "rr {{ {{ rr rr rr {{ _2 __ __ __ __ ~~ ~1 ~1 ~1 ~5 rr rr ~7 .. ~6 .. .. .. .. ~7 %c .. .. .. %a %% %% %% %% %% rr "
+            "rr {{ {{ {{ rr {{ {L __ __ __ __ ~8 ~8 ~8 ~~ ~~ ~~ ~~ ~~ b~ ~9 ~~ ~~ ~d .. .. == .. .. .. .. .. .. .. %e bb %% rr "
+            "rr {{ rr {{ {{ {L _3 __ __ _c {G {{ {{ {{ {H -a ~~ ~~ ~~ ~~ %% b~ ~~ bb %7 bb ~6 %5 .. .. .. %3 %5 .. .. %b %% rr "
+            "rr {{ {L _3 _1 __ __ __ __ {G {{ rr rr rr {{ {H ~~ ~~ ~~ ~~ ~~ ~~ ~~ %% %% %% ~6 %% %5 .. ~3 ~9 ~9 ~d .. bb %% rr "
+            "rr {{ _3 __ __ __ __ __ _4 {{ rr rr {{ rr rr {{ ~2 ~~ ~~ ~~ ~~ ~~ ~~ ~9 ~1 ~9 ~c %% %% %% ~6 %% %% .. .. %b %% rr "
+            "rr {{ _a __ __ __ __ __ _4 {{ rr {{ {{ {{ rr {{ ~2 ~~ -- ~~ ~~ b~ %% %% ~6 %% %% %% %% bb ~~ bb %% .. %7 bb %% rr "
+            "rr {{ {H _a __ __ __ __ _c {{ rr {{ {{ {{ rr {{ ~2 -- __ -- ~~ ~~ ~5 %% ~6 %c bb ~3 ~1 ~9 ~8 ~9 ~9 =| ~9 ~9 ~9 ~~ "
+            "rr {{ {{ {H _a _8 _8 _c {G {{ rr rr {{ rr rr {{ ~2 __ __ __ ~~ ~~ ~~ b~ ~~ bb %3 ~~ bb bb %% %% %% .. .. bb %e rr "
+            "rr rr {{ {{ {{ {{ {{ {{ bb {{ {{ rr {{ {{ {{ {L ~~ -- __ -- ~~ ~~ ~~ ~~ -- ~~ ~~ ~~ ~~ ~5 %% %% %% %5 .. .. .. rr "
+            "rr rr rr rr rr {1 rr {{ {{ {{ rr rr b~ ~1 ~1 ~~ ~~ ~~ -- ~~ ~~ ~~ ~~ ~~ __ __ ~~ b~ %% ~~ ~9 b~ ~9 ~d .. bb .. rr "
+            "rr rr rr rr rr .. rr rr rr rr rr bb ~~ ~~ b~ ~~ ~~ ~8 ~8 ~8 ~8 ~8 ~~ ~~ __ __ ~~ ~~ ~~ %% %% %% %c .. .. .. .. rr "
+            "rr rr rr rr {{ {2 .. rr rr rr bb ~3 ~~ b~ ~~ ~c {G {{ {{ {{ {{ {{ {H ~a ~~ ~~ ~~ ~~ ~~ ~d bb .. .. .. bb %7 .. rr "
+            "rr rr rr rr {{ {2 .. rr rr rr b~ ~~ ~~ ~~ ~c {G {{ rr rr rr rr rr bb bb {H ~a ~~ -- ~~ %c .. .. .. .. %3 %% %5 rr "
+            "rr rr {{ bb {1 .. .. bb rr bb ~~ ~~ ~~ ~~ {G {{ {{ rr .. .. .. rr .. .. bb {H ~~ -- ~4 bb .. .. .. bb %% ~7 %% rr "
+            "rr {{ {{ {2 .. .. .. .. ~C ~3 ~~ -- -- ~4 {A {{ rr rr .. .. .. rr .. .. .. bb ~2 -- ~4 %d .. .. .. %b ~b ~~ ~d rr "
+            "rr {{ bb .. .. .. bb ~C ~3 ~~ -- -- -- ~4 bb {{ rr && .. .. .. .. .. .. .. bb ~2 -- ~4 bb .. .. .. bb %% ~e %% rr "
+            "rr {{ {2 .. .. .. .. ~b ~~ -- -- __ -- ~4 {# {{ rr rr .. .. .. rr .. .. .. bb ~2 -- ~4 %5 .. .. .. .. %a %% %c rr "
+            "rr {{ bb .. .. .. bb ~% ~~ -- __ __ __ ~~ {J {{ {{ rr .. .. .. rr .. .. bb {L ~~ -- ~~ %% bb .. .. .. bb %e .. rr "
+            "rr rr {{ {2 .. .. .. .. ~a -- -- __ -- -- ~5 {J {{ rr rr .. rr rr bb bb {L ~3 ~~ -- ~~ ~d .. .. .. .. .. .. .. rr "
+            "rr rr rr bb .. .. .. bb {H ~~ -- __ __ -- ~~ b~ {J {{ {{ {6 {{ {{ {{ {L ~3 ~~ -- -- ~~ bb .. bb .. .. .. bb .. rr "
+            "rr rr rr {{ {2 .. {4 {{ rr ~a -- -- __ -- -- ~~ ~~ ~1 ~1 ~1 ~5 {N ~3 ~~ ~~ -- -- -- ~~ b~ rr rr .. .. .. .. rr rr "
+            "rr rr rr bb .. .. .. bb rr rr ~~ -- __ __ -- -- ~~ -- -- -- ~~ ~~ ~~ -- -- -- ~~ ~~ ~~ ~~ b~ rr rr rr .. .. rr rr "
+            "rr rr rr {{ {2 .. {4 {{ rr ~b ~~ -- __ __ __ -- -- __ __ __ -- -- -- -- -- ~~ ~~ b~ ~~ ~~ ~~ ~~ ~5 rr .. .. rr rr "
+            "rr rr {{ bb .. .. .. bb {{ {H ~~ -- -- -- __ __ __ __ __ __ __ -- -- ~~ ~~ ~~ b~ bb b~ ~~ ~~ b~ ~~ rr .. .. .. rr "
+            "rr rr {{ {2 .. .. {4 {{ {{ {{ ~a ~8 ~8 ~~ -- -- -- __ __ __ -- -- ~~ ~~ b~ rr rr rr rr xx xx ~~ ~~ xx xx .. .. rr "
+            "rr {{ bb .. .. .. bb {A {{ {{ {{ {{ {{ {H ~a ~8 ~~ -- -- -- ~~ ~8 ~c rr rr rr xx xx xx xx __ __ __ __ xx ,, xx xx "
+            "rr {{ {2 .. .. .. .. bb {1 bb {{ {{ {{ {{ {{ {{ {H ~a ~8 ~c {G {{ {{ bb .. bb xx ,, ,, w+ __ __ __ __ w+ ,, ,, xx "
+            "rr {{ bb .. .. .. .. .. .. .. {1 bb {1 bb {1 bb {1 bb .. bb {1 bb {1 .. .. .. ,, ,, ,, ,, ee ee ee ee ,, ,, ,, xx "
+            "rr rr {{ {2 {8 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. xx ,, ,, w+ __ __ __ __ w+ ,, ,, xx "
+            "rr rr {{ bb {{ bb {8 bb .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. {8 bb xx xx xx xx __ __ __ __ xx xx xx xx "
+            "rr rr rr rr rr {{ {{ {2 .. .. .. .. .. .. .. .. {8 .. {8 .. .. .. {8 bb {{ {{ xx xx xx __ __ __ __ __ __ xx xx xx "
+            "rr rr rr rr rr {{ {{ bb .. .. .. bb {8 bb {8 bb {{ bb {{ bb {8 bb {{ {{ {{ rr xx xx xx __ __ __ __ __ __ xx xx xx "
+            "rr rr rr rr {{ {{ {{ {2 .. .. .. {4 {{ {{ {{ rr rr rr rr {{ {{ {{ {{ rr rr rr xx xx xx xx __ __ __ __ xx xx xx xx "
+            "rr rr {{ {{ {{ {{ {{ bb .. .. .. bb {{ {{ {{ {{ rr rr rr rr rr rr rr rr rr rr xx xx xx xx xx xx xx xx xx xx xx xx "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        (list
+          (list
+            (kern-mk-place 'p_hydra_fen "Hydra Fen"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                  "rr rr rr rr rr rr {{ {{ {{ {{ {{ {{ {{ rr rr rr rr rr rr "
+                  "rr rr rr rr rr {{ {{ {{ {{ {{ {{ {{ {{ {{ rr rr rr rr rr "
+                  "rr rr rr rr {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ rr rr rr rr "
+                  "rr rr rr {{ {{ {{ {{ {C %3 %% %5 {A {{ {{ {{ {{ rr rr rr "
+                  "rr rr {{ {{ {{ {C %3 %% %% %% %% %% %5 {A {{ {{ {{ rr rr "
+                  "rr {{ {{ {{ {C %3 %% %% %% %% %% %% %% %5 {A {{ {{ {{ rr "
+                  "rr {{ {{ {{ %3 %% %% %% %% %% %% %% %% %% %5 {{ {{ {{ rr "
+                  "rr {{ {{ {{ %% %% %% %% %% %% %% %% %% %% %% {{ {{ {{ rr "
+                  "rr {{ {{ {{ %% %% %% %% %% %% %% %% %% %% %% {{ {{ {{ rr "
+                  "rr {{ {{ {{ %% %% %% %% %% %% %% %% %% %% %% {{ {{ {{ rr "
+                  "rr {{ {{ {{ %% %% %% %% ee ee ee %% %% %% %c {{ {{ {{ rr "
+                  "rr {{ {{ {{ %a %% %% oo ee ee ee oo %% %% {# {{ {{ {{ rr "
+                  "rr rr {{ {{ {% %a %% %% ee ee ee %% %% %c {{ {{ {{ rr rr "
+                  "rr rr rr {{ {{ {% %e oo ee ee ee oo %e {# {{ {{ rr rr rr "
+                  "rr rr rr rr {{ {{ {{ {{ ee ee ee {{ {{ {{ {{ rr rr rr rr "
+                  "rr rr rr rr rr {{ {{ {{ {2 .. {4 {{ {{ {{ rr rr rr rr rr "
+                  "rr rr rr rr rr rr {{ {{ {2 .. {4 {{ {{ rr rr rr rr rr rr "
+                  "rr rr rr rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              nil ;; neighbors
+              (list ;; objects in p_hydra_fen
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'hydra
+                    )
+                  ) ;; bind
+                9 9)
+              ) ;; end of objects in p_hydra_fen
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_hydra_fen
+
+          1)
+        ) ;; end neighbors of p_deepness
+        (list ;; objects in p_deepness
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'headless
+              )
+            ) ;; bind
+          5 21)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'headless
+              )
+            ) ;; bind
+          3 20)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'kraken
+              )
+            ) ;; bind
+          5 9)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'sea-serpent
+              )
+            ) ;; bind
+          18 11)
+          (list
+            (bind
+              (kern-mk-obj t_step_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'step-pt
+                "A yellow slime oozes up!"
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+                (list
+                  (list
+                    'yellow-slime
+                    32
+                    11
+                  )
+                )
+              )
+            ) ;; bind
+          33 10)
+          (list
+            (bind
+              (kern-mk-obj t_step_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'step-pt
+                "A yellow slime oozes up!"
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+                (list
+                  (list
+                    'yellow-slime
+                    26
+                    3
+                  )
+                )
+              )
+            ) ;; bind
+          26 5)
+          (list
+            (bind
+              (kern-mk-obj t_step_trig 1
+                ;; hooks
+                (list
+                  (list
+                    ef_permanent_invisibility
+                    '()
+                    2
+                    0
+                  )
+                )
+              )
+              (list
+                'spawn-kraken-lakes-sea-serpent
+                '()
+              )
+            ) ;; bind
+          31 31)
+          (list
+            (bind
+              (kern-mk-obj t_portcullis 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                '()
+                #f
+                '()
+              )
+            ) ;; bind
+          31 28)
+          (list
+            (bind
+              (kern-mk-obj t_portcullis 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                '()
+                #f
+                '()
+              )
+            ) ;; bind
+          32 28)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          26 31)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_open_door_in_stone
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                  (list
+                    's_magically_locked_solid_wood_door_in_stone
+                    #t
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          35 29)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_windowed_wood_door_in_rock
+                    #f
+                    5
+                  )
+                  (list
+                    's_open_door_in_rock
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_windowed_wood_door_in_rock
+                    #f
+                    5
+                  )
+                  (list
+                    's_magically_locked_windowed_wood_door_in_rock
+                    #f
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          34 31)
+          (list
+            (bind
+              (kern-mk-obj t_door 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                0
+                '()
+                #f
+                #f
+                #f
+                (list
+                  (list
+                    's_closed_windowed_wood_door_in_rock
+                    #f
+                    5
+                  )
+                  (list
+                    's_open_door_in_rock
+                    #f
+                    0
+                  )
+                  (list
+                    's_locked_windowed_wood_door_in_rock
+                    #f
+                    5
+                  )
+                  (list
+                    's_magically_locked_windowed_wood_door_in_rock
+                    #f
+                    5
+                  )
+                )
+              )
+            ) ;; bind
+          29 31)
+          (list
+            (bind
+              (kern-mk-obj t_ladder_down 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'p_lost_garrison
+                11
+                11
+              )
+            ) ;; bind
+          12 9)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'headless
+              )
+            ) ;; bind
+          3 22)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'headless
+              )
+            ) ;; bind
+          7 22)
+        ) ;; end of objects in p_deepness
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 37 37) ;; Northwest
+          (list 1 9 37) ;; North
+          (list 2 0 37) ;; Northeast
+          (list 3 37 19) ;; West
+          (list 4 19 19) ;; Here
+          (list 5 0 19) ;; East
+          (list 6 37 0) ;; Southwest
+          (list 7 29 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_deepness
+
+    1)
+  ) ;; end neighbors of p_pools
+  (list ;; objects in p_pools
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'yellow-slime
+        )
+      ) ;; bind
+    4 6)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'yellow-slime
+        )
+      ) ;; bind
+    10 13)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 7)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_great_hall
+          9
+          6
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'yellow-slime
+        )
+      ) ;; bind
+    11 3)
+  ) ;; end of objects in p_pools
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_pools
+
+p_deepness
+p_hydra_fen
+(kern-mk-place 'p_lost_garrison "Deep Fortress"
+  nil ;; sprite
+  (kern-mk-map
+    nil     38 38 pal_expanded
+    (list
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr xx xx xx rr rr rr xx xx xx rr rr rr xx xx rr rr rr xx xx rr rr rr "
+      "rr rr rr xx xx xx w+ xx ,, x! ,, xx w+ xx xx xx xx xx rr x! xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx rr rr "
+      "rr .. rr xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      ".. .. .. rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, .. ,, ,, xx ,, ,, ,, xx ,, ,, xx ,, xx ,, ,, xx xx rr rr "
+      ".. .. .. w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, rr xx xx x! ,, x! xx xx xx xx rr rr "
+      ".. .. .. xx ,, ,, .. ,, ,, ,, .. bb ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      ".. .. .. ,, ,, ,, ,, ,, ,, ,, ,, .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx ,, xx ,, ,, xx rr rr rr "
+      ".. .. .. x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, ,, x! ,, ,, ,, xx xx xx xx ,, xx xx xx xx rr rr rr "
+      ".. .. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx xx rr rr "
+      ".. .. .. xx ,, ,, bb ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx xx rr rr "
+      ".. .. .. w+ ,, ,, ,, ,, ,, ,, ,, ,, .. ,, ,, w+ ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx rr rr "
+      ".. .. .. xx ,, ,, ,, ,, ,, .. ,, ,, bb ,, ,, xx ,, ,, ,, ,, ,, .. xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, .. .. .. xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr xx xx xx xx w+ w+ x! w+ x! w+ w+ xx xx xx xx xx xx x! xx xx xx ,, ,, ,, x! ,, [[ @@ @@ @@ ]] ,, x! xx rr rr "
+      "rr rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx rr xx xx rr xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr rr rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb rr rr rr rr rr rr xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr rr x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! rr rr rr rr rr rr xx ,, ,, ,, xx xx xx xx xx xx xx xx xx xx rr rr "
+      "rr rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr rr rr xx ,, ,, ,, xx [[ .M .E .D .I .K ]] xx xx rr rr "
+      "rr rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr rr rr rr rr ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr rr xx xx rr xx rr xx xx xx xx ,, ,, ,, xx xx rr rr xx xx xx rr ,, ,, ,, x! ,, ,, ,, ,, ,, ,, ,, x! rr rr rr "
+      "rr rr rr xx ,, ,, ,, [[ @@ @@ ]] xx ,, ,, ,, x! xx xx x! xx xx xx x! ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, bb rr rr rr "
+      "rr rr rr xx 00 ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+      "rr rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx rr rr "
+      "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx xx rr rr "
+      "rr rr xx xx xx xx xx xx x! xx xx xx xx xx xx ,, ,, xx xx xx xx ,, ,, xx xx xx xx xx xx xx xx xx rr xx xx rr rr rr "
+      "rr rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, 00 xx rr rr rr "
+      "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx xx rr rr "
+      "rr rr rr rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, [[ @@ @@ @@ @@ @@ @@ @@ @@ ]] ,, ,, ,, 00 xx xx rr rr "
+      "rr rr rr rr .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx rr rr rr "
+      "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, 00 xx rr rr rr "
+      "rr rr xx rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr ,, [[ @@ @@ @@ @@ @@ @@ @@ @@ ]] ,, ,, ,, && xx xx rr rr "
+      "rr rr xx bb ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, 00 xx xx xx rr "
+      "rr rr xx xx xx xx xx xx xx xx xx rr xx xx xx xx xx xx xx xx xx x! xx xx xx xx xx x! xx xx xx xx xx xx xx xx rr rr "
+      "rr rr rr xx rr xx xx xx rr rr xx xx xx xx rr rr rr xx xx xx xx xx rr xx rr xx rr xx xx rr xx xx rr rr xx rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_lost_garrison
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    29 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    29 7)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    31 4)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    31 7)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    26 12)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    26 24)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    21 26)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    22 26)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 26)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    16 26)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 24)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'edwp2
+          #f
+          '()
+        )
+      ) ;; bind
+    4 17)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+          'ednp2
+          #f
+          '()
+        )
+      ) ;; bind
+    4 16)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+          'ede1p2
+          #f
+          '()
+        )
+      ) ;; bind
+    14 16)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+          'ede2p2
+          #f
+          '()
+        )
+      ) ;; bind
+    25 4)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    4 25)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    5 28)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 28)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    11 28)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    14 28)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    17 28)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    5 30)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 30)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    11 30)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    14 30)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    17 30)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    5 32)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    8 32)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    11 32)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    14 32)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    17 32)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    28 21)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    32 24)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    30 24)
+    (list
+      (kern-mk-obj t_bed 1
+        ;; hooks
+        (list
+        )
+      )
+    32 22)
+    (list
+      (kern-mk-obj t_garrison_log 1
+        ;; hooks
+        (list
+        )
+      )
+    4 23)
+    (list
+      (kern-mk-obj t_food 21
+        ;; hooks
+        (list
+        )
+      )
+    33 27)
+    (list
+      (kern-mk-obj t_food 1
+        ;; hooks
+        (list
+        )
+      )
+    22 29)
+    (list
+      (kern-mk-obj t_food 1
+        ;; hooks
+        (list
+        )
+      )
+    27 32)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'troll-m
+        )
+      ) ;; bind
+    6 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'troll-m
+        )
+      ) ;; bind
+    11 19)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'cave-goblin-berserker-m
+        )
+      ) ;; bind
+    29 11)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'cave-goblin-slinger-m
+        )
+      ) ;; bind
+    32 13)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'cave-goblin-berserker-m
+        )
+      ) ;; bind
+    32 23)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'gint-warrior-m
+        )
+      ) ;; bind
+    23 28)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'gint-warrior-m
+        )
+      ) ;; bind
+    28 33)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_armor_chain
+            )
+            (list
+              1
+              't_sword_2
+            )
+            (list
+              1
+              't_scratched_shield
+            )
+          )
+        )
+      ) ;; bind
+    7 24)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "halberdier"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          14 1024
+          6 4
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_halberd
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-halberdier
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    18 12)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "halberdier"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          18 16384
+          10 8
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 1 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_halberd
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-halberdier
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    17 6)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "halberdier"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          16 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_halberd
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-halberdier
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    24 12)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "crossbowman"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          15 2048
+          7 5
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 10 t_bolt)
+              (list 1 t_dagger)
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_crossbow
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_bolt
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-crossbowman
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    8 17)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "crossbowman"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          16 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 10 t_bolt)
+              (list 1 t_dagger)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_crossbow
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_bolt
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-crossbowman
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    14 5)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "halberdier"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          17 8192
+          9 7
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_halberd
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-halberdier
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    24 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              2
+              't_heal_potion
+            )
+            (list
+              1
+              't_crossbow
+            )
+            (list
+              13
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    13 6)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    11 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_bolt
+            )
+            (list
+              1
+              't_bolt
+            )
+            (list
+              1
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    17 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_mana_potion
+            )
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    7 29)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              2
+              't_gold_coins
+            )
+            (list
+              4
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    30 30)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gazer"
+          sp_gazer
+          oc_wizard
+          s_gazer
+          5
+          0 0 0
+          0 0
+          0 0
+          19 32768
+          44 9
+          #f ;; dead?
+          nil
+          nil
+          'gazer-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'poison-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d2+1"
+                      't_mana_potion
+                    )
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'sulphorous_ash
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'ginseng
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'garlic
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'spider_silk
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'blood_moss
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'black_pearl
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'nightshade
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'mandrake
+                    )
+                    (list
+                      5
+                      "1"
+                      't_in_mani_corp_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_xen_corp_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_quas_xen_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_an_xen_exe_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gazer
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    25 8)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gazer"
+          sp_gazer
+          oc_wizard
+          s_gazer
+          5
+          0 0 0
+          0 0
+          0 0
+          18 16384
+          40 8
+          #f ;; dead?
+          nil
+          nil
+          'gazer-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'lightning-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d2+1"
+                      't_mana_potion
+                    )
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'sulphorous_ash
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'ginseng
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'garlic
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'spider_silk
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'blood_moss
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'black_pearl
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'nightshade
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'mandrake
+                    )
+                    (list
+                      5
+                      "1"
+                      't_in_mani_corp_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_xen_corp_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_quas_xen_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_an_xen_exe_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gazer
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    22 31)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gazer"
+          sp_gazer
+          oc_wizard
+          s_gazer
+          5
+          0 0 0
+          0 0
+          0 0
+          17 8192
+          36 7
+          #f ;; dead?
+          nil
+          nil
+          'gazer-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'poison-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d2+1"
+                      't_mana_potion
+                    )
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'sulphorous_ash
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'ginseng
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'garlic
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'spider_silk
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'blood_moss
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'black_pearl
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'nightshade
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'mandrake
+                    )
+                    (list
+                      5
+                      "1"
+                      't_in_mani_corp_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_xen_corp_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_quas_xen_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_an_xen_exe_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gazer
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    7 25)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gazer"
+          sp_gazer
+          oc_wizard
+          s_gazer
+          5
+          0 0 0
+          0 0
+          0 0
+          16 4096
+          32 6
+          #f ;; dead?
+          nil
+          nil
+          'gazer-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'lightning-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d2+1"
+                      't_mana_potion
+                    )
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'sulphorous_ash
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'ginseng
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'garlic
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'spider_silk
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'blood_moss
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'black_pearl
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'nightshade
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'mandrake
+                    )
+                    (list
+                      5
+                      "1"
+                      't_in_mani_corp_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_xen_corp_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_quas_xen_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_an_xen_exe_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gazer
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    32 11)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gint warrior"
+          sp_gint
+          oc_warrior
+          s_ettin
+          5
+          0 0 0
+          0 0
+          0 0
+          90 16384
+          10 8
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_2h_sword
+            t_2h_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "4d25"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gint-warrior-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    5 6)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gint warrior"
+          sp_gint
+          oc_warrior
+          s_ettin
+          5
+          0 0 0
+          0 0
+          0 0
+          85 8192
+          9 7
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_2h_sword
+            t_2h_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "4d25"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gint-warrior-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    12 32)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "gint warrior"
+          sp_gint
+          oc_warrior
+          s_ettin
+          5
+          0 0 0
+          0 0
+          0 0
+          80 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_2h_sword
+            t_2h_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "4d25"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'gint-warrior-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    30 27)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          5
+          0 0 0
+          0 0
+          0 0
+          34 8192
+          9 7
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    7 19)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          5
+          0 0 0
+          0 0
+          0 0
+          32 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 1 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    29 17)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          5
+          0 0 0
+          0 0
+          0 0
+          30 2048
+          7 5
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    10 29)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          5
+          0 0 0
+          0 0
+          0 0
+          30 2048
+          7 5
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    31 21)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          5
+          0 0 0
+          0 0
+          0 0
+          28 1024
+          6 4
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 1 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    13 16)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin berserker"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_berserk
+          5
+          0 0 0
+          0 0
+          0 0
+          18 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 1 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_axe
+            t_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d15"
+                      't_gold_coins
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-berserker-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    12 31)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin berserker"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_berserk
+          5
+          0 0 0
+          0 0
+          0 0
+          17 2048
+          7 5
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_axe
+            t_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d15"
+                      't_gold_coins
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-berserker-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    9 32)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin berserker"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_berserk
+          5
+          0 0 0
+          0 0
+          0 0
+          16 1024
+          6 4
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_axe
+            t_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d15"
+                      't_gold_coins
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-berserker-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    18 8)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin slinger"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_slinger
+          5
+          0 0 0
+          0 0
+          0 0
+          18 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'spike-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_sling
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      20
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-slinger-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    7 20)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin slinger"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_slinger
+          5
+          0 0 0
+          0 0
+          0 0
+          17 2048
+          7 5
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'spike-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_sling
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      20
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-slinger-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    12 16)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin slinger"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_slinger
+          5
+          0 0 0
+          0 0
+          0 0
+          16 1024
+          6 4
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_sling
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      20
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-slinger-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    10 32)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin slinger"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_slinger
+          5
+          0 0 0
+          0 0
+          0 0
+          15 512
+          5 3
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_sling
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      20
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-slinger-m
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    32 16)
+    (list
+      (bind
+        (kern-mk-obj t_buried 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          't_rune_p
+          1
+        )
+      ) ;; bind
+    3 33)
+    (list
+      (bind
+        (kern-mk-obj t_roomdata 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+          0
+          #t
+          #t
+          (list
+            'p_deeps_1
+            'p_deeps_2
+            'p_deeps_5
+            'p_deeps_3
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_deepness
+          12
+          9
+        )
+      ) ;; bind
+    11 11)
+    (list
+      (kern-tag 'ednp1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    8 3)
+    (list
+      (kern-tag 'ednp2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            'ednp1
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    10 3)
+    (list
+      (kern-tag 'edwp1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    3 8)
+    (list
+      (kern-tag 'edwp2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            'edwp1
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    3 10)
+    (list
+      (kern-tag 'ede1p1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    15 8)
+    (list
+      (kern-tag 'ede1p2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            'ede1p1
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    15 10)
+    (list
+      (kern-tag 'ede2p1
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    22 8)
+    (list
+      (kern-tag 'ede2p2
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #t
+            'ede2p1
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    22 10)
+  ) ;; end of objects in p_lost_garrison
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+    'deeps-room-handle-garrison
+  )
+  (list ;; edge entrances
+    (list 0 37 37) ;; Northwest
+    (list 1 19 37) ;; North
+    (list 2 0 37) ;; Northeast
+    (list 3 37 19) ;; West
+    (list 4 19 19) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 37 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_lost_garrison
+
+(kern-mk-place 'p_deeps_1 "endless deepness"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_deeps_1
+    (list
+      (bind
+        (kern-mk-obj t_roomdata 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+          1
+          #f
+          #f
+          (list
+            'p_deeps_2
+            'p_deeps_5
+            'p_deeps_3
+            'p_deeps_4
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_deeps_1
+  (list ;; on-entry-hooks
+    'deeps-room-handle-deeps
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_deeps_1
+
+(kern-mk-place 'p_deeps_2 "endless deepness"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      ".. .. .. .. .. .. .B .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_deeps_2
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_roomdata 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+          2
+          #f
+          #f
+          (list
+            'p_deeps_5
+            'p_deeps_3
+            'p_deeps_4
+            'p_deeps_1
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_deeps_2
+  (list ;; on-entry-hooks
+    'deeps-room-handle-deeps
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_deeps_2
+
+(kern-mk-place 'p_deeps_3 "endless deepness"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .C .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_deeps_3
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_roomdata 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+          3
+          #f
+          #f
+          (list
+            'p_deeps_4
+            'p_deeps_1
+            'p_deeps_2
+            'p_deeps_5
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_deeps_3
+  (list ;; on-entry-hooks
+    'deeps-room-handle-deeps
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_deeps_3
+
+(kern-mk-place 'p_deeps_4 "endless deepness"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      ".. .. .. .. .. .. .D .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_deeps_4
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_roomdata 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+          4
+          #f
+          #f
+          (list
+            'p_deeps_1
+            'p_deeps_2
+            'p_deeps_5
+            'p_deeps_3
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_deeps_4
+  (list ;; on-entry-hooks
+    'deeps-room-handle-deeps
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_deeps_4
+
+(kern-mk-place 'p_deeps_5 "endless deepness"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      ".. .. .. .. .. .. .E .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr .. .. .. .. .. .. .. .. .. .. .. .. .. rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+      "rr rr rr rr rr .. .. .. .. .. .. .. .. .. rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_deeps_5
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_roomdata 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          0
+          5
+          #f
+          #f
+          (list
+            'p_deeps_3
+            'p_deeps_4
+            'p_deeps_1
+            'p_deeps_2
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_deeps_5
+  (list ;; on-entry-hooks
+    'deeps-room-handle-deeps
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_deeps_5
+
+(kern-mk-place 'p_forsaken_prison "Forsaken Prison"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, xx ,, ,, ,, xx ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, xx ,, ,, ,, xx ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx ,, ,, ,, xx xx xx xx xx xx xx xx "
+      "xx xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx ,, xx xx ,, ,, ,, xx xx ,, xx xx xx xx xx "
+      "xx ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx "
+      "xx xx xx xx xx ,, xx xx ,, ,, ,, xx xx ,, xx xx xx xx xx "
+      "xx xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx "
+      "xx xx ?? ?? ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx "
+      "xx xx ?? xx xx xx xx xx ,, ,, ,, xx xx xx xx xx xx xx xx "
+      "xx ,, ,, ,, xx ,, ,, xx ,, ,, ,, xx ,, ,, xx xx xx xx xx "
+      "xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+      "xx ,, ,, ,, xx ,, ,, xx ,, ,, ,, xx ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_forsaken_prison
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 7)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bandit"
+          sp_human
+          oc_wrogue
+          s_brigand
+          8
+          0 0 0
+          0 0
+          0 0
+          14 1024
+          6 4
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'self-destruct-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_sword
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "2d6-2"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_picklock
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_torch
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'bandit
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    5 2)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "cave goblin berserker"
+          sp_cave_goblin
+          oc_warrior
+          s_cgob_berserk
+          3
+          0 0 0
+          0 0
+          0 0
+          16 1024
+          6 4
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'spike-trap
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_axe
+            t_axe
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d15"
+                      't_gold_coins
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'cave-goblin-berserker
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    6 15)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "troll"
+          sp_troll
+          oc_warrior
+          s_troll
+          6
+          0 0 0
+          0 0
+          0 0
+          32 4096
+          8 6
+          #f ;; dead?
+          nil
+          nil
+          'std-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_thrown_boulder)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_thrown_boulder
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_thrown_boulder
+                    )
+                    (list
+                      25
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "2d10"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'troll
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    2 9)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "warlock"
+          sp_human
+          oc_wizard
+          s_wizard
+          5
+          0 0 0
+          0 0
+          0 0
+          18 16384
+          10 8
+          #f ;; dead?
+          nil
+          nil
+          'warlock-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'lightning-trap
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_dagger
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d2+1"
+                      't_mana_potion
+                    )
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'sulphorous_ash
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'ginseng
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'garlic
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'spider_silk
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'blood_moss
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'black_pearl
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'nightshade
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'mandrake
+                    )
+                    (list
+                      5
+                      "1"
+                      't_in_mani_corp_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_xen_corp_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_quas_xen_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_an_xen_exe_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'warlock
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    13 16)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "halberdier"
+          sp_human
+          oc_warrior
+          s_guard
+          5
+          0 0 0
+          0 0
+          0 0
+          13 512
+          5 3
+          #f ;; dead?
+          nil
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_heal_potion)
+              (list 1 t_in_an_scroll)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_halberd
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      50
+                      "1d5"
+                      't_food
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'corrupt-halberdier
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    17 9)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "skeletal warrior"
+          sp_skeleton
+          oc_warrior
+          s_skeleton
+          5
+          0 0 0
+          0 0
+          0 0
+          17 2048
+          7 5
+          #f ;; dead?
+          nil
+          nil
+          'generic-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_iron_helm
+            t_shield
+            t_sword
+          )
+          ;; hooks
+          (list
+            (list
+              ef_poison_immunity
+              '()
+              2
+              0
+            )
+            (list
+              ef_disease_immunity
+              '()
+              2
+              0
+            )
+            (list
+              ef_fire_immunity
+              '()
+              2
+              0
+            )
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'skeletal-warrior
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    13 1)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              2
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    14 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_arrow
+            )
+          )
+        )
+      ) ;; bind
+    12 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              5
+              't_gold_coins
+            )
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    14 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              4
+              't_bolt
+            )
+            (list
+              4
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    5 6)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_paladins_hold
+          8
+          17
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_mans_hideout
+          9
+          3
+        )
+      ) ;; bind
+    2 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 2)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 2)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    13 7)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    13 11)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 16)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    7 16)
+  ) ;; end of objects in p_forsaken_prison
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_forsaken_prison
+
+(kern-mk-place 'p_old_mine "Old Mine"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr bb bb rr rr rr rr rr bb bb bb .. .. .. .. bb bb rr "
+      "rr bb .. .. bb rr rr rr bb .. .. .. .. .. .. .. .. bb rr "
+      "rr bb .. .. .. .. .. .. .. .. .. .. rr rr .. .. .. bb rr "
+      "rr rr .. .. .. .. .. .. .. .. .. bb rr rr rr .. .. rr rr "
+      "rr rr .. .. rr rr rr rr .. .. .. rr rr rr rr .. .. rr rr "
+      "rr rr .. .. bb rr rr rr rr .. .. bb bb rr rr .. .. rr rr "
+      "rr rr .. .. .. bb bb bb bb .. .. .. bb .. bb .. .. rr rr "
+      "rr rr .. .. .. bb bb .. .. .. .. .. .. .. .. .. .. rr rr "
+      "rr rr .. .. bb rr .. .. .. .. .. .. .. .. .. .. .. rr rr "
+      "rr rr .. .. rr bb .. .. .. .. .. rr rr .. .. .. .. bb rr "
+      "rr rr .. .. rr rr .. .. .. .. bb rr rr rr rr .. .. rr rr "
+      "rr rr .. .. .. bb .. .. rr bb rr rr rr rr rr .. .. rr rr "
+      "rr rr .. .. .. .. .. rr rr rr rr .. .. rr .. .. .. rr rr "
+      "rr bb .. .. .. .. .. rr .. .. .. .. .. .. .. .. .. rr rr "
+      "rr bb .. .. .. .. .. .. .. .. .. .. .. .. .. rr .. rr rr "
+      "rr rr bb .. .. .. .. .. .. rr rr .. .. rr rr rr .. .. rr "
+      "rr rr rr rr bb rr rr rr rr rr rr rr rr rr rr rr .. .. rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_old_mine
+    (list
+      (bind
+        (kern-mk-obj t_step_trig 1
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        (list
+          'wind-trap
+          '()
+        )
+      ) ;; bind
+    15 14)
+    (list
+      (bind
+        (kern-mk-obj t_step_trig 1
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        (list
+          'wind-trap
+          '()
+        )
+      ) ;; bind
+    16 12)
+    (list
+      (bind
+        (kern-mk-obj t_step_trig 1
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        (list
+          'wind-trap
+          '()
+        )
+      ) ;; bind
+    2 8)
+    (list
+      (bind
+        (kern-mk-obj t_step_trig 1
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        (list
+          'wind-trap
+          '()
+        )
+      ) ;; bind
+    10 3)
+    (list
+      (kern-mk-obj t_gem 8
+        ;; hooks
+        (list
+        )
+      )
+    6 7)
+    (list
+      (kern-mk-obj t_gem 3
+        ;; hooks
+        (list
+        )
+      )
+    1 14)
+    (list
+      (kern-mk-obj t_gem 7
+        ;; hooks
+        (list
+        )
+      )
+    11 1)
+    (list
+      (kern-mk-obj t_gem 5
+        ;; hooks
+        (list
+        )
+      )
+    1 2)
+    (list
+      (kern-mk-obj t_gem 5
+        ;; hooks
+        (list
+        )
+      )
+    2 1)
+    (list
+      (kern-mk-obj t_gem 2
+        ;; hooks
+        (list
+        )
+      )
+    9 1)
+    (list
+      (kern-mk-obj t_gem 4
+        ;; hooks
+        (list
+        )
+      )
+    17 3)
+    (list
+      (kern-mk-obj t_gem 3
+        ;; hooks
+        (list
+        )
+      )
+    4 9)
+    (list
+      (kern-mk-obj t_gem 8
+        ;; hooks
+        (list
+        )
+      )
+    5 12)
+    (list
+      (kern-mk-obj t_gem 9
+        ;; hooks
+        (list
+        )
+      )
+    5 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    3 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_mana_potion
+            )
+            (list
+              1
+              't_food
+            )
+          )
+        )
+      ) ;; bind
+    15 6)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              2
+              't_bolt
+            )
+          )
+        )
+      ) ;; bind
+    8 3)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_mana_potion
+            )
+            (list
+              2
+              't_arrow
+            )
+            (list
+              1
+              't_mana_potion
+            )
+          )
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_gold_coins
+            )
+          )
+        )
+      ) ;; bind
+    8 14)
+    (list
+      (kern-mk-field f_web_perm -1)    2 1)
+    (list
+      (kern-mk-field f_web_perm -1)    3 1)
+    (list
+      (kern-mk-field f_web_perm -1)    1 2)
+    (list
+      (kern-mk-field f_web_perm -1)    2 2)
+    (list
+      (kern-mk-field f_web_perm -1)    3 2)
+    (list
+      (kern-mk-field f_web_perm -1)    4 2)
+    (list
+      (kern-mk-field f_web_perm -1)    1 3)
+    (list
+      (kern-mk-field f_web_perm -1)    2 3)
+    (list
+      (kern-mk-field f_web_perm -1)    3 3)
+    (list
+      (kern-mk-field f_web_perm -1)    4 3)
+    (list
+      (kern-mk-field f_web_perm -1)    5 3)
+    (list
+      (kern-mk-field f_web_perm -1)    2 4)
+    (list
+      (kern-mk-field f_web_perm -1)    3 4)
+    (list
+      (kern-mk-field f_web_perm -1)    4 4)
+    (list
+      (kern-mk-field f_web_perm -1)    5 4)
+    (list
+      (kern-mk-field f_web_perm -1)    2 5)
+    (list
+      (kern-mk-field f_web_perm -1)    3 5)
+    (list
+      (kern-mk-field f_web_perm -1)    2 6)
+    (list
+      (kern-mk-field f_web_perm -1)    3 6)
+    (list
+      (kern-mk-field f_web_perm -1)    4 6)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_trolls_den
+          3
+          15
+        )
+      ) ;; bind
+    17 17)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    4 15)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-warrior
+        )
+      ) ;; bind
+    15 2)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'skeletal-spear-thrower
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ghast
+        )
+      ) ;; bind
+    15 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ghast
+        )
+      ) ;; bind
+    11 14)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ghast
+        )
+      ) ;; bind
+    9 4)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    3 3)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'giant-spider
+        )
+      ) ;; bind
+    4 4)
+  ) ;; end of objects in p_old_mine
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_old_mine
+
+(kern-mk-place 'p_lich_tomb "Lich Tomb"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx %3 %% %% %5 pp ,, ,, ,, cc ,, ,, ,, pp %3 %% %% %5 xx "
+      "xx %% %% %% %% ,, ,, cc cc cc cc cc ,, ,, %% %% %% %% xx "
+      "xx %% %% %% %% ,, cc cc cc cc cc cc cc ,, %% %% %% %% xx "
+      "xx %% %% %% %% ,, ,, cc cc cc cc cc ,, ,, %% %% %% %% xx "
+      "xx %% %% %% %% pp ,, ,, cc cc cc ,, ,, pp %% %% %% %% xx "
+      "xx %a %% %% %% %% %% ,, cc cc cc ,, %% %% %% %% %% %c xx "
+      "xx .. %a %% %% %% %% pp cc cc cc pp %% %% %% %% %c .. xx "
+      "xx .. .. %a %% %% %% ,, cc cc cc ,, %% %% %% %c .. .. xx "
+      "xx .. .. .. %a %% %c pp cc cc cc pp %a %% %c .. .. .. xx "
+      "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+      "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_lich_tomb
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_crypt
+          9
+          10
+        )
+      ) ;; bind
+    9 16)
+    (list
+      (kern-mk-field f_sleep_perm -1)    8 1)
+    (list
+      (kern-mk-field f_sleep_perm -1)    10 1)
+    (list
+      (bind
+        (kern-char-force-drop          (kern-mk-char
+            'ch_lich_king
+            "Lich King"
+            sp_lich
+            oc_wizard
+            s_lich
+            5
+            10 10 10
+            10 1
+            0 0
+            54 0
+            50 8
+            #f ;; dead?
+            nil
+            nil
+            'lich-ai
+            (kern-mk-container
+              t_chest
+              ;; trap
+              'lightning-trap
+              ;; contents
+              (list
+                (list 1 t_morning_star)
+                (list 1 t_armor_chain_4)
+                (list 1 t_chain_coif_4)
+                (list 100 t_gold_coins)
+                (list 3 t_mana_potion)
+                (list 3 t_heal_potion)
+                (list 1 t_lich_skull)
+              )
+              ;; hooks
+              (list
+              )
+            )
+            nil
+            ;; hooks
+            (list
+              (list
+                ef_poison_immunity
+                '()
+                2
+                0
+              )
+              (list
+                ef_disease_immunity
+                '()
+                2
+                0
+              )
+              (list
+                ef_fire_immunity
+                '()
+                2
+                0
+              )
+            )
+          )
+        #t) ;; kern-char-force-drop
+        '()
+      ) ;; bind
+    9 2)
+  ) ;; end of objects in p_lich_tomb
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_lich_tomb
+
+(kern-mk-place 'p_altar_room "Altar Room"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx pp ,, ,, ,, pp xx xx xx xx xx xx xx "
+      "xx xx ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, xx xx "
+      "xx xx ,, cc cc cc cc cc cc aa cc cc cc cc cc cc ,, xx xx "
+      "xx xx ,, cc ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, cc ,, xx xx "
+      "xx xx ,, cc ,, xx xx pp ,, cc ,, pp xx xx ,, cc ,, xx xx "
+      "xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx "
+      "xx pp ,, cc ,, pp xx xx vv vv vv xx xx pp ,, cc ,, pp xx "
+      "xx ,, cc cc cc ,, ,, vv vv vv vv vv ,, ,, cc cc cc ,, xx "
+      "xx ,, cc aa cc cc cc vv vv vv vv vv cc cc cc aa cc ,, xx "
+      "xx ,, cc cc cc ,, ,, vv vv vv vv vv ,, ,, cc cc cc ,, xx "
+      "xx pp ,, cc ,, pp xx xx vv vv vv xx xx pp ,, cc ,, pp xx "
+      "xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx xx ,, cc ,, xx xx "
+      "xx xx ,, cc ,, xx xx pp ,, cc ,, pp xx xx ,, cc ,, xx xx "
+      "xx xx ,, cc ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, cc ,, xx xx "
+      "xx xx ,, cc cc cc cc cc cc aa cc cc cc cc cc cc ,, xx xx "
+      "xx xx ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx pp ,, ,, ,, pp xx xx xx xx ,, ,, xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_altar_room
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'warlock
+        )
+      ) ;; bind
+    6 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'warlock
+        )
+      ) ;; bind
+    12 9)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_death_knights_hold
+          17
+          9
+        )
+      ) ;; bind
+    17 17)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "warlock"
+          sp_human
+          oc_wizard
+          s_wizard
+          5
+          0 0 0
+          0 0
+          0 0
+          30 67108864
+          22 20
+          #f ;; dead?
+          nil
+          nil
+          'warlock-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_dagger
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                    (list
+                      100
+                      "1d2+1"
+                      't_mana_potion
+                    )
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      10
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      10
+                      "1"
+                      't_cure_potion
+                    )
+                    (list
+                      10
+                      "1"
+                      't_poison_immunity_potion
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'sulphorous_ash
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'ginseng
+                    )
+                    (list
+                      20
+                      "1d5"
+                      'garlic
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'spider_silk
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'blood_moss
+                    )
+                    (list
+                      10
+                      "1d3"
+                      'black_pearl
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'nightshade
+                    )
+                    (list
+                      5
+                      "1d2"
+                      'mandrake
+                    )
+                    (list
+                      5
+                      "1"
+                      't_in_mani_corp_scroll
+                    )
+                    (list
+                      5
+                      "1"
+                      't_xen_corp_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_in_quas_xen_scroll
+                    )
+                    (list
+                      10
+                      "1"
+                      't_an_xen_exe_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_in_an_scroll
+                    )
+                    (list
+                      20
+                      "1"
+                      't_vas_mani_scroll
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'warlock
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    9 6)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'warlock
+        )
+      ) ;; bind
+    9 12)
+  ) ;; end of objects in p_altar_room
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_altar_room
+
+(kern-mk-place 'p_dank_cave "Dank Cave"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr .. .. .. rr rr rr rr rr rr rr rr "
+      "rr rr rr rr {{ rr rr rr {8 .. {8 rr rr rr {{ rr rr rr rr "
+      "rr rr rr {{ {{ {{ rr {{ {{ {e {{ {{ rr {{ {{ {{ rr rr rr "
+      "rr rr {{ {C %f {A {{ {{ {{ {{ {{ {{ {{ {C .! {A {{ rr rr "
+      "rr {{ {{ %7 .! %3 %d {{ {{ rr {{ {{ %b %% %% %5 {{ {{ rr "
+      "rr {{ {{ %a %% %c {# {{ rr rr rr {{ {% %a %% %c {{ {{ rr "
+      "rr rr {{ {% %e {# {{ {{ {{ rr {{ {{ {{ {% %e {# {{ rr rr "
+      "rr rr rr {{ {{ {{ rr {{ {{ {{ {{ {{ rr {{ {{ {{ rr rr rr "
+      "rr rr rr rr {{ rr rr rr {{ {{ {{ rr rr rr {{ rr rr rr rr "
+      "rr rr rr {{ {{ {{ rr {{ {{ {{ {{ {{ rr {{ {{ {{ rr rr rr "
+      "rr rr {{ {C %7 {A {{ {{ {{ rr {{ {{ {{ {C %7 {A {{ rr rr "
+      "rr {{ {{ %3 %% %d {A {{ rr rr rr {{ {C %3 %% %5 {{ {{ rr "
+      "rr {{ {{ %a %% .! %7 {A {{ rr {{ {C %3 %% %% %c {{ {{ rr "
+      "rr rr {{ {% %a %% %% %d {{ {{ {{ %b %% .! %e {# {{ rr rr "
+      "rr rr rr {{ {% %a %c {# {{ rr {{ {% %a %d {# {{ rr rr rr "
+      "rr rr rr rr {{ {{ {{ {{ rr rr rr {{ {{ {{ {{ rr rr rr rr "
+      "rr rr rr rr rr {{ {{ rr rr rr rr rr {{ {{ rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_dank_cave
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bat
+        )
+      ) ;; bind
+    5 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'rat
+        )
+      ) ;; bind
+    4 2)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'snake
+        )
+      ) ;; bind
+    17 12)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_custom_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'grow-trig
+          'mandrake
+          "1d5"
+        )
+      ) ;; bind
+    14 14)
+    (list
+      (bind
+        (kern-mk-obj t_custom_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'grow-trig
+          'nightshade
+          "1d5"
+        )
+      ) ;; bind
+    6 14)
+    (list
+      (bind
+        (kern-mk-obj t_custom_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'grow-trig
+          'ginseng
+          "1d5"
+        )
+      ) ;; bind
+    3 12)
+    (list
+      (bind
+        (kern-mk-obj t_custom_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'grow-trig
+          'ginseng
+          "1d5"
+        )
+      ) ;; bind
+    3 5)
+    (list
+      (bind
+        (kern-mk-obj t_custom_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'grow-trig
+          'garlic
+          "1d5"
+        )
+      ) ;; bind
+    15 5)
+    (list
+      (bind
+        (kern-mk-obj t_custom_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'grow-trig
+          'garlic
+          "1d5"
+        )
+      ) ;; bind
+    3 13)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_shamans_grove
+          14
+          11
+        )
+      ) ;; bind
+    9 1)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'gazer
+        )
+      ) ;; bind
+    9 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'headless
+        )
+      ) ;; bind
+    8 7)
+  ) ;; end of objects in p_dank_cave
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_dank_cave
+
+(kern-mk-place 'p_eastpass "Eastpass"
+  s_keep ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      ".. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      ".. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      ".. .. {5 {{ {{ {{ {{ xx ,, xx {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      ".. .. {4 {{ {{ {{ {{ w+ ,, w+ {5 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ "
+      ".. .. .. {1 {1 {1 {1 xx ,, xx .. {1 {5 {{ ^^ ^^ ^^ ^^ ^^ "
+      ".. .. .. .. .. xx xx xx ,, xx xx xx {4 {{ {{ ^^ ^^ ^^ ^^ "
+      ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. {5 {{ {{ ^^ ^^ ^^ "
+      ".. .. .. .. .. x! ,, ,, ,, ,, ,, x! .. .. {5 {{ {{ ^^ ^^ "
+      ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. .. .. {5 {{ {{ ^^ "
+      ".. .. .. .. .. ,, ,, ,, ,, ,, ,, ,, .. .. .. .. {d {{ ^^ "
+      ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. .. .. {c {{ {{ ^^ "
+      ".. .. .. .. .. x! ,, ,, ,, ,, ,, x! .. .. {4 {{ {{ ^^ ^^ "
+      ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. .. {c {{ ^^ ^^ ^^ "
+      ".. .. .. .. .. xx xx xx ,, xx xx xx .. {c {{ {{ ^^ ^^ ^^ "
+      ".. .. .. .. .. .. .. xx ,, xx .. .. {c {{ {{ ^^ ^^ ^^ ^^ "
+      ".. .. .. {8 {8 {8 {8 w+ ,, w+ {8 {c {{ {{ ^^ ^^ ^^ ^^ ^^ "
+      ".. .. {c {{ {{ {{ {{ xx ,, xx {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+      ".. {4 {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      ".. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_eastpass
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bandit
+        )
+      ) ;; bind
+    4 9)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            0
+            7
+            37
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "knight"
+          sp_human
+          oc_warrior
+          s_human_knight
+          2
+          0 0 0
+          0 0
+          0 0
+          11 140
+          3 1
+          #f ;; dead?
+          'knight-conv
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 1 t_armor_plate)
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_iron_helm
+            t_2h_sword
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'knight
+          #f
+          #t
+          (list
+            7
+            8
+          )
+        )
+      ) ;; bind
+    7 8)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "squire"
+          sp_human
+          oc_warrior
+          s_guard
+          2
+          0 0 0
+          0 0
+          0 0
+          11 128
+          3 1
+          #f ;; dead?
+          'knight-conv
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 2 t_bolt)
+              (list 1 t_dagger)
+              (list 1 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_crossbow
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_bolt
+                    )
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'squire
+          #f
+          #t
+          (list
+            9
+            8
+          )
+        )
+      ) ;; bind
+    9 8)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "squire"
+          sp_human
+          oc_warrior
+          s_guard
+          2
+          0 0 0
+          0 0
+          0 0
+          11 128
+          3 1
+          #f ;; dead?
+          'knight-conv
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 4 t_bolt)
+              (list 1 t_dagger)
+              (list 1 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_chain_coif
+            t_crossbow
+            t_armor_chain
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_bolt
+                    )
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d2-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'squire
+          #f
+          #t
+          (list
+            7
+            10
+          )
+        )
+      ) ;; bind
+    7 10)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "knight"
+          sp_human
+          oc_warrior
+          s_human_knight
+          2
+          0 0 0
+          0 0
+          0 0
+          11 128
+          3 1
+          #f ;; dead?
+          'knight-conv
+          nil
+          'guard-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            (list
+              (list 1 t_armor_plate)
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_iron_helm
+            t_2h_sword
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d20"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'knight
+          #f
+          #t
+          (list
+            9
+            10
+          )
+        )
+      ) ;; bind
+    9 10)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_westpass
+          4
+          14
+        )
+      ) ;; bind
+    14 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    11 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+          4
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 9)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'knight
+        )
+      ) ;; bind
+    7 8)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'knight
+        )
+      ) ;; bind
+    9 10)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'squire
+        )
+      ) ;; bind
+    7 10)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'squire
+        )
+      ) ;; bind
+    9 8)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bandit
+        )
+      ) ;; bind
+    3 8)
+  ) ;; end of objects in p_eastpass
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_eastpass
+
+(kern-mk-place 'p_westpass "Westpass"
+  s_keep ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {a tt tt || || || || || || "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ tt tt || || || || || || "
+      "^^ ^^ ^^ {{ bb && bb {{ ^^ ^^ {{ tt tt || || || || || || "
+      "^^ ^^ {{ {3 .. .. .. {5 {{ ^^ {C ta tt tt || || || || || "
+      "^^ ^^ {{ {2 .. .. .. .. {5 {{ bb t% tt tt tt || || || || "
+      "^^ ^^ bb .. .. .. .. .. .. bb {A {2 ta tt tt tt || || || "
+      "^^ ^^ ^5 bb {8 .. .. .. .. .. bb .. t% ta tt tt tt tt tt "
+      "^^ ^^ ^^ ^^ {{ {a .. .. .. .. bb .. .. t% ta tt tt tt tt "
+      "^^ ^^ ^^ ^^ bb {{ {2 .. .. bb .. .. .. .. .. .. .. .. .. "
+      "^^ ^^ ^^ ^^ bb {A {2 .. .. /c /d /d /d /d /d /d /d /d /d "
+      "^^ ^^ ^^ ^^ bb bb .. .. .. bb .. .. .. .. .. .. .. .. .. "
+      "^^ ^^ ^^ {{ {{ {2 .. .. .. .. bb .. .. tC t3 tt tt tt tt "
+      "^^ ^^ {{ {3 {1 .. .. .. {8 .. bb .. tC t3 tt tt tt tt tt "
+      "^^ {{ {3 .. .. .. .. bb ^^ bb {& tC t3 tt tt tt || || || "
+      "^^ {{ {2 .. .. .. {4 {{ ^^ {{ {{ t3 tt tt tt || || || || "
+      "^^ {{ {a .. .. .. {c {{ ^^ ^^ {{ ta tt tt || || || || || "
+      "^^ {{ {{ {a {8 {c {{ ^^ ^^ ^^ {{ {% tt || || || || || || "
+      "^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ tt || || || || || || "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tt || || || || || || "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_westpass
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            0
+            7
+            36
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "ranger"
+          sp_human
+          oc_warrior
+          s_companion_ranger
+          2
+          0 0 0
+          0 0
+          0 0
+          11 128
+          3 1
+          #f ;; dead?
+          'ranger-conv
+          nil
+          'ranger-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 1 t_sword)
+              (list 16 t_arrow)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_bow
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'ranger
+          #f
+          #t
+          (list
+            9
+            11
+          )
+        )
+      ) ;; bind
+    9 11)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "ranger"
+          sp_human
+          oc_warrior
+          s_companion_ranger
+          2
+          0 0 0
+          0 0
+          0 0
+          13 512
+          5 3
+          #f ;; dead?
+          'ranger-conv
+          nil
+          'ranger-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'burn
+            ;; contents
+            (list
+              (list 1 t_sword)
+              (list 18 t_arrow)
+              (list 1 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_bow
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'ranger
+          #f
+          #t
+          (list
+            4
+            12
+          )
+        )
+      ) ;; bind
+    4 12)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "ranger"
+          sp_human
+          oc_warrior
+          s_companion_ranger
+          2
+          0 0 0
+          0 0
+          0 0
+          10 152
+          3 1
+          #f ;; dead?
+          'ranger-conv
+          nil
+          'ranger-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'spike-trap
+            ;; contents
+            (list
+              (list 1 t_sword)
+              (list 16 t_arrow)
+              (list 1 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_bow
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'ranger
+          #f
+          #t
+          (list
+            9
+            7
+          )
+        )
+      ) ;; bind
+    9 7)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "ranger"
+          sp_human
+          oc_warrior
+          s_companion_ranger
+          2
+          0 0 0
+          0 0
+          0 0
+          11 128
+          3 1
+          #f ;; dead?
+          'ranger-conv
+          nil
+          'ranger-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            'spike-trap
+            ;; contents
+            (list
+              (list 1 t_sword)
+              (list 17 t_arrow)
+              (list 2 t_heal_potion)
+            )
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            t_leather_helm
+            t_bow
+            t_armor_leather
+          )
+          ;; hooks
+          (list
+            (list
+              ef_loot_drop
+              (list
+                'loot-drop-gob
+                'drop-generic
+                (list
+                  (list
+                    (list
+                      100
+                      "1d10"
+                      't_gold_coins
+                    )
+                    (list
+                      100
+                      "1d10"
+                      't_arrow
+                    )
+                    (list
+                      30
+                      "1d3"
+                      't_food
+                    )
+                    (list
+                      100
+                      "1d3-1"
+                      't_heal_potion
+                    )
+                  )
+                )
+              )
+              2
+              0
+            )
+          )
+        )
+        (list
+          'npcg
+          'ranger
+          #f
+          #t
+          (list
+            5
+            4
+          )
+        )
+      ) ;; bind
+    5 4)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_eastpass
+          14
+          9
+        )
+      ) ;; bind
+    4 14)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ranger
+        )
+      ) ;; bind
+    9 7)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ranger
+        )
+      ) ;; bind
+    9 11)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ranger
+        )
+      ) ;; bind
+    5 4)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ranger
+        )
+      ) ;; bind
+    4 12)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-stalker
+        )
+      ) ;; bind
+    11 8)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-hunter
+        )
+      ) ;; bind
+    11 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'forest-goblin-stalker
+        )
+      ) ;; bind
+    11 10)
+  ) ;; end of objects in p_westpass
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_westpass
+
+(kern-load "keep_crypt_mech.scm")
+
+(kern-mk-place 'p_crypt "Crypt"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx ,, ,, ,, xx x! ,, ,, ,, x! xx ,, ,, ,, xx ,, xx "
+      "xx xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, xx "
+      "xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, xx "
+      "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, xx xx xx xx xx ?? xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx ,, xx xx xx .C .R .Y .P .T xx xx xx ,, xx xx xx "
+      "xx .. .. ,, .. .. xx xx xx x! xx xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx xx xx ,, xx xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx xx ,, ,, ,, xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx xx ,, ,, ,, xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. x! xx xx ,, xx xx x! .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx ,, ,, ,, ,, ,, xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx ,, ,, ,, ,, ,, xx .. .. ,, .. .. xx "
+      "xx .. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, .. .. xx "
+      "xx .. .. .. .. .. xx ,, ,, ,, ,, ,, xx .. .. .. .. .. xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_crypt
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    3 8)
+    (list
+      (kern-tag 'kc_pa
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            'kc_kcma
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    6 16)
+    (list
+      (kern-tag 'kc_pb
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            'kc_kcmb
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    12 16)
+    (list
+      (kern-tag 'kc_pc
+        (bind
+          (kern-mk-obj t_portcullis 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            '()
+            #f
+            '()
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    9 13)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'kc_pb
+          #f
+          '()
+        )
+      ) ;; bind
+    4 2)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'kc_pa
+          #f
+          '()
+        )
+      ) ;; bind
+    14 2)
+    (list
+      (bind
+        (kern-mk-obj t_lever 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          'kc_pc
+          #f
+          '()
+        )
+      ) ;; bind
+    17 1)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 9)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 10)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 11)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 12)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 13)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 14)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 15)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 16)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 16)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 16)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 16)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    1 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    2 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    3 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    4 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    5 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    13 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    14 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    15 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    16 17)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          '()
+        )
+      ) ;; bind
+    17 17)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (kern-tag 'kc_kcma
+        (bind
+          (kern-mk-obj t_kcm 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            (list
+              1
+              9
+              5
+              9
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    0 0)
+    (list
+      (kern-tag 'kc_kcmb
+        (bind
+          (kern-mk-obj t_kcm 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            #f
+            (list
+              13
+              9
+              5
+              9
+            )
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_green_tower_lower
+          17
+          1
+        )
+      ) ;; bind
+    9 3)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_lich_tomb
+          9
+          16
+        )
+      ) ;; bind
+    9 10)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #t
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    12 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    6 7)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    12 7)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    15 8)
+  ) ;; end of objects in p_crypt
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_crypt
+
+(kern-mk-place 'p_ancient_derelict "Ancient Derelict"
+  s_void_ship ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ "
+      "^^ {{ {{ bb {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {3 {5 {{ {{ ^^ "
+      "{{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {3 #> bb {5 {{ ^^ "
+      "{{ {{ {{ {3 {1 {5 {{ {{ {{ ^^ ^^ ^^ {{ {2 ee .. {4 {{ ^^ "
+      "{{ {{ {3 .. .. #> #> #> {{ ^^ ^^ #> {{ {2 .. ee #> {{ ^^ "
+      "{1 {1 .. .. .. .. ee ee {{ {{ ^^ {{ {3 .. .. {4 {{ ^^ ^^ "
+      ".. .. #> .. ee ee ee ee ee {{ {{ {{ ee ee .. #> ^^ ^^ ^^ "
+      ".. .. bb ee ee ee ee ee ee ee {1 ee ee ee ee #> {1 {5 ^^ "
+      ".. .. #> .. ee ee ee ee ee ee ee ee ee ee .. ee #> .. {1 "
+      ".. .. .. .. .. ee ee ee ee ee ee .. .. #> #> .. #> .. .. "
+      "{8 {8 bb .. #> #> #> #> #> .. #> #> .. .. .. .. .. bb .. "
+      "{{ {{ {a .. .. .. .. .. .. bb .. .. .. .. .. .. .. .. .. "
+      "{{ {{ {{ {a {8 {8 .. .. .. .. .. .. .. {8 {8 {8 bb .. .. "
+      "^^ {{ bb {{ {{ {{ {a {8 .. .. .. .. {c {{ {{ {{ {{ {a {8 "
+      "^^ ^^ {{ {{ {{ {{ {{ {{ {2 .. .. {c {{ {{ {{ {{ {{ {{ {{ "
+      "^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {2 .. {4 {{ ^^ ^^ ^^ {{ {{ {{ {{ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {2 .. {4 {{ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_ancient_derelict
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'wisp
+        )
+      ) ;; bind
+    7 9)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'wisp
+        )
+      ) ;; bind
+    10 9)
+    (list
+      (kern-mk-obj t_power_core 1
+        ;; hooks
+        (list
+        )
+      )
+    12 5)
+    (list
+      (bind
+        (kern-mk-obj t_corpse 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          (list
+            (list
+              1
+              't_staff
+            )
+            (list
+              1
+              't_vas_rel_por_scroll
+            )
+          )
+        )
+      ) ;; bind
+    9 10)
+  ) ;; end of objects in p_ancient_derelict
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_ancient_derelict
+
+(kern-load "joel.scm")
+
+(kern-load "r2a_mech.scm")
+
+(kern-mk-place 'p_road_to_absalot_3 "Passage to Absalot"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr {C !! !! !c {{ {{ {{ {{ {{ !a !! !! {A rr rr rr "
+      "rr rr {C !3 !! !c {# {{ {{ {{ {{ {{ {{ {% !! !5 {A rr rr "
+      "rr {C !3 !! !c {# {{ {{ bb xx xx {{ {{ {{ !a !! !5 {A rr "
+      "rr !! !! !c {# {{ {{ xx rr rr xx xx {{ {{ {% !a !! !! rr "
+      "rr !! !! {# {{ {{ xx xx xx xx xx xx xx {{ {{ {% !! !! rr "
+      "rr !! !! {{ {{ xx xx xx ,, ,, ,, bb rr xx {{ {{ !! !! rr "
+      "rr !! !! {{ {{ rr xx xx ,, ,, ,, rr xx xx {{ {{ !! !! rr "
+      "rr !! !! {{ {{ bb rr xx ,, ,, ,, xx xx xx {{ {{ !! !! rr "
+      "rr !! !! {A {{ {{ xx xx xx ,, xx xx xx {{ {{ {C !! !! rr "
+      "rr !! !! !5 {A {{ {{ xx xx ,, xx xx {{ {{ {C !3 !! !! rr "
+      "rr !! !! !! !5 {A {{ {{ xx ,, xx {{ {{ {C !3 !! !! !! rr "
+      "rr {% !! !! !! !5 {A {{ ,, ,, ,, {{ !3 !! !! !! !! {# ~r "
+      "rr {{ !a !! !! !! !5 {{ {2 ,, ,, {{ !! !! !! !! !c {{ rr "
+      "rr {{ {% !a !! !! !! {{ ,, ,, ,, {{ !! !! !! !c {# {{ rr "
+      "rr {{ {{ {% !a !! xx rr ,, ,, .. xx xx !! !c {# {{ {{ rr "
+      "rr rr {{ {{ {% !a xx ,, ,, ,, ,, ,, xx !c {# {{ {{ {{ rr "
+      "rr rr rr {{ {{ {{ rr bb ,, ,, ,, ,, ?? {{ {{ {{ {{ rr rr "
+      "rr rr rr rr rr xx xx xx ,, ,, ,, xx xx xx rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  (list
+    (list
+      (kern-mk-place 'p_fire_bridge "Fire Bridge"
+        nil ;; sprite
+        (kern-mk-map
+          nil           19 19 pal_expanded
+          (list
+            "xx xx xx rr rr xx xx xx ,, ,, ,, xx xx xx xx xx xx xx xx "
+            "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr "
+            "xx ,, .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb rr "
+            "rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr "
+            "rr ,, ,, ,, ,, xx rr xx ,, w+ ,, xx xx xx ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, xx !_ !_ ,, ,, !! !_ !_ xx ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, w+ !! !_ !_ !_ !_ !_ !! w+ ,, ,, ,, ,, xx "
+            "rr ,, ,, ,, ,, xx !! !! !_ !_ !_ !! !! rr ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, xx xx !! !! !! !! !! xx xx ,, .. ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, w+ !! ,, ,, !! !! w+ ,, ,, ,, ,, ,, rr "
+            "xx ,, ,, ,, ,, ,, w+ !! ,, ,, bb !! w+ ,, ,, ,, ,, ,, xx "
+            "xx ,, ,, ,, ,, ,, w+ !! ,, ,, ,, !! w+ ,, ,, ,, ,, ,, xx "
+            "xx xx ,, ,, ,, xx rr !! !! ,, ,, !! xx xx ,, ,, ,, xx xx "
+            "!! xx bb w+ w+ xx !! !! ,, ,, ,, !! !! xx w+ w+ w+ xx !! "
+            "!! !! ,, !! !! !! !! !! ,, ,, !! !! !! !! !! !! !! !! !! "
+            "!! !! ,, !! !! !! !c {& ,, ,, {4 {% !a !! !! !! !! !! !! "
+            "rr {{ {% !a !! !c {# {{ ,, ,, ,, {{ {% !a !! !c {# {{ rr "
+            "rr {{ {{ {{ {{ {{ {{ {{ {2 ,, ,, {{ {{ {{ {{ {{ {{ rr rr "
+            "rr rr rr rr rr rr rr rr ,, ,, ,, rr rr rr rr rr rr rr rr "
+          )
+        )
+        #f #t #f #f
+        ;; subplaces
+        nil
+        (list
+          (list
+            (kern-mk-place 'p_road_to_absalot_1 "Passage to Absalot"
+              nil ;; sprite
+              (kern-mk-map
+                nil                 19 19 pal_expanded
+                (list
+                  "rr rr rr rr !! rr rr rr ,, ,, ,, rr rr rr rr !! rr rr rr "
+                  "rr rr rr rr !! rr rr {{ ,, .. ,, {{ {{ {{ rr !! rr rr rr "
+                  "rr rr rr {{ !! {A {{ {C ,, ,, ,, {{ !3 !! !! !! {{ rr rr "
+                  "rr {{ {{ {C !! !! !! !! ,, ,, ,, {{ !! bb {F !! {{ rr rr "
+                  "rr {{ !3 !! !! {& bb !! ,, ,, {4 {{ !! {# bb !! {{ rr rr "
+                  "rr {{ !! bb !! {{ {% !! ,, ,, ,, {{ !e {{ {% !! {{ rr rr "
+                  "rr {{ !e {& !! {{ {{ !e .. ,, ,, {A {{ {{ {{ !! {{ {{ ~r "
+                  "rr {{ {{ {{ !! {{ {{ pp ,, ,, ,, pp {{ {{ {C !! {A {{ rr "
+                  "rr rr {{ {C !! {A {C ,, ,, ,, ,, ,, {{ !3 !! !! !5 {{ rr "
+                  "rr rr {{ !3 !! !! !! ,, ,, ,, ,, ,, {{ !! bb bb !! {{ rr "
+                  "rr rr {{ !! bb bb !! ,, ,, ,, ,, ,, {{ !! bb {& !e {{ rr "
+                  "rr rr {{ !! {& bb !! pp {8 ,, ,, bb {{ !! {# {{ {{ {{ rr "
+                  "rr {{ {{ !! {{ {% !! {# {{ {{ {{ {{ {{ !! {{ {{ {{ {{ rr "
+                  "rr {{ {{ !! {{ {{ !e {{ {{ rr {{ {{ {{ !! {{ {{ {{ {{ rr "
+                  "rr {{ {{ !e {{ {{ {{ {{ rr rr {{ {{ {{ !! {{ {{ {{ {{ rr "
+                  "rr rr {{ {{ {{ rr {{ {{ rr rr rr {{ {{ !e {{ {{ rr bb rr "
+                  "rr rr rr {{ rr rr {{ rr rr rr rr rr {{ {{ {{ rr rr rr rr "
+                  "rr rr rr {{ rr rr rr rr rr rr rr rr rr {{ rr rr rr rr rr "
+                  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+                )
+              )
+              #f #t #f #f
+              ;; subplaces
+              nil
+              nil ;; neighbors
+              (list ;; objects in p_road_to_absalot_1
+                (list
+                  (bind
+                    (kern-mk-obj t_trap_door 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'p_absalot_passage
+                      1
+                      38
+                    )
+                  ) ;; bind
+                18 6)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'troll
+                    )
+                  ) ;; bind
+                4 12)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'troll
+                    )
+                  ) ;; bind
+                13 4)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'headless
+                    )
+                  ) ;; bind
+                9 4)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'headless
+                    )
+                  ) ;; bind
+                5 4)
+                (list
+                  (bind
+                    (kern-mk-obj t_spawn_pt 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'spawn-pt
+                      'gazer
+                    )
+                  ) ;; bind
+                3 17)
+                (list
+                  (bind
+                    (kern-mk-obj t_monman 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'monman
+                      (list
+                        0
+                        0
+                        0
+                        -1
+                        6
+                        -1
+                      )
+                    )
+                  ) ;; bind
+                0 0)
+                (list
+                  (bind
+                    (kern-mk-obj t_ladder_up 1
+                      ;; hooks
+                      (list
+                      )
+                    )
+                    (list
+                      'p_gate_to_absalot
+                      9
+                      1
+                    )
+                  ) ;; bind
+                9 9)
+              ) ;; end of objects in p_road_to_absalot_1
+              (list ;; on-entry-hooks
+                'on-entry-to-dungeon-room
+              )
+              (list ;; edge entrances
+                (list 0 18 18) ;; Northwest
+                (list 1 9 18) ;; North
+                (list 2 0 18) ;; Northeast
+                (list 3 18 9) ;; West
+                (list 4 9 9) ;; Here
+                (list 5 0 9) ;; East
+                (list 6 18 0) ;; Southwest
+                (list 7 9 0) ;; South
+                (list 8 0 0) ;; SoutheastUp
+              )
+            ) ;; end of place p_road_to_absalot_1
+
+          7)
+        ) ;; end neighbors of p_fire_bridge
+        (list ;; objects in p_fire_bridge
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'ghast
+              )
+            ) ;; bind
+          14 9)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'craven-archer
+              )
+            ) ;; bind
+          13 9)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'death-knight
+              )
+            ) ;; bind
+          8 3)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'death-knight
+              )
+            ) ;; bind
+          10 3)
+          (list
+            (bind
+              (kern-mk-obj t_spawn_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'demon
+              )
+            ) ;; bind
+          16 2)
+          (list
+            (bind
+              (kern-mk-obj t_monman 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'monman
+                (list
+                  0
+                  0
+                  0
+                  -1
+                  6
+                  -1
+                )
+              )
+            ) ;; bind
+          0 0)
+          (list
+            (kern-tag 'fb-p2
+              (bind
+                (kern-mk-obj t_portcullis 1
+                  ;; hooks
+                  (list
+                  )
+                )
+                (list
+                  #f
+                  '()
+                  #f
+                  '()
+                )
+              ) ;; bind
+            ) ;; kern-tag
+          8 4)
+          (list
+            (kern-tag 'fb-p1
+              (bind
+                (kern-mk-obj t_portcullis 1
+                  ;; hooks
+                  (list
+                  )
+                )
+                (list
+                  #f
+                  'fb-p2
+                  #f
+                  '()
+                )
+              ) ;; bind
+            ) ;; kern-tag
+          10 4)
+          (list
+            (kern-tag 'fb-b1
+              (bind
+                (kern-mk-obj t_terrain_blitter 1
+                  ;; hooks
+                  (list
+                  )
+                )
+                (list
+                  'p_fire_bridge
+                  8
+                  6
+                  3
+                  3
+                  'm_deck_section
+                )
+              ) ;; bind
+            ) ;; kern-tag
+          1 1)
+          (list
+            (bind
+              (kern-mk-obj t_lever 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                'fb-p1
+                #f
+                '()
+              )
+            ) ;; bind
+          3 10)
+          (list
+            (bind
+              (kern-mk-obj t_lever 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                #f
+                'fb-b1
+                #f
+                '()
+              )
+            ) ;; bind
+          15 10)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'craven-archer
+              )
+            ) ;; bind
+          5 10)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'ghast
+              )
+            ) ;; bind
+          3 11)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'skeletal-spear-thrower
+              )
+            ) ;; bind
+          5 9)
+          (list
+            (bind
+              (kern-mk-obj t_guard_pt 1
+                ;; hooks
+                (list
+                )
+              )
+              (list
+                'spawn-pt
+                'craven-archer
+              )
+            ) ;; bind
+          13 11)
+        ) ;; end of objects in p_fire_bridge
+        (list ;; on-entry-hooks
+          'on-entry-to-dungeon-room
+        )
+        (list ;; edge entrances
+          (list 0 18 18) ;; Northwest
+          (list 1 9 18) ;; North
+          (list 2 0 18) ;; Northeast
+          (list 3 18 9) ;; West
+          (list 4 9 9) ;; Here
+          (list 5 0 9) ;; East
+          (list 6 18 0) ;; Southwest
+          (list 7 9 0) ;; South
+          (list 8 0 0) ;; SoutheastUp
+        )
+      ) ;; end of place p_fire_bridge
+
+    7)
+  ) ;; end neighbors of p_road_to_absalot_3
+  (list ;; objects in p_road_to_absalot_3
+    (list
+      (bind
+        (kern-mk-obj t_ladder_up 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_tower_of_absalot
+          9
+          9
+        )
+      ) ;; bind
+    9 7)
+    (list
+      (bind
+        (kern-mk-obj t_trap_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_absalot_passage
+          1
+          2
+        )
+      ) ;; bind
+    18 12)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ghast
+        )
+      ) ;; bind
+    10 8)
+    (list
+      (bind
+        (kern-mk-obj t_guard_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'death-knight
+        )
+      ) ;; bind
+    8 8)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'craven-archer
+        )
+      ) ;; bind
+    10 6)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'zorn
+        )
+      ) ;; bind
+    8 6)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #t
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    9 10)
+  ) ;; end of objects in p_road_to_absalot_3
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_road_to_absalot_3
+
+p_fire_bridge
+p_road_to_absalot_1
+(kern-mk-place 'p_absalot_passage "Secret Passage"
+  nil ;; sprite
+  (kern-mk-map
+    nil     19 40 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      ".. {8 .. .. {c {{ rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr {{ {2 rr {{ {3 rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. bb rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr .. {c {{ rr rr rr rr rr rr rr rr *7 rr rr "
+      "rr rr rr rr rr rr {{ {3 rr rr rr *7 rr rr rr *3 vv *5 rr "
+      "rr rr rr rr rr rr rr .. rr rr rr vv *5 rr rr vv vv vv rr "
+      "rr rr rr rr rr rr rr .. rr rr *3 vv vv vv vv vv vv vv vv "
+      "rr rr rr rr rr rr {{ {2 rr rr *2 vv vv vv vv vv vv vv vv "
+      "rr rr rr rr rr rr {1 bb rr rr vv vv vv vv vv vv vv vv vv "
+      "rr rr rr rr rr rr .. rr rr *3 vv vv vv vv vv *c rr vv vv "
+      "rr rr rr rr rr {{ .. rr *3 vv vv vv vv vv *c rr rr *2 vv "
+      "rr rr rr rr rr .. *3 vv vv vv vv vv vv vv rr rr rr *2 vv "
+      "rr !! !! !! rr .. *2 vv vv vv vv vv vv vv rr rr bb vv vv "
+      "!! !! !! !! !! !! ** vv vv vv vv vv vv vv *5 rr *3 vv vv "
+      "!! !_ !_ !_ !_ !_ *. vv vv vv vv vv vv vv vv vv vv vv vv "
+      "!_ !_ !_ !_ +s !! ** vv vv vv vv vv vv vv vv vv vv vv vv "
+      "!_ !_ !! !_ !_ !_ ** vv vv vv vv vv vv vv vv vv vv vv vv "
+      "!! !! !! !! !! !! *. vv vv vv vv vv vv vv vv vv vv vv vv "
+      "!! !! rr rr rr {c {h vv vv vv vv vv vv vv vv vv vv vv vv "
+      "rr rr rr rr rr {{ .. *2 vv vv vv vv vv vv vv vv vv vv vv "
+      "rr rr rr rr rr rr .. *2 vv vv vv vv vv *c rr vv vv vv vv "
+      "rr rr rr rr rr {{ .l vv vv vv vv vv vv bb rr *a vv vv vv "
+      "rr rr rr rr rr .. *3 vv vv vv vv vv vv rr rr rr vv vv vv "
+      "rr rr rr rr rr .. *2 vv vv vv vv vv vv *5 rr *3 vv vv vv "
+      "rr rr rr rr rr {{ *2 vv vv vv vv vv vv vv vv vv vv vv vv "
+      "rr rr rr rr {{ .. *a vv vv vv vv vv vv vv vv vv vv vv vv "
+      "rr rr rr rr {1 {8 rr rr *a vv vv vv vv vv vv vv vv vv vv "
+      "rr rr rr {{ {6 {{ rr rr rr *a vv vv vv vv vv vv vv vv vv "
+      "rr rr rr {{ {2 rr rr rr rr rr vv vv vv vv vv vv *c rr rr "
+      "rr rr rr {1 {8 rr rr rr rr rr *2 vv *c rr vv *c rr rr rr "
+      "rr rr rr {4 {{ rr rr rr rr rr *e rr rr rr *e rr rr rr rr "
+      "rr rr rr bb {1 rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr {{ {2 rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr {{ {2 rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr {4 {{ {3 rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      ".. .. rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+    )
+  )
+  #f #t #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_absalot_passage
+    (list
+      (bind
+        (kern-mk-obj t_trap_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_road_to_absalot_3
+          17
+          12
+        )
+      ) ;; bind
+    0 2)
+    (list
+      (bind
+        (kern-mk-obj t_trap_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_road_to_absalot_1
+          17
+          6
+        )
+      ) ;; bind
+    0 38)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_r2a_statue
+          "Statue"
+          sp_statue
+          nil
+          s_statue
+          2
+          0 0 0
+          0 0
+          0 0
+          189 0
+          9 9
+          #f ;; dead?
+          'r2a-statue-conv
+          nil
+          'ankh-ai
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        '()
+      ) ;; bind
+    4 17)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bat
+        )
+      ) ;; bind
+    15 22)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bat
+        )
+      ) ;; bind
+    10 10)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bat
+        )
+      ) ;; bind
+    10 30)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bat
+        )
+      ) ;; bind
+    16 30)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'bat
+        )
+      ) ;; bind
+    16 15)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+  ) ;; end of objects in p_absalot_passage
+  (list ;; on-entry-hooks
+    'fix-lava
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 39) ;; Northwest
+    (list 1 9 39) ;; North
+    (list 2 0 39) ;; Northeast
+    (list 3 18 20) ;; West
+    (list 4 9 20) ;; Here
+    (list 5 0 20) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_absalot_passage
+
+(kern-mk-place 'p_gate_to_absalot "Gate To Absalot"
+  s_keep ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ xx xx xx xx xx ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx xx xx xx xx ,, ,, ,, xx xx xx xx rr ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx ,, ,, ,, xx .. ,, ,, xx ,, ,, ,, bb ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx bb ,, ,, ,, ,, ,, ,, ,, ,, .. ,, rr ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx ,, .. ,, xx ,, ,, ,, xx ,, ,, ,, xx ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx ,, ,, ,, xx xx bb xx rr ,, ,, bb xx ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx ,, ,, bb xx bb bb bb xx ,, ,, ,, xx ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx ,, ,, ,, w+ .. bb .. w+ ,, ,, ,, xx ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx ,, ,, ,, xx .. .. .. xx bb ,, ,, xx ^^ ^^ ^^ "
+      "^^ ^^ ^^ xx xx w+ xx rr .. .. .. xx xx w+ xx xx ^^ ^^ ^^ "
+      "^^ ^^ ^^ {{ {a .. .. .. .. .. .. .. .. .. {c {{ ^^ ^^ ^^ "
+      "^^ ^^ ^^ {{ {{ {2 .. .. .. .. .. .. .. {4 {{ {{ ^^ ^^ ^^ "
+      "^^ ^^ ^^ {{ {{ {2 .. .. .. && .. .. .. {4 {{ {{ ^^ ^^ ^^ "
+      "^^ ^^ ^^ {{ {{ {a .. .. .. .. .. .. .. {c {{ {{ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ {{ {{ {a .. .. .. .. .. {c {{ {{ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ {{ {{ {3 .. .. .. .. .. {5 {{ {{ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ {{ {{ {3 .. .. .. .. .. .. .. {5 {{ {{ ^^ ^^ ^^ "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_gate_to_absalot
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_road_to_absalot_1
+          9
+          9
+        )
+      ) ;; bind
+    9 1)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_joel
+          "Joel"
+          sp_human
+          nil
+          s_companion_shepherd
+          2
+          0 0 0
+          0 0
+          0 0
+          13 0
+          5 3
+          #f ;; dead?
+          'joel-conv
+          sch_joel
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    8 9)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bull"
+          sp_bull
+          nil
+          s_bull
+          0
+          0 0 0
+          0 0
+          0 0
+          28 1024
+          4 4
+          #f ;; dead?
+          nil
+          nil
+          'animal-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'npcg
+          'bull
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    12 12)
+    (list
+      (bind
+        (kern-mk-char
+          nil
+          "bull"
+          sp_bull
+          nil
+          s_bull
+          0
+          0 0 0
+          0 0
+          0 0
+          28 1024
+          4 4
+          #f ;; dead?
+          nil
+          nil
+          'animal-ai
+          (kern-mk-container
+            t_chest
+            ;; trap
+            nil
+            ;; contents
+            nil
+            ;; hooks
+            (list
+            )
+          )
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'npcg
+          'bull
+          #f
+          #f
+          '()
+        )
+      ) ;; bind
+    10 15)
+  ) ;; end of objects in p_gate_to_absalot
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_gate_to_absalot
+
+(kern-mk-place 'p_tower_of_absalot "Tower of Absalot"
+  s_keep ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "^^ tt tt tc %% te bb %% .. .. ta tc bb ta tc %% %% %c ^^ "
+      "^^ ta tt %b ~f %% %% %% %% =| %d bb %b %% %% %% ~f ^3 ^^ "
+      "^^ ^5 tt t5 %e t7 bb %e .. .. .. %f bb t7 %a ~f ^b ^^ ^^ "
+      "^^ ^^ tt tt tt tt td bb .. .. .. bb tb tt t5 %a ~f ^a ^^ "
+      "^^ ^^ tt tt tc xx w+ xx rr .. xx xx bb xx ta tt tt t5 ^^ "
+      "^^ ^^ tt tt xx xx ,, ,, w+ .. w+ ,, ,, xx xx tt tt tt ^^ "
+      "^^ ^^ tt tt w+ ,, ,, ,, rr d, xx ,, ,, ,, w+ tt tt tt ^^ "
+      "^^ ^^ ta tt xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx tt tt tc ^^ "
+      "^^ ^^ ^5 tt xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx tt tt ^3 ^^ "
+      "^^ ^^ ^^ tt bb .. ,, ,, ,, /c ,, ,, ,, ,, w+ tt tt ^^ ^^ "
+      "^^ ^^ ^^ tt t5 .. ,, ,, ,, ,, ,, ,, ,, ,, rr tt tt ^^ ^^ "
+      "^^ ^^ ^c tt tc .. .. ,, ,, ,, ,, ,, ,, ,, rr tt tt ^^ ^^ "
+      "^^ ^^ t3 tt bb .. ,, ,, ,, ,, ,, ,, ,, ,, w+ tt tt ^^ ^^ "
+      "^^ ^^ ta tt rr rr ,, ,, ,, ,, ,, ,, ,, xx xx tt tc ^^ ^^ "
+      "^^ ^^ ^5 tt t5 rr w+ xx xx w+ xx xx w+ xx t3 tt ^3 ^^ ^^ "
+      "^^ ^^ ^^ ta tt tt tt tt tt tt tt tt tt tt tt tc ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^5 ta tt tt tt tt tt tt tt tt tc ^3 ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_tower_of_absalot
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'death-knight
+        )
+      ) ;; bind
+    6 7)
+    (list
+      (bind
+        (kern-mk-obj t_spawn_pt 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'spawn-pt
+          'ghast
+        )
+      ) ;; bind
+    12 11)
+    (list
+      (bind
+        (kern-mk-obj t_monman 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'monman
+          (list
+            0
+            0
+            0
+            -1
+            6
+            -1
+          )
+        )
+      ) ;; bind
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_ladder_down 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_road_to_absalot_3
+          9
+          7
+        )
+      ) ;; bind
+    9 9)
+  ) ;; end of objects in p_tower_of_absalot
+  (list ;; on-entry-hooks
+    'on-entry-to-dungeon-room
+  )
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 9 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 9) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 9) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 9 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_tower_of_absalot
+
+(kern-load "mesmeme.scm")
+
+(kern-load "jake.scm")
+
+(kern-load "slywan.scm")
+
+(kern-load "tooth.scm")
+
+(kern-load "tetzl.scm")
+
+(kern-mk-place 'p_kun "Kun"
+  s_town ;; sprite
+  (kern-mk-map
+    nil     19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx {{ {2 .. {4 {{ ^^ ^^ ^^ "
+      "xx [[ .C .A .N .T .I .N .A ]] xx {{ {2 .. {4 {{ {{ ^^ ^^ "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx {{ {2 .. {4 {{ {{ {{ ^^ "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ws {{ {2 .. {4 {{ ^^ ^^ ^^ "
+      "xx ,, ,, 00 00 00 00 00 ,, ,, xx {{ {2 .. {4 {{ ^^ ^^ {{ "
+      "xx ,, ,, 00 ,, ,, ,, 00 ,, ,, xx {{ {2 .. {4 {{ {{ {{ {{ "
+      "xx ,, ,, 00 00 00 00 00 ,, ,, xx {{ {2 .. .. {1 {1 {1 {1 "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ws {{ {2 .. .. .. .. .. .. "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx {{ {2 .. .. .. {8 .. {8 "
+      "xx xx ws xx xx ,, sT xx ws xx xx {{ {2 .. .. bb {{ bb {{ "
+      ".. .. .. .. .. .. .. .. .. .. .. {1 .. .. {4 {{ {{ {{ ^^ "
+      ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. bb {{ ^^ ^^ "
+      "{8 .. {8 .. .. .. .. {8 .. .. .. .. .. .. {4 {{ ^^ ^^ ^^ "
+      "{{ bb {{ bb .. .. {4 {{ xx xx xx xx sE ,, xx xx xx xx xx "
+      "{{ {{ {{ {{ {2 .. {4 {{ xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "^^ {{ {{ bb .. .. {4 {{ xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "^^ ^^ {{ {{ {2 .. {4 {{ xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "^^ ^^ ^^ {{ {2 .. {4 {{ xx .D .U .T .Y @@ .F .R .E .E xx "
+      "^^ ^^ ^^ {{ {2 .. {4 {{ xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  nil ;; neighbors
+  (list ;; objects in p_kun
+    (list
+      (bind
+        (kern-mk-char
+          'ch_tooth
+          "Tooth"
+          sp_rat
+          oc_wrogue
+          s_rat
+          2
+          0 0 0
+          0 0
+          0 1
+          8 256
+          4 2
+          #f ;; dead?
+          'tooth-conv
+          sch_tooth
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    6 7)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_tetzl
+          "Tetzl"
+          sp_spider
+          oc_wright
+          s_spider
+          2
+          0 0 0
+          0 0
+          0 0
+          10 256
+          4 2
+          #f ;; dead?
+          nil
+          sch_tetzl
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    3 3)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_open_door_in_rock
+              #f
+              0
+            )
+            (list
+              's_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+            (list
+              's_magically_locked_windowed_wood_door_in_rock
+              #f
+              5
+            )
+          )
+        )
+      ) ;; bind
+    5 9)
+    (list
+      (bind
+        (kern-mk-obj t_door 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #f
+          0
+          '()
+          #f
+          #f
+          #f
+          (list
+            (list
+              's_closed_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_open_door_in_stone
+              #f
+              0
+            )
+            (list
+              's_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+            (list
+              's_magically_locked_solid_wood_door_in_stone
+              #t
+              5
+            )
+          )
+        )
+      ) ;; bind
+    13 13)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_mesmeme
+          "Mesmeme"
+          sp_gazer
+          oc_wizard
+          s_gazer
+          2
+          0 0 0
+          12 2
+          0 1
+          28 256
+          18 2
+          #f ;; dead?
+          'mesmeme-conv
+          sch_mesmeme
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        '()
+      ) ;; bind
+    8 4)
+    (list
+      (bind
+        (kern-mk-char
+          'ch_jake
+          "Jake&Percival"
+          sp_gint
+          nil
+          s_ettin
+          2
+          0 0 0
+          0 0
+          0 0
+          60 256
+          4 2
+          #f ;; dead?
+          'jake-conv
+          sch_jake
+          nil
+          nil ;; inventory
+          nil
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          #t
+        )
+      ) ;; bind
+    4 5)
+    (list
+      (bind
+        (kern-char-force-drop          (kern-mk-char
+            'ch_slywan
+            "Slywan"
+            sp_human
+            oc_wrogue
+            s_brigand
+            2
+            0 0 0
+            0 0
+            0 1
+            12 256
+            6 2
+            #f ;; dead?
+            'slywan-conv
+            sch_slywan
+            nil
+            (kern-mk-container
+              t_chest
+              ;; trap
+              nil
+              ;; contents
+              nil
+              ;; hooks
+              (list
+              )
+            )
+            nil
+            ;; hooks
+            (list
+            )
+          )
+        #t) ;; kern-char-force-drop
+        '()
+      ) ;; bind
+    3 7)
+  ) ;; end of objects in p_kun
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 18 18) ;; Northwest
+    (list 1 5 18) ;; North
+    (list 2 0 18) ;; Northeast
+    (list 3 18 7) ;; West
+    (list 4 9 9) ;; Here
+    (list 5 0 11) ;; East
+    (list 6 18 0) ;; Southwest
+    (list 7 13 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_kun
+
+(kern-load "raise-merciful-death.scm")
+
+(kern-mk-place 'p_shard "The Shard Surface"
+  nil ;; sprite
+  (kern-mk-composite-map
+    nil     4 3
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "*. *. *. *. ** ** *. *. ** *. *. *. *. ** *. ** ** ** *. *. *. ** ** *. *. ** *. *. ** ** ** ** "
+        "** ** ** ** ** ** *. *. ** ** ** ** ** *. ** *. ** ** *. *. *. *. ** ** ** ** *. ** ** *. ** ** "
+        "** *. *. *. *. *. *. *. *. *. *. ** ** ** ** *. ** ** ** ** ** ** ** ** ** ** *. ** *. *. ** ** "
+        "*. ** *. *. *. ** ** ** *. ** *. ** ** ** ** *. ** *. ** ** ** *. *. ** *. ** ** ** *. *. *. *. "
+        "*. *. *. ** ** *. *. *. *. ** ** ** ** ** ** *. ** ** ** ** *. ** ** *. ** *. *. ** ** ** *. ** "
+        "** *. ** *. ** ** ** *. ** ** ** ** *. *8 *8 *8 *8 *8 *8 *8 *8 *8 *8 ** ** ** ** ** ** ** ** *. "
+        "** *. *. ** ** ** *. *. ** *. *. *c ^g ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a *. ** ** *. *. ** ** "
+        "** *. ** ** ** *. ** ** *. ** ^g ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a ** *. *. *. ** *. "
+        "*. ** ** *. *. *. *. *. *. *4 ^^ ^^ ^^ .! ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a *8 *. ** ** *. "
+        "*. ** ** ** ** ** ** ** *. *c ^^ ^c tb tt td ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a ** ** "
+        "** ** ** *. ** ** *. *. ** ^g ^^ %b %5 tt %b %d ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *. ** "
+        "*. *. ** ** *. *. ** *. *4 ^^ ^^ t7 %% ta tt tt tt t5 ^a ^^ ^^ ^^ ^^ ^^ ^c %3 %% %5 ^a ^^ *a ** "
+        "*. ** *. ** *. ** ** *. *c ^^ ^^ tt %% %5 ta tt tt tt tt tt tt tt tt tt td %% -7 %% %5 ^^ ^h *a "
+        "** *. *. ** ** *. ** *. ^g ^^ ^c te %% %c ^3 ^^ ^d tt tt tc %3 %% %5 te %3 -b -- -d %% ^^ ^^ ^^ "
+        "*. *. *. *. ** ** ** *4 ^^ ^^ t7 %3 %c ^3 ^^ ^c %7 ta tt %3 %c ^7 %a %% %% %% -e %% %c ^^ ^^ ^^ "
+        "*. ** *. *. *. ** ** *4 ^^ ^^ tt %% ^b ^^ ^c %3 %% %d tt %% ^b ^^ ^d %% t7 %a %% %c {B {{ ^^ tf "
+        "** ** *. ** *. *. ** *4 ^^ ^^ te %a %% %% %% %% %% ^f tt %a %5 ^e %3 %c tt tt tt td %7 {E t7 {E "
+        "*. *. ** *. ** ** ** *4 ^^ ^^ ^5 t7 ^f %% %% %% %% tb tt t5 %a %% %c t3 tt tt tt %3 %% %d tt %3 "
+        "** *. ** *. ** ** ** ** ^j ^^ ^^ te %3 %c ^3 ^5 %% %5 ta tt tt tt tt tc t& tt tt %a %c t3 tt %% "
+        "*. *. ** ** ** ** *. *. *5 ^^ ^^ ^5 %% ^b ^^ ^^ %% %% %5 t% ta tt tt %3 %5 ta tt tt tt tt tc %a "
+        "*. ** ** ** ** ** ** *. *4 ^^ ^^ ^c %% %5 ^^ ^c %% %% %% ^7 t% tt tc %% %% %5 t% tt {# {{ {% t3 "
+        "** *. *. ** *. ** ** *. *4 ^^ ^^ %3 %% %% ^^ %3 %% %% %c {1 tC tt %3 %c ^7 %a %5 tt {{ {{ {{ tt "
+        "*. ** ** *. *. ** *. ** *4 ^^ ^^ %% ^f %% ^^ %a %% %% tb tt tt tt %% ^b ^^ ^d %% te {A {{ {C te "
+        "** *. ** ** *. *. ** *. *4 ^^ ^^ %a %% %% ^^ ^5 %% %% %% %5 ta tt %a %d ^e %3 %% %5 tb tt td %3 "
+        "** ** ** ** *. ** *. *. ** ^j ^^ ^5 %a %% ^a ^c %% %% -7 %% %5 tt tt t5 %b %% %% %% %5 te %3 %% "
+        "*. ** *. *. *. *. *. *. *. *5 ^j ^^ ^5 %a %% %% %% -b -- -d %% tt ^f tt tt tt t5 %% %% %% %% -b "
+        "*. ** *. ** *. ** *. *. *. *. *5 ^^ ^^ ^^ ^5 %a %% %% -e %% %c tt tt tt tt tt tt %% %c ^7 %a %% "
+        "** *. ** ** ** ** *. *. *. *. *. ^j ^^ ^^ ^^ ^5 t7 %a %% %c t3 tc %3 %% %5 ta tt %e ^b ^^ ^d %a "
+        "** ** *. *. *. ** *. *. *. ** *. ** *1 *5 ^^ ^^ ta tt tt tt tt %3 %% -7 %% %5 tt t5 %7 ^e %7 t3 "
+        "** *. *. *. ** ** *. *. *. ** *. ** *. *4 ^^ ^^ {2 .. .. t% tt %% -b -- -d %% tt tt %a %% %c tt "
+        "*. *. ** *. ** ** ** *. *. *. ** ** *. *4 ^^ ^^ {a .. .. .. tt %a %% -e %% %c tt tt tt tt tt tc "
+        "** *. ** ** *. *. ** *. *. *. *. *. *. *4 ^^ ^^ {{ {a {8 .. ta t5 %a %% %c t3 tc t# {8 {8 .. .. "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "** *. ** ** ** ** ** *. *. ** ** ** *. *. ** *. *. *. ** ** ** *. ** *. *. *. *. ** *. *. *. *. "
+        "** *. ** *. ** *. ** *. *. ** ** ** ** ** *. ** ** *. *. *. *. *. ** *. ** ** *. *. *. ** *. *. "
+        "** ** *. *. *. *. ** *. *. ** ** *. *. ** ** ** *. *. *. *. *. ** *. ** ** ** ** *. ** *. *. *. "
+        "** *. ** ** *. *. *. *. ** ** *. *. *. ** *. *. *. *8 *8 *8 ** ** ** *. *. *. ** *. ** ** ** ** "
+        "** *. *. ** ** *. *. ** ** ** ** *. *. ** ** *c ^g ^^ .. ^^ ^h *a ** ** ** ** ** *. *. ** *. *. "
+        "** ** ** *. *. *. *. *. ** ** ** ** *. *. ** ^g ^^ {{ {6 {{ ^^ ^h ** ** *. *. *. *. ** *. ** ** "
+        "*. *. *. ** *. ** *. *. ** ** *. *. *. *. *4 ^^ {{ {3 .. {5 {{ ^^ *2 ** ** ** *. ** ** ** *. ** "
+        "*. *. *. ** ** ** *. *. ** ** *. ** ** *. ** ^j {{ {a .. {c ^^ ^l *. ** *. ** ** *. *. ** *. *. "
+        "*. ** ** *. *. *. *. ** *. *. ** *. ** ** *. *5 {j {{ {e ^^ ^l *3 *. *. *. ** *. ** ** ** ** ** "
+        "** ** *. *. *. ** *. ** ** ** ** *. *. ** *. *. *5 {j {{ {l *3 *. *. *. ** ** ** *. *. *. *. *. "
+        "*. *. *. ** *. *. ** ** *. *. *. *. ** *. *8 *. *. *. *1 ** ** *. *. *. ** *. ** *. ** *. ** ** "
+        "** *. *8 *8 ** *. *. ** *. ** ** *. *c {g {{ {h *a *. ** ** *. *. ** ** ** ** *. *. ** *. *. *. "
+        "*c ^g ^^ ^^ ^h *a *8 *. ** *. *. *. {g {{ ^^ {{ {h ** *. *. ** *. ** ** *. ** ** *. ** *. *. *. "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h ** *. ** *c {{ ^^ ^^ ^^ {{ *2 ** ** ** *. ** *. *. ** *. *. ** *. ** ** "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ *2 *. *c {g {{ {{ ^^ {{ {l *. ** ** *. ** *. ** *. ** ** *. *. ** ** *. "
+        "{{ {{ {C tf {A {{ ^^ ^^ *2 *. {g {{ ^^ {{ {{ {l *3 ** *. *. *. ** *8 *. *. ** *. ** ** *. *8 *c "
+        "%3 -7 %% %5 t7 {{ ^^ ^^ *a *4 {{ ^^ ^^ ^^ {{ *3 ** *. ** *8 *c ^g ^^ ^h *a *. ** *. ** ^g ^^ ^^ "
+        "-b -- -d %% tt {{ ^^ ^^ ^h *e {{ {{ ^^ {{ {l ** ** *c ^g ^^ ^^ ^^ ^^ ^^ ^h *a *. *. *4 ^^ ^^ ^^ "
+        "%% -e %% %c te {{ ^^ ^^ ^^ {{ {{ {{ {{ {{ *3 ** *c ^g ^^ ^^ ^^ {{ ^^ ^^ ^^ ^h *. *. *4 ^^ ^^ ^^ "
+        "%% %% %% tf {B {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ *a *c ^g ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ *a *. *4 ^^ ^^ ^^ "
+        "td %% %% %5 tf {A ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^h *e ^^ ^^ ^^ "
+        "%3 %c ^7 %a %5 t7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "%% ^b ^^ ^d %% tt ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 {1 {1 {1 {5 {{ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "%% %5 ^e %3 %c te ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 tC t3 tt t5 tA {5 ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "-7 %% %% %c tf ^3 ^^ ^^ ^^ ^^ ^^ {{ {3 .. t3 tt tt tt t5 {4 {{ ^^ ^^ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ "
+        "-- -d %% t7 ^3 ^^ ^^ ^^ ^^ ^^ ^^ {{ {a .. tt tt ~7 tt tt {4 {{ {{ ^^ {{ {{ ^^ {{ {{ ^^ ^^ ^^ ^^ "
+        "-e %% %c te ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {2 ta tt ~6 tt tt tA {5 {{ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ "
+        "%% %c t7 {# ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {2 t% tt ~6 ta tt t5 tA {5 {{ {{ {{ ^^ {{ {{ {{ {{ ^^ ^^ "
+        "tt tt tc {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. tt ~a ~9 ~5 ta t5 tA {1 {1 {1 {1 {5 {{ {{ {{ {{ {{ "
+        "/3 .. .. {5 {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 .. tC tt tt t5 ~a ~5 tt tt tt tt tt t5 tA {1 {1 {1 {1 {1 "
+        "/7 .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ {{ {2 .. t3 tt tt tt t5 ~6 te ~3 ~9 ~9 ~5 ta tt tt tt tt tt t5 "
+        "/7 .. .. .. {5 {{ {{ ^^ ^^ ^^ ^^ {{ {2 .. ta tt tt tt tt ~2 ~9 ~c t3 t5 ~2 ~9 ~9 ~9 ~9 ~9 ~5 ta "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "*. *. *. ** ** ** ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "** ** ** ** *. *. *5 ^j ^^ ^^ ^^ ^l *3 *1 *1 *5 ^j ^^ ^^ ^^ ^l *3 *1 *1 *5 ^j ^^ ^^ ^^ ^^ ^c |# "
+        "** ** ** ** ** ** *. *5 ^j ^^ ^l *3 ** ** ** ** *5 ^j ^^ ^l *3 *. ** ** ** *5 ^j ^^ ^^ ^^ || tt "
+        "*. *. *. ** *. *. *. *. *5 ^^ *3 ** *c ^g ^h *a ** *5 ^^ *3 *. *c ^g ^h *a ** *5 ^^ ^^ *b *d tt "
+        "** ** *. *. *. *. *. ** *4 ^^ *2 *. ^g ^^ ^^ ^h *. *4 ^^ *2 *. ^g ^^ ^^ ^h *. *4 ^^ tf .. .. {4 "
+        "*. ** ** *. ** *. ** *. ** ^n ** *4 ^^ ^^ ^^ ^^ *a ** ^n *. *4 ^^ ^^ ^^ ^^ *a *c ^^ {2 .. *f tt "
+        "** *. ** ** ** *. *. ** *. *. *. *c ^^ ^^ ^^ ^^ ^h *a *. *. *c ^^ ^^ ^^ ^^ tt .. ^^ {2 tb tt tt "
+        "*. ** ** *. *. ** ^g ^h *a *8 *c ^g ^^ ^^ ^^ ^^ ^^ ^h *a *c ^g ^^ ^^ ^^ ^^ ^^ {2 {1 {4 ^^ ^5 |A "
+        "*. ** *. *. ** *. ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ tb tt td ^^ ^^ ^^ "
+        "*. ** *. ** ** ** *5 ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "** ** *. *. ** ** *. *5 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "** ** ** *. *. ** ** *c ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ "
+        "*. *. *. *. ** ** ** ^g ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ "
+        "** *. *. *. *. *. *4 ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^L -3 -1 -1 -1 -5 ^J {{ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ "
+        "** *8 *8 *8 *. ** *c ^^ ^^ ^^ ^^ {{ {{ {{ ^L -3 -- -- -8 -- -- -5 {J {{ ^^ ^^ ^^ ^^ ^^ {{ ^^ {{ "
+        "^g ^^ ^^ ^^ ^h *e ^g ^^ ^^ ^^ ^^ ^^ {{ {{ -3 -- -c ^G ^^ ^H -a -- -5 {{ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ -2 -- ^G ^^ ^^ ^^ ^H -- -4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ -2 -4 ^^ ^^ ^^ ^^ ^^ -2 -4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^L -- -4 {5 ^^ {7 ^^ {3 -2 -- ^J ^^ ^^ ^^ ^^ ^^ {{ {{ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {7 ^^ -3 -- -4 .. {1 /7 {1 .. -2 -- -5 ^^ {{ ^^ ^^ ^^ {{ {{ {3 "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {b .. {1 -a __ -c .. .. /7 .. .. -a __ -c {5 {{ {{ ^^ {{ {{ {3 .. "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ /0 /d /d == /d /d /d /9 /e /c /e __ /c /d /2 {A {{ {{ {3 .. .. "
+        "^^ {{ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ /7 t7 -3 __ -- -5 ~A .. ~C -3 -- __ -5 .. /8 /d /e /c /e {8 .. "
+        "^^ {{ {{ ^^ {{ {{ {{ {{ {{ {{ {C /7 tt -2 __ __ -- -- -1 -- -- __ __ -4 .. {c {{ {{ {{ {{ {{ {a "
+        "{{ {{ {{ {{ {{ {3 {1 {1 {1 {1 /0 /a tt -a -- __ __ __ __ __ __ __ -- -c {4 {{ {{ ^^ ^^ {{ {{ {{ "
+        "{{ {{ {{ {3 {1 tC tb tt tt t5 /7 tb tt tH -a -- -- __ __ __ __ -- -c ~# {4 {{ ^^ ^^ ^^ ^^ ^^ {{ "
+        "^^ {{ {{ {2 t3 td ~3 ~9 ~5 tt /8 /2 tt tt tt tH -a -- __ __ -- -- ~B .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        "{{ {{ {3 .. tt ~3 ~c t7 ~6 ta t5 /7 ta tt || tt tM -- __ __ -- -- -- -5 ~A {1 {5 {{ {{ {{ ^^ ^^ "
+        "{{ {3 .. tC tt ~6 t3 tt ~a ~5 tt /7 t% ta tt tt -3 -- __ __ -- __ __ -- -- -5 ~A {1 {5 {{ ^^ ^^ "
+        "{1 .. tC t3 tc ~6 tt tt t5 ~6 tt /8 /2 .. tD tt -2 __ __ __ __ __ __ __ __ -- -- -5 {4 {{ {{ ^^ "
+        "tE t3 tt tc ~3 ~c tt t& tt ~6 ta td /7 tb tt tc -- __ __ __ __ __ __ __ __ __ __ -- ~A {5 {{ ^^ "
+        "tt tc ~3 ~9 ~c t3 tc .. tt ~a ~9 ~9 =| ~9 ~9 ~9 -- -- __ __ __ __ __ __ __ __ __ -- -5 {4 {{ ^^ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "tt tt tt *f ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "tc t& ta tt || ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {7 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        "^3 ^^ ^5 ta tt ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {3 .. {5 {{ {{ ^^ ^^ ^^ ^^ "
+        "^^ .. ^^ tD tt ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {b .. .. .. {d {{ ^^ ^^ ^^ ^^ "
+        "^^ ^~ ^^ tt *f ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a .. {c {{ {{ ^^ ^^ ^^ ^^ "
+        "t5 .. t3 tt || ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {6 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        "tt *f tt |C ^3 ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {6 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {e ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ {{ {{ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ {7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ {{ {{ {{ {{ {3 {1 {1 {1 {1 {1 {1 {1 {1 {1 {1 {1 {1 {5 {{ {{ ^^ {{ /7 {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ {{ {{ {{ {3 {1 .. .. .. .. .. .. .. .. .. .. .. .. .. .. {5 {{ {{ {{ /b {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "{{ {{ {{ {3 .. .. tC t3 tt tt tt tt tt tt tt tt tt tt t5 .. .. {5 {{ {{ {6 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        "{{ {{ {{ {2 .. t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tA .. .. {1 {1 /3 {1 {5 ^^ ^^ ^^ ^^ ^^ "
+        "{{ {{ {3 .. .. tt tt tt || || || || || || || || || tt tt t5 .. .. .. .. /b .. .. {5 ^^ ^^ ^^ ^^ "
+        "{{ {3 .. .. tC tt tt || || || || || || || || || || tt tt tL -3 -1 -5 .. .. /c /d /2 {1 {5 ^^ ^^ "
+        "{3 .. .. tC t3 tt tt || || ~b ~9 ~9 ~9 ~9 ~5 || || || tt -3 -- -- -- ~A .. .. .. /b .. .. {5 ^^ "
+        "{2 .. t3 tt tt tt tt || || || || || || |% ~6 |A || || tt -2 -- -- -- -5 .. .. .. /3 .. .. {4 ^^ "
+        ".. .. tt tt tt || || || || || || || || || ~a ~5 |A || tL -- -- -- -- -- ~A .. .. /b .. .. {4 ^^ "
+        ".. .. tt tt || || || || || || || || || || |% ~a ~5 tL -3 -- -- -- -- -- -- -5 ~A .. .. ~C _3 -- "
+        ".. .. tt tt || || ~b ~9 ~9 ~9 ~9 ~9 ~5 |A || |D -- -- -- -- -- __ -- -- -- -- -- -1 -1 -- -- -- "
+        ".. .. tt tt || || || || || || || |% ~a ~9 ~1 ~9 -8 -- -- -- -- __ __ __ -- -- -- -- -- -- -- -- "
+        ".. .. tt tt tt || || || || || || || || |D ~6 |# || tH -- -- __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{2 .. ta tt tt || || || |C ~3 ~9 ~9 ~9 ~9 ~c || || || -2 -- __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{a .. t% tt tt || || ~b ~9 ~c |# || || || || || || tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ {a .. tt tt || || || || || || || || || || || || -3 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ {{ {2 ta tt tt || || || || || || || tt tt tt tt -2 -- __ -- __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ {2 t% ta tt tt tt tt tt tt tt tt tt tt tt tc -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ {a .. .. t% ta tt tt tt tt tt tt tt tc t# .. -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ ^^ {{ {a {8 {8 {8 .. .. .. .. .. .. {8 {8 {8 {8 -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ {{ {{ {{ {{ {{ {a {8 {8 {8 {8 {c {{ {{ {{ {{ -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "*. ** *. *. ** ** ** ** *. ** *. *. ** *c ^^ ^^ {{ {{ {{ {a t% ta tt tt tt tc t# {# {{ {{ {a /0 "
+        "*. ** ** *. *. ** ** *. *. *. *. *. ^g ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {a {8 {8 {4 {{ {{ ^^ {{ {{ /7 "
+        "** *. *. ** ** ** *. *. ** *. *. *. ^j ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {6 {{ ^^ ^^ ^^ {{ /7 "
+        "*. *. *. ** *. *. *. *. ** ** ** ** *5 ^j ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {6 {{ {{ ^^ {{ {C /7 "
+        "** ** ** ** *. ** *. ** *. *. *. ** ** *5 ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a {5 {{ {{ {C /0 /a "
+        "** ** ** ** *. *. *. ** *. *. *. *. *. *. *5 ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a {9 {9 /0 /a {# "
+        "** ** *. ** ** ** *c .i *a *. ** *. *. *. ** *5 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ /7 {# {{ "
+        "*. *. ** ** *. *. .k .. .m ** *. ** *. *. *. *4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ /7 {{ {{ "
+        "*. *. *. *. ** ** *5 .n *3 *. ** *. ** ** ** *4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ /7 {1 {5 "
+        "** ** ** ** ** *. ** *. ** *. *. ** ** *. ** *c ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {3 /7 .. .. "
+        "** ** ** ** *. ** *. *. *. *. ** ** *. ** *c ^g ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {3 {1 .. /7 .. .. "
+        "*. *. ** *. ** ** *. ** ** ** *. *. ** *c ^g ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {2 .. .. /7 .. .. "
+        "*. ** ** ** *. ** *. *. ** *. ** ** *. ^g ^^ ^^ ^^ ^^ {{ {{ ~7 {{ {{ {{ {{ {3 .. .. .. /7 .. .. "
+        "*. *. ** *. *. ** ** *. *. ** ** *. *4 ^^ ^^ ^^ {{ {{ {{ {{ ~6 {1 t3 tt t5 .. .. .. .. /7 .. .. "
+        "*. ** *. *. *. *. *. *. *. *. *. *. *c ^^ ^^ ^^ {{ {{ {{ {3 ~6 .. te ~7 te .. .. .. .. /7 .. .. "
+        "** *. ** *. *. ** ** ** *. *. *. ** ^g ^^ ^^ ^^ {{ {{ ~b ~9 ~4 .. .. ~6 .. .. .. .. .. /7 .. .. "
+        "*. *. ** *. *. *. *. *. *. ** ** *4 ^^ ^^ ^^ ^^ {{ {{ {{ {2 ~6 .. .. ~6 .. .. .. .. .. /7 .. .. "
+        "** *. ** *. *. *. *. ** *. *. *. *4 ^^ ^^ ^^ ^^ {{ {{ {3 .. ~a ~9 ~9 ~4 .. .. .. .. .. /7 .. .. "
+        "*. *. ** ** ** ** ** *. ** *. ** *4 ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. .. ~6 .. .. .. .. .. /7 .. .. "
+        "*. *. *. *. *. *. *. ** ** *. ** *c ^^ ^^ ^^ ^^ {{ {3 /0 /d /d /d /d == /d /d /d /d /d /7 .. .. "
+        "** ** ** ** *. *. ** *. *. *c ^g ^^ ^^ ^^ ^^ ^^ {{ {2 /7 .. .. .. .. ~6 .. .. .. .. .. /8 /d /d "
+        "*. *. *. *. ** ** *. ** *c ^g ^^ ^^ ^^ ^^ ^^ {{ {{ {2 /7 .. .. .. .. ~a ~9 ~9 ~5 .. .. .. .. .. "
+        "** ** *. ** ** *. ** ** ^g ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a /7 .. t3 td .. .. .. .. ~6 .. .. .. .. ~3 "
+        "*. ** *. ** ** *. *. *4 ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ /7 tC tt ~b ~5 .. .. .. ~6 .. .. .. .. ~6 "
+        "** ** ** *. ** ** ** *4 ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ {{ {{ /7 t3 tt td ~6 .. .. .. ~a ~9 -1 -1 -- -4 "
+        "*. *. ** *. ** ** ** *4 ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ {{ {{ /7 tt ~b ~9 ~8 ~5 .. .. .. ~C -- __ __ -4 "
+        "** *. *. *. *. *. ** *4 ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ {{ /7 ta t5 tA .. ~a ~1 ~9 ~1 -- -- __ __ -4 "
+        "*. ** *. *. ** ** *. *4 ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ /7 t% tt td .. .. ~6 .. -a -- __ __ -- -- "
+        "*. *. *. *. *. ** ** *4 ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {3 /7 tC tt ~b ~5 .. ~6 .. ~% -- -- -- -- -- "
+        "*. ** ** ** ** ** *. *4 ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ {{ {2 /7 t3 tt td ~~ ~9 ~c .. .. -2 -- tG tH ~a "
+        "** *. ** ** ** *. *. *4 ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {2 /7 tt ~b ~9 ~c .. .. .. ~C -- -c tt tt tt "
+        "** *. ** ** ** *. *. *. ^j ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {2 /7 ta td .. .. .. .. .. -3 -- tG tt tt tt "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "/a .. .. {8 .. {5 {{ {{ ^^ ^^ ^^ ^^ {2 .. t% tt tt tt tc ~6 t3 tt tt tt ~6 t3 tt tt tt t5 ~a ~9 "
+        ".. .. {c {{ {a .. {5 {{ {{ ^^ ^^ ^^ {2 .. .. tt ~3 ~9 ~9 ~c tt t# tD tt ~6 tt t# {8 t% ta tt tt "
+        ".. {c {{ {{ {{ {a {c {{ {{ ^^ ^^ ^^ {a .. .. tt ~6 t3 tt tt tc .. t3 tc ~6 tt {4 ^^ {a {8 {8 {8 "
+        "{c {{ {{ {{ {{ {{ {{ {{ {{ {{ ^^ {{ {{ {2 tC tt ~6 tt t# {8 {8 .. tt ~3 ~c tt {4 ^^ ^^ ^^ {{ {{ "
+        "{{ {{ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ {2 t3 tc ~6 tt {4 ^^ {{ {2 tt ~6 t3 tt tA {5 ^^ ^^ ^^ {{ "
+        "{{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {3 tC tt ~3 ~c tt {4 ^^ ^^ {2 tt ~6 ta tt t5 {4 {{ ^^ ^^ ^^ "
+        "{{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {b .. t3 tt ~6 t3 tt {4 {{ ^^ {2 tt ~a ~9 ~5 tt {4 {{ {{ ^^ ^^ "
+        "{{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {2 tt tt ~e tt tt {c {{ {{ {2 ta tt t5 ~e tt {4 {{ {{ ^^ ^^ "
+        "{{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {2 ta tt tt tt tc {{ ^^ ^^ {a {8 t% ta tt tc {4 {{ ^^ ^^ ^^ "
+        "{1 {1 {5 {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {a t% ta tt tc t# {{ ^^ ^^ {{ {{ {a {8 {8 {8 {c ^^ ^^ ^^ ^^ "
+        ".. .. t7 {A {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {a {8 {8 {c ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. tt ~7 t7 {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. te ~6 tt {A {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ {C tf {{ tf {A ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. .. ~6 tt td {5 {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tf t# {1 t% tf {{ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. .. ~6 tt ~3 ~9 ~9 ~9 ~9 ~d ^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. {4 {{ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. .. ~6 te ~6 t7 {# {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ tf tA /3 tC tf {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. .. ~a ~9 ~4 te {5 {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {% tf /7 tf {# ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {7 {{ "
+        ".. .. .. .. .. ~~ ~9 ~9 ~5 tb td {A ^^ ^^ ^^ ^^ ^^ ^^ {% /7 {# ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 .. {5 "
+        ".. ~3 ~9 ~9 ~9 ~c t3 t5 ~a ~1 ~d tf {{ ^^ ^^ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {b .. .. .. "
+        ".. ~6 .. .. .. .. ta tt td ~6 tf {# {3 {1 tf ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {a .. {c "
+        "/d == /d /d /2 .. .. .. .. == .. {1 {8 {c {{ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {e {{ "
+        ".. ~6 .. .. /7 .. .. {8 tf ~6 tb td {A {{ {{ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "~9 ~c .. .. /7 .. {4 {{ {% ~a ~9 ~5 tf {{ ^^ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. .. .. /7 .. {4 {{ ^^ ^^ ^5 ~a ~d ^^ ^^ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        ".. .. .. .. /7 .. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ /7 ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ {{ "
+        ".. .. .. .. /7 .. .. {1 {5 {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {C /7 {A {{ {{ {C t7 {A {{ {{ ^^ ^^ ^^ {{ "
+        ".. .. .. .. /8 /d /d /d /d /2 {{ ^^ ^^ ^^ ^^ {{ t3 tt t5 /7 t3 tt tt tt tt tt tt t5 {{ ^^ {{ {C "
+        "~A .. .. .. .. .. .. {c {% /7 {{ ^^ ^^ {{ {{ {{ ta tt tc /7 ta tt tt tt tt tt tt tc {A {{ {C tf "
+        "~5 ~A .. .. .. .. {c {{ {{ /7 {A ^^ ^^ ^^ {{ {3 .. /0 /d /9 /d /d /d /d /d /d /d /d /d /d /d /d "
+        "-- -- ~5 ~A .. {4 {{ {{ {{ /8 /d {{ ^^ {{ /d /d /d /a .. .. .. .. t3 tt tt tt tt tt tt tt tt tt "
+        "tH ~a -- ~~ ~9 ~9 ~9 ~9 ~5 {A {{ ^^ ^^ ^^ {{ {a .. .. .. .. .. .. ta tt tt tt tt tt tt || || tt "
+        "tt tH ~~ -c {# {{ {{ {% ~a ~5 {{ {{ ^^ ^^ {{ {{ {2 .. .. .. .. .. .. t% tt tt tt tt || || || || "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "~9 ~9 ~c t3 tt tc t# .. ta tt tt td /7 tb tt tt tH -- __ __ -- -- -- -- __ __ __ -- -4 {4 {{ ^^ "
+        "tt tt tt tc t# {8 {8 .. .. .. .. .. /7 .. .. .. .. -a -8 -8 -c ~# ~% -- __ __ __ __ -4 {4 {{ {{ "
+        "{8 {8 {8 {8 {c {{ {{ {a {8 .. /0 /d /a {8 .. .. .. .. {8 {8 {8 {8 {8 -a -- __ __ __ -- ~A {5 {{ "
+        "{{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {a /7 {# {{ {{ {a {8 {8 {c {{ {{ {{ {{ {{ {H -- __ __ __ -- -- -1 -1 "
+        "{{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ /7 {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ -2 __ __ __ __ __ __ __ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ /7 {{ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ -2 __ __ __ __ __ __ __ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ /7 ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ -a -- __ __ __ __ __ __ "
+        "^c |# || |% ^a ^^ ^^ ^^ ^^ ^^ /8 /2 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^H -a -8 -- -- __ __ __ "
+        "|# || || || |% ^a ^^ ^^ ^^ ^^ ^d /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c tf ^a ^^ ^^ ^^ ^H -a -- __ __ "
+        "|| || || || || t5 ^a ^^ ^^ ^^ /0 /a ^^ ^^ ^^ ^c |& ^a ^^ tb tt td /7 t7 ^^ ^^ ^^ ^^ ^H -- -- __ "
+        "|A || || || || tt t5 ^a ^^ ^c /7 ^3 ^^ ^^ ^^ |# || |% ^e /0 /d /d /a te ^^ ^^ ^^ ^^ ^^ -2 -- __ "
+        "^5 |A || |C ^7 ta tt tt tt t5 /7 ^^ ^^ ^^ ^c || || || t5 /7 tb tt td ^3 ^^ ^^ ^^ ^^ ^^ -2 -- __ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^5 ta tt tc /7 ^a ^^ ^^ t3 tt || tt tt /7 ^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^L -- -- __ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^5 /0 /d /9 /2 ^a ^c ta tt tt tt tc /7 ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ -b -- -- -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ /7 t3 t5 /8 /d /d /d /d /d /d /d /a t7 ^a ^^ ^^ ^^ ^^ ^^ ^^ ~% -a -- -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ /7 tt tt tt tt tt tt tt tt tt tt tt tt t5 ^a ^^ ^^ ^^ ^^ ^^ {2 .. ~% -- "
+        "^^ ^^ ^^ ^^ ^^ {{ {{ {C /7 tt || || || || || tt tt tt || || || tt tt t5 ^^ ^^ ^^ ^^ {a .. .. -a "
+        "{{ {{ {{ {{ ^^ {{ /0 /d /a tt || || || || || tt tt tt tt || || || tt tt ^^ ^^ ^^ ^^ ^^ {a .. ~% "
+        "{9 {9 {5 {{ {{ {C /7 t3 tt tt || || || || || || tt tt || || || || || tt ^^ ^^ ^^ ^^ ^^ ^^ {a {8 "
+        "{{ {{ {a {5 {C tf /7 tt || || || || || || || tt tt tt || || || || || tt ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ {{ {{ /0 /d /d /a tt || || || || || || || || tt tt || || || || || tt t5 ^^ ^^ ^^ ^^ ^^ ^^ ^c "
+        "^^ ^^ {{ /7 t3 tt tt || || || || || || || || || tt tt tt || || || tt tt tt ^a ^^ ^^ ^^ ^^ ^^ t3 "
+        "^^ {{ {C /7 tt || || || || || || || || || || || || tt tt || || || tt tt tt || |% ^a ^^ ^^ ^c tt "
+        "{{ {C t7 /7 tt || || || || || || tt || || || || || tt tt tt || || || tt || || || || || || tt tt "
+        "{C tb tc /7 tt || || || || tt tt tt || || || || || || tt tt || || || || || || || || || || tt tt "
+        "/0 /d /d /a tt || || || tt tt tt tt tt || || || || || tt tt tt || || || || || |C ^7 |A || tt tt "
+        "/7 t3 tt tt tt tt || || tt tt || tt tt tt || tt tt tt tt tt || || || || || || ^b ^^ ^5 tt tt tt "
+        "/7 tt tt tt tt tt tt tt tt tt || || tt tt || tt || tt tt tt || || || || || || |% ^^ ^^ ta tt tt "
+        "/a tt tt tt tt tt tt tt tt || || || tt tt tt tt tt tt tt || || || || || || || tt ^^ ^^ ^5 ta tt "
+        "tt tt tt tt tt tt tt || || || || || || tt tt || || || || || || || || || || || tc ^^ ^^ ^^ ^5 ta "
+        "|| || tt tt tt || || || || || || || || || || || || || || || || || || || || tt ^3 ^^ ^^ ^^ ^^ ^d "
+        "|| || || tt tt || || || || || || || || || || || || || || || || || || || || tc ^^ ^^ ^^ ^^ ^^ t3 "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {L -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ ^^ ^^ ^^ -7 {J {{ {{ {{ {{ {{ {{ {{ {{ {C ~C -3 -- __ __ __ __ __ __ __ __ __ ~~ ~~ ~~ __ __ "
+        "^^ ^^ ^^ ^^ -2 -- _1 _1 _1 _1 _1 -1 -1 -1 -1 -- -- -- __ __ __ __ __ __ __ __ ~~ -- -- -- ~~ __ "
+        "-1 -5 ^J ^L -- -- __ __ __ __ __ __ __ -- -- -- -- __ __ __ __ __ __ __ ~~ -- -- -c ^I -a -- __ "
+        "-- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ ~~ -- -- ^K ^^ ^M -- __ "
+        "-- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -- -- -- -5 ^N -3 -- __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- -- __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- ~~ ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -- -- -8 -8 -- -- -- -- -- -- -- -- __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c {G {{ {{ ^H -a -- -- -- -- -- -- __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- {G {{ ^^ ^^ ^^ ^M -- -c ^I -a -- -- __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ ^^ ^^ ^^ ^^ ~3 -- ^K ^^ ^M -- __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ {{ ^^ ^^ ^^ ~a -- -5 ^N -3 -- -- __ -- "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -4 {{ {{ ^^ ^^ ^^ ^H ~a -- -- -- -- -- -- -- "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ -- -- -- ^I -a -- "
+        "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -- {G {{ ^^ !3 !5 {{ !3 !5 ^^ -a -- -4 ^^ ^M -- "
+        "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c {{ ^^ ^^ !a !! =! !! !c ^^ ^H -a -c ^^ -3 -- "
+        "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- {G {{ ^^ ^^ ^^ !e {{ !e ^^ ^^ ^^ {{ {{ ^^ -2 __ "
+        "-2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ {{ ^^ -2 __ "
+        "-2 -- -- __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ ^^ _2 __ "
+        "-a -- -- -- -- __ __ __ __ __ __ __ __ __ __ -- {J {{ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^L __ __ "
+        "tH -a -- -- -- -- __ __ __ __ __ __ __ __ __ -- -5 {{ ^^ ^^ ^^ {{ ^^ ^^ {{ {{ {{ ^^ ^L _3 __ __ "
+        "tt tt tH -a -- -- __ __ __ __ __ __ __ __ __ __ -- {J {{ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^L _3 __ __ __ "
+        "tt tt tt tH -- -- __ __ __ __ __ __ __ __ __ __ -- -- -5 ^J ^^ ^^ ^^ ^^ ^^ ^^ ^^ _3 __ __ __ __ "
+        "tt tt tt tt -2 -- __ __ __ __ __ __ __ __ __ __ __ __ -- -- -5 ^J ^L -3 -5 ^J ^L __ __ __ __ __ "
+        "tt tt tt tt -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- __ __ __ __ __ __ "
+        "tt tt tt tt -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tt tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tt -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tL -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ -- -c ^I -a -- __ __ __ __ __ __ __ __ __ "
+        "tt tt -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- ^K ^^ ^M -- __ __ __ __ __ __ __ __ __ "
+        "tt tt -2 -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ -- -5 ^N -3 -- __ __ __ __ __ __ __ __ __ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "*. ** *. ** *. *. ** ** *. *5 ^^ ^^ ^^ ^^ ^^ {{ {3 .. /7 .. .. .. .. .. .. ~C -- -- tJ tt tt tt "
+        "** *. ** ** *. ** ** ** ** *4 ^^ ^^ ^^ {{ {{ {3 .. .. /7 .. .. .. .. .. ~C ~3 -- -- -5 tJ tt tt "
+        "** ** ** ** ** ** ** ** *. *c ^^ ^^ {{ {{ /0 /d /d /d /9 /d /d /2 .. .. -3 -- -- __ -- -5 tt tt "
+        "*. ** ** *. ** *. ** ** *c ^g ^^ ^^ {{ {3 /7 {c {{ {{ {{ {{ {a /7 .. .. -2 -- __ __ __ -4 tt tt "
+        "** *. *. *. ** *. ** *c ^g ^^ ^^ ^^ {{ {2 /7 {{ {{ ^^ ^^ {{ {{ /7 .. ~C -- -- -- __ -- -c tt tt "
+        "*. *. *. *. *. *. *c ^g ^^ ^^ ^^ ^^ {{ {2 /7 {{ ^^ ^^ ^^ ^^ {{ /7 .. -3 -- -- -- -- -c tG tt tt "
+        "*. ** *. ** *. *c {g {{ ^^ ^^ ^^ ^^ {{ {2 /7 {{ ^^ ^^ ^^ ^^ {{ /7 .. -2 -- -- -c tG tt tt tt tt "
+        "** *8 *8 *c {g {{ {{ ^^ ^^ ^^ ^^ ^^ {{ {2 /7 {{ {{ ^^ ^^ {{ {C /7 .. -2 -- -- tG tt tt tt tt tt "
+        "^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {3 .. /7 {5 {{ {{ {{ {C /0 /a ~C -- -- -- tJ tt tt {# {{ {{ "
+        "^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ {{ {3 /0 /d /9 /d /d /d /d /d /a ~C -3 -- -- -- -5 tJ tc {{ ^^ ^^ "
+        "^^ ^^ ^^ {{ {{ ^^ ^^ ^^ {{ {{ {3 .. /7 .. .. .. .. .. .. .. .. -3 -- -- -- ~~ -- -- -5 ^^ ^^ ^^ "
+        "^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {3 .. .. /7 .. .. .. .. .. .. .. ~C -- ~~ -- -- -- -- -- -c ^^ ^^ ^^ "
+        "^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {2 .. .. /7 .. ~C _3 _1 _5 ~A ~C ~3 ~~ -- -- -- -- -- -- ^K ^^ ^^ ^^ "
+        "^^ ^^ {{ {{ {{ ^^ ^^ ^^ {3 .. .. .. /7 ~C _3 __ __ __ __ __ __ __ __ -- -- -- -- -- -5 ^^ ^^ ^^ "
+        "^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ {2 .. .. .. .. _3 __ __ __ __ __ __ __ __ __ __ -- __ __ __ -- ^J ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ {{ {{ {{ {2 .. .. .. .. _a __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 ^^ ^^ "
+        "^^ ^^ ^^ ^^ {{ {L ~3 ~1 ~5 ~A .. .. .. ~% _a __ __ __ _c ~& _a __ __ __ __ __ __ __ __ -- ^J ^L "
+        "^^ ^^ ^^ {{ {L ~3 ~~ ~~ ~~ ~~ ~5 .. .. .. ~% _a _8 _c ~# .. ~% -- __ __ __ __ __ __ __ -- -- -- "
+        "^^ ^^ ^^ {{ ~3 ~~ -- ~~ ~~ ~~ ~~ ~A .. .. .. .. .. .. .. .. ~C -- __ __ __ __ __ __ __ __ __ __ "
+        "^^ ^^ ^^ {{ ~2 -- -- -- -- -- ~~ ~5 ~A .. .. .. .. .. .. ~C -3 -- -- -- -- __ __ __ __ __ __ __ "
+        "^^ ^^ ^^ {{ ~2 -- -- -- -- -- ~~ ~~ ~~ ~5 ~A .. .. ~C -3 -- -- ~~ ~~ ~~ -- -- __ __ __ __ __ __ "
+        "^^ ^^ ^^ {{ ~a ~~ -- -- -- -- ~~ ~~ ~~ ~~ ~~ -1 -1 -- -- -- ~~ ~c ~& ~a ~~ -- __ __ __ __ __ __ "
+        "^^ ^^ ^^ {{ {H ~a ~~ -- -- ~~ ~c ~& ~a ~~ ~~ ~~ ~~ ~~ ~~ -- ~~ ~B .. ~D ~~ -- __ -- -- -- -8 -- "
+        "^^ ^^ ^^ ^^ {{ {H ~a ~~ ~~ ~~ ~B .. ~D ~~ -- -- -- -- -- -- ~~ ~5 ~E ~3 ~~ -- -- -- -c {G {{ {H "
+        "^^ ^^ ^^ ^^ ^^ {{ {{ {H ~~ ~~ ~5 ~E ~3 ~~ -- -- -- -- -- -- -- ~~ ~~ ~~ -- -- -c {G {{ {{ ^^ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ~a ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- -- -- -- -- -- ~~ {G {{ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {H ~a ~~ -- -- -- -- ~~ ~~ ~8 ~8 ~8 ~8 ~~ ~~ ~~ ~~ ~c {{ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {H ~a ~8 ~8 ~8 ~8 ~c {G {{ {{ {{ {{ {H ~a ~c {G {{ {{ ^^ ^^ ^^ ^^ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {L "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -b -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {H -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "tt tt ~6 {# {{ ^^ {{ {{ {% ~6 {A {{ {{ ^^ ^^ {{ tb tt td .. .. .. .. .. tt tt tt || || || || || "
+        "tt tt ~6 {{ ^^ ^^ ^^ ^^ {{ ~a ~d {{ ^^ ^^ ^^ {{ {{ {{ {{ {a {8 {8 .. tC tt || || || || || || || "
+        "tt tt ~6 {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ tb tt tt tt || || tt tt tt || "
+        "tt tt ~6 {A {{ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {% ta tt tt tt tt tt tt tt "
+        "tt tt ~a ~5 {A {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {% tt tt || tt tt tt || "
+        "tt tt t5 ~a ~9 ~9 ~d {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ {{ tt tt || || || || || "
+        "tt tt tt tt tt tt td {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {L ~7 {J {{ ^^ ^^ ^^ {{ tt tt tt tt tt tt tt "
+        "tt tt tt tt tc {# {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ~b -- ~d {{ ^^ ^^ ^^ {{ te {# {{ {{ {{ {% ta "
+        "{{ {% te {# {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {% ~6 {# {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+        "^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~6 ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c ~6 ^^ ^^ ^^ {{ {C ~7 {J {{ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~3 ~c ^^ ~3 ~9 ~9 ~9 -- ~d {{ ^^ ^^ ^^ ^^ ^^ "
+        "{{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c ~6 ^b ^c ~6 ^3 {{ {% ~e {G {{ ^^ ^^ {{ {{ {{ "
+        "{{ ^^ {{ {{ {{ {{ {{ {7 {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ~3 ~8 ~9 ~9 ~4 ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ {C "
+        "{{ {{ {{ {{ {{ {{ {3 .. {5 {{ {{ ^^ ^^ ^^ ^^ ^c ~6 ^3 ^^ ^5 ~6 ^a ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ t3 "
+        "{L -3 -5 {J {{ {3 .. .. .. {5 {{ ^^ ^^ ^^ ^c ~3 ~c ^^ ^^ ^^ ~a ~9 ~d ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ta "
+        "-3 -- -- -- -5 ~A .. .. .. {4 {{ {{ ^^ ^L -3 ~~ ^J ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {3 .. "
+        "-- __ __ __ -- -5 ~A .. ~C -3 -1 -1 -1 -- -- -- -5 ^J ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {2 .. "
+        "__ __ __ __ __ -- -- -1 -- -- __ __ __ __ __ __ -- -- -5 ^J ^^ ^L -3 -1 -5 {J {{ {{ {{ {3 .. .. "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -1 -- -- __ -- -- _5 {J {{ {2 .. .. "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _1 _1 _5 ~A "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _5 "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-a -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{H -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{L -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "|| || || || tt || || || || || || || || || || || || || || || || || || || ^3 ^^ ^^ ^^ ^^ ^^ ^^ tt "
+        "|| || || || tt tt || || || || tt || || || || || || || || || || || || || ^a ^^ ^^ ^^ ^^ ^^ ^^ tt "
+        "tt tt tt || || tt || || tt tt tt || || || || || || || || || || || || || |% ^^ ^^ ^^ ^^ ^^ ^^ tt "
+        "tt || tt || || tt tt tt tt || tt tt || || || || || || tt tt || || || || |C ^^ ^^ ^^ ^^ ^^ ^^ tt "
+        "|| || tt tt tt tt tt || || || || tt || || || || || || tt tt tt || || || ^b ^^ ^^ ^^ ^^ ^^ ^c tt "
+        "|| || || tt tt || || || || || tt tt || || || || || tt tt || tt tt tt tt t5 ^a ^^ ^^ ^^ ^c t3 tt "
+        "|| || tt tt || || || || tt tt tt tt tc {# {{ {{ {% tt || || || tt tt tt tt t5 ^a ^^ ^c t3 tt tt "
+        "tt tt tt tt || || tt tt tt tc {# {{ {{ {{ ^^ ^^ {{ tt tt || tt tt tt tt tt tt t5 ^e t3 tt tt tL "
+        "{% ta tt || || || tt {# {{ {{ {{ ^^ ^^ ^^ ^^ ^^ {{ tt ~b ~9 ~9 ~9 ~9 ~5 tt tt tt tt tt tt tt -3 "
+        "{{ {% tt tt || tt tc {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ta tt tt tt tt t5 ~6 tt tt tt tt tt tt tL -- "
+        "{{ {C tt tt tt tt {# {{ {{ ^^ ^^ ^^ ^^ ^^ {{ {{ tf {{ {{ {% ta tt tt ~6 ta tt tL -3 -1 -1 -- -- "
+        "{{ t3 tt tt tt tc {{ {{ {{ {{ {{ {{ {{ ^^ ^^ {{ {{ ^^ ^^ {{ {% tt tt ~a ~1 ~9 ~~ ~~ -- -- -- -- "
+        "{C tt tt tt t# .. {5 {{ {{ tb tt t5 {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tt tt t5 ~6 t7 -a -- -- -- -- -- "
+        "t3 tt tt tc .. .. .. {1 {1 .. t% te {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ ta tt tt ~6 tt tM -- -- -- -- -8 "
+        "tt t# .. .. .. .. .. .. .. .. .. .. {5 {{ {{ {{ ^^ ^^ ^^ ^^ {{ {% ta tc ~6 tL -3 -- -- -c tG tt "
+        "tc .. .. .. .. .. .. .. .. .. ~C -3 -5 ~A {5 {{ {{ ^^ ^^ ^^ ^^ {{ {{ {% ~2 -- -- -- tG tt tt tt "
+        ".. .. .. .. .. .. .. .. -b -1 -- -- -- -5 ~A {5 {{ ^^ ^^ ^^ ^^ ^^ {{ {{ -2 -- -- -- tJ tt tt tt "
+        ".. .. .. .. .. .. .. .. ~% -- -- -- -- -- -5 ~A {{ ^^ ^^ ^^ ^^ {{ {{ {L -- -- -- -- -5 tJ tt tt "
+        ".. .. .. .. .. .. .. .. ~C -- -- __ __ -- -- -5 {{ ^^ ^^ ^^ ^^ {{ {L -3 -- ~~ -- -- -- -5 tJ tL "
+        ".. .. .. .. .. .. .. ~C -3 -- -- __ __ -- -- -- {J {{ {{ ^^ {{ -3 -- -- -- ~~ -- -- ~~ -- -- -- "
+        ".. .. .. .. .. ~C -3 -- -- -- -- __ __ __ -- -- -- -5 {{ ^^ {{ -2 -- -- ~~ ~~ ~~ __ -- ~~ -- -- "
+        "~A .. .. ~C -3 -- -- -- -- -- __ __ __ __ __ -- -- -- {J {{ {L -- -- __ __ ~~ __ __ __ __ ~~ ~~ "
+        "__ _1 _1 -- -- -- -- -- __ __ __ __ __ __ __ __ -- -- -- -1 -- -- -- __ __ __ __ __ __ __ __ __ "
+        "__ __ __ -- -- -- __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      (list
+        "tt tt -a -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tt tH -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tt tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tt -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tt -2 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tt tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt tL -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-3 -- -- -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- -- -- ~~ ~~ ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -c tI -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- tG tt -2 -- -- -8 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- tJ tL -- -c tG tt tH -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- -- -- tG tt tt tt -2 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- -- -4 tt tt tt tL -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tH -- -- -- tJ tt tL -3 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "tt -2 ~~ -- -- -1 -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- __ __ __ __ __ __ __ __ "
+        "tL -- -- ~~ ~~ ~~ ~~ ~~ -- __ __ __ __ __ __ __ __ __ __ __ -- -c ~& -a -- __ __ __ __ __ __ __ "
+        "-3 -- ~~ -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c ~# .. ~% -- __ __ __ __ __ __ __ "
+        "-- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c ~# tC t7 .. -2 __ __ __ __ __ __ __ "
+        "-- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~# tC t3 tt .. -a -- __ __ __ __ __ __ "
+        "~~ -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c tC t3 |. tt tA ~% -a -- __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~# t3 |. |. |. tt td .. ~D ~~ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -4 .. tt |. |. |. tc t# ~C -3 -- ~~ ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~A ta |. |. tc t# -3 -- -- -- -- ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 t% tt |. t# -3 -- __ __ -- -- ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~A ta tc {8 -2 -- __ __ -- -- ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 {# {{ {{ -a -- -- -- -- -- ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- {J ^^ ^^ {H -a -8 -c {G {M ~~ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 {J {{ ^^ {{ {{ {{ {L -3 -- __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 {J ^^ ^^ ^^ {L -3 -- __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -5 {J {L -3 -- __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- __ __ __ __ __ "
+      )
+    )
+  )
+  #f #f #t #f
+  ;; subplaces
+  (list
+    (list
+      p_moongate_clearing
+    51 46) ;; coords of p_moongate_clearing
+    (list
+      p_gregors_hut
+    61 67) ;; coords of p_gregors_hut
+    (list
+      p_abandoned_farm
+    43 51) ;; coords of p_abandoned_farm
+    (list
+      p_trigrave
+    29 51) ;; coords of p_trigrave
+    (list
+      p_enchanters_tower
+    29 21) ;; coords of p_enchanters_tower
+    (list
+      p_green_tower
+    80 59) ;; coords of p_green_tower
+    (list
+      p_bole
+    86 40) ;; coords of p_bole
+    (list
+      p_glasdrin
+    82 18) ;; coords of p_glasdrin
+    (list
+      p_oparine
+    12 78) ;; coords of p_oparine
+    (list
+      p_absalot
+    120 4) ;; coords of p_absalot
+    (list
+      p_mans_hideout
+    92 10) ;; coords of p_mans_hideout
+    (list
+      p_engineers_hut
+    50 4) ;; coords of p_engineers_hut
+    (list
+      p_void_temple
+    7 39) ;; coords of p_void_temple
+    (list
+      p_poor_house
+    19 65) ;; coords of p_poor_house
+    (list
+      p_ankh_shrine
+    97 4) ;; coords of p_ankh_shrine
+    (list
+      p_westpass
+    45 61) ;; coords of p_westpass
+    (list
+      p_eastpass
+    43 61) ;; coords of p_eastpass
+    (list
+      p_ancient_derelict
+    43 17) ;; coords of p_ancient_derelict
+    (list
+      p_gate_to_absalot
+    120 10) ;; coords of p_gate_to_absalot
+    (list
+      p_tower_of_absalot
+    120 8) ;; coords of p_tower_of_absalot
+    (list
+      p_kun
+    60 38) ;; coords of p_kun
+  ) ; end of subplaces
+  nil ;; neighbors
+  (list ;; objects in p_shard
+    (list
+      (kern-tag 'mg-4
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    21 19)
+    (list
+      (kern-tag 'mg-5
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #t
+            '()
+            #t
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    56 27)
+    (list
+      (kern-tag 'mg-6
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    90 26)
+    (list
+      (kern-tag 'mg-7
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    125 18)
+    (list
+      (kern-tag 'mg-8
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    50 7)
+    (list
+      (kern-mk-obj t_edge_spawn 1
+        ;; hooks
+        (list
+        )
+      )
+    0 0)
+    (list
+      (bind
+        (kern-mk-obj t_dungeon 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_kurpolis_entrance
+          9
+          10
+        )
+      ) ;; bind
+    53 18)
+    (list
+      (bind
+        (kern-mk-obj t_dungeon 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_mushroom_cave
+          7
+          12
+        )
+      ) ;; bind
+    78 74)
+    (list
+      (bind
+        (kern-mk-obj t_dungeon 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_lost_halls_1
+          2
+          2
+        )
+      ) ;; bind
+    39 75)
+    (list
+      (bind
+        (kern-mk-obj t_dungeon 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_necromancers_lair
+          9
+          9
+        )
+      ) ;; bind
+    40 70)
+    (list
+      (bind
+        (kern-mk-obj t_dungeon 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_smoldering_cave
+          9
+          9
+        )
+      ) ;; bind
+    118 46)
+    (list
+      (bind
+        (kern-mk-obj t_dungeon 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'p_slimy_cavern
+          8
+          30
+        )
+      ) ;; bind
+    13 8)
+    (list
+      (bind
+        (kern-mk-obj t_raise_listener 1
+          ;; hooks
+          (list
+          )
+        )
+        (list
+          'raise-merciful-death
+          '()
+        )
+      ) ;; bind
+    121 87)
+    (list
+      (bind
+        (kern-mk-obj t_step_trig 1
+          ;; hooks
+          (list
+            (list
+              ef_permanent_invisibility
+              '()
+              2
+              0
+            )
+          )
+        )
+        (list
+          'mk-angriss-lair
+          '()
+        )
+      ) ;; bind
+    89 70)
+    (list
+      (kern-tag 'mg-1
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    62 50)
+    (list
+      (kern-tag 'mg-2
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    34 56)
+    (list
+      (kern-tag 'mg-3
+        (bind
+          (kern-mk-obj t_moongate 1
+            ;; hooks
+            (list
+            )
+          )
+          (list
+            'ord
+            #f
+            '()
+            #f
+            #f
+            10
+          )
+        ) ;; bind
+      ) ;; kern-tag
+    19 82)
+  ) ;; end of objects in p_shard
+  nil ;; on-entry-hook
+  (list ;; edge entrances
+    (list 0 127 95) ;; Northwest
+    (list 1 64 95) ;; North
+    (list 2 0 95) ;; Northeast
+    (list 3 127 48) ;; West
+    (list 4 64 48) ;; Here
+    (list 5 0 48) ;; East
+    (list 6 127 0) ;; Southwest
+    (list 7 64 0) ;; South
+    (list 8 0 0) ;; SoutheastUp
+  )
+) ;; end of place p_shard
+
+(kern-mk-player
+  'player
+  s_wanderer
+  "Walk"
+  sound-walking
+  22 71
+  651 ;; turns to next meal
+  nil
+  m_campsite
+  nil
+  nil ; player's vehicle
+  (kern-mk-container
+    nil
+    ;; trap
+    nil
+    ;; contents
+    (list
+      (list 5 sulphorous_ash)
+      (list 5 ginseng)
+      (list 5 garlic)
+      (list 6 spider_silk)
+      (list 3 blood_moss)
+      (list 3 black_pearl)
+      (list 1 nightshade)
+      (list 1 mandrake)
+      (list 1 t_heal_potion)
+      (list 1 t_cure_potion)
+      (list 1 t_mana_potion)
+      (list 4 t_torch)
+      (list 4 t_picklock)
+      (list 1 t_manual)
+      (list 1 t_letter_from_enchanter)
+      (list 3 t_arrow)
+    )
+    ;; hooks
+    (list
+    )
+  )
+  (list
+    ch_wanderer
+    ch_amy
+  )
+)
+;;--------------
+;; Miscellaneous
+;;--------------
+(kern-set-damage-sprite s_hit)
+(kern-set-crosshair t_crosshair)
+(kern-set-clock 0 0 0 0 21 23)
+(kern-set-time-accel 1)
+(kern-mk-dtable
+  (list    2    0   -1   -1   -1   -2   -2   -2    0   -2   -2    0 )
+  (list    0    2    2   -2   -2   -2   -2   -2   -2   -2   -2   -2 )
+  (list   -1    2    2   -2   -1   -2   -2   -2   -2   -2   -2   -2 )
+  (list   -1   -2   -2    2   -1   -2    0   -2   -2   -1   -2   -2 )
+  (list   -1   -2   -1   -1    2   -2   -1   -1   -2   -1   -2   -2 )
+  (list   -2   -2   -2   -2   -2    2   -1    0   -2    0   -2    0 )
+  (list   -2   -2   -2    0   -1   -1    2   -2   -2   -1   -2   -2 )
+  (list   -2   -2   -2   -2   -1    0   -2    2   -2   -1   -2    0 )
+  (list    0   -2   -2   -2   -2   -2   -2   -2    2   -2   -2   -1 )
+  (list   -2   -2   -2   -1   -1    0   -1   -1   -2    2   -2   -1 )
+  (list   -2   -2   -2   -2   -2   -2   -2   -2   -2   -2    2   -2 )
+  (list    0   -2   -2   -2   -2    0   -2    0   -1   -1   -2    2 )
+)
+;; ---------
+;; Astronomy
+;; ---------
+(kern-mk-astral-body
+  'sun ; tag
+  "Fyer (the sun)"     ; name
+  1    ; distance
+  1    ; minutes_per_phase
+  4    ; minutes_per_degress
+  0    ; initial_arc
+  0    ; initial_phase
+  nil  ; gifc
+  (list
+    (list s_sun 255 "full")
+  )
+)
+(bind-astral-body
+  (kern-mk-astral-body
+    'lumis     ; tag
+    "Lumis"    ; name
+    0  ; distance
+    300        ; minutes_per_phase
+    10 ; minutes_per_degress
+    22 ; initial_arc
+    0  ; initial_phase
+    'source-moon-ifc
+    (list
+      (list s_new_moon 0 "new")
+      (list s_wax_quarter_moon 32 "1/4 waxing")
+      (list s_wax_half_moon 64 "1/2 waxing")
+      (list s_wax_three_quarter_moon 96 "3/4 waxing")
+      (list s_full_moon 128 "full")
+      (list s_wane_three_quarter_moon 96 "3/4 waning")
+      (list s_wane_half_moon 64 "1/2 waning")
+      (list s_wane_quarter_moon 32 "1/4 waning")
+    )
+  )
+  (list
+    'mg-1
+    'mg-2
+    'mg-3
+    'mg-4
+    'mg-5
+    'mg-6
+    'mg-7
+    'mg-8
+  )
+) ;; bind-astral-body
+(bind-astral-body
+  (kern-mk-astral-body
+    'ord       ; tag
+    "Ord"      ; name
+    0  ; distance
+    540        ; minutes_per_phase
+    6  ; minutes_per_degress
+    67 ; initial_arc
+    7  ; initial_phase
+    nil        ; gifc
+    (list
+      (list s_new_moon 0 "new")
+      (list s_wax_quarter_moon 32 "1/4 waxing")
+      (list s_wax_half_moon 64 "1/2 waxing")
+      (list s_wax_three_quarter_moon 96 "3/4 waxing")
+      (list s_full_moon 128 "full")
+      (list s_wane_three_quarter_moon 96 "3/4 waning")
+      (list s_wane_half_moon 64 "1/2 waning")
+      (list s_wane_quarter_moon 32 "1/4 waning")
+    )
+  )
+  (list
+    'mg-1
+    'mg-2
+    'mg-3
+    'mg-4
+    'mg-5
+    'mg-6
+    'mg-7
+    'mg-8
+  )
+) ;; bind-astral-body
+(kern-set-wind 2 0)
+(kern-add-reveal 0)
+(kern-add-quicken 0)
+(kern-add-time-stop 0)
+(kern-add-magic-negated 0)
+(kern-add-xray-vision 0)
diff --git a/worlds/haxima-1.002/bandit-hideout.scm b/worlds/haxima-1.002/bandit-hideout.scm
new file mode 100644 (file)
index 0000000..798a28d
--- /dev/null
@@ -0,0 +1,190 @@
+(kern-load "nate.scm")
+
+(mk-19x19-town
+ 'p_bandit_hideout_l1 "Bandit Stockade" s_ruin
+ (list
+               "tt tt tt tt t5 t3 tt tt tt tt tt tt tt tt tc rr rr rr rr "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tc rr rr rr ~7 rr rr "
+               "tt bb rr bb bb rr rr bb bb bb rr rr rr rr bb ~b __ ~d rr "
+               "tt rr .. dd dd dd .. .. .. .. t7 rr rr bb ee ee ~e rr rr "
+               "tt bb dd dd && dd dd dd dd .. ta t5 %b %% ee %c bb rr bb "
+               "tc bb bb dd dd dd dd .. dd dd .. tt tt %a ee bb rr rr t3 "
+               ".. .. bb bb bb .. dd .. .. dd dd dd dd .. dd rr bb tb tt "
+               ".. .. .. .. rr dd dd xx xx w+ xx xx dd dd dd .. bb bb .. "
+               "dd .. .. .. rr dd .. rr ,, ,, dd rr .. dd .. && bb bb dd "
+               "dd dd .. dd .. dd .. ,, dd dd cc w+ cc dd dd .. bb dd dd "
+               ".. dd dd dd rr dd .. xx dd dd ,, xx .. .. bb bb rr bb dd "
+               ".. .. dd .. bb dd .. xx rr ,, xx xx bb bb bb dd rr bb .. "
+               "t5 rr bb rr bb dd dd .. .. dd .. bb dd dd dd dd rr bb t3 "
+               "tt bb dd dd dd dd dd dd dd dd bb bb dd dd .. dd bb t3 tt "
+               "tt bb dd dd && dd dd .. .. .. bb dd dd .. dd dd rr tt tt "
+               "tt bb bb dd dd dd bb bb bb bb bb bb dd dd dd bb rr tt tt "
+               "tt t5 bb bb rr rr bb t3 tt tt t5 bb bb bb rr rr t3 tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tc ta "
+               "tt tt tt tt tc ta tt tt tt tt tt tt tt tt tt tt tt t5 t3 "
+  )
+   (list ;;entrances
+       (list southwest 18 5)
+   )
+ (put (mk-ladder-down 'p_bandit_hideout_l2a 9 9) 9 9)
+ (put (mk-door) 4 9)
+ (put (kern-tag 'p_bhl1_p1 (mk-portcullis)) 7 9)
+ (put (kern-tag 'p_bhl1_p2 (mk-portcullis)) 9 11)
+ (put (mk-sense-trig 'generic-trig-exec 'p_bhl1_p1 'signal)  12 9)
+ (put (mk-lever 'p_bhl1_p2)  10 9)
+
+ ;; Release the hounds!
+ (put (mk-step-trig 'terrain-changer 10 14 't_dirt) 9 6)
+
+ ;; Bandits
+ (put (mk-npc 'bandit 1) 3 4)
+ (put (mk-npc 'footpad 2) 5 4)
+ (put (mk-npc 'bandit 1) 3 14)
+ (put (mk-npc 'footpad 2) 5 14)
+ (put (mk-npc 'footpad 1) 5 8)
+ (put (mk-npc 'footpad 1) 5 10)
+ (put (mk-npc 'bandit 1) 15 9)
+ (put (mk-npc 'bandit 1) 15 7)
+ (put (mk-npc 'highwayman 2) 9 8)
+
+ ;; Wolves in the pen
+ (put (kern-being-set-base-faction (mk-npc 'wolf 1) 
+                                   faction-outlaw) 13 14)
+ (put (kern-being-set-base-faction (mk-npc 'wolf 1)
+                                   faction-outlaw) 14 13)
+ (put (mk-corpse) 13 13)
+
+ ;; Traps
+ (put (mk-caltrops) 8 12)
+
+ )
+
+(mk-place-music p_bandit_hideout_l1 'ml-outdoor-adventure)
+
+(mk-dungeon-room
+ 'p_bandit_hideout_l2a "Stockade Barracks"
+ (list
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  "rr rr bb dd dd dd dd dd dd dd dd dd dd dd dd dd dd rr rr "
+  "rr bb dd dd dd bb dd xx xx xx xx bb dd dd dd dd bb dd rr "
+  "rr dd dd dd dd dd dd xx ,, ,, xx xx xx xx xx dd dd dd rr "
+  "rr dd dd xx xx xx xx xx ,, ,, ,, ,, ,, x! xx dd dd bb rr "
+  "rr dd dd xx x! ,, ,, xx xx xx xx ,, ,, ,, xx dd && bb rr "
+  "rr dd dd xx ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx bb bb bb rr "
+  "rr dd dd xx ,, ,, ,, xx x! ,, xx xx ,, xx xx xx xx bb rr "
+  "rr dd xx xx ?? xx xx xx ,, ,, ,, x! ,, xx ,, ,, xx dd rr "
+  "rr dd xx ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx dd rr "
+  "rr dd xx ,, ,, xx ,, x! ,, ,, ,, xx xx xx ,, xx xx dd rr "
+  "rr dd xx ?? xx xx ,, xx xx ,, x! xx ,, ,, ,, xx dd dd rr "
+  "rr dd dd dd xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx dd dd rr "
+  "rr dd bb dd xx ,, ,, ,, xx xx xx xx ,, ,, x! xx dd dd rr "
+  "rr dd dd dd xx x! ,, ,, ,, ,, ,, xx xx ~x xx xx dd dd rr "
+  "rr dd dd dd xx xx xx xx xx ,, ,, xx dd dd dd dd dd dd rr "
+  "rr rr dd dd dd dd dd bb xx xx xx xx dd dd dd dd dd rr rr "
+  "rr rr rr dd dd dd bb bb bb bb bb bb dd dd dd dd rr rr rr "
+  "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  )
+ (put (mk-ladder-up 'p_bandit_hideout_l1 9 9) 9 9)
+
+ ;; Portculli and levers
+ (put (kern-tag 'p_bh2_1 (mk-portcullis)) 8 14)
+ (put (kern-tag 'p_bh2_2 (mk-portcullis)) 14 10)
+ (put (mk-lever 'p_bh2_1) 8 3)
+ (put (mk-lever 'p_bh2_2) 3 9)
+
+ ;; Trapped doors
+ (put (trap-door (mk-door) 'spike-trap)  9 7)
+ (put (trap-door (mk-door) 'sleep-trap)  7 9)
+ (put (trap-door (mk-door) 'poison-trap) 9 11)
+ (put (trap-door (mk-door) 'bomb-trap)   11 9)
+ (put (trap-door (mk-door) 'sleep-trap) 10 4)
+
+ ;; Chests & prisoners
+ ;; arms...
+ (let ((kchest (mk-chest nil
+                         '((10 t_oil)
+                           (50 t_arrow)
+                           (20 t_spear)
+                           ))))
+   (ifccall kchest 'add-trap 'sleep-trap)
+   (ifccall kchest 'add-trap 'poison-trap)
+   (put kchest 10 14))
+
+ ;; medical...
+ (let ((kchest (mk-chest nil
+                         '((10 t_heal_potion)
+                           (3 t_cure_potion)
+                           (2 t_poison_immunity_potion)
+                           (1 t_invisibility_potion)
+                           (1 t_slime_vial)
+                           ))))
+   (ifccall kchest 'add-trap 'lightning-trap)
+   (ifccall kchest 'add-trap 'self-destruct-trap)
+   (put kchest 10 15))
+ ;; wrogue supplies...
+ (let ((kchest (mk-chest nil
+                         '((5 t_torch)
+                           (5 t_picklock)
+                           (3 t_gem)
+                           (1 t_pick)
+                           (1 t_in_ex_por_scroll)
+                           (1 t_wis_an_ylem_scroll)
+                           (1 t_wis_quas_scroll)
+                           ))))
+   (ifccall kchest 'add-trap 'bomb-trap)
+   (put kchest 9 15))
+
+ (put (mk-corpse) 15 8)
+ (put (mk-npc 'cave-goblin-berserker 4) 14 8)
+
+ ;; Guards
+ (put (mk-npc 'footpad 2) 6 6)
+ (put (mk-npc 'highwayman 3) 4 6)
+ (put (mk-npc 'footpad 2) 6 12)
+ (put (mk-npc 'highwayman 3) 7 14)
+ (put (mk-npc 'footpad 2) 12 12)
+ (put (mk-npc 'footpad 2) 12 6)
+ (put (mk-npc 'footpad 2) 2 15)
+ (put (kern-being-set-base-faction (mk-npc 'wolf 1) 
+                                   faction-outlaw) 9 14)
+
+ ;; Traps
+ (put (mk-step-trig 'wind-trap nil) 1 10)
+ (put (mk-step-trig 'wind-trap nil) 7 1)
+ (put (mk-caltrops) 4 1)
+
+ ;; Cryptozoic denizens
+ (put (spawn-pt 'giant-spider faction-spider) 16 16)
+ (put (mk-corpse-with-loot) 12 16)
+ (put (mk-corpse-with-loot) 17 15)
+
+ ;; Nate
+ (put (mk-nate) 16 3)
+)
+
+(mk-place-music p_bandit_hideout_l2a 'ml-dungeon-adventure)
+
+;  (put (spawn-pt 'cave-goblin-slinger) 18 7)
+;  (put (spawn-pt 'cave-goblin-slinger) 18 11)
+;  (put (spawn-pt 'cave-goblin-berserker) 15 9)
+;  (put (guard-pt 'crossbowman) 12 9)
+;  (put (guard-pt 'crossbowman) 12 11)
+;  (put (guard-pt 'halberdier) 10 10)
+
+ ;; Make a test chest with a bunch of traps on it.
+;  (let ((kchest (mk-chest nil
+;                 '((1 t_sword)
+;                   (5 t_arrow)
+;                   (2 t_torch)))))
+;    (map (lambda (trap)
+;           (ifccall kchest 'add-trap trap))
+;         (list 'sleep-trap
+;               'poison-trap
+;               'burn-trap
+;               'spike-trap
+;               'lightning-trap
+;               'self-destruct-trap
+;               'bomb-trap))
+;    (put kchest 5 8))
+;  (put (mk-caltrops) 6 9)
+;  (put (mk-beartrap) 6 10)
diff --git a/worlds/haxima-1.002/bart.scm b/worlds/haxima-1.002/bart.scm
new file mode 100644 (file)
index 0000000..fddaa07
--- /dev/null
@@ -0,0 +1,181 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Oparine.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_bart
+               (list 0  0  black-barts-bed      "sleeping")
+               (list 11 0  black-barts-ship     "working")
+               (list 18 0  bilge-water-hall     "idle")
+               (list 23 0  black-barts-bed      "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (bart-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Bart is a hard-drinking goblin shipwright who dwells in Oparine.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (bart-hail knpc kpc)
+  (say knpc "[You meet a taciturn goblin who smells of whiskey] "
+       "Unh."))
+
+(define (bart-default knpc kpc)
+  (say knpc "Eh?"))
+
+(define (bart-name knpc kpc)
+  (say knpc "Bart."))
+
+(define (bart-join knpc kpc)
+  (say knpc "[He looks at you oddly and shakes his head]"))
+
+(define (bart-job knpc kpc)
+  (say knpc "Bart make ship. Good ship."))
+
+(define (bart-bye knpc kpc)
+  (say knpc "Ja."))
+
+;; Trade...
+(define (bart-trade knpc kpc)
+
+  (define (buy-ship)
+    (let* ((town (loc-place (kern-obj-get-location knpc)))
+           (town-loc (kern-place-get-location town))
+           (ship-loc (loc-offset town-loc east)))
+      (if (ship-at? ship-loc)
+          (say knpc "Hunh. No room at dock. Somebody need move ship first.")
+          (begin
+            (kern-obj-relocate (mk-ship) ship-loc nil)
+            (take-player-gold oparine-ship-price)
+            (say knpc "Ship ready ready outside town.")
+            ))))
+
+  (define (sell-ship)
+    (let* ((town (loc-place (kern-obj-get-location knpc)))
+           (town-loc (kern-place-get-location town))
+           (ship-loc (loc-offset town-loc east))
+           (kship (kern-place-get-vehicle ship-loc)))
+      (if (null? kship)
+          (say knpc "Bart no see ship. Park at dock, come back.")
+          (begin
+            (say knpc "You want sell that junk ship? Bart give " 
+                 oparine-ship-tradein-price
+                 ". Ok?")
+            (if (kern-conv-get-yes-no? kpc)
+                (begin
+                  (say knpc "Bart too generous, you lucky.")
+                  (kern-obj-remove kship)
+                  (give-player-gold oparine-ship-tradein-price))
+                (say knpc "Hunh. That ship sink soon."))))))
+
+  (if (not (string=? "working" (kern-obj-get-activity knpc)))
+      (say knpc "Not work now. Now drink!")
+      (begin
+        (say knpc "You want buy ship?")
+        (if (yes? kpc)
+            (begin
+              (say knpc "Ship " oparine-ship-price " gold. Want ship?")
+              (if (kern-conv-get-yes-no? kpc)
+                  (if (player-has-gold? oparine-ship-price)
+                      (buy-ship)
+                      (begin
+                        (say knpc "You not have gold! You try cheat Bart? "
+                             "[He spits on the ground]")
+                        (kern-conv-end)))
+                  (say knpc "Fine. You swim.")))
+            (begin
+              (say knpc "You want sell ship?")
+              (if (yes? kpc)
+                  (sell-ship)
+                  (begin
+                    (say knpc "Then what hell you bother Bart for?")
+                    (kern-conv-end))))))))
+
+;; Drink...
+(define (bart-drink knpc kpc)
+  (if (not (string=? "working" (kern-obj-get-activity knpc)))
+      (say knpc "Let's drink!")
+      (say knpc "Work now. Drink later.")))
+
+
+;; Townspeople...
+(define (bart-opar knpc kpc)
+  (say knpc "Smells like fish."))
+
+(define (bart-gher knpc kpc)
+  (say knpc "Tu-gu. Bad ghost.[He makes a strange sign in the air]"))
+
+(define (bart-alch knpc kpc)
+  (say knpc "Hi-lu-to. He take low road from burning city. "
+       "Goblins cousins remember."))
+
+(define (bart-seaw knpc kpc)
+  (say knpc "She smell like fish."))
+
+(define (bart-osca knpc kpc)
+  (say knpc "Tu-to. Bart not know man-words."))
+
+(define (bart-henr knpc kpc)
+  (say knpc "Bart friend. Make good drink! Bart love drink."))
+
+(define bart-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default bart-default)
+       (method 'hail bart-hail)
+       (method 'bye bart-bye)
+       (method 'job bart-job)
+       (method 'name bart-name)
+       (method 'join bart-join)
+       
+       ;; drink
+       (method 'drin bart-drink)
+
+       ;; trade
+       (method 'trad bart-trade)
+       (method 'ship bart-trade)
+       (method 'buy bart-trade)
+       (method 'sell bart-trade)
+
+       ;; town & people
+       (method 'opar bart-opar)
+       (method 'alch bart-alch)
+       (method 'gher bart-gher)
+       (method 'witc bart-seaw)
+       (method 'osca bart-osca)
+       (method 'henr bart-henr)
+       (method 'ja   bart-bye)
+
+       ))
+
+(define (mk-bart)
+  (bind 
+   (kern-mk-char 'ch_bart           ; tag
+                 "Bart"             ; name
+                 sp_forest_goblin    ; species
+                 nil                 ; occ
+                 s_fgob_civilian     ; sprite
+                 faction-men         ; starting alignment
+                 0 0 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 1  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'bart-conv         ; conv
+                 sch_bart           ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_axe)))                 ; container
+                 nil                 ; readied
+                 )
+   (bart-mk)))
diff --git a/worlds/haxima-1.002/beds.scm b/worlds/haxima-1.002/beds.scm
new file mode 100644 (file)
index 0000000..4a484b9
--- /dev/null
@@ -0,0 +1,16 @@
+;; ----------------------------------------------------------------------------
+;; Beds
+;;
+;; Player can k)amp in beds to sleep in town. The kernel identifies bed objects
+;; by their layer.
+;;
+;; ----------------------------------------------------------------------------
+
+(mk-obj-type 't_bed    ;; tag
+             "bed"     ;; name
+             s_bed     ;; sprite
+             layer-bed ;; layer
+             nil       ;; interface
+             )
+
+(define (mk-bed) (kern-mk-obj t_bed 1))
diff --git a/worlds/haxima-1.002/bigobjects.png b/worlds/haxima-1.002/bigobjects.png
new file mode 100644 (file)
index 0000000..d62a09f
Binary files /dev/null and b/worlds/haxima-1.002/bigobjects.png differ
diff --git a/worlds/haxima-1.002/bill.scm b/worlds/haxima-1.002/bill.scm
new file mode 100644 (file)
index 0000000..9cedb2c
--- /dev/null
@@ -0,0 +1,211 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define bill-start-lvl 3)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Bole.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_bill
+               (list 0  0  bole-bed-bill "sleeping")
+               (list 6  0  bole-table-1  "idle")
+               (list 7  0  bole-n-woods  "working")
+               (list 12 0  bole-table-2  "eating")
+               (list 13 0  bole-n-woods  "working")
+               (list 18 0  bole-table-2  "eating")
+               (list 19 0  bole-dining-hall "idle")
+               (list 21 0  bole-bills-hut "idle")
+               (list 22 0  bole-bed-bill "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (bill-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Bill is a woodcutter who lives in Bole.
+;; Not the sharpest tool in the shed.
+;;----------------------------------------------------------------------------
+(define bill-catalog
+  (list
+   (list t_staff 10 "It's hard tuh find branches straight enought to make a staff.") ;; rather cheap
+   (list t_torch  3 "Ah always like tuh see at night, so I make torches.") ;; rather cheap
+   (list t_arrow  3 "The rangers from Green Tower sometimes buy my arrows.")
+   (list t_bolt   4 "Not many folks use crossbows 'round here.")
+   ))
+
+(define bill-merch-msgs
+  (list nil ;; closed
+        "I make all this stuff my self." ;; buy
+        nil ;; sell
+        nil ;; trade
+        "I hope they work ok for you." ;; sold-something
+        "If ye change yer mind ah'll be around." ;; sold-nothing
+        nil ;; bought-something
+        nil ;; bought-nothing
+        nil ;; traded-something
+        nil ;; traded-nothing
+        ))
+
+
+(define (bill-buy knpc kpc) (conv-trade knpc kpc "buy" bill-merch-msgs bill-catalog))
+
+(define (bill-goods knpc kpc)
+  (say knpc "Want to buy some?")
+  (if (kern-conv-get-yes-no? kpc)
+      (bill-buy knpc kpc)
+      (say knpc "Just ask if you ever do.")))
+
+(define (bill-may knpc kpc)
+  (say knpc "She runs the tavern in town an' is a good lady."))
+
+(define (bill-lady knpc kpc)
+  (say knpc "There's uh lady in town now. She's real pretty. But she has "
+       "a big, mean boyfrien'."))
+
+(define (bill-bole knpc kpc)
+  (say knpc "Yeah, Ah like Bole. "
+       "There's uh tavern, where Ah eat an' get shit-faced. "
+       "An' muh house is there."))
+
+(define (bill-wolves knpc kpc)
+  (say knpc "I hafta wach out for them. "
+       "They stays mostly inna south, away from town."))
+
+(define (bill-scared knpc kpc)
+  (say knpc "Ah wuz west o' the town, "
+       "where's I hardly never go on account o' the wulves. "
+       "There was a great big, old, dead oak. "
+       "I sez to myself, that's a good-un! "
+       "Well, no sooner had muh axe bit into the bark "
+       "but it wakes up!"))
+
+(define (bill-thie knpc kpc)
+  (say knpc "There wuz a right nervous feller at the tavern not long ago. "
+       "He had some words with the pretty lady. I think they got in uh "
+       "argument over somethin'. I saw him go into the hills in the "
+       "northeast cornah uh town, you know? And he never came out. I "
+       "don' know where he went! Them hills is uh dead-end! Plumb strange "
+       "if'n you ask me."))
+
+(define (bill-mous knpc kpc)
+  (say knpc "Therez mice all over. Jus' the other day I saw a man what "
+       "scurried lak a mouse!"))
+
+(define bill-conv
+  (ifc nil
+       (method 'default (lambda (knpc kpc) (say knpc "[He shrugs]")))
+       (method 'hail (lambda (knpc kpc) (say knpc "Hi-dee.")))
+       (method 'bye (lambda (knpc kpc) (say knpc "Fare thee well.")))
+       (method 'job (lambda (knpc kpc) 
+                      (say knpc "I's a woodcutter.")))
+       (method 'name (lambda (knpc kpc) (say knpc "Called Bill.")))
+       (method 'join (lambda (knpc kpc) 
+                       (say knpc "No, sirree! Yousa ass-kicker, "
+                            "and I'sa woodcutter. Not a good match, no "
+                            "offense.")))
+
+       (method 'arro bill-goods)
+       (method 'axe
+               (lambda (knpc kpc)
+                 (say knpc "It works better than muh knife on most trees.")))
+       (method 'buy bill-buy)
+       (method 'bole bill-bole)
+       (method 'chop
+               (lambda (knpc kpc)
+                 (say knpc "Ah use muh axe.")))
+       (method 'fore
+               (lambda (knpc kpc)
+                 (say knpc "Yeah, the forest is plumb full o' trees. "
+                      "And wolves, too.")))
+       (method 'haun
+               (lambda (knpc kpc)
+                 (say knpc "[He leans in close and whispers] "
+                      "Thar's a haunted tree west o' the town. "
+                      "Scared the jinkins outta me! Har!")))
+       (method 'jink bill-scared)
+       (method 'ladi bill-lady)
+       (method 'lady bill-lady)
+       
+       (method 'may bill-may)
+
+       (method 'wood
+               (lambda (knpc kpc)
+                 (say knpc "I cuts down trees and chops 'em into firewood. "
+                      "Sometimes Ah make torches or arrows, too. Um-hm.")))
+       (method 'shit
+               (lambda (knpc kpc)
+                 (say knpc "Oops! Sorry. I's not supposed to say that. "
+                      "May's alwiz tellin' me not tuh say words lak shit and "
+                      "damn. Ladies don' lak that, you know.")))
+       (method 'scar bill-scared)
+       (method 'thie bill-thie)
+       (method 'mous bill-mous)
+       (method 'man  bill-thie)
+       (method 'scur bill-thie)
+       (method 'torc bill-goods)
+       (method 'town bill-bole)
+       (method 'trad bill-buy)
+       (method 'tree
+               (lambda (knpc kpc)
+                 (say knpc "There be all kinds uh trees in this forest. "
+                      "Why, t'other day I even came me across a haunted "
+                      "tree!")))
+       (method 'wake
+               (lambda (knpc kpc)
+                 (say knpc "Aye! That old dead oak came alive! "
+                      "It bellered like a bull and two great eyes opened "
+                      "und stared right at me! Uh jumped out of my britches!"
+                      "I dropped muh axe and ran like nothing!")))
+       (method 'wolv bill-wolves)
+       (method 'wulv bill-wolves)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-bill)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_bill ;;......tag
+     "Bill" ;;.......name
+     sp_human ;;.....species
+     nil ;;..........occupation
+     s_townsman ;;...sprite
+     faction-men ;;..faction
+     2 ;;............custom strength modifier
+     0 ;;............custom intelligence modifier
+     0 ;;............custom dexterity modifier
+     0 ;;............custom base hp modifier
+     0 ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     bill-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'bill-conv ;;...conversation (optional)
+     sch_bill ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+
+     ;;..............container (and contents)
+     (mk-inventory
+      (list
+       (list 10  t_torch)
+       (list 100 t_arrow)
+       (list 1   t_2h_axe)
+       ))
+     nil ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (bill-mk)))
diff --git a/worlds/haxima-1.002/bim.scm b/worlds/haxima-1.002/bim.scm
new file mode 100644 (file)
index 0000000..dfb7ea8
--- /dev/null
@@ -0,0 +1,88 @@
+;; bim - binary mechanism
+
+(define (state-mk sprite-tag opacity pclass light)
+  (list sprite-tag opacity pclass light))
+(define (state-sprite state) (eval (car state)))
+(define (state-opacity state) (cadr state))
+(define (state-pclass state) (caddr state))
+(define (state-light state) (cadddr state))
+
+;; ctor
+(define (bim-mk on? port members)
+  ;;(display "bim-mk")(newline)
+  (list on? port #f members))
+
+;; accessors
+(define (bim-on? bim) (car bim))
+(define (bim-port bim) (cadr bim))
+(define (bim-active? bim) (caddr bim))
+(define (bim-members bim) (cadddr bim))
+
+;; mutators
+(define (bim-set-on! bim val) (set-car! bim val))
+(define (bim-set-active! bim val) (set-car! (cddr bim) val))
+
+;; helpers
+(define (bim-send-signal kobj sig)
+  (let ((bim (gob-data (kobj-gob kobj))))
+    (if (not (bim-active? bim))
+        (let ((port (bim-port bim)))
+          (if (and (not (null? port)) 
+                   (defined? port))
+              (begin
+                (bim-set-active! bim #t)
+                ((kobj-ifc (eval port)) sig (eval port) kobj)
+                (bim-set-active! bim #f)))))))
+
+(define (bim-change-state kobj khandler on?)
+  ;;(display "bim-change-state")(newline)
+  (let ((bim (gob-data (kobj-gob kobj))))
+    (bim-set-on! bim on?)
+    (let ((state ((kobj-ifc kobj) 'state on? kobj)))
+      ;;(display "state:")(display state)(newline)
+      (kern-obj-set-sprite kobj (state-sprite state))
+      (kern-obj-set-opacity kobj (state-opacity state))
+      (kern-obj-set-pclass kobj (state-pclass state))
+      (kern-obj-set-light kobj (state-light state))
+      )))
+
+;; handlers
+(define (bim-on kobj khandler) 
+  ;(display "bim-on")(newline)
+  (bim-change-state kobj khandler #t 'on)
+  (bim-send-signal kobj 'on)
+  )
+
+(define (bim-off kobj khandler) 
+  ;(display "bim-off")(newline)
+  (bim-change-state kobj khandler #f 'on)
+  (bim-send-signal kobj 'off)
+  )
+
+(define (bim-toggle kobj khandler)
+  ;;(display "bim-toggle")(newline)
+  (let ((bim (gob-data (kobj-gob kobj))))
+    (if (bim-on? bim) 
+        (bim-off kobj khandler)
+        (bim-on kobj khandler))))
+
+(define (bim-init kobj)
+  (let ((bim (gob-data (kobj-gob kobj))))
+    (if (bim-on? bim)
+        (bim-on kobj '())
+        (bim-off kobj '()))))
+
+(define (bim-is-on? kobj)
+  (let ((bim (kobj-gob-data kobj)))
+    (bim-on? bim)))
+
+;; ifc - extensions must add a 'state message handler
+(define bim-ifc
+  (ifc '()
+       (method 'on bim-on)
+       (method 'off bim-off)
+       (method 'toggle bim-toggle)
+       (method 'init bim-init)
+       (method 'is-on? bim-is-on?)
+       ))
+
diff --git a/worlds/haxima-1.002/blendterrains.scm b/worlds/haxima-1.002/blendterrains.scm
new file mode 100644 (file)
index 0000000..eba6816
--- /dev/null
@@ -0,0 +1,428 @@
+;; --------------- regular water ------------------------
+
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "water" pclass-deep
+                   (mk-composite-sprite (cons s_shallow sprites))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_wshore_n  s_grass_n )
+(mk-blend-terrain 't_wshore_w  s_grass_w )
+(mk-blend-terrain 't_wshore_nw s_grass_nw)
+(mk-blend-terrain 't_wshore_e  s_grass_e )
+(mk-blend-terrain 't_wshore_ne s_grass_ne)
+(mk-blend-terrain 't_wshore_we s_grass_e s_grass_w)
+(mk-blend-terrain 't_wshore_nwe s_grass_ne s_grass_nw)
+(mk-blend-terrain 't_wshore_s  s_grass_s )
+(mk-blend-terrain 't_wshore_ns s_grass_s s_grass_n)
+(mk-blend-terrain 't_wshore_ws s_grass_sw)
+(mk-blend-terrain 't_wshore_nws s_grass_sw s_grass_nw)
+(mk-blend-terrain 't_wshore_es s_grass_se)
+(mk-blend-terrain 't_wshore_nes s_grass_se s_grass_ne)
+(mk-blend-terrain 't_wshore_wes s_grass_se s_grass_sw)
+(mk-blend-terrain 't_wshore_c s_grass_se s_grass_sw s_grass_ne s_grass_nw)
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "deep water" pclass-deep
+                   (mk-composite-sprite (cons s_deep sprites))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_dshore_n  s_grass_n )
+(mk-blend-terrain 't_dshore_w  s_grass_w )
+(mk-blend-terrain 't_dshore_nw s_grass_nw)
+(mk-blend-terrain 't_dshore_e  s_grass_e )
+(mk-blend-terrain 't_dshore_ne s_grass_ne)
+(mk-blend-terrain 't_dshore_we s_grass_e s_grass_w)
+(mk-blend-terrain 't_dshore_nwe s_grass_ne s_grass_nw)
+(mk-blend-terrain 't_dshore_s  s_grass_s )
+(mk-blend-terrain 't_dshore_ns s_grass_s s_grass_n)
+(mk-blend-terrain 't_dshore_ws s_grass_sw)
+(mk-blend-terrain 't_dshore_nws s_grass_sw s_grass_nw)
+(mk-blend-terrain 't_dshore_es s_grass_se)
+(mk-blend-terrain 't_dshore_nes s_grass_se s_grass_ne)
+(mk-blend-terrain 't_dshore_wes s_grass_se s_grass_sw)
+(mk-blend-terrain 't_dshore_c s_grass_se s_grass_sw s_grass_ne s_grass_nw)
+
+(kern-mk-terrain 't_water_rocks "boulder" pclass-waterboulder
+                   (mk-composite-sprite (list s_shoals s_boulder_over))
+                   lgt 0 nil)
+
+;;----------------------------
+;; Water edges
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "grass" pclass-grass
+                   (mk-composite-sprite (cons s_shoals (cons s_grassi_c sprites)))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_grassw_ne s_grasso_se s_grasso_sw s_grasso_nw)
+(mk-blend-terrain 't_grassw_nw s_grasso_se s_grasso_sw s_grasso_ne)
+(mk-blend-terrain 't_grassw_es s_grasso_sw s_grasso_ne s_grasso_nw)
+(mk-blend-terrain 't_grassw_ws s_grasso_se s_grasso_ne s_grasso_nw)
+(mk-blend-terrain 't_grassw_nwe s_grasso_se s_grasso_sw)
+(mk-blend-terrain 't_grassw_nes s_grasso_sw s_grasso_nw)
+(mk-blend-terrain 't_grassw_nws s_grasso_se s_grasso_ne)
+(mk-blend-terrain 't_grassw_wes s_grasso_ne s_grasso_nw)
+
+(kern-mk-terrain 't_grassw_c "grass" pclass-shoals
+                   (mk-composite-sprite (list s_shoals s_grassi_c))
+                   trn 0 nil)
+                                  
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "trees" pclass-trees
+                   (mk-composite-sprite (cons s_shoals (cons s_trees_c sprites)))
+                   lgt 0 nil))
+
+(mk-blend-terrain 't_treew_ne s_trees_se s_trees_sw s_trees_nw)
+(mk-blend-terrain 't_treew_nw s_trees_se s_trees_sw s_trees_ne)
+(mk-blend-terrain 't_treew_es s_trees_sw s_trees_ne s_trees_nw)
+(mk-blend-terrain 't_treew_ws s_trees_se s_trees_ne s_trees_nw)
+(mk-blend-terrain 't_treew_nwe s_trees_se s_trees_sw)
+(mk-blend-terrain 't_treew_nes s_trees_sw s_trees_nw)
+(mk-blend-terrain 't_treew_nws s_trees_se s_trees_ne)
+(mk-blend-terrain 't_treew_wes s_trees_ne s_trees_nw)
+
+(kern-mk-terrain 't_treew_c "trees" pclass-trees
+                   (mk-composite-sprite (list s_shoals s_trees_c))
+                   lgt 0 nil)
+                                  
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "hills" pclass-hills
+                   (mk-composite-sprite (cons s_shoals (cons s_hills_c sprites)))
+                   dns 0 nil))
+
+(mk-blend-terrain 't_hillw_ne s_hills_se s_hills_sw s_hills_nw)
+(mk-blend-terrain 't_hillw_nw s_hills_se s_hills_sw s_hills_ne)
+(mk-blend-terrain 't_hillw_es s_hills_sw s_hills_ne s_hills_nw)
+(mk-blend-terrain 't_hillw_ws s_hills_se s_hills_ne s_hills_nw)
+(mk-blend-terrain 't_hillw_nwe s_hills_se s_hills_sw)
+(mk-blend-terrain 't_hillw_nes s_hills_sw s_hills_nw)
+(mk-blend-terrain 't_hillw_nws s_hills_se s_hills_ne)
+(mk-blend-terrain 't_hillw_wes s_hills_ne s_hills_nw)
+
+(kern-mk-terrain 't_hillw_c "hills" pclass-trees
+                   (mk-composite-sprite (list s_shoals s_hills_c))
+                   dns 0 nil)
+                                  
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "mountains" pclass-mountains
+                   (mk-composite-sprite (cons s_shoals (cons s_mount_c sprites)))
+                   opq 0 nil))
+
+(mk-blend-terrain 't_mountw_ne s_mount_se s_mount_sw s_mount_nw)
+(mk-blend-terrain 't_mountw_nw s_mount_se s_mount_sw s_mount_ne)
+(mk-blend-terrain 't_mountw_es s_mount_sw s_mount_ne s_mount_nw)
+(mk-blend-terrain 't_mountw_ws s_mount_se s_mount_ne s_mount_nw)
+(mk-blend-terrain 't_mountw_nwe s_mount_se s_mount_sw)
+(mk-blend-terrain 't_mountw_nes s_mount_sw s_mount_nw)
+(mk-blend-terrain 't_mountw_nws s_mount_se s_mount_ne)
+(mk-blend-terrain 't_mountw_wes s_mount_ne s_mount_nw)
+
+(kern-mk-terrain 't_mountw_c "mountains" pclass-mountains
+                   (mk-composite-sprite (list s_shoals s_mount_c))
+                   opq 0 nil)
+
+;;----------------------------------------------------------------------------
+;; Some blended hill terrain types
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "grass" pclass-grass
+                   (mk-composite-sprite (cons s_grass sprites))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_hilledge_n  s_hill_n )
+(mk-blend-terrain 't_hilledge_w  s_hill_w )
+(mk-blend-terrain 't_hilledge_nw s_hill_n s_hill_w)
+(mk-blend-terrain 't_hilledge_e  s_hill_e )
+(mk-blend-terrain 't_hilledge_ne s_hill_n s_hill_e)
+(mk-blend-terrain 't_hilledge_we s_hill_e s_hill_w)
+(mk-blend-terrain 't_hilledge_nwe s_hill_n s_hill_e s_hill_w)
+(mk-blend-terrain 't_hilledge_s  s_hill_s )
+(mk-blend-terrain 't_hilledge_ns s_hill_s s_hill_n)
+(mk-blend-terrain 't_hilledge_ws s_hill_s s_hill_w)
+(mk-blend-terrain 't_hilledge_nws s_hill_s s_hill_w s_hill_n)
+(mk-blend-terrain 't_hilledge_es s_hill_s s_hill_e)
+(mk-blend-terrain 't_hilledge_nes s_hill_s s_hill_e s_hill_n)
+(mk-blend-terrain 't_hilledge_wes s_hill_s s_hill_e s_hill_w)
+(mk-blend-terrain 't_hilledge_c s_hill_s s_hill_e s_hill_w s_hill_n)
+
+;; inner hill corners
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "hills" pclass-hills
+                   (mk-composite-sprite (cons s_grass (cons s_hills_c sprites)))
+                   dns 0 nil))
+
+(mk-blend-terrain 't_hilli_ne s_hills_se s_hills_sw s_hills_nw)
+(mk-blend-terrain 't_hilli_nw s_hills_se s_hills_sw s_hills_ne)
+(mk-blend-terrain 't_hilli_es s_hills_sw s_hills_ne s_hills_nw)
+(mk-blend-terrain 't_hilli_ws s_hills_se s_hills_ne s_hills_nw)
+(mk-blend-terrain 't_hilli_nwe s_hills_se s_hills_sw)
+(mk-blend-terrain 't_hilli_nes s_hills_sw s_hills_nw)
+(mk-blend-terrain 't_hilli_nws s_hills_se s_hills_ne)
+(mk-blend-terrain 't_hilli_wes s_hills_ne s_hills_nw)
+
+(kern-mk-terrain 't_hilli_c "hills" pclass-trees
+                   (mk-composite-sprite (list s_grass s_hills_c))
+                   1 0 nil)
+
+;;---------------------------------------------------------------------------
+;; swamp corners
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "bog" pclass-hills
+                   (mk-composite-sprite (cons s_bog sprites))
+                   trn 0 'terrain-effect-swamp))
+
+(mk-blend-terrain 't_bog_nw s_grass_nw)
+(mk-blend-terrain 't_bog_ne s_grass_ne)
+(mk-blend-terrain 't_bog_nwe s_grass_ne s_grass_nw)
+(mk-blend-terrain 't_bog_ws s_grass_sw)
+(mk-blend-terrain 't_bog_nws s_grass_sw s_grass_nw)
+(mk-blend-terrain 't_bog_es s_grass_se)
+(mk-blend-terrain 't_bog_nes s_grass_se s_grass_ne)
+(mk-blend-terrain 't_bog_wes s_grass_se s_grass_sw)
+(mk-blend-terrain 't_bog_c s_grass_se s_grass_sw s_grass_ne s_grass_nw)
+
+;;----------------------------------------------------------------
+;; mountain corners
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "mountains" pclass-mountains
+                   (mk-composite-sprite (cons s_grass (cons s_mount_c sprites)))
+                   opq 0 nil))
+
+(mk-blend-terrain 't_mountg_ne s_mount_se s_mount_sw s_mount_nw)
+(mk-blend-terrain 't_mountg_nw s_mount_se s_mount_sw s_mount_ne)
+(mk-blend-terrain 't_mountg_es s_mount_sw s_mount_ne s_mount_nw)
+(mk-blend-terrain 't_mountg_ws s_mount_se s_mount_ne s_mount_nw)
+(mk-blend-terrain 't_mountg_nwe s_mount_se s_mount_sw)
+(mk-blend-terrain 't_mountg_nes s_mount_sw s_mount_nw)
+(mk-blend-terrain 't_mountg_nws s_mount_se s_mount_ne)
+(mk-blend-terrain 't_mountg_wes s_mount_ne s_mount_nw)
+
+(kern-mk-terrain 't_mountg_c "mountains" pclass-mountains
+                   (mk-composite-sprite (list s_grass s_mount_c))
+                   0 0 nil)
+                                
+;;----------------------------------------------------------------
+;; forest corners
+  
+                                  
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "forest" pclass-forest
+                   (mk-composite-sprite (cons s_grass (cons s_forest_c sprites)))
+                   hvy 0 nil))
+
+(mk-blend-terrain 't_forestg_ne s_forest_se s_forest_sw s_forest_nw)
+(mk-blend-terrain 't_forestg_nw s_forest_se s_forest_sw s_forest_ne)
+(mk-blend-terrain 't_forestg_es s_forest_sw s_forest_ne s_forest_nw)
+(mk-blend-terrain 't_forestg_ws s_forest_se s_forest_ne s_forest_nw)
+(mk-blend-terrain 't_forestg_nwe s_forest_se s_forest_sw)
+(mk-blend-terrain 't_forestg_nes s_forest_sw s_forest_nw)
+(mk-blend-terrain 't_forestg_nws s_forest_se s_forest_ne)
+(mk-blend-terrain 't_forestg_wes s_forest_ne s_forest_nw)
+                       
+                                  
+                                  
+;;-------------------------------------------------------
+;; void *
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "cliff edge" pclass-space
+                   (mk-composite-sprite (cons s_null sprites))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_voids_n  s_grass_n )
+(mk-blend-terrain 't_voids_w  s_grass_w )
+(mk-blend-terrain 't_voids_nw s_grass_nw)
+(mk-blend-terrain 't_voids_e  s_grass_e )
+(mk-blend-terrain 't_voids_ne s_grass_ne)
+(mk-blend-terrain 't_voids_we s_grass_e s_grass_w)
+(mk-blend-terrain 't_voids_nwe s_grass_ne s_grass_nw)
+(mk-blend-terrain 't_voids_s  s_grass_s )
+(mk-blend-terrain 't_voids_ns s_grass_s s_grass_n)
+(mk-blend-terrain 't_voids_ws s_grass_sw)
+(mk-blend-terrain 't_voids_nws s_grass_sw s_grass_nw)
+(mk-blend-terrain 't_voids_es s_grass_se)
+(mk-blend-terrain 't_voids_nes s_grass_se s_grass_ne)
+(mk-blend-terrain 't_voids_wes s_grass_se s_grass_sw)
+(mk-blend-terrain 't_voids_c s_grass_se s_grass_sw s_grass_ne s_grass_nw)
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "grass" pclass-grass
+                   (mk-composite-sprite (cons s_null (cons s_grassi_c sprites)))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_grassv_ne s_grasso_se s_grasso_sw s_grasso_nw)
+(mk-blend-terrain 't_grassv_nw s_grasso_se s_grasso_sw s_grasso_ne)
+(mk-blend-terrain 't_grassv_es s_grasso_sw s_grasso_ne s_grasso_nw)
+(mk-blend-terrain 't_grassv_ws s_grasso_se s_grasso_ne s_grasso_nw)
+(mk-blend-terrain 't_grassv_nwe s_grasso_se s_grasso_sw)
+(mk-blend-terrain 't_grassv_nes s_grasso_sw s_grasso_nw)
+(mk-blend-terrain 't_grassv_nws s_grasso_se s_grasso_ne)
+(mk-blend-terrain 't_grassv_wes s_grasso_ne s_grasso_nw)
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "hills" pclass-hills
+                   (mk-composite-sprite (cons s_null (cons s_hills_c sprites)))
+                   dns 0 nil))
+
+(mk-blend-terrain 't_hillv_ne s_hills_se s_hills_sw s_hills_nw)
+(mk-blend-terrain 't_hillv_nw s_hills_se s_hills_sw s_hills_ne)
+(mk-blend-terrain 't_hillv_es s_hills_sw s_hills_ne s_hills_nw)
+(mk-blend-terrain 't_hillv_ws s_hills_se s_hills_ne s_hills_nw)
+(mk-blend-terrain 't_hillv_nwe s_hills_se s_hills_sw)
+(mk-blend-terrain 't_hillv_nes s_hills_sw s_hills_nw)
+(mk-blend-terrain 't_hillv_nws s_hills_se s_hills_ne)
+(mk-blend-terrain 't_hillv_wes s_hills_ne s_hills_nw)
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "mountains" pclass-mountains
+                   (mk-composite-sprite (cons s_null (cons s_mount_c sprites)))
+                   opq 0 nil))
+
+(mk-blend-terrain 't_mountv_ne s_mount_se s_mount_sw s_mount_nw)
+(mk-blend-terrain 't_mountv_nw s_mount_se s_mount_sw s_mount_ne)
+(mk-blend-terrain 't_mountv_es s_mount_sw s_mount_ne s_mount_nw)
+(mk-blend-terrain 't_mountv_ws s_mount_se s_mount_ne s_mount_nw)
+(mk-blend-terrain 't_mountv_nwe s_mount_se s_mount_sw)
+(mk-blend-terrain 't_mountv_nes s_mount_sw s_mount_nw)
+(mk-blend-terrain 't_mountv_nws s_mount_se s_mount_ne)
+(mk-blend-terrain 't_mountv_wes s_mount_ne s_mount_nw)
+
+;;---------------------------------------------------------------------------
+;; tree corners
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "trees" pclass-trees
+                   (mk-composite-sprite (cons s_trees sprites))
+                   lgt 0 nil))
+
+(mk-blend-terrain 't_trees_nw s_treesi_nw s_grasso_nw)
+(mk-blend-terrain 't_trees_ne s_treesi_ne s_grasso_ne)
+(mk-blend-terrain 't_trees_nwe s_treesi_ne s_grasso_ne s_treesi_nw s_grasso_nw)
+(mk-blend-terrain 't_trees_ws s_treesi_sw s_grasso_sw)
+(mk-blend-terrain 't_trees_nws s_treesi_sw s_grasso_sw s_treesi_nw s_grasso_nw)
+(mk-blend-terrain 't_trees_es s_treesi_se s_grasso_se)
+(mk-blend-terrain 't_trees_nes s_treesi_se s_grasso_se s_treesi_ne s_grasso_ne)
+(mk-blend-terrain 't_trees_wes s_treesi_se s_grasso_se s_treesi_sw s_grasso_sw)
+(mk-blend-terrain 't_trees_c s_treesi_se s_grasso_se s_treesi_sw s_grasso_sw s_treesi_ne s_grasso_ne s_treesi_nw s_grasso_nw)
+
+;; grass with tree corners
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "grass" pclass-grass
+                   (mk-composite-sprite (cons s_grass sprites))
+                   trn 0 nil))
+
+(mk-blend-terrain 't_grasst_nw s_treeso_nw)
+(mk-blend-terrain 't_grasst_ne s_treeso_ne)
+(mk-blend-terrain 't_grasst_nwe s_treeso_ne s_treeso_nw)
+(mk-blend-terrain 't_grasst_ws s_treeso_sw)
+(mk-blend-terrain 't_grasst_nws s_treeso_sw s_treeso_nw)
+(mk-blend-terrain 't_grasst_es s_treeso_se)
+(mk-blend-terrain 't_grasst_nes s_treeso_se s_treeso_ne)
+(mk-blend-terrain 't_grasst_wes s_treeso_se s_treeso_sw)
+(mk-blend-terrain 't_grasst_c s_treeso_se s_treeso_sw s_treeso_ne s_treeso_nw)
+
+
+;;--------------------------------------------------------------------------
+;; lava corners
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "lava" pclass-hills
+                   (mk-composite-sprite (cons s_lava sprites))
+                   trn 0 'terrain-effect-lava))
+
+(mk-blend-terrain 't_lava_n  s_grass_n )
+(mk-blend-terrain 't_lava_w  s_grass_w )
+(mk-blend-terrain 't_lava_nw s_grass_nw)
+(mk-blend-terrain 't_lava_e  s_grass_e )
+(mk-blend-terrain 't_lava_ne s_grass_ne)
+(mk-blend-terrain 't_lava_we s_grass_e s_grass_w)
+(mk-blend-terrain 't_lava_nwe s_grass_ne s_grass_nw)
+(mk-blend-terrain 't_lava_s  s_grass_s )
+(mk-blend-terrain 't_lava_ns s_grass_s s_grass_n)
+(mk-blend-terrain 't_lava_ws s_grass_sw)
+(mk-blend-terrain 't_lava_nws s_grass_sw s_grass_nw)
+(mk-blend-terrain 't_lava_es s_grass_se)
+(mk-blend-terrain 't_lava_nes s_grass_se s_grass_ne)
+(mk-blend-terrain 't_lava_wes s_grass_se s_grass_sw)
+(mk-blend-terrain 't_lava_c s_grass_se s_grass_sw s_grass_ne s_grass_nw)
+
+;;----------------------------------------------------------------
+;; natural stone edges
+
+(define (mk-blend-terrain tag . sprites)
+  (kern-mk-terrain tag "natural stone wall" pclass-wall
+                   (mk-composite-sprite (cons s_nat_rock sprites))
+                   opq 0 nil))
+
+(mk-blend-terrain 't_nat_rock_n s_nat_rock_n)
+(mk-blend-terrain 't_nat_rock_s s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_w s_nat_rock_w)
+(mk-blend-terrain 't_nat_rock_e s_nat_rock_e)
+(mk-blend-terrain 't_nat_rock_nw s_nat_rock_n s_nat_rock_w)
+(mk-blend-terrain 't_nat_rock_ne s_nat_rock_n s_nat_rock_e)
+(mk-blend-terrain 't_nat_rock_ns s_nat_rock_n s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_we s_nat_rock_w s_nat_rock_e)
+(mk-blend-terrain 't_nat_rock_ws s_nat_rock_w s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_es s_nat_rock_e s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_nwe s_nat_rock_n s_nat_rock_w s_nat_rock_e)
+(mk-blend-terrain 't_nat_rock_nws s_nat_rock_n s_nat_rock_w s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_nes s_nat_rock_n s_nat_rock_e s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_wes s_nat_rock_w s_nat_rock_e s_nat_rock_s)
+(mk-blend-terrain 't_nat_rock_nwes s_nat_rock_n s_nat_rock_w s_nat_rock_e s_nat_rock_s)
+
+;;--------------------------------------------------------------------
+;; fix terrain types
+
+(define bad-terrain-list
+  (list t_bog
+        t_lava
+        t_deep_lava
+        t_fire_terrain
+        t_fireplace
+        t_inv_wall
+        t_wall_torch
+               t_lava_n t_lava_w t_lava_nw t_lava_e 
+               t_lava_ne t_lava_we t_lava_nwe t_lava_s 
+               t_lava_ns t_lava_ws t_lava_nws t_lava_es 
+               t_lava_nes t_lava_wes t_lava_c
+               t_lava
+               t_bog_nw t_bog_ne t_bog_nwe t_bog_ws 
+               t_bog_nws t_bog_es t_bog_nes t_bog_wes 
+               t_bog_c 
+        ))
+               
+(define inflammable-terrain-list
+  (list t_bog
+        t_deep
+        t_shallow
+        t_shoals
+        t_sunlit_deep
+        t_stars
+               t_void
+               t_chasm
+               t_bog_nw t_bog_ne t_bog_nwe t_bog_ws 
+               t_bog_nws t_bog_es t_bog_nes t_bog_wes 
+               t_bog_c 
+               t_shore_n t_shore_w t_shore_nw t_shore_e
+               t_shore_ne t_shore_we t_shore_nwe t_shore_s
+               t_shore_ns t_shore_ws t_shore_nws t_shore_es
+               t_shore_nes t_shore_wes t_shore_c
+               t_wshore_n t_wshore_w t_wshore_nw t_wshore_e
+               t_wshore_ne t_wshore_we t_wshore_nwe t_wshore_s
+               t_wshore_ns t_wshore_ws t_wshore_nws t_wshore_es
+               t_wshore_nes t_wshore_wes t_wshore_c
+               t_dshore_n t_dshore_w t_dshore_nw t_dshore_e
+               t_dshore_ne t_dshore_we t_dshore_nwe t_dshore_s
+               t_dshore_ns t_dshore_ws t_dshore_nws t_dshore_es
+               t_dshore_nes t_dshore_wes t_dshore_c
+               t_voids_n t_voids_w t_voids_nw t_voids_e 
+               t_voids_ne t_voids_we t_voids_nwe t_voids_s 
+               t_voids_ns t_voids_ws t_voids_nws t_voids_es 
+               t_voids_nes t_voids_wes t_voids_c 
+        ))
+               
\ No newline at end of file
diff --git a/worlds/haxima-1.002/bodies.png b/worlds/haxima-1.002/bodies.png
new file mode 100644 (file)
index 0000000..5aae0df
Binary files /dev/null and b/worlds/haxima-1.002/bodies.png differ
diff --git a/worlds/haxima-1.002/bole.scm b/worlds/haxima-1.002/bole.scm
new file mode 100644 (file)
index 0000000..0c452c0
--- /dev/null
@@ -0,0 +1,196 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map 
+ 'm_bole 48 39 pal_expanded
+       (list
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~6 ^a ^^ ^c ~6 ^a ^^ ^^ ~6 || || || || || || || || || ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^c t7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~6 |B || |% ~6 |# |% ^e ~6 || || || || || || || || || ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^c t3 tt tc {5 ^^ ^^ ^^ ^^ ^^ ^^ ~a ~5 |A |C ~6 |A |C ~3 ~c || || || || || || || || || |% ^a ^^ ^^ ^^ ^^ ^c |& ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ t3 tt tc t# .. {1 {5 ^^ ^^ ^^ ^c |& ~a ~1 ~~ ~~ ~~ ~1 ~c |# || || || || || || || || || || |% ^^ ^^ ^c |# || || |% ^e t3 tt tt tt t5 ^^ ^^ "
+               "^^ ^c tt t# .. .. .. .. .. {5 ^c tb tt || |% ~a ~~ bb ~~ ~c |# || || || tt tt tt tt tt tt tt tt || ^a ^c |# || || || || tt tc bb .. bb te ^a ^^ "
+               "^^ t3 tc .. .. .. .. .. .. .. bb .. t% tt || tH ~a ~~ ~c tG || || || tc t# .. .. .. t% ta tt tt || || || || || || |C ^7 tt bb .. .. .. bb t7 ^^ "
+               "^^ tt t# .. .. .. .. .. .. bb .. .. .. ta tt tt td ~6 tb tt || || tt t# tC t3 tt t5 tA .. t% ta tt tt tt || || || ^3 ^^ tt .. .. .. .. tb tt ^^ "
+               "^^ tt .. .. rr rr rr rr rr rr rr .. .. .. .. .. .. == .. t% ta tt tc .. t3 || || || || t5 .. .. .. t% tt || || |C ^^ ^^ tt bb .. .. .. bb tt ^^ "
+               "^^ tt .. .. rr .. .. .. .. .. rr .. .. tC t3 tt td ~6 t7 tA .. .. .. tC tt || || || || tt tA .. .. tC tt || |C ^3 ^^ ^^ ta t5 bb .. bb t3 tc ^^ "
+               "^^ tt .. .. rr .. .. .. .. .. rr .. .. t3 || || ~3 ~c || tt tt tt tt tt || || || || || tt t5 .. .. t3 tt || ^3 ^^ ^^ ^^ ^5 ta tt tt tt tc ^3 ^^ "
+               "^^ tt .. .. rr .. .. && .. .. .. .. .. tt || || ~6 |# || || || || || || || || || || || || tt .. tC tt || |C ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ tt .. .. rr .. .. .. .. .. rr .. .. tt || |C ~6 || || || || || || || || || || tt tt tt tc .. t3 || |C ^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ tt .. .. rr .. .. .. .. .. rr .. .. tt || ~3 ~c tt tt tt tt tt tt tt tt || || tt t# .. .. tC tt || ^b ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ tt .. .. rr rr rr .. rr rr rr .. .. || |C ~6 t3 tt tt tt tt tt tt tt tt tt || tt .. t3 tt tt || || |% ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ tt tA .. .. .. .. .. .. bb .. .. tC || ~3 ~c tt xx xx xx xx xx xx xx xx tt tt tc .. tt tt tt tt tt tt t5 ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ tt t5 tA .. .. .. .. bb {8 tC t3 tt || ~6 t3 tt xx cc cc cc cc cc cc xx te bb .. tC tt tt tt tt tt tt tt tt td ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ta tt t5 .. .. .. {c ^^ ^c t3 tt || || ~6 tt tt xx cc xx cc cc cc cc xx .. .. .. t3 tt xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ^^ ^^ "
+               "^^ ^5 tt tt tA .. {c ^^ ^^ t3 tt || tt tc ~6 tt tt xx xx xx cc cc cc cc cc .. .. bb tt tt xx cc cc cc cc cc x! cc cc xx cc cc cc cc cc xx ^^ ^^ "
+               "^^ ^^ ta tt tt td ^^ ^^ ^c tt tt || tt ~3 ~c tt tt tt t5 xx cc cc cc cc xx .. .. tb tt tt xx cc cc x! cc cc cc cc cc xx cc cc cc cc cc xx ^^ ^^ "
+               "^^ ^^ ^5 ta tc ^3 ^^ ^^ t3 tt tt || tt ~6 t3 tt tt tt tt xx cc cc cc cc xx .. .. bb tt tt xx xx xx xx cc cc xx xx xx xx cc cc cc cc cc xx ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c tt || || tt tc ~6 tt || || tt tt xx xx xx && xx xx .. .. .. ta tt xx cc cc cc cc cc cc cc cc xx cc cc cc cc cc xx ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^c t3 tt || tt tc ~3 ~c tt || || tt tt tt t5 xx xx xx t7 bb .. .. bb tt xx cc cc x! cc cc x! cc cc xx cc cc cc cc cc xx ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ t3 tt tt tt tt tc ~3 ~c t3 tt || || || tt tt tt tt tt tt tt td .. .. tb tt xx xx xx xx cc cc xx xx xx xx xx xx xx cc cc xx ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ tt || || || tt ~3 ~c t3 tt || || || || || || tt tt tt tt tt bb .. .. bb tt xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ tt || || tt tc ~6 t3 tt || || || || || || || || || tt tt tt td .. .. tb tt xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+               "^^ |& ^a ^^ ^c ta tt tt tc ~3 ~c tt || || || || || || || || || || || tt bb .. .. .. bb te xx cc cc 00 cc cc xx xx xx cc cc cc cc cc cc xx ^^ ^^ "
+               "|| || |% ^a td td ta tL ~3 ~4 t3 tt || || || || || || || || || || || tc .. .. .. .. .. .. sI cc cc 00 cc cc && xx && cc cc cc xx cc cc xx ^^ ^^ "
+               "|| || tt td td tL ~3 ~~ ~~ ~4 tt || || || || || || tt tt tt || || || bb .. .. .. .. .. .. cc cc cc 00 cc cc && xx && cc cc cc xx xx xx xx ^^ ^^ "
+               "|| tt tt ~3 ~1 ~~ ~~ ~~ ~~ ~4 tt || || || || || tt tt tt tt tt || || t5 .. .. .. .. .. .. xx cc cc 00 cc cc xx xx xx cc cc cc cc cc cc xx ^^ ^^ "
+               "tt tt tt ~2 ~~ b~ ~~ ~~ ~~ ~c tt || || || || tt tt tc ^7 ta tt tt || tt bb .. .. .. bb t7 xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+               "tt tt tt ~a ~~ ~~ ~~ b~ ~~ tG tt || || || tt tt tc ^3 ^^ ^5 ta tt || || tt td .. .. tb tt xx cc cc cc cc cc cc cc cc cc cc 00 xx cc cc xx ^^ ^^ "
+               "tt tt tt tH ~a ~~ ~~ ~~ ~c tt || || || || tt tt ^b ^^ ^^ ^^ ^d tt tt || || bb .. .. bb tt xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx ^^ ^^ "
+               "|| tt tt tt tH ~a ~8 ~c tG tt || || || || tt tt t5 ^a ^^ ^c t3 tt tt || || td .. .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt t5 ^^ ^^ ^^ "
+               "|| || || tt tt tt tt tt tt || || || tt tt tt tt tt tt tt tt tt tt || || tt bb .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt t5 ^a ^^ "
+               "|| || || || || tt tt tt || || || tt tt tt tt tt tt tt tt tt tt || || || tc .. .. .. tb tt tt || || || || || || || || || || || tt tt tt tt td ^^ "
+               "|| || || || || tt bb tt || || tt tt bb tt || || || || || || || || || || bb .. .. .. bb || || || || || || || || || || || || || || || tt tc ^3 ^^ "
+               "|| || || || || tt tt tt tt tt tt tt tt tt || || || || || || || || || || td .. .. tb tt || || || || || || || || || || || || || || || tt ^b ^^ ^^ "
+               "|| || || || || || tt tt tt tt tt tt || || || || || || || || || || || || bb .. .. bb || || || || || || || || || || || || || || || || tt t5 ^a ^^ "
+               "|| || || || || || || || || || || || || || || || || || || || || || || || t5 .. .. t3 || || || || || || || || || || || || || || || || || tt t5 ^^ "
+       )
+)
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "may.scm")
+(mk-may)
+
+(kern-load "kathryn.scm")
+(mk-kathryn)
+
+(kern-load "thud.scm")
+(mk-thud)
+
+(kern-load "bill.scm")
+(mk-bill)
+
+(kern-load "melvin.scm")
+(mk-melvin)
+
+(kern-load "hackle.scm")
+(mk-hackle)
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_bole     ; tag
+ "Bole"      ; name
+ s_hamlet           ; sprite
+ m_bole             ; map
+ #f                 ; wraps
+ #f                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ (list ;; objects
+
+   ;; Tag the special door used as the player's guest room:
+   (list (kern-tag 'bole-inn-room-door (mk-locked-door)) 33 17)
+
+   (list (mk-locked-door) 36 18)
+   (list (mk-locked-door) 33 20)
+   (list (mk-locked-door) 36 20)
+   (list (mk-locked-door) 42 25)
+   (list (mk-door) 42 28)
+   (list (mk-windowed-door) 30 27)
+   (list (mk-bed) 31 18)
+   (list (mk-bed) 38 18)
+   (list (mk-bed) 31 21)
+   (list (mk-bed) 38 21)
+   (list (mk-bed) 40 17)
+   (list (mk-bed) 44 17)
+   (list (mk-clock) 35 17)
+
+   ;; Bill's hut
+   (list (mk-locked-door) 24 17)
+   (list (mk-locked-door) 19 15)
+   (list (mk-bed) 23 19)
+
+   ;; Hackle's hut
+   (list (mk-bed) 5 8)
+   (list (mk-windowed-door-in-rock) 7 13)
+   (list (mk-windowed-door-in-rock) 10 10)
+
+   ;; Thief's door
+   (put (mk-thief-door 'p_traps_1 4 16) 43 6)
+
+   ;; npc's
+   (list ch_may   44 17)
+   (list ch_kathryn 31 18)
+   (list ch_thud 32 18)
+   (list ch_bill  22 8)
+   (put ch_melvin 44 17)
+   (put ch_hackle 0 0)
+   (put (mk-npc 'bull 1) 6 4)
+   )
+
+ ;; on-entry-hook
+ (list 'lock-inn-room-doors)
+
+ (list ;; edge entrances
+  (list north 26 38)
+  (list east  0  30)
+  (list northeast 7 38)
+  (list northwest 45 38)
+  )
+
+ )
+
+(mk-place-music p_bole 'ml-small-town)
+
+;;-----------------------------------------------------------------------------
+;; Make a special cave for the dryad so it doen't kill the town with its wolves
+;;-----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_dryad_grove 19 19 pal_expanded
+       (list
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^c |# || || || || || || || || || || |% ^a ^^ "
+               "^^ ^^ ^^ {3 tb tt tt || || tt tt tt || || || || || |% ^^ "
+               "^^ ^^ {3 .. tD tt tt tt tt tc t& ta tt tt || || || || || "
+               "^^ ^c t7 tE t3 tt tt tt tt tB .. tD tt tt tt tt || || || "
+               "^^ |# tt tt tt || || tt tt t5 tE t3 tt tt tt tt tt tt tt "
+               "^^ || || || || || || || || tt tt tt || || tt tt tt tt tt "
+               "^^ || || || || || || || || || || || || || tt tt tc t# .. "
+               "^^ || || || || || || || || || || || || || tt tt t# .. .. "
+               "^^ || || || || || || || || || || || || || tt tt .. .. .. "
+               "^^ || || tt tt tt || || || || || || || || tt tt tA .. .. "
+               "^^ || tt tt tt tt tt || || || || || || || tt tt t5 tA .. "
+               "^^ || tt tt tt tt tt tt || || || || || tt tt tt tt tt tt "
+               "^^ || tt tt tt tt tt tt tt || || || || tt tt tt tt tt tt "
+               "^^ || tt tt tt tt tt tt tt || || || tt tt tt || || || || "
+               "^^ || || tt tt tt tt tt tt || || || tt tt tt || || || || "
+               "^^ || || || tt tt tt tt || || || tt tc t& ta tt || |C ^^ "
+               "^^ |A || || || || || || || || || tc t# {8 t% ta |C ^3 ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+       )
+ )
+(kern-mk-place 
+ 'p_dryad_grove ; tag
+ "Dryad Grove"   ; name
+ nil     ; sprite
+ m_dryad_grove  ; map
+ #f               ; wraps
+ #f                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ ;; neighbors
+ (list
+  )
+ ;; objects
+ (list
+  (put (mk-npc 'dryad 8) 4 14)
+  (put (kern-mk-obj t_2H_axe 1) 5 15)
+  )
+
+ nil ; hooks
+ nil ; edge entrances
+ )
+
+(mk-dungeon-level 
+ (list p_dryad_grove p_bole)
+ )
+
+(mk-place-music p_dryad_grove 'ml-small-town)
diff --git a/worlds/haxima-1.002/books.png b/worlds/haxima-1.002/books.png
new file mode 100644 (file)
index 0000000..74c9184
Binary files /dev/null and b/worlds/haxima-1.002/books.png differ
diff --git a/worlds/haxima-1.002/books.scm b/worlds/haxima-1.002/books.scm
new file mode 100644 (file)
index 0000000..4b4902c
--- /dev/null
@@ -0,0 +1,1067 @@
+;; ----------------------------------------------------------------------------
+;; books.scm -- reading material
+;; ----------------------------------------------------------------------------
+
+(kern-mk-sprite-set 'ss_books 32 32 2 2 0 0 "books.png")
+
+(kern-mk-sprite 's_lexicon ss_books 1 0 #f 0)
+(kern-mk-sprite 's_manual  ss_books 1 1 #f 0)
+(kern-mk-sprite 's_scroll  ss_books 1 2 #f 0)
+
+;; Fixme: see if something like this will work for books:
+(define (mk-book tag name . text)
+  (mk-reusable-item 
+   tag name s_manual norm
+   (lambda ()
+     (kern-ui-page-text text))))
+
+;;----------------------------------------------------------------------------
+;; player manual
+(define (basic-survival-manual-commands)
+  (kern-ui-page-text
+   "Command Summary"
+   "Use the arrow keys to indicate direction."
+   "Use the ESC key to cancel commands."
+   "Use the first letter to start a command."
+   "For detailed info see the Users Guide."
+   ""
+   "A)ttack something"
+   "B)oard a ship or other vehicle"
+   "C)ast a spell"
+   "E)nter a town or dungeon"
+   "F)ire a ship's cannon or other ordnance"
+   "G)et something on the ground"
+   "H)andle a lever or other mechanism"
+   "L)oiter a few hours"
+   "N)ew-Order (rearrange party order)"
+   "O)pen a chest, door or other closed object"
+   "Q)uit and optionally save the game"
+   "R)eady arms for a party member"
+   "S)earch for hidden stuff"
+   "T)alk to somebody"
+   "U)se an item in inventory"
+   "Z)tats (show party status)"
+   "X)amine around"
+   "@)AT (info about place & time)"
+   "<space> (pass a turn)"
+   "CTRL-S)ave the game"
+   "CTRL-R)eload a game"
+   "SHIFT+ARROWKEY pan viewer"
+   )
+  result-ok)
+
+(mk-reusable-item 't_manual "Basic Survival Manual" s_manual (/ norm 3)
+                  basic-survival-manual-commands)
+
+;;----------------------------------------------------------------------------
+;; letter from enchanter
+(mk-reusable-item 
+ 't_letter_from_enchanter "Important Letter" s_lexicon norm
+ (lambda (klexicon kuser)
+   (kern-ui-page-text
+    "To the Wanderer -- IMPORTANT"
+   ""
+   "It is most ^c+rcritical^c- that you FIND ME. "
+   "The peasant who cares for this shrine can "
+   "point the way. Beware."
+   ""
+   "--Enchanter\n"
+   )
+   (quest-data-assign-once 'questentry-calltoarms)
+   result-ok))
+
+;;----------------------------------------------------------------------------
+;; book of the demon gate
+(mk-reusable-item 
+ 't_demon_gate_book "Ragged Text" s_scroll v-hard
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+   "THE DEMON GATE"
+   ""
+   "...the Wise of old locked the Demon Gate and scattered the keys... "
+   "the Shrine of the Demon Gate was not to be revealed again until the world is made ANEW... "
+   "they concealed the road to the Shrine with an illusion... "
+   "where there is a path, the unwise see only a mountain... "
+   ""
+   "... the River of Stars, and follow it to its source... "
+   ""
+   "...to he who opens the Gate, power unimaginable..."
+   ""
+   "...Nossifer awaits."
+   ""
+   "--Fildex the Unclean\n"
+   )
+   result-ok))
+
+;;----------------------------------------------------------------------------
+;; Kathryn's Letter
+(mk-reusable-item 
+ 't_kathryns_letter "Letter" s_scroll norm
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+   "Letter"
+   "K,"
+   "The Enchanter has one of the Runes. Acquire "
+   "it by any means necessary, and leave no one "
+   "to tell the tale. Not even a ghost."
+   "--S")
+   result-ok))
+
+
+;;----------------------------------------------------------------------------
+;; The soliloquy from Hamlet:
+(mk-reusable-item 
+ 't_playbook_hamlet "Playbook" s_scroll norm
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+   "A partial playbook"
+
+   "To be, or not to be: that is the question:"
+   "Whether 'tis nobler in the mind to suffer"
+   "The slings and arrows of outrageous fortune,"
+   "Or to take arms against a sea of troubles,"
+   "And by opposing end them? To die: to sleep;"
+   "No more; and by a sleep to say we end"
+   "The heart-ache and the thousand natural shocks"
+   "That flesh is heir to, 'tis a consummation"
+   "Devoutly to be wish'd. To die, to sleep;"
+   "To sleep: perchance to dream: ay, there's the rub;"
+   ""
+   "For in that sleep of death what dreams may come"
+   "When we have shuffled off this mortal coil,"
+   "Must give us pause: there's the respect"
+   "That makes calamity of so long life;"
+   ""
+   "For who would bear the whips and scorns of time,"
+   "The oppressor's wrong, the proud man's contumely,"
+   "The pangs of despised love, the law's delay,"
+   "The insolence of office and the spurns"
+   "That patient merit of the unworthy takes,"
+   "When he himself might his quietus make"
+   "With a bare bodkin? who would fardels bear,"
+   "To grunt and sweat under a weary life,"
+   "But that the dread of something after death,"
+   "The undiscover'd country from whose bourn"
+   "No traveller returns, puzzles the will"
+   "And makes us rather bear those ills we have"
+   "Than fly to others that we know not of?"
+   ""
+   "Thus conscience does make cowards of us all;"
+   "And thus the native hue of resolution"
+   "Is sicklied o'er with the pale cast of thought,"
+   "And enterprises of great pith and moment"
+   "With this regard their currents turn awry,"
+   "And lose the name of action.--Soft you now!"
+   "The fair Ophelia! Nymph, in thy orisons"
+   "Be all my sins remember'd."
+   )))
+
+;;----------------------------------------------------------------------------
+;; Spell books
+(mk-reusable-item 
+ 't_ylem_an_ex_book "spell book: YAE" s_manual hard
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+   "Web Spell- Ylem An Ex"
+   ""
+   "A useful spell for beginning spellcasters, "
+   "web allows a distant opponent to be "
+   "entangled and made helpless for a short "
+   "period of time."
+   ""
+   "If used correctly, it can also block an "
+   "area with webs temporarily, although this is "
+   "hard for novices to achieve."
+   ""
+   "The spell requires spider silk, of course, "
+   "and also black pearl, to project the web at "
+   "the desired target."
+   ""
+   "With the appropriate mixture, intone "
+   "Ylem An Ex (Matter to Negate Freedom) and "
+   "hurl the net of web at your foe."
+   ) 
+   result-ok))
+
+(mk-reusable-item 
+ 't_bet_flam_hur_book "spell book: BFH" s_manual hard
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+   "Fire Spray- Bet Flam Hur"
+   ""
+   "While the effectiveness of the Flame Wind spell is renowned, it is difficult to cast, exhausting, and well beyond the means of all but the greatest mages."
+   ""
+   "The Fire Spray spell is an adaption of the Flame Wind spell to more modest requirements. While it cannot be cast by an absolute beginner, it requires minimal ability. The effectiveness of the spell increases, of course, with the caster's ability."
+   ""
+   "The Fire Spray spell has a limited range- not much greater than a polearm- and does not have sufficient power to leave the blazing fields associated with the Flame Wind spell."
+   ""
+   "The spell requires sulphurous ash to power the flame. The initial launch of the spell is provided by black pearl, and blood moss instills the motion of the spreading cone of fire."
+   ""
+   "With this mixture, intone Bet Flam Hur (Small Fire Wind) and direct the cone to engulf your foes."
+   )
+   result-ok))
+
+(mk-reusable-item
+ 't_ranger_orders "Ranger orders" s_scroll norm
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+    "Ranger Orders"
+    ""
+    "The bearer of this letter may conscript "
+    "one (1) ranger into limited temporary "
+    "service.")
+   result-ok))
+
+(mk-reusable-item
+ 't_prisoner_receipt "Prisoner Receipt" s_scroll norm
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+    "Prisoner Receipt"
+    ""
+    "The bearer of this letter has delivered "
+    "one (1) prisoner to the gaoler.")
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; White Magick ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_white_magick_1 "White Magick: Booke I" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "White Magick: Booke I"
+    "Spells of Healing, of the First Circle"
+    "+-----------------------------------------+"
+    "|  M)ix thy reagents to craft a spell,    |"
+    "|  then C)ast it in thine hour of need.   |"
+    "|  Through lore of WHITE shall ye HEAL,   |"
+    "|  though as ye MEND be ye yet WISE!      |"
+    "+-----------------------------------------+"
+    "Cure Poison <AN NOX>"
+    "- Mix Ginseng and Garlic"
+    ""
+    "Awaken <AN ZU>"
+    "- Mix Ginseng and Garlic"
+    ""
+    "Minor Healing <MANI>"
+    "- Mix Ginseng and Spider Silk"
+    )
+   result-ok))
+
+(mk-reusable-item
+ 't_spell_book_white_magick_2 "White Magick: Booke II"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "White Magick: Booke II"
+    "Spells of Healing and Protection"
+    "+-----------------------------------------+"
+    "|  The Lore ye know to Mix and Cast.      |"
+    "|  Well-served by these chants be.        |"
+    "|  Yet forget not, oh Wise, of Duty,      |"
+    "|  to Heal all which come to thee.        |"
+    "+-----------------------------------------+"
+    "Poison Ward <SANCT NOX>"
+    "- Mix Garlic, Nightshade and Royal Cape"
+    ""
+    "Fire Ward <IN FLAM SANCT>"
+    "- Mix Sulphurous Ash, Garlic, "
+    "- and forget ye not: [SMUDGED WORD]"
+    ""
+    "Dispel Magic <An Ort Xen>"
+    "- Mix Sulphurous Ash, Garlic, Mandrake"
+    ""
+    "Protection <IN SANCT>"
+    "- Mix Sulphurous Ash, Garlic, Ginseng"
+    ""
+    "Mass Cure Poison <VAS AN NOX>"
+    "- Mix Garlic, Ginseng, Mandrake"
+    ""
+    "Great Heal <VAS MANI>"
+    "- Mix Ginseng, Spider Silk, Mandrake"
+    )
+   result-ok))
+
+(mk-reusable-item
+ 't_spell_book_white_magick_3 "White Magick: Booke III"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "White Magick: Booke III"
+    "Spells of Healing, of High Magick"
+    "+-----------------------------------------+"
+    "|  Mix ye now, and Crowned Master, Cast!  |"
+    "|   But beckon, Power to thee hastens!    |"
+    "|    If ye be Wise, then act ye thus:     |"
+    "|  KAL WIS - IN MANI - AN CORP - ZU QUAS  |"
+    "+-----------------------------------------+"
+    "Mass Cure Poison <VAS AN NOX>"
+    "- Mix Ginseng, Garlic, Mandrake"
+    ""
+    "Mass Poison Ward <VAS SANCT NOX>"
+    "- Mix Garlic, Nightshade, Mandrake and Royal Cape"
+    ""
+    "Great Heal <VAS MANI>"
+    "- Mix Ginseng, Spider Silk, Mandrake"
+    ""
+    ""
+    "--------------- HIGH MAGICK --------------"
+    ""
+    "Resurrection <IN MANI CORP>"
+    "- Mix Ginseng, Garlic, Spider Silk"
+    "-     Sulphurous Ash, Blood Moss, Mandrake"
+    ""
+    "  -- Slay not that which should live! -- "
+    "  -- Raise not that which ought rest! -- "
+
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Force Magick ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_force_magick_12 "Magick of Force: Booke I" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: Booke I"
+    "Spells of Might, of the Circles I, II      "
+    "+-----------------------------------------+"
+    "|  M)ix thy reagents to craft a spell,    |"
+    "|  then C)ast it in thine hour of need.   |"
+    "|  By FORCE shall thy foes know FEAR,     |"
+    "|  yet FOOLS thus casting shall know WOE! |"
+    "+-----------------------------------------+"
+    "Spells of the Circle I:"
+    "-----------------------"
+    "Magic Missile <GRAV POR>"
+    "- Mix Sulphurous Ash and Black Pearl"
+    ""
+    "Light <IN LOR>"
+    "- Mix Sulphurous Ash"
+    ""
+    "------------------------"
+    "Spells of the Circle II:"
+    "------------------------"
+    "Change Wind <REL HUR>"
+    "- Mix Sulphurous Ash and Blood Moss"
+    ""
+    "Fire Spray <BET FLAM HUR>"
+    "- Mix Sulphurous Ash, Blood Moss, "
+    "-     and Black Pearl"
+    ""
+    "Poison Bolt <IN NOX POR>"
+    "- Mix Nightshade, Blood Moss, "
+    "-     and Black Pearl"
+    )
+   result-ok))
+
+(mk-reusable-item
+ 't_spell_book_force_magick_battle "Magick of Force: Of Battle"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: Of Battle"
+    "+-----------------------------------------+"
+    "|    Battle near: Chant runes and Mix     |"
+    "|      Battle on: Cast and hurl           |"
+    "|  Thy foes know pain, and death indeed   |"
+    "|  Yet wield ye but Might, or be ye Wise? |"
+    "+-----------------------------------------+"
+    "Spells of the Circle I:"
+    "-----------------------"
+    "Magic Missile <GRAV POR>"
+    "- Mix Sulphurous Ash and Black Pearl"
+    ""
+    "Lightning Bolt <ORT GRAV>"
+    "- Mix Sulphurous Ash, Black Pearl, Mandrake"
+    ""
+    "-------------------------"
+    "Spells of the Circle III:"
+    "-------------------------"
+    "Fire Ball <VAS FLAM>"
+    "- Mix Sulphurous Ash, Black Pearl"
+    ""
+    "Fire Ward <IN FLAM SANCT>"
+    "- Mix Sulphurous Ash, [CHARRED WORD], "
+    "- and forget ye not: Royal [ASHY SMUDGE]"
+    ""
+    "------------------------"
+    "Spells of the Circle VI:"
+    "------------------------"
+    "Tremor <IN VAS POR YLEM>"
+    "- Mix Sulphurous Ash, Blood Moss, Mandrake"
+    )
+   result-ok))
+
+
+(mk-reusable-item
+'t_spell_book_force_magick_winds "Magick of Force: Deadly Winds"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: Deadly Winds"
+    "+-----------------------------------------+"
+    "|  For Wind ye shall Mix, for Wind Cast!  |"
+    "|  Thy foe, sleeping, shall know naught,  |"
+    "|  Thy foe, struck, shall burn or fester, |"
+    "|       Yet, can ye Change the Wind?      |"
+    "|  For what Wind changes not, blows not.  |"
+    "|      Shall ye then have Changed it?     |"
+    "+-----------------------------------------+"
+    "Spells of the Circle I and II:"
+    "------------------------------"
+    "Conjure Smoke <Bet Ylem Hur>"
+    "- Mix Sulphurous Ash"
+    ""
+    "Change Wind <REL HUR>"
+    "- Mix Sulphurous Ash, Blood Moss"
+    ""
+    "Fire Spray <BET FLAM HUR>"
+    "- Mix Sulphurous Ash, Blood Moss, "
+    "-     and Black Pearl"
+    ""
+    "-------------------------"
+    "Spells of the Circle VII:"
+    "-------------------------"
+    "Wind of Sleep <IN ZU HUR>"
+    "- Mix Ginseng, Blood Moss, Mandrake"
+    ""
+    "Poison Wind <IN NOX HUR>"
+    "- Mix Sulphurous Ash, Blood Moss, "
+    "-     and Nightshade"
+    ""
+    "--------------------------"
+    "Spells of the Circle VIII:"
+    "--------------------------"
+    "Flame Wind <IN FLAM HUR>"
+    "- Mix Sulphurous Ash, Blood Moss, "
+    "-     and Mandrake"
+    )
+   result-ok))
+(mk-reusable-item
+'t_spell_book_force_magick_matter "Magick of Force: Upon Matter"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: Upon Matter"
+    "+-----------------------------------------+"
+    "|  Mix and Cast, by Force control Matter. |"
+    "|  Powers subtle and grand both wield.    |"
+    "|  If ye be wise then riddle this rede:   |"
+    "|    What secret, steel? (Flesh is soft)  |"
+    "|    What sound, one hand? (Butterfly)    |"
+    "+-----------------------------------------+"
+    "Spells of the Circles I and II:"
+    "-------------------------------"
+    "Disarm Trap <AN SANCT YLEM>"
+    "- Mix Blood Moss"
+    ""
+    "Unlock <AN SANCT>"
+    "- Mix Sulphurous Ash, Blood Modd"
+    ""
+    "Lock <SANCT>"
+    "- Mix Sulphurous Ash, Spider Silk"
+    ""
+    "Change Wind <REL HUR>"
+    "- Mix Sulphurous Ash, Blood Moss"
+    ""
+    "------------------------"
+    "Spells of the Circle VI:"
+    "------------------------"
+    "Tremor <IN VAS POR YLEM>"
+    "- Mix Sulphurous Ash, Blood Moss, Mandrake"
+    ""
+    "Telekinesis <IN REL POR>"
+    "- Mix Spider Silk, Blood Moss, Black Pearl"
+    ""
+    "----------------"
+    "[Scrawled Notes]"
+    "----------------"
+    "Raise Matter Above Water <VAS UUS YLEM>"
+    "- Trial 1: Mix Ash, Pearl, Mandrake ???"
+    "- Trial 2: Mix [CHARRED], Eye of Newt ?"
+    "- Gazer eyes? Dragon spleen? Ogre spittle?"
+    )
+   result-ok))
+
+(mk-reusable-item
+'t_spell_book_force_magick_mechanismus "Magick of Force: Mechanismus"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: Mechanismus"
+    "+-----------------------------------------+"
+    "|  Knowing, Mix, and with craft, Cast!    |"
+    "|  Fear ye luggage? Chest dangers, past!  |"
+    "|  Keys bereft? Claviger be thou despite! |"
+    "|    Glowing portal bar not this wight!   |"
+    "|      Keep in tempo, keep in vogue       |"
+    "|        Keep in Time (or its Lord)       |"
+    "|      With such runes, let no wrogue     |"
+    "|     snatch the closing [MISSING WORD]   |"
+    "+-----------------------------------------+"
+    "Spells of the Circles I and II:"
+    "-------------------------------"
+    "Disarm Trap <An Sanct Ylem>"
+    "- Mix Blood Moss"
+    ""
+    "Unlock <An Sanct>"
+    "- Mix Sulphurous Ash, Blood Moss"
+    ""
+    "Lock <Sanct>"
+    "- Mix Sulphurous Ash, Spider Silk"
+    ""
+    "-----------------------"
+    "Spells of the Circle V:"
+    "-----------------------"
+    "Magic Unlock <In Ex Por>"
+    "- Mix Sulphurous Ash, Blood Moss"
+    ""
+    "Magic Lock <An Ex Por>"
+    "- Mix Sulphurous Ash, Garlic, Blood Moss"
+    )
+   result-ok))
+
+(mk-reusable-item
+'t_spell_book_force_magick_fields "Magick of Force: Upon Fields"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: Upon Fields"
+    "+-----------------------------------------+"
+    "|  Mix and Cast, by powers form Fields.   |"
+    "|  Conjure Sleep, Poison, Fire, or Force, |"
+    "|  or should such bar ye, then Dispel.    |"
+    "|  IN GRAV - AN POR - AN GRAV - EX POR    |"
+    "+-----------------------------------------+"
+    "Spells of the Circle III:"
+    "-------------------------"
+    "Sleep Field <In Zu Grav>"
+    "- Mix Ginseng, Spider Silk, Black Pearl"
+    ""
+    "Poison Field <In Nox Grav>"
+    "- Mix Spider Silk, Black Pearl, Nightshade"
+    ""
+    "Fire Field <In Flam Grav>"
+    "- Mix Sulphurous Ash, Spider Silk, "
+    "-     Black Pearl"
+    ""
+    "------------------------"
+    "Spells of the Circle IV:"
+    "------------------------"
+    "Force Field <In Sanct Grav>"
+    "- Mix Spider Silk, Black Pearl, Mandrake"
+    ""
+    "Dispel Field <An Grav>"
+    "- Mix Sulphurous Ash, Black Pearl"
+    )
+   result-ok))
+
+(mk-reusable-item
+'t_spell_book_force_magick_high_magick "Magick of Force: High Magick"  s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Magick of Force: High Magick"
+    "+-----------------------------------------+"
+    "|  BE WARE, be ye not Mighty in deed!     |"
+    "|    BEWARE, be ye not Wise indeed!       |"
+    "|  Written here are runes of HIGH MAGICK  |"
+    "|  If ye be a FOOL, ye shall know DEATH   |"
+    "|  Yet if you would, here is graven POWER |"
+    "+-----------------------------------------+"
+    "Circle VI - Negate Magic <In An>"
+    "- Mix Sulphurous Ash, Garlic, Mandrake"
+    ""
+    "Circle VII - Death Bolt <Xen Corp>"
+    "- Mix Black Pearl, Mandrake"
+    ""
+    "Circle VIII - Death Wind <In Vas Grav Corp>"
+    "- Mix Sulphurous Ash, Nighthsade, Mandrake"
+    ""
+    "Circle VIII - Time Stop <An Tym>"
+    "- Mix Garlic, Blood Moss, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Necromancy ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_necromancy "Mysteries of Death and Undeath" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Mysteries of DEATH and UNDEATH             "
+    "+-----------------------------------------+"
+    "| Sanctus Corporem ex Nihilo, Rel Oculume |"
+    "| De Vermiis Mysteriis, Astralis Sangrem  |"
+    "+-----------------------------------------+"
+    "II - Turn Undead <An Xen Corp>"
+    "- Mix Sulphurous Ash, Garlic"
+    ""
+    "VIII - Summon Undead <Kal Xen Corp>"
+    "- Mix Spider Silk, Nightshade, Mandrake"
+    ""
+    "II - Poison Bolt <In Nox Por>"
+    "- Mix Blood Moss, Black Pearl, Nightshade"
+    ""
+    "VII - Poison Wind <In Nox Hur>"
+    "- Mix Sulphrous Ash, Blood Moss, Nightshade"
+    ""
+    "VII - Death Bolt <Xen Corp>"
+    "- Mix Black Pearl, Nightshade"
+    ""
+    "VII - Clone <In Quas Xen>"
+    "- Mix Sulphurous Ash, Ginseng, Spider Silk,"
+    "-     Blood Moss, Nightshade, Mandrake"
+    ""
+    "VIII - Resurrection <In Mani Corp>"
+    "- Mix Sulphurous Ash, Ginseng, Garlic, "
+    "-     Spider Silk, Blood Moss, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Summoning ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_summoning "Summoning: Beasts and Entities" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Summoning: Beasts and Entities"
+    "+-----------------------------------------+"
+    "| KAL     To the Summoner - BEWARE    KAL |"
+    "| CORP         Lest ye Call Up,       XEN |"
+    "| BET  That which ye cannot Send Back ORT |"
+    "| SANCT  [ABRAD] - [ACAD] - [ABRA]   YLEM |"
+    "+-----------------------------------------+"
+    "II - Summon Vermin <In Bet Xen>"
+    "- Mix Sulphurous Ash, Blood Moss, "
+    "-     Spider Silk"
+    ""
+    "V - Summon Beast <Kal Xen>"
+    "- Mix Spider Silk, Mandrake"
+    ""
+    "VIII - Summon Slime <Kal Xen Nox>"
+    "- Mix Spider Silk, Nightshade, Mandrake"
+    ""
+    "VIII - Summon Undead <Kal Xen Corp>"
+    "- Mix Spider Silk, Nightshade, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Dimensions and Gate Magick ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_gate_magick "Upon Dimensions: Gates" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Upon Dimensions: Gates"
+    "+-----------------------------------------+"
+    "| In Travel, is Freedom indeed, oh Seeker |"
+    "|       IN POR - IN WIS - EX POR WIS      |"
+    "|                                         |"
+    "| The Lore of Moons - Controls the Gates! |"
+    "|      SUN - FYER  Radiant 24  (12,12)    |"
+    "|     MOON - LUMIS Yellow  60, (5)x8      |"
+    "|     MOON - ORD   Blue    36, (9)x8      |"
+    "|                                         |"
+    "| If ye be Wise        Watch Wax and Wane |"
+    "+-----------------------------------------+"
+    "Locate <In Wis>"
+    "- Mix Nightshade"
+    ""
+    "Vision <In Quas Wis>"
+    "- Mix Nightshade, Mandrake"
+    ""
+    "Blink <Bet Por>"
+    "- Mix Blood Moss, Black Pearl"
+    ""
+    "Ascend <Uus Por>"
+    "- Mix it not, cast it not! Space tears!"
+    ""
+    "Descend <Des Por>"
+    "- Beware the warp! Seek ye not this lore!"
+    ""
+    "Quickness <Rel Tym>"
+    "- Mix Sulphurous Ash, Blood Moss, Mandrake"
+    ""
+    "Teleport Party <Vas Por>"
+    "- Mix Blood Moss, Black Pearl, Mandrake"
+    ""
+    "Gate <Vas Rel Por>"
+    "- Mix Sulphurous Ash, Black Pearl, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Enchantment ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_enchantment_wards "Enchantment: Wards" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Enchantment: Wards"
+    "+-----------------------------------------+"
+    "| SANCT -     Protect Thyself!    - SANCT |"
+    "|  Mix Wards!  Cast spells of Protection! |"
+    "|  Surround thyself with Fields of Force  |"
+    "| Seeker   - Ye are in Danger! -  Beware! |"
+    "+-----------------------------------------+"
+    "Poison Ward <Sanct Nox>"
+    "- Mix Garlic, Nightshade, Royal Cape"
+    ""
+    "Fire Ward <In Flam Sanct>"
+    "- Mix [BLURRED], [SMEARED],"
+    "      and the Cap of the Coastal Prince"
+    ""
+    "Mass Poison Ward <Vas Sanct Nox>"
+    "- Mix Garlic, Nightshade, Mandrake, Royal Cape"
+    ""
+    "Protection <In Sanct>"
+    "- Mix Sulphurous Ash, Ginseng, Garlic"
+    ""
+    "Dispel Magic <An Ort Xen>"
+    "- Mix Sulphurous Ash, Garlic, Mandrake"
+    ""
+    "Negate Magic <In An>"
+    "- Mix Sulphurous Ash, Garlic, Mandrake"
+    ""
+    "Force Field <In Sanct Grav>"
+    "- Mix Spider Silk, Black Pearl, Mandrake"
+    )
+   result-ok))
+
+(mk-reusable-item
+ 't_spell_book_enchantment_curses "Enchantment: Curses" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Enchantment: Curses"
+    "+-----------------------------------------+"
+    "|             To the Reader               |"
+    "|    Be ye ACCURSED, I strike ye BLIND!   |"
+    "|    ----------------------------------   |"
+    "|        Gentle Reader - Be ye Wise       |"
+    "|     Mix and Cast these Runes at Need    |"
+    "+-----------------------------------------+"
+    "Web <Ylem An Ex>"
+    "- Mix Spider Silk, Black Pearl"
+    ""
+    "Calm Spiders <An Xen Bet>"
+    "- Mix Garlic, Spider Silk"
+    ""
+    "Sleep <Xen Zu>"
+    "- Mix Ginseng, Spider Silk"
+    ""
+    "Charm Monster <An Xen Ex>"
+    "- Mix Spider Silk, Black Pearl, Nightshade"
+    ""
+    "Confusion <Quas An Wis>"
+    "- Mix Nightshade, Mandrake"
+    ""
+    "Fear <In Quas Corp>"
+    "- Mix Garlic, Nightshade, Mandrake"
+    )
+   result-ok))
+
+(mk-reusable-item
+ 't_spell_book_enchantment_miscellanea "Enchantment: Miscellanea" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Enchantment: Miscellanea"
+    "+-----------------------------------------+"
+    "| [SMUDGED TEXT] the Secrets!   [BLURRED] |"
+    "| Conceal the [STAIN] from [SMEARED WORD] |"
+    "| AN EX WIS -                  - KAL QUAS |"
+    "+-----------------------------------------+"
+    "Quickness <Rel Tym>"
+    "- Mix Sulphurous Ash, Blood Moss, Mandrake"
+    ""
+    "X-Ray Vision <Wis An Ylem>"
+    "- Mix Sulphurous Ash, Mandrake"
+    ""
+    "Invisibility <Sanct Lor>"
+    "- Mix Blood Moss, Nightshade, Mandrake"
+    ""
+    "Telekinesis <In Rel Por>"
+    "- Mix Spider Silk, Blood Moss, Black Pearl"
+    ""
+    "Poison Wind <In Nox Hur>"
+    "- Mix Sulphurous Ash,Blood Moss, Nightshade"
+    ""
+    "Wind of Sleep <In Zu Hur>"
+    "- Mix Ginseng, Blood Moss, Mandrake"
+    ""
+    "Time Stop <An Tym>"
+    "- Mix Garlic, Blood Moss, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Illusions, Misdirections, and Schemes ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_spell_book_illusion_1 "Illusions: Lesser Secrets" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Illusions: Lesser Secrets"
+    "+-----------------------------------------+"
+    "|          Be ye Wrogue, or Mage?         |"
+    "|   By Artifice, by Cunning, ye Survive   |"
+    "| Use well these Runes, Mix and Cast them |"
+    "+-----------------------------------------+"
+    "Conjure Smoke <Bet Ylem Hur>"
+    "- Mix Sulphurous Ash"
+    ""
+    "Detect Traps <Wis Sanct>"
+    "- Mix Sulphurous Ash"
+    ""
+    "Sleep <Xen Zu>"
+    "- Mix Ginseng, Spider Silk"
+    ""
+    "Calm Spiders <An Xen Bet>"
+    "- Mix Garlic, Spider Silk"
+    )
+   result-ok))
+
+(mk-reusable-item
+'t_spell_book_illusion_2 "Illusions: Greater Secrets" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Illusions: Greater Secrets"
+    "+-----------------------------------------+"
+    "|   Be ye Master Thief, or Cloaked Mage?  |"
+    "| Artifice Superlative                    |"
+    "|     Cunning Extraordinary               |"
+    "|         Survival Quotidian              |"
+    "|             Mix and Cast the Runes      |"
+    "|                 CAVEAT LECTOR           |"
+    "| NON CARBORUNDUM ILLEGITEMI              |"
+    "+-----------------------------------------+"
+    "Confusion <Quas An Wis>"
+    "- Mix Nightshade, Mandrake"
+    ""
+    "Charm Monster <An Xen Ex>"
+    "- Mix Spider Silk, Black Pearl, Nightshade"
+    ""
+    "Fear <In Quas Corp>"
+    "- Mix Garlic, Nightshade, Mandrake"
+    ""
+    "Invisibility <Sanct Lor>"
+    "- Mix Blood Moss, Nightshade, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Divination Magick ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+'t_spell_book_divination "Mysteries of Divination" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Mysteries of Divination"
+    "+-----------------------------------------+"
+    "|     IN WIS - AN QUAS - VAS KAL EX WIS   |"
+    "| Oh Seeker, are ye Wise? Riddle me then  |"
+    "|   I Seek the Seeker,  I Slay the Slayer |"
+    "|   I Wreak the Wrogue, I Work the Wright |"
+    "|              What then am I?            |"
+    "+-----------------------------------------+"
+    "Detect Traps <Wis Sanct>"
+    "- Mix Sulphurous Ash"
+    ""
+    "Disarm Trap <An Sanct Ylem>"
+    "- Mix Blood Moss"
+    ""
+    "Locate <In Wis>"
+    "- Mix Nightshade"
+    ""
+    "Vision <In Quas Wis>"
+    "- Mix Nightshade Mandrake"
+    ""
+    "Reveal <Wis Quas>"
+    "- Mix Sulphurous Ash, Nightshade"
+    ""
+    "X-Ray Vision <Wis An Ylem>"
+    "- Mix Sulphurous Ash, Mandrake"
+    )
+   result-ok))
+
+
+;;;;;;;;;;;;;;;;;;;; Master Spellbook ;;;;;;;;;;;;;;;;;;;;
+
+(mk-reusable-item
+ 't_basic_spell_book "Spell Book" s_manual (/ norm 3)
+ (lambda (kbook kuser)
+   (kern-ui-page-text
+    "Spell Book"
+    ""
+    "+-----------------------------------------+"
+    "|   M)ix thy reagents to craft a spell,   |"
+    "|   then C)ast it in thine hour of need.  |"
+    "|   This tome will always serve thee well |"
+    "|   but oh so carefully thou must read!   |"
+    "+-----------------------------------------+"
+    "                                           "
+    "................ Reagents ................."
+    "GI Ginseng                   SS Spider Silk"
+    "GA Garlic                    BP Black Pearl"
+    "SA Sulphurous Ash            BM Blood Moss "
+    "NI Nightshade                MA Mandrake   "
+    "................. Spells .................."
+    "-------------- First Circle ---------------"
+    "An Nox           Cure Poison    GI, GA     "
+    "An Zu            Awaken         GI, GA     "
+    "Grav Por         Magic Missile  SA, BP     "
+    "In Lor           Light          SA         "
+    "Mani             Heal           GI, SS     "
+    "Wis Sanct        Detect Trap    SA         "
+    "An Sanct Ylem    Disarm Trap    BM         "
+    "-------------- Second Circle --------------"
+    "An Sanct         Unlock         SA, BM     "
+    "An Xen Corp      Repel Undead   GA, SA     "
+    "In Wis           Locate         NI         "
+    "Rel Hur          Change Wind    SA, BM     "
+    "In Nox Por       Poison Missile NI, BM, BP "
+    "In Bet Xen       Summon Vermin  SS, BM, SA "
+    "-------------- Third Circle ---------------"
+    "In Flam Grav     Fire Field     SA, BP, SS "
+    "In Zu Grav       Sleep Field    GI, BP, SS "
+    "In Nox Grav      Poison Field   NI, BP, SS "
+    "Vas Flam         Fire Ball      BP, SA     "
+    "Vas Lor          Great Light    SA, MA     "
+    "-------------- Fourth Circle --------------"
+    "An Grav          Dispel Field   BP, SA     "
+    "In Sanct Grav    Energy Field   MA, BP, SS "
+    "In Sanct         Protection     SA, GI, GA "
+    "Wis Quas         Reveal Hidden  NI, SA     "
+    "Bet Por          Blink (Caster) BP, BM     "
+    "-------------- Fifth Circle ---------------"
+    "In Ex Por        Unlock Magic   SA, BM     "
+    "An Ex Por        Magic Lock     SA, BM, GA "
+    "In Zu            Sleep          GI, NI, SS "
+    "Vas Mani         Great Heal     GI, SS, MA "
+    "Rel Tym          Quickness      SA, BM, MA "
+    "Kal Xen          Summon Beast   SS, MA     "
+    "-------------- Sixth Circle ---------------"
+    "An Xen Ex        Charm          BP, NI, SS "
+    "In An            Negate Magic   GA, MA, SA "
+    "In Vas Por Ylem  Earthquake     BM, MA, SA "
+    "Quas An Wis      Confuse        MA, NI     "
+    "Wis An Ylen      Xray Vision    MA, SA     "
+    "In Rel Por       Telekinesis    BP, BM, SS "
+    "Vas Por          Teleport Party MA, BP, BM "
+    "------------- Seventh Circle --------------"
+    "In Nox Hur       Poison Wind    NI, SA, BM "
+    "In Quas Corp     Fear           NI, MA, GA "
+    "In Quas Wis      Peer           NI, MA     "
+    "In Quas Xen      Clone          NI, MA, SA,"
+    "...              ...            SS, BM, GI "
+    "Sanct Lor        Invisibility   NI, MA, BM "
+    "Xen Corp         Kill           NI, BP     "
+    "-------------- Eighth Circle --------------"
+    "An Tym           Time Stop      MA, GA, BM "
+    "In Flam Hur      Flame Wind     MA, SA, BM "
+    "In Vas Grav Corp Energy Wind    MA, SA, NI "
+    "In Mani Corp     Resurrect      GA, GI, SS,"
+    "...              ...            SA, BM, MA "
+    "Kal Xen Corp     Summon Undead  SS, MA, NI "
+    "Vas Rel Por      Gate Travel    SA, MA, BP "
+    )
+   result-ok))
+   
+;;----------------------------------------------------------------------------
+;; Anaxes letters
+(mk-reusable-item
+ 't_anaxes_letter "Letter to Anaxes" s_scroll v-hard
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+    "Letter"
+    ""
+    "Anaxes,                                      "
+    "                                             "
+    "My dearest love. The Twelve have cast you out" 
+    "(Luximene has them thoroughly cowed). He hath"
+    "issued an edict that the old religion is     "
+    "illegal, and all who show piety to any god   "
+    "but he are Accursed.                         "
+    "                                             "
+    "As I write, the legions of Glasdrin and      "
+    "Tulemane march on Brundegardt. I go to       "
+    "destroy them before they reach you. Seal the "
+    "entrance lest my sacrifice be in vain.       "
+    "                                             "
+    "Know, my love, that I never betrayed you. May"
+    "our spirits meet in the void, and Vale exact "
+    "his price from our enemies.                  "
+    "                                             "
+    "Love,                                        "
+    "  Isin                                       "
+    "                                             "
+    "P.S. The Titans are safe. I have seen that   "
+    "those who knew of them were slain.           "
+    )
+   result-ok))
+
+;;----------------------------------------------------------------------------
+;; Stewardess's Journal
+;;
+;; TODO: update last entry time to match when warritrix quest becomes available
+;; Journal should not be updated if stolen by wanderer (This would also destroy its applicability as evidence)
+;;
+(mk-reusable-item 
+ 't_stewardess_journal "Victoria's Journal" s_lexicon norm
+ (lambda (klexicon kuser)
+   (kern-ui-page-text
+    "Victoria's Journal"
+    ""
+    "1.3.1610"
+    "I fear that if the Warritrix grows more      "
+    "popular, then the next time she defies me it "
+    "will lead to open revolt. Extreme measures   "
+    "must be taken, I fear. I must be most        "
+    "careful. Perhaps 'our friends' can help us.  "
+    "They owe us a large debt. Not that they can  "
+    "be trusted. "
+    ""
+    "..."
+    ""
+    "11.13.1610"
+    "I finally managed to get that pest Valus     "
+    "out of the way. A little evidence in the     "
+    "right place, a few nasty rumours, and the    "
+    "people are ready to accept that he has become"
+    "a deviant drunkard. I believe the desperate  "
+    "fool would have had the temerity to strike   "
+    "the statue if I had not detained him in a    "
+    "cell. The statue's powers are probably a     "
+    "myth, but I see no point in taking chances.  "
+    ""
+    "..."
+    ""
+    "4.1.1611"
+    "S. has warned me that rumours of a Wanderer  "
+    "are afoot. S. is such a useful tool. I do    "
+    "wonder where he gets his information. I don't"
+    "know why he is worked up about a Wanderer,   "
+    "anyway. I'm sure the legends about them are  "
+    "greatly exaggerated. The last time a Wanderer"
+    "appeared, the Old Gods still walked the      "
+    "Shard, if the myths are true.                "
+    ""
+    "..."
+    ""
+    "6.12.1611"
+    "I have received word from S. All is prepared."
+    "I will suggest to Jeffries that the rumours  "
+    "of feral gints occupying the Lost Halls must "
+    "be investigated, and will insist on the      "
+    "Warritrix leading the expedition. They will  "
+    "expect gint riff-raff, not sorcery, and S.   "
+    "will ensure the way is shut behind them.     "
+    "There will be no escape, and if there is, I  "
+    "am not culpable. If anything, that fool      "
+    "Jeffries will go down for incompetence.      "
+    ""
+    "The only thing that could condemn me is this "
+    "journal. But no one will ever find it, and   "
+    "when I am queen of all the Shard the scribes "
+    "will need it for their histories.            "
+    ""
+    "..."
+   )
+   result-ok))
diff --git a/worlds/haxima-1.002/boom.wav b/worlds/haxima-1.002/boom.wav
new file mode 100644 (file)
index 0000000..bc0b7f1
Binary files /dev/null and b/worlds/haxima-1.002/boom.wav differ
diff --git a/worlds/haxima-1.002/bridge.scm b/worlds/haxima-1.002/bridge.scm
new file mode 100644 (file)
index 0000000..1592fbc
--- /dev/null
@@ -0,0 +1,36 @@
+
+;; The 'init signal is sent after the instance is created. This is our chance
+;; to initialize fields to non-default values. Note: all the pclass values are
+;; defined in game.scm.
+(define (bridge-init kbridge)
+  (kern-obj-set-pclass kbridge pclass-bridge))
+
+;; Define the interface for the type
+(define bridge-ifc
+  (ifc '()
+       (method 'init bridge-init)))
+
+;; Make an object type. This is like a "class" in OO languages.
+(mk-obj-type 'TF_ew_bridge  ;; tag
+             "bridge"       ;; name
+             s_ew_bridge    ;; sprite
+             layer-tfeat    ;; stacking layer
+             bridge-ifc     ;; interface
+             )
+
+(mk-obj-type 'TF_ns_bridge  ;; tag
+             "bridge"       ;; name
+             s_ns_bridge    ;; sprite
+             layer-tfeat    ;; stacking layer
+             bridge-ifc     ;; interface
+             )
+;; ----------------------------------------------------------------------------
+;; mk-bridge -- 'dir' is the orientation, one of the four cardinal directions
+;; and should be prepended by a single tick when called, as in 'north 'south
+;; 'east and 'west
+;; ----------------------------------------------------------------------------
+(define (mk-bridge dir)
+  (case dir
+    ((north) (bind (kern-mk-obj TF_ns_bridge 1) nil))
+    ((south) (bind (kern-mk-obj TF_ns_bridge 1) nil))
+    (else (bind (kern-mk-obj TF_ew_bridge 1) nil))))
diff --git a/worlds/haxima-1.002/brundegardt.scm b/worlds/haxima-1.002/brundegardt.scm
new file mode 100644 (file)
index 0000000..ae172a4
--- /dev/null
@@ -0,0 +1,1115 @@
+(kern-load "anaxes.scm")
+
+;;----------------------------------------------------------------------------
+;; Entrance to Brundegardt
+(kern-mk-place 
+ 'p_brundegardt     ; tag
+ "Brundegardt"      ; name
+ s_dungeon          ; sprite
+ (kern-mk-map 
+  nil 19 19 pal_expanded
+  (list
+               ".. .. .. .. .. .. .. .. .. .. ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. .. .. .. .. .. .. .. {4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. .. .. .. .. .. .. .. {4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. .. .. .. .. .. .. .. {4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ {7 ^^ "
+               ".. .. .. .. .. .. .. tC t3 tt t5 ^^ ^^ ^^ ^^ ^c |& {c ^^ "
+               ".. .. .. .. .. .. tC t3 tt tt tt ^^ ^^ ^^ ^^ |# |C ^^ ^^ "
+               ".. .. .. .. tC t3 tt tt tt tt || ^a ^^ ^^ ^^ || ^3 ^^ ^^ "
+               ".. .. .. .. tb tt tt tt tt || || |% ^^ ^^ ^^ || ^^ ^^ ^^ "
+               ".. .. .. .. tD tt tt || || || || || ^a ^^ ^c || ^^ ^^ ^^ "
+               ".. .. tC t3 tt tt tt || || || || || |% ^e |# |C ^^ ^^ ^^ "
+               ".. .. t3 tt tt tt tt tt || || || || || || || ^3 ^^ ^^ ^^ "
+               ".. .. tt tt tt tt tt tt tc bb .. bb .. bb ^3 ^^ ^^ ^^ ^^ "
+               ".. .. tt tt || || tt tt t# .. .. .. .. {4 ^^ ^^ ^^ ^^ ^^ "
+               ".. .. tt tt || || || tt .. .. .. .. .. .. {5 ^^ ^^ ^^ ^^ "
+               ".. .. tt tt || || || || bb .. .. && .. .. {4 ^^ ^^ ^^ ^^ "
+               ".. .. tt tt tt || || || .. .. .. .. .. .. {c ^^ ^^ ^^ ^^ "
+               ".. .. ta tt tt || || || bb .. .. .. .. {4 ^^ ^^ ^^ ^^ ^^ "
+               ".. .. t% tt tt tt || || || bb .. bb .. bb ^^ ^^ ^^ ^^ ^^ "
+               ".. .. .. tt tt tt tt || || || || || || ^^ ^^ ^^ ^^ ^^ ^^ "
+   ))
+ #f                 ; wraps
+ #f                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+  (put (spawn-pt 'troll) 12 14)
+  (put (spawn-pt 'troll) 11 15)
+  (put (let ((kriddle (mk-riddle 'noor 't_doorway 18 3 1 1 #t
+                                 "All who would pass must speak the password!")))
+         (riddle-set-rm-on-wrong! (gob kriddle) #f)
+         kriddle)
+       17 3)
+  )
+
+ (list 'on-entry-to-dungeon-room) ; hooks
+
+ ;; edge entrances
+ (list
+  (list west 18 3)
+  )
+ )
+
+(mk-place-music p_brundegardt 'ml-dungeon-adventure)
+
+;;----------------------------------------------------------------------------
+;; Brundegardt Keep
+(kern-mk-place 
+ 'p_brundegardt_keep     ; tag
+ "Brundegardt Keep"      ; name
+ nil
+ (kern-mk-map 
+  nil 25 25 pal_expanded
+  (list
+               "rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn rn rn rn rn r4 gg gg gg r2 "
+               "rn rn rn rn xx cc cc cc xx r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn r5 gg r3 rn "
+               "rn rn rn rn xx cc cc cc cc gg gg gg gg gg gg gg gg gg gg r2 rn r4 gg r2 rn "
+               "rn rn rn rn xx cc cc cc xx r1 r1 xx xx xx xx xx xx xx gg ra r8 rc gg r2 rn "
+               "rn rn rn rn xx xx cc xx xx xx xx xx cc cc cc cc cc xx gg gg gg gg gg r2 rn "
+               "rn rn rn rn xx xx cc xx cc cc cc xx cc cc cc cc cc xx xx xx xx xx xx xx xx "
+               "rn rn rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx cc cc cc xx "
+               "rn rn rn rn xx xx gg xx cc cc cc xx cc cc cc cc cc xx xx cc cc cc cc cc xx "
+               "rn rn rn rn xx xx cc xx xx xx xx xx cc cc cc cc cc xx xx cc xx cc cc cc xx "
+               "rn rn xx xx xx cc cc cc w+ cc xx xx xx xx cc xx xx xx xx cc xx xx xx xx xx "
+               "rn xx xx cc cc cc cc cc w+ cc xx xx xx xx cc xx cc cc cc cc cc cc cc cc xx "
+               "xx xx cc cc cc cc cc cc w+ cc xx cc cc xx cc xx cc [[ ]] cc [[ ]] cc cc xx "
+               "cc cc cc cc cc cc cc cc w+ cc cc cc cc cc cc xx cc cc cc cc cc cc cc cc xx "
+               "xx xx cc cc cc cc cc cc w+ cc xx cc cc xx cc xx cc [[ ]] cc [[ ]] cc cc xx "
+               "rn xx xx cc cc cc cc cc w+ cc xx xx xx xx cc xx cc cc cc cc cc cc cc cc xx "
+               "rn rn xx xx xx cc cc cc w+ cc xx xx xx xx cc xx xx xx xx cc xx xx cc xx xx "
+               "rn rn rn rn xx xx cc xx xx xx xx xx cc cc cc cc cc xx xx cc xx cc cc cc xx "
+               "rn rn rn rn xx xx cc xx cc cc cc xx cc cc cc cc cc xx xx cc xx cc cc cc xx "
+               "rn rn rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx cc cc cc xx "
+               "rn rn rn rn xx xx cc xx cc cc cc xx cc cc cc cc cc xx xx xx xx cc cc cc xx "
+               "xx xx xx xx xx xx cc xx xx xx xx xx cc cc cc cc cc xx rn rn xx xx xx xx xx "
+               "xx cc cc cc w+ cc cc cc xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+               "xx cc cc cc w+ cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+               "xx cc cc cc w+ cc cc cc xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+               "xx xx xx xx xx xx xx xx xx rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   ))
+ #f                 ; wraps
+ #t                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+
+  ;; mechanisms
+  (put (mk-locked-windowed-door) 6 4)
+  (put (kern-tag 'bgk-p1 (mk-portcullis)) 6 20)
+  (put (kern-tag 'bgk-p2 (mk-portcullis)) 8 22)
+  (put (kern-tag 'bgk-p3 (mk-portcullis)) 6 16)
+  (put (kern-tag 'bgk-p4 (mk-portcullis)) 6 8)
+  (put (mk-lever-on 'bgk-p1) 5 21)
+  (put (mk-lever 'bgk-p2) 1 21)
+  (put (mk-lever-on 'bgk-p3) 5 18)
+  (put (mk-lever-on 'bgk-p4) 5 6)
+  (put (mk-door) 7 6)
+  (put (mk-door) 11 6)
+  (put (mk-door) 14 9)
+  (put (mk-door) 13 12)
+  (put (mk-door) 10 12)
+  (put (mk-door) 14 15)
+  (put (mk-door) 11 18)
+  (put (mk-door) 7 18)
+  (put (mk-door) 17 18)
+  (put (mk-door) 19 15)
+  (put (mk-locked-door) 22 15)
+  (put (mk-door) 19 9)
+  (put (mk-door) 17 6)
+  (put (mk-magic-locked-door) 20 7)
+
+  ;; ladders
+  (put (mk-ladder-down 'p_ratling_warren 6 2) 6 2)
+  (put (mk-ladder-down 'p_ratling_warren 6 22) 6 22)
+  (put (mk-ladder-down 'p_ratling_warren 2 22) 2 22)
+  (put (mk-ladder-down 'p_ratling_warren 22 19) 22 19)
+
+  ;; npc generators
+  (put (spawn-pt 'skeletal-warrior) 6 14)
+  (put (spawn-pt 'skeletal-warrior) 6 10)
+  (put (spawn-pt 'skeletal-warrior) 6 22)
+  (put (spawn-pt 'skeletal-warrior) 6 2)
+  (put (spawn-pt 'skeletal-archer) 9 10)
+  (put (spawn-pt 'skeletal-archer) 9 10)
+  (put (spawn-pt 'skeletal-archer) 3 22)
+  (put (spawn-pt 'ghast) 9 6)
+  (put (spawn-pt 'ghast) 14 6)
+  (put (spawn-pt 'ghast) 12 12)
+  (put (spawn-pt 'ghast) 9 18)
+  (put (spawn-pt 'ghast) 14 18)
+  (put (spawn-pt 'ghast) 18 12)
+  (put (spawn-pt 'ghast) 21 12)
+
+  ;; loot
+  (put (kern-mk-obj t_sword 1) 8 5)
+  (put (kern-mk-obj t_sword 1) 9 5)
+  (put (kern-mk-obj t_sword 1) 10 5)
+  (put (kern-mk-obj t_shield 1) 8 7)
+  (put (kern-mk-obj t_shield 1) 9 7)
+  (put (kern-mk-obj t_shield 1) 10 7)
+  (put (kern-mk-obj t_sword 1) 8 17)
+  (put (kern-mk-obj t_sword 1) 9 17)
+  (put (kern-mk-obj t_sword 1) 10 17)
+  (put (kern-mk-obj t_shield 1) 8 19)
+  (put (kern-mk-obj t_shield 1) 9 19)
+  (put (kern-mk-obj t_shield 1) 10 19)
+  (put (kern-mk-obj t_bow 1) 11 11)
+  (put (kern-mk-obj t_bow 1) 12 11)
+  (put (kern-mk-obj t_arrow 20) 11 13)
+  (put (kern-mk-obj t_arrow 20) 12 13)
+  (put (mk-chest nil
+                 '((10 t_food))) 21 16)
+  (put (mk-mimic) 21 17)
+  (put (mk-mimic) 16 4)
+  (put (mk-chest nil
+                 '((5 t_wine))) 23 16)
+  (put (mk-chest nil
+                 '((5 garlic)
+                   (5 ginseng))) 23 17)
+  (put (mk-chest 'bomb-trap
+                 '((1 t_an_tym_scroll)
+                   (1 t_in_mani_corp_scroll)
+                   (1 t_wis_quas_scroll)
+                   (1 t_wis_an_ylem_scroll))) 23 6)
+  (put (mk-chest 'lightning-trap
+                 '((5 blood_moss)
+                   (5 black_pearl)
+                   (3 nightshade)
+                   (3 mandrake))) 23 7)
+  (put (mk-chest 'poison-trap
+                 '((1 t_staff)
+                   (1 t_dagger)
+                   (1 t_slime_vial)
+                   (3 t_heal_potion)
+                   (3 t_mana_potion))) 23 8)
+  )
+
+ (list 'on-entry-to-dungeon-room) ; hooks
+
+ ;; edge entrances
+ (list
+  (list west 24 22)
+  (list south 22 0)
+  )
+ )
+
+(mk-place-music p_brundegardt_keep 'ml-dungeon-adventure)
+
+;;----------------------------------------------------------------------------
+;; Cave Shrine
+(mk-dungeon-room
+ 'p_cave_shrine "Cave Shrine"
+ (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn ,V ,I ,G ,I ,L ,A ,N ,C ,E rn rn rn rn rn "
+               "rn rn rn r8 rc !! !! !! !! !! !! !! !! !! ra r8 rn rn rn "
+               "rn rn r4 gg gg gg gg gg gg gg gg gg gg gg gg gg r2 rn rn "
+               "rn rn rc gg gg gg dd bb dd dd dd bb dd gg gg gg ra rn rn "
+               "rn r4 gg gg gg gg dd dd dd dd dd dd dd gg gg gg gg r2 rn "
+               "rn r4 gg gg dd dd dd dd dd dd dd dd dd dd dd gg gg r2 rn "
+               "rn rc gg gg bb dd dd dd dd dd dd dd dd dd bb gg gg ra rn "
+               "r4 !! gg gg dd dd dd dd gg gg gg dd dd dd dd gg gg !! r2 "
+               "r4 !! gg gg dd dd dd dd gg aa gg dd dd dd dd gg gg !! r2 "
+               "r4 !! gg gg dd dd dd dd gg gg gg dd dd dd dd gg gg !! r2 "
+               "rn r5 gg gg bb dd dd dd dd gg dd dd dd dd bb gg gg r3 rn "
+               "rn r4 gg gg dd dd dd dd dd gg dd dd dd dd dd gg gg r2 rn "
+               "rn r4 gg gg gg gg dd dd dd gg dd dd dd gg gg gg gg r2 rn "
+               "rn rn r5 gg gg gg dd bb dd gg dd bb dd gg gg gg r3 rn rn "
+               "rn rn r4 gg gg gg gg gg gg gg gg gg gg gg gg gg r2 rn rn "
+               "rn rn rn r1 r5 gg gg gg gg gg gg gg gg gg r3 r1 rn rn rn "
+               "rn rn rn rn rn r1 r1 r5 gg gg gg r3 r1 r1 rn rn rn rn rn "
+               "rn rn rn rn rn rn rn r4 gg gg gg r2 rn rn rn rn rn rn rn "
+  )
+ (put (mk-anaxes) 9 8)
+ )
+
+(mk-place-music p_cave_shrine 'ml-dungeon-adventure)
+;;----------------------------------------------------------------------------
+;; Ratling Warren
+(kern-mk-place 
+ 'p_ratling_warren     ; tag
+ "Ratling Warren"      ; name
+ nil
+ (kern-mk-map 
+  nil 25 25 pal_expanded
+  (list
+               "rn rn rn rn xx xx xx xx xx rn rn r8 r8 r8 r8 r8 rn rn rn r8 r8 r8 r8 rn rn "
+               "rn rn rn rn xx cc cc cc xx rn rc bb dd dd dd bb ra rn rc bb dd dd bb ra rn "
+               "rn rn rn rn xx cc cc cc xx r4 dd dd dd dd dd dd dd r6 bb dd dd dd dd bb r2 "
+               "rn rn rn rn xx cc cc cc xx rn rd bb dd dd dd bb r3 r4 dd dd dd dd dd dd r2 "
+               "rn rn rn rn xx xx cc xx xx rc dd dd dd dd bb r3 rn r4 dd dd dd dd dd dd r2 "
+               "rn rn r8 rc %f .. dd .. dd dd dd dd bb dd dd r2 r8 r4 bb dd dd dd dd dd r2 "
+               "rn rc dd dd .. dd .. %f .. dd r3 r9 r9 r9 r9 rc bb ra rd bb dd dd dd bb r2 "
+               "r4 dd dd bb dd .. %f bb .. r3 rc dd dd bb bb dd dd dd dd dd dd dd dd r3 rn "
+               "rn r5 dd .. dd dd r3 r1 r1 rc dd dd dd dd dd dd dd dd dd dd dd dd dd r2 rn "
+               "rn rn r5 %f .. r3 rn rn rc dd dd dd dd dd dd dd dd dd dd dd dd dd bb r2 rn "
+               "rn rn r8 r9 r9 r8 r8 rc bb dd dd dd dd dd dd dd dd dd bb r3 r1 r1 r1 rn rn "
+               "rn rc %7 .. dd dd dd dd dd dd dd dd dd dd dd dd dd dd r3 rn rn rn rn rn rn "
+               "r4 %b %c .. dd dd dd dd dd dd dd dd dd dd dd dd dd dd r2 rn rn rn rn rn rn "
+               "r4 .. .. dd dd dd dd dd dd dd dd dd dd dd dd dd dd dd ra rn rn rn rn rn rn "
+               "r4 dd dd dd dd r3 r1 r5 bb dd dd dd dd dd dd dd dd dd bb r2 rn rn rn rn rn "
+               "r4 dd dd dd r3 rn rn rn r5 .. .. .. dd dd dd dd dd dd dd r2 r8 r8 rn rn rn "
+               "r4 dd dd .. r2 rn rn rn r4 bb %3 %d .. dd dd dd dd dd bb r6 dd dd ra rn rn "
+               "r4 dd .. %f r2 rn rn rn rn r5 %e .. dd dd dd dd dd dd r3 rc dd dd dd ra rn "
+               "r4 dd dd .. r2 rn rn rn rn r4 .. dd dd dd dd dd dd r3 r4 dd dd dd dd dd r2 "
+               "r4 bb dd bb r2 rn rn rn rn r4 bb dd dd dd dd dd bb r2 r4 dd dd dd dd dd r2 "
+               "xx rd dd rb xx r8 r8 xx xx r8 rd bb dd dd dd r3 r1 rn r4 dd dd dd dd dd r2 "
+               "xx cc cc cc w+ bb cc cc re bb dd dd dd dd dd r2 rn rn rn r5 dd dd dd dd r2 "
+               "xx cc cc cc rf cc cc cc dd dd dd dd dd .. dd r2 rn rn rn rn r5 dd dd r3 rn "
+               "xx cc cc bb w+ cc cc cc r7 bb dd dd .. %f bb r2 rn rn rn rn rn r1 r1 rn rn "
+               "xx xx r1 xx xx xx xx xx xx r1 r1 r1 r1 r1 r1 rn rn rn rn rn rn rn rn rn rn "
+   ))
+ #f                 ; wraps
+ #t                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+
+  ;; mechs
+  (put (kern-tag 'rw-p1 (mk-portcullis)) 6 4)
+  (put (mk-lever 'rw-p1) 7 1)
+
+  ;; prisoners (long dead)
+  (put (mk-corpse) 1 7)
+  (put (mk-corpse) 5 6)
+  (put (mk-corpse) 4 9)
+
+  ;; ladders
+  (put (mk-ladder-up 'p_brundegardt_keep 6 2) 6 2)
+  (put (mk-ladder-up 'p_brundegardt_keep 6 22) 6 22)
+  (put (mk-ladder-up 'p_brundegardt_keep 2 22) 2 22)
+  (put (mk-ladder-up 'p_brundegardt_keep 22 19) 22 19)
+
+  ;; loot chamber
+  (put (mk-chest nil '((5 t_gem))) 20 16)
+  (put (mk-chest nil '((100 t_gold_coins))) 21 16)
+  (put (mk-chest nil '((10 sulphorous_ash))) 19 18)
+  (put (mk-mimic) 19 19)
+  (put (mk-chest nil '((10 ginseng))) 19 20)
+  (put (mk-chest nil '((10 garlic))) 20 21)
+  (put (spawn-pt 'skeletal-warrior) 20 19)
+
+  ;; ratlings!
+  (put (guard-pt 'ratling-sorcerer) 13 13)
+  (put (guard-pt 'ratling-sorcerer) 12 13)
+  (put (guard-pt 'ratling-sorcerer) 14 14)
+  (put (spawn-pt 'ratling-swarmer) 2 22)
+  (put (spawn-pt 'ratling-swarmer) 20 4)
+  (put (spawn-pt 'ratling-swarmer) 2 22)
+  (put (spawn-pt 'ratling-swarmer) 13 15)
+
+  ;; ratling stash
+  (put (kern-mk-obj t_heal_potion 1) 20 1)
+  (put (kern-mk-obj t_torch 1) 21 1)
+  (put (kern-mk-obj t_dagger 1) 19 2)
+  (put (kern-mk-obj garlic 1) 20 2)
+  (put (kern-mk-obj t_cure_potion 1) 21 2)
+  (put (kern-mk-obj t_food 1) 22 2)
+  (put (kern-mk-obj t_gold_coins 1) 18 3)
+  (put (kern-mk-obj t_in_an_scroll 1) 19 3)
+  (put (kern-mk-obj ginseng 1) 20 3)
+  (put (kern-mk-obj t_picklock 1) 21 3)
+  (put (kern-mk-obj t_bolt 1) 22 3)
+  (put (mk-corpse) 23 3)
+
+  (put (kern-mk-obj t_int_potion 1) 18 4)
+  (put (mk-broken-clock s_clock_hand_s s_clock_hand_n "The clock reads 6:00") 19 4)
+  (put (kern-mk-obj t_mana_potion 1) 20 4)
+  (put (kern-mk-obj t_gem 1) 21 4)
+  (put (kern-mk-obj t_gold_coins 2) 22 4)
+  (put (kern-mk-obj t_arrow 1) 23 4)
+
+  (put (kern-mk-obj t_wine 1) 19 5)
+  (put (kern-mk-obj t_poison_immunity_potion 1) 20 5)
+  (put (kern-mk-obj t_pick 1) 21 5)
+  (put (kern-mk-obj t_oil 1) 22 5)
+
+  )
+  (list 'on-entry-to-dungeon-room) ; hooks
+ nil ;; edge entrances
+ )
+
+(mk-place-music p_ratling_warren 'ml-dungeon-adventure)
+;;----------------------------------------------------------------------------
+;; Tunnel Turn
+(kern-mk-place 
+ 'p_tunnel_turn "Tunnel Turn"
+ nil
+ (kern-mk-map 
+  nil 19 19 pal_expanded
+  (list
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn xx xx xx xx xx xx xx rn rn rn rn rn rn "
+   "rn rn rn rn rn rn xx cc cc cc cc cc xx rn rn rn rn rn rn "
+   "rn rn rn rn rn rn xx cc pp cc pp cc xx xx xx xx xx xx xx "
+   "rn rn rn rn rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc "
+   "rn rn rn rn rn rn xx cc pp cc pp cc xx xx xx xx xx xx xx "
+   "rn rn rn rn rn rn xx cc cc cc cc cc xx rn rn rn rn rn rn "
+   "rn rn rn rn rn rn xx xx xx cc xx xx xx rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn xx cc xx rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn xx cc xx rn rn rn rn rn rn rn rn "
+   "xx xx xx xx xx xx xx xx xx cc xx rn rn rn rn rn rn rn rn "
+   "cc cc cc cc cc cc cc cc cc cc xx rn rn rn rn rn rn rn rn "
+   "xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn rn rn rn rn "
+   "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+   ))
+ #f                 ; wraps
+ #t                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ (list
+  (put (mk-monman) 0 0)
+  (put (mk-windowed-door) 9 12)
+  (put (mk-windowed-door) 12 9)
+  (put (spawn-pt 'carabid) 9 9)
+  )
+  (list 'on-entry-to-dungeon-room) ; hooks
+ ;; edge entrances
+ (list
+  (list east 0 16)
+  )
+ )
+
+(mk-place-music p_tunnel_turn 'ml-dungeon-adventure)
+;; randomly scatter gems through the rocks
+(put-random-stuff p_tunnel_turn
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_nat_rock))
+                  (lambda (loc)
+                    (kern-obj-put-at (kern-mk-obj t_gem 1)
+                                     loc))
+                  10)         
+                  
+;;----------------------------------------------------------------------------
+;; Black River
+(mk-dungeon-room
+ 'p_black_canal "Black Canal"
+ (list
+               "rn rn r8 r8 r8 rn rn r8 r8 r8 r8 r8 rn rn rn rn rn rn rn "
+               "rn rc gg gg gg ra rc bb ~s _s _s _s ra rn rn rn rn rn rn "
+               "r4 gg gg bb gg gg ~s ~s ~s bb ~s _s _s ra rn rn rn rn rn "
+               "r4 gg gg gg gg ~s _s _s ~s ~s ~s _s _s _s ra r8 rn rn rn "
+               "rn r5 gg gg ~s _s _s _s _s _s ~s bb ~s _s _s _s r2 rn rn "
+               "rn rn r1 rd _s _s _s _s _s _s ~s ~s ~s bb ~s _s r2 rn rn "
+               "rn rn rc _s _s _s _s _s _s _s _s _s ~s ~s ~s _s r2 rn rn "
+               "xx xx _s _s _s _s _s _s _s _s _s _s _s ~s _s _s xx xx rn "
+               "xx ee ee oo ee ee ee oo ~s ee ee oo ee ee oo ee ee xx xx "
+               "cc ee ee ee ee ~s ee ee ee ee ee ee ee ee ee ee ee cc cc "
+               "xx ee ee oo ee ee ee oo ee ee ee oo ~s ee oo ee ee xx xx "
+               "xx xx _s ~s _s _s _s ~s _s _s _s ~s _s _s ~s _s xx xx rn "
+               "rn rn r5 ~s bb ~s _s _s _s _s _s _s _s _s _s rb rn rn rn "
+               "rn rn rc ~s ~s ~s bb ~s _s _s _s _s _s _s _s ~s ra rn rn "
+               "rn r4 ~s _s _s _s ~s _s _s _s _s ~s bb ~s _s _s ~s r2 rn "
+               "rn r4 _s _s _s _s _s _s _s _s _s _s ~s _s _s _s _s r2 rn "
+               "rn rn r5 _s _s _s _s _s _s _s _s _s _s _s _s _s r3 rn rn "
+               "rn rn rn r1 r5 _s _s r3 r1 r1 r1 r5 _s _s r3 r1 rn rn rn "
+               "rn rn rn rn rn r1 r1 rn rn rn rn rn r1 r1 rn rn rn rn rn "
+  ) 
+ (put (spawn-pt 'sludge-kraken) 9 4)
+ )
+
+(mk-place-music p_black_canal 'ml-dungeon-adventure)
+
+;; random loot corpses
+(put-random-stuff p_black_canal
+                  (mk-rect 1 1 4 4)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_gravel))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  8)
+                  
+;;----------------------------------------------------------------------------
+;; Tunnels
+(mk-dungeon-room
+ 'p_tunnels "Tunnels"
+ (list
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx cc cc cc xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx cc pp cc xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx cc cc cc xx rn rn rn rn rn rn rn "
+         "xx xx xx xx xx xx xx xx cc pp cc xx xx xx xx xx xx xx xx "
+         "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+         "xx xx xx xx xx xx xx xx cc pp cc xx xx xx xx xx xx xx xx "
+         "rn rn rn rn rn rn rn xx cc cc cc xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx cc pp cc xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx cc cc cc xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+         "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  )
+ (put (mk-locked-windowed-door) 7 9)
+ (put (mk-locked-windowed-door) 11 9)
+ (put (mk-corpse-with-loot) 8 8)
+ (put (mk-corpse-with-loot) 8 10)
+ (put (mk-corpse-with-loot) 10 8)
+ (put (mk-corpse-with-loot) 10 10)
+ (put (spawn-pt 'carabid) 9 7)
+ (put (spawn-pt 'carabid) 9 11)
+ )
+
+(mk-place-music p_tunnels 'ml-dungeon-adventure)
+
+;; randomly scatter gems through the rocks
+(put-random-stuff p_tunnels
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_nat_rock))
+                  (lambda (loc)
+                    (kern-obj-put-at (kern-mk-obj t_gem 1)
+                                     loc))
+                  10)
+
+;;----------------------------------------------------------------------------
+;; Chasm Drawbridge
+(mk-dungeon-room
+ 'p_wide_chasm "Wide Chasm"
+ (list
+               "rn rn rn rn rn rn rn r8 r8 r8 r8 r8 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rc *3 *1 *1 *1 *5 ra rn rn rn rn rn rn "
+               "rn rn rn rn rn rc *3 vv vv vv vv vv *5 ra rn rn rn rn rn "
+               "rn rn rn rn r4 *3 vv vv vv vv vv vv vv *5 r2 rn rn rn rn "
+               "rn rn rn xx xx *2 vv vv vv vv vv vv vv *4 xx xx rn rn rn "
+               "rn rn xx xx cc *2 vv vv vv ee vv vv vv *4 cc xx xx rn rn "
+               "rn xx xx cc cc *2 vv vv *4 ee *2 vv vv *4 cc cc xx xx rn "
+               "xx xx cc cc cc *2 vv vv *c ee *a vv vv *4 cc cc cc xx xx "
+               "xx cc cc cc cc *2 vv vv ee ee ee vv vv *4 cc cc cc cc xx "
+               "cc cc cc cc cc *2 vv *4 ee oo ee *2 vv *4 cc cc cc cc cc "
+               "xx cc cc cc cc *2 vv vv ee ee ee vv vv *4 cc cc cc cc xx "
+               "xx xx cc cc cc *2 vv vv *5 ee *3 vv vv *4 cc cc cc xx xx "
+               "rn xx xx cc cc *2 vv vv *4 ee *2 vv vv *4 cc cc xx xx rn "
+               "rn rn xx xx cc *2 vv vv vv ee vv vv vv *4 cc xx xx rn rn "
+               "rn rn rn xx xx *2 vv vv vv vv vv vv vv *4 xx xx rn rn rn "
+               "rn rn rn rn r4 *a vv vv vv vv vv vv vv *c r2 rn rn rn rn "
+               "rn rn rn rn rn r5 *a vv vv vv vv vv *c r3 rn rn rn rn rn "
+               "rn rn rn rn rn rn r5 *a *8 *8 *8 *c r3 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn r1 r1 r1 r1 r1 rn rn rn rn rn rn rn "
+  )
+  (put (mk-weather-vane) 9 9)
+  (put (mk-wind-bridge) 5 5)
+  (put (spawn-pt 'bat) 9 8)
+  (put (spawn-pt 'bat) 9 9)
+  (put (spawn-pt 'bat) 8 8)
+  (put (spawn-pt 'bat) 8 10)
+  (put (spawn-pt 'bat) 10 9)
+  (put (spawn-pt 'bat) 10 10)
+  (put (mk-chest 'spike-trap
+       '((3 sulphorous_ash)
+         (3 blood_moss))) 14 7)
+ )
+
+(mk-place-music p_wide_chasm 'ml-dungeon-adventure)
+
+(kern-place-add-on-entry-hook p_wide_chasm 'set-wind-north)
+
+;;----------------------------------------------------------------------------
+;; Tower L1
+(mk-dungeon-room
+ 'p_brundegardt_tower_1 "BrundeGardt Tower L1"
+ (list
+  "rn rn rn rn rn xx xx xx xx xx xx xx xx xx rn rn rn rn rn "
+  "rn rn rn xx xx xx xx xx cc cc cc xx xx xx xx xx rn rn rn "
+  "rn rn xx xx xx cc cc xx cc cc cc xx cc cc cc cc xx rn rn "
+  "rn xx xx cc cc cc cc xx cc cc cc cc cc cc xx cc xx xx rn "
+  "rn xx xx cc xx xx xx xx xx cc xx xx xx xx xx cc cc xx rn "
+  "xx xx cc cc xx cc cc xx cc cc cc xx cc cc xx cc cc xx xx "
+  "xx xx cc cc xx cc cc xx cc cc cc cc cc cc xx cc cc xx xx "
+  "xx xx xx cc xx xx cc xx xx xx xx xx cc xx xx xx xx xx xx "
+  "xx cc cc cc xx cc cc cc cc cc cc xx cc cc xx cc cc cc xx "
+  "cc cc cc cc cc cc cc cc cc cc cc xx cc cc xx cc cc cc xx "
+  "xx cc cc cc xx cc cc cc cc cc cc xx cc cc xx cc cc cc xx "
+  "xx xx xx cc xx xx xx xx xx xx xx xx xx cc xx xx cc xx xx "
+  "xx xx cc cc xx cc cc xx cc cc cc cc cc cc xx cc cc xx xx "
+  "xx xx cc cc cc cc cc cc cc cc cc xx cc cc xx cc cc xx xx "
+  "rn xx ?? xx xx xx xx xx xx cc xx xx xx xx xx cc cc xx rn "
+  "rn xx cc xx cc cc cc xx cc cc cc xx cc cc xx cc xx xx rn "
+  "rn rn xx xx cc cc cc cc cc cc cc cc cc cc cc cc xx rn rn "
+  "rn rn rn xx xx xx xx xx cc cc cc xx xx xx xx xx rn rn rn "
+  "rn rn rn rn rn xx xx xx xx xx xx xx xx xx rn rn rn rn rn "
+  )
+
+ ;; doors
+ (put (mk-door) 4 9)
+ (put (mk-door) 3 7)
+ (put (mk-door) 3 11)
+ (put (mk-door) 4 13)
+ (put (mk-windowed-door) 7 13)
+ (put (mk-door) 11 16)
+ (put (mk-locked-door) 14 16)
+ (put (mk-door) 15 15)
+ (put (mk-magic-locked-door) 16 11)
+ (put (mk-door) 11 12)
+ (put (mk-door) 13 11)
+ (put (mk-windowed-door) 12 7)
+ (put (mk-windowed-door) 11 6)
+ (put (mk-locked-door) 9 4)
+ (put (mk-door) 11 3)
+ (put (mk-locked-windowed-door) 15 3)
+ (put (mk-door) 3 4)
+
+ (put (mk-portcullis) 7 8)
+ (put (mk-portcullis) 7 10)
+ (put (kern-tag 'bt1_p1 (mk-portcullis)) 7 9)
+ (put (kern-tag 'bt1_p2 (mk-portcullis)) 4 3)
+ (put (kern-tag 'bt1_p3 (mk-portcullis)) 7 16)
+ (put (kern-tag 'bt1_p4 (mk-portcullis)) 6 7)
+ (put (mk-lever 'bt1_p1) 16 6)
+ (put (mk-lever 'bt1_p3) 8 10)
+ (put (mk-lever 'bt1_p4) 2 15)
+
+ (put (mk-ladder-up 'p_brundegardt_tower_2 10 9) 10 9)
+
+ (put (spawn-pt 'yellow-slime) 8 16)
+ (put (spawn-pt 'yellow-slime) 10 16)
+ (put (spawn-pt 'yellow-slime) 9 13)
+
+ (put (spawn-pt 'ratling-sorcerer) 15 12)
+ (put (spawn-pt 'ratling-sorcerer) 16 12)
+
+ (put (spawn-pt 'insect) 5 12)
+ (put (spawn-pt 'insect) 6 12)
+ (put (spawn-pt 'insect) 5 13)
+ (put (spawn-pt 'insect) 6 13)
+
+ (put (guard-pt 'skeletal-warrior) 5 8)
+ (put (guard-pt 'skeletal-warrior) 5 10)
+ (put (guard-pt 'skeletal-spear-thrower) 8 9)
+ (put (guard-pt 'skeletal-spear-thrower) 9 9)
+
+ (put (spawn-pt 'giant-spider) 8 12)
+ (put (spawn-pt 'giant-spider) 8 6)
+
+ (put (spawn-pt 'rat) 2 5)
+ (put (spawn-pt 'rat) 3 5)
+
+ (put (spawn-pt 'giant-spider) 9 2)
+ (put (spawn-pt 'giant-spider) 8 1)
+
+ (put (spawn-pt 'giant-spider) 13 3)
+
+ (put (mk-corpse-with-loot) 5 5)
+ (put (mk-corpse-with-loot) 5 2)
+ (put (mk-corpse-with-loot) 6 3)
+ (put (mk-corpse-with-loot) 5 16)
+ (put (mk-corpse-with-loot) 2 9)
+
+ ;; demon room
+ (put (kern-mk-obj F_energy_perm 1) 15 9)
+ (put (kern-mk-obj F_energy_perm 1) 16 9)
+ (put (kern-mk-obj F_energy_perm 1) 17 9)
+ (put (mk-npc 'demon 4) 16 8)
+ (put (mk-chest 'bomb-trap
+                '((1 t_an_tym_scroll)
+                  (1 t_in_mani_corp_scroll)
+                  (1 t_xen_corp_scroll)
+                  (1 t_sanct_lor_scroll)
+                  (100 t_gold_coins)))
+      15 8)
+ (put (mk-chest 'poison-trap
+                '((1 t_str_potion)
+                  (1 t_dex_potion)
+                  (1 t_int_potion)
+                  (100 t_gold_coins)))
+      17 8)
+ )
+
+(mk-place-music p_brundegardt_tower_1 'ml-dungeon-adventure)
+
+;; random loot corpses
+(put-random-stuff p_brundegardt_tower_1
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_cobblestone))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  5)
+                  
+;;----------------------------------------------------------------------------
+;; Tower L2
+(mk-dungeon-room
+ 'p_brundegardt_tower_2 "BrundeGardt Tower L2"
+ (list
+               "rn rn r8 r8 rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rc bb bb ra r8 xx xx xx xx xx xx xx rn rn rn rn rn rn "
+               "r4 bb dd dd bb bb dd cc cc cc cc cc xx xx xx rn rn rn rn "
+               "r4 bb dd dd dd dd cc cc cc cc cc cc cc cc xx xx rn rn rn "
+               "rn r5 bb dd && dd cc pp cc cc cc pp cc cc cc xx xx rn rn "
+               "rn r4 bb dd dd dd cc cc cc cc cc cc cc cc cc cc xx rn rn "
+               "rn xx dd cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx rn "
+               "rn xx cc cc pp cc cc pp cc cc cc pp cc cc pp cc cc xx rn "
+               "rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn "
+               "rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn "
+               "rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn "
+               "rn xx cc cc pp cc cc pp cc cc cc pp cc cc pp cc cc xx rn "
+               "rn xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx rn "
+               "rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn rn "
+               "rn rn xx xx cc cc cc pp cc cc cc pp cc cc cc xx xx rn rn "
+               "rn rn rn xx xx cc cc cc cc cc cc cc cc cc xx xx rn rn rn "
+               "rn rn rn rn xx xx xx cc cc cc cc cc xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn xx xx xx xx xx xx xx rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  )
+ (put (mk-ladder-down 'p_brundegardt_tower_1 10 9) 10 9)
+ (put (mk-ladder-up 'p_brundegardt_tower_3 8 9) 8 9)
+ (put (spawn-pt 'troll-geomancer) 3 4)
+ (put (spawn-pt 'troll) 4 3)
+ (put (spawn-pt 'troll) 5 4)
+ (put (spawn-pt 'troll) 3 5)
+ )
+
+(mk-place-music p_brundegardt_tower_2 'ml-dungeon-adventure)
+
+;;----------------------------------------------------------------------------
+;; Tower L3
+(mk-dungeon-room
+ 'p_brundegardt_tower_3 "BrundeGardt Tower L3"
+ (list
+  "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  "rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn "
+  "rn rn rn rn rn xx xx xx cc cc cc xx xx xx rn rn rn rn rn "
+  "rn rn rn rn xx xx cc cc cc cc cc cc cc xx xx rn rn rn rn "
+  "rn rn rn xx xx cc cc pp cc cc cc pp cc cc xx xx rn rn rn "
+  "rn rn rn xx cc cc cc cc cc cc cc cc cc cc cc xx rn rn rn "
+  "rn rn xx xx cc pp cc pp cc cc cc pp cc pp cc xx xx rn rn "
+  "rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn rn "
+  "rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn rn "
+  "rn rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn rn "
+  "rn rn xx xx cc pp cc pp cc cc cc pp cc pp cc xx xx rn rn "
+  "rn rn rn xx cc cc cc cc cc cc cc cc cc cc cc xx rn rn rn "
+  "rn rn rn xx xx cc cc pp cc cc cc pp cc cc xx xx rn rn rn "
+  "rn rn rn rn xx xx cc cc cc cc cc cc cc xx xx rn rn rn rn "
+  "rn rn rn rn rn xx xx xx cc cc cc xx xx xx rn rn rn rn rn "
+  "rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn "
+  "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  )
+ (put (mk-ladder-down 'p_brundegardt_tower_2 8 9) 8 9)
+ (put (mk-ladder-up 'p_brundegardt_tower_4 10 9) 10 9)
+ (put (spawn-pt 'queen-spider) 12 9)
+ (put (spawn-pt 'queen-spider) 9 12)
+ )
+
+(mk-place-music p_brundegardt_tower_3 'ml-dungeon-adventure)
+
+;;----------------------------------------------------------------------------
+;; Tower L4
+(kern-load "tim.scm")
+(mk-19x19-town
+ 'p_brundegardt_tower_4 "BrundeGardt Tower L4" nil
+ (list
+               "^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. "
+               "^. ^. ^. ^. ^. bb {1 {5 {{ {{ {3 {1 {1 bb ^. ^. ^. ^. ^. "
+               "^. ^. ^. bb {1 .. .. .. {1 {1 .. {8 {4 {{ {3 bb ^. ^. ^. "
+               "^. ^. {3 .. {8 {8 .. .. .. .. {4 {{ {2 {1 .. .. bb ^. ^. "
+               "^. ^. {2 {c {{ {{ xx w+ xx w+ xx w+ xx .. .. {c {{ ^. ^. "
+               "^. bb {4 {{ {{ xx xx cc cc cc cc cc xx xx {4 {{ {{ bb ^. "
+               "^. {a .. {1 xx xx xx xx xx cc cc cc cc xx xx {5 {{ {6 ^. "
+               "^. {{ {2 .. w+ cc cc cc xx cc cc pp cc cc w+ .. {1 .. bb "
+               "^. {3 .. .. xx cc cc cc xx cc cc cc cc cc xx .. .. .. .. "
+               "^. {a {8 .. w+ cc cc cc cc cc cc cc cc cc cc .. .. .. .. "
+               "^. {{ {{ {2 xx cc cc cc xx cc cc cc cc cc xx .. .. .. .. "
+               "^. {3 {1 .. w+ cc cc cc xx cc cc pp cc cc w+ .. {8 {8 bb "
+               "^. {2 .. .. xx xx xx xx xx cc cc cc cc xx xx {4 {{ {{ ^. "
+               "^. bb .. .. .. xx xx cc cc cc cc cc xx xx .. .. {1 bb ^. "
+               "^. ^. {2 .. .. .. xx w+ xx w+ xx w+ xx .. .. {8 {4 ^. ^. "
+               "^. ^. bb .. {8 .. .. .. .. {4 {{ {{ {2 .. {4 {{ bb ^. ^. "
+               "^. ^. ^. bb {{ {2 .. {8 .. .. {1 {1 .. .. {8 bb ^. ^. ^. "
+               "^. ^. ^. ^. bb bb {c {{ {a {8 {8 {8 {8 bb ^. ^. ^. ^. ^. "
+               "^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. "
+  )
+    nil ;;entrances
+ (put (mk-ladder-down 'p_brundegardt_tower_3 10 9) 10 9)
+ (put (mk-ladder-up 'p_brundegardt_tower_5 6 9) 6 9)
+ (put (mk-tim) 16 9)
+ (put (mk-corpse) 9 8)
+ (put (mk-corpse) 9 10)
+ (put (mk-corpse) 11 5)
+ (let ((kdoor (mk-door)))
+   (lock-door-with-key kdoor 't_brundegardt_tower_4_key)
+   (put kdoor 8 9))
+ )
+
+(mk-place-music p_brundegardt_tower_4 'ml-outdoor-adventure)
+
+;;----------------------------------------------------------------------------
+;; Tower L5
+(kern-load "eye-of-brune.scm")
+(mk-19x19-town
+ 'p_brundegardt_tower_5 "BrundeGardt Tower L5" nil
+ (list
+               "^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. "
+               "^. ^. ^. ^. ^. bb {1 {5 {{ {{ {3 {1 {1 bb ^. ^. ^. ^. ^. "
+               "^. ^. ^. bb {1 .. .. .. {1 {1 .. {8 {4 {{ {3 bb ^. ^. ^. "
+               "^. ^. {3 .. {8 {8 .. .. .. .. {4 {{ {2 {1 .. .. bb ^. ^. "
+               "^. ^. {2 {c {{ {{ ee ee ee x. ee ee ee .. .. {c {{ ^. ^. "
+               "^. bb {4 {{ {{ ee ee x. x. x. x. x. ee ee {4 {{ {{ bb ^. "
+               "^. {a .. {1 ee ee x. x. cc cc cc x. x. ee ee {5 {{ {6 ^. "
+               "^. {{ {2 .. ee x. x. cc cc cc cc cc x. x. ee .. {1 .. bb "
+               "^. {3 .. .. ee x. cc cc cc cc cc cc cc x. ee .. .. .. .. "
+               "^. {a {8 .. x. x. cc cc cc cc cc cc cc x. x. .. .. .. .. "
+               "^. {{ {{ {2 ee x. cc cc cc cc cc cc cc x. ee .. .. .. .. "
+               "^. {3 {1 .. ee x. x. cc cc cc cc cc x. x. ee .. {8 {8 bb "
+               "^. {2 .. .. ee ee x. x. cc cc cc x. x. ee ee {4 {{ {{ ^. "
+               "^. bb .. .. .. ee ee x. x. x. x. x. ee ee .. .. {1 bb ^. "
+               "^. ^. {2 .. .. .. ee ee ee x. ee ee ee .. .. {8 {4 ^. ^. "
+               "^. ^. bb .. {8 .. .. .. .. {4 {{ {{ {2 .. {4 {{ bb ^. ^. "
+               "^. ^. ^. bb {{ {2 .. {8 .. .. {1 {1 .. .. {8 bb ^. ^. ^. "
+               "^. ^. ^. ^. bb bb {c {{ {a {8 {8 {8 {8 bb ^. ^. ^. ^. ^. "
+               "^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. ^. "
+  )
+    nil ;;entrances
+ (put (mk-ladder-down 'p_brundegardt_tower_4 6 9) 6 9)
+ (put (kern-mk-obj t_eye_of_brune 1) 9 9)
+ (put (mk-corpse-with-loot) 8 9)
+ (put (mk-corpse-with-loot) 9 8)
+ (put (mk-corpse-with-loot) 10 10)
+ (put (kern-mk-obj t_spell_book_divination 1) 9 10)
+ (put (mk-ambient-sound 'sound-wind) 18 18)
+ )
+
+(mk-place-music p_brundegardt_tower_5 'ml-outdoor-adventure)
+
+(block-teleporting 
+ p_brundegardt_tower_5
+ (list
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# ee ee ee x. ee ee ee x# x# x# x# x# x# "
+  "x# x# x# x# x# ee ee x. x. x. x. x. ee ee x# x# x# x# x# "
+  "x# x# x# x# ee ee x. x. cc cc cc x. x. ee ee x# x# x# x# "
+  "x# x# x# x# ee x. x. cc cc cc cc cc x. x. ee x# x# x# x# "
+  "x# x# x# x# ee x. cc cc cc cc cc cc cc x. ee x# x# x# x# "
+  "x# x# x# x# x. x. cc cc cc cc cc cc cc x. x. x# x# x# x# "
+  "x# x# x# x# ee x. cc cc cc cc cc cc cc x. ee x# x# x# x# "
+  "x# x# x# x# ee x. x. cc cc cc cc cc x. x. ee x# x# x# x# "
+  "x# x# x# x# ee ee x. x. cc cc cc x. x. ee ee x# x# x# x# "
+  "x# x# x# x# x# ee ee x. x. x. x. x. ee ee x# x# x# x# x# "
+  "x# x# x# x# x# x# ee ee ee x. ee ee ee x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  )
+)                  
+
+;;----------------------------------------------------------------------------
+;; Griffin Peak
+(mk-19x19-town
+ 'p_griffin_peak_s "South Face of Griffin Peak" nil
+ (list
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {2 .. {4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {2 .. {4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^c bb .. .. .. bb ^a ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^c bb .. dd .. dd .. bb ^a ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ bb .. dd dd dd .. dd .. bb ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ .. dd dd dd dd dd dd dd .. ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ bb dd dd dd dd dd dd dd bb ^^ ^^ ^^ ^^ ^^ "
+               "^. ^. ^^ ^^ ^^ .. dd .. dd dd dd dd dd .. ^^ ^^ ^^ ^. ^. "
+               "{5 ^. ^. ^^ ^^ bb .. dd dd dd dd dd .. bb ^^ ^^ ^. ^. {3 "
+               "{4 {{ ^. ^. ^^ ^5 bb .. dd .. dd .. bb ^3 ^^ ^. ^. {{ {2 "
+               ".. {1 {5 ^. ^. ^^ ^5 bb .. dd .. bb ^3 ^^ ^^ ^. {{ {3 .. "
+               "^v .. .. {5 ^. ^. ^^ ^^ ^^ bb ^^ ^^ ^^ ^^ ^. ^. {3 .. ^v "
+               "^v ^v .. {4 {{ ^. ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {{ {2 .. ^v "
+               "^v ^v ^v .. {5 ^. ^. ^. ^^ ^^ ^^ ^^ ^. ^. {3 {9 .. .. ^v "
+               "^v ^v ^v .. .. {1 {5 ^. ^. ^^ ^. ^. ^. {3 {c {C bb .. ^v "
+               "^v ^v ^v {8 bb .. {4 {{ ^. ^. ^. {{ {3 {4 {{ bb .. .. ^v "
+               "^v ^v {4 {{ {2 .. .. {1 {1 {1 {1 {1 .. .. {1 .. .. bb ^v "
+               "^v ^v ^v {1 ^v ^v ^v .. .. .. .. .. ^v ^v ^v ^v ^v ^v ^v "
+               "^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v "
+  )
+    nil ;;entrances
+ (put (spawn-pt 'griffin) 9 13)
+ (put (spawn-pt 'griffin) 3 3)
+ (put (spawn-pt 'griffin) 9 17)
+ (put (mk-ambient-sound 'sound-wind) 10 10)
+ )
+
+(mk-place-music p_griffin_peak_s 'ml-outdoor-adventure)
+
+;; random loot corpses
+(put-random-stuff p_griffin_peak_s
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_grass))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  20)
+
+(block-teleporting 
+ p_griffin_peak_s
+ (list
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ x# x# x# ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ x# x# x# ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ x# x# x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ x# x# x# x# x# ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ x# ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ "
+  ))
+                   
+
+(mk-19x19-town
+ 'p_griffin_peak_se "Southeast Face of Griffin Peak" nil
+ (list
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. {a .. .. ^v ^v ^v ^v ^v ^v ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {a .. ^v ^v ^v ^v ^v ^v ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. {{ {2 .. ^v ^v ^v ^v {{ ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {2 .. ^v ^v ^v {{ {{ ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {2 .. ^v ^v ^v ^v ^v {{ {{ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. {{ {2 .. ^v ^v ^v ^v ^v {{ ^v "
+               "^. ^. ^. ^. ^. ^^ ^^ ^^ ^. {3 .. .. ^v ^v ^v {{ {{ ^v ^v "
+               "^. {{ {7 {{ ^. ^. ^^ ^. ^. {2 .. ^v ^v ^v ^v ^v {{ ^v ^v "
+               "{1 {1 .. {1 {5 ^. ^. ^. {{ {2 .. ^v ^v ^v ^v ^v ^v ^v ^v "
+               ".. .. .. .. .. {1 {1 {1 {1 .. .. .. bb ^v ^v ^v ^v ^v ^v "
+               ".. ^v ^v ^v .. .. .. .. .. .. bb .. .. .. .. ^v ^v ^v ^v "
+               "^v ^v ^v ^v ^v .. .. ^v ^v .. .. .. {8 .. .. bb ^v ^v ^v "
+               "^v ^v ^v ^v ^v ^v ^v ^v ^v ^v .. {4 {{ {2 .. .. .. ^v ^v "
+               "^v ^v ^v ^v ^v ^v ^v ^v ^v ^v .. .. {1 && .. .. .. ^v ^v "
+               "^v {{ ^v ^v ^v ^v {{ ^v ^v ^v bb .. .. .. .. .. .. ^v ^v "
+               "^v ^v {{ {{ {{ {{ ^v ^v ^v ^v ^v .. .. .. .. bb ^v ^v ^v "
+               "^v {C t3 tt tt t5 {A ^v ^v ^v ^v ^v bb .. .. ^v ^v ^v ^v "
+               "{{ t3 tt |. |. tt t5 {{ ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v "
+               "{{ tt |. |. |. |. tt {{ ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v {{ "
+  )
+    nil ;;entrances
+ (put (spawn-pt 'griffin) 8 7)
+ (put (spawn-pt 'griffin) 7 8)
+ (put (spawn-pt 'griffin) 9 9)
+ (put (spawn-pt 'griffin) 12 6)
+ (put (spawn-pt 'troll) 12 13)
+ (put (spawn-pt 'troll) 13 12)
+ (put (spawn-pt 'troll-geomancer) 14 13)
+ (put (spawn-pt 'troll) 13 14)
+ (put (mk-ambient-sound 'sound-wind) 13 13)
+ )
+
+(mk-place-music p_griffin_peak_se 'ml-outdoor-adventure)
+
+;; random loot corpses
+(put-random-stuff p_griffin_peak_se
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_grass))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  5)
+
+(mk-19x19-town
+ 'p_griffin_peak_ne "Northeast Face of Griffin Peak" nil
+ (list
+               "^v ^v ^v {{ ta |. |. |. tc {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v {% ta |. tc {# ^. ^. ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v ^v {% te {# {{ ^v ^. ^. ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v {{ ^v {{ ^v {{ {{ {{ ^. ^. ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v ^v ^v ^v ^v {{ ^v ^v {{ ^. ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v ^v ^v ^v ^v {{ ^v ^v ^. ^. ^. ^^ ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v ^v ^v ^v ^v ^v {{ ^v ^. ^. ^. ^. ^^ ^^ ^^ ^^ "
+               "^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^. ^. ^. ^. ^. ^^ "
+               ".. {8 .. .. .. ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^. ^. ^. ^. "
+               "{4 {{ {a {8 {8 .. .. .. .. .. ^v ^v ^v ^v {{ ^v ^. ^. ^. "
+               "{8 {d ^. ^. {{ {a .. .. .. .. .. ^v ^v {{ {{ ^v ^v {{ ^. "
+               "^. ^. ^. ^. ^. ^. {a {8 .. .. .. ^v ^v ^v ^v {{ {{ ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^. ^. {{ {2 .. .. ^v ^v ^v ^v {{ {{ ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {a .. .. ^v ^v ^v ^v ^v {{ ^v ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {a .. ^v ^v ^v ^v ^v {{ {{ ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. {{ {2 ^v ^v ^v ^v ^v {{ {{ ^v "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. {3 .. ^v ^v ^v {{ ^v ^v {{ {{ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. {2 .. ^v ^v ^v ^v {{ {{ {{ {{ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^. {{ {2 .. ^v ^v ^v ^v ^v ^v {{ {{ "
+  )
+    nil ;;entrances
+    (put (spawn-pt 'bat) 18 2)
+    (put (spawn-pt 'bat) 15 4)
+    (put (spawn-pt 'bat) 17 6)
+    (put (spawn-pt 'bat) 13 3)
+    (put (mk-landslide 6 11 3 3) 8 11)
+    (put (mk-ambient-sound 'sound-wind) 13 9)
+ )
+
+(mk-place-music p_griffin_peak_ne 'ml-outdoor-adventure)
+
+(mk-19x19-town
+ 'p_griffin_peak_n "North Face of Griffin Peak" nil
+ (list
+               "^v ta |. ~a ~5 tt ^v ^v ^. ^. ^. ^^ ^^ ^^ ^^ ^^ ^^ ^. ^. "
+               "^v ^v tt |. ~~ |. t5 ^v ^v ^. ^. ^. ^. ^^ ^^ ^^ ^. ^. ^. "
+               "^v tb |. ~3 ~c |. tt ^v ^v ^v ^. ^. ^. ^^ ^^ ^. ^. ^. ^v "
+               "^v ^v tt ~6 |. |. tt ^v ^v ^v ^v ^v ^. ^. ^. ^. ^. ^v ^v "
+               "^v ^v tt ~~ ~~ ~5 |. t5 ^v ^v ^v ^v ^. ^. ^. ^v ^v ^v ^v "
+               "^v t3 |. ~~ _! _! ~5 tJ ^v ^v ^v ^v ^v ^. ^v ^v ^v ^v ^v "
+               "^v ta |. ~a _! _! ~~ ~~ ~5 ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v "
+               "^v ^v ta td ~~ ~c ^v ^v ~a ~5 ^v ^v ^v ^v ^v ^v ^v ^v ^v "
+               "^v ^v ^v ^v ~6 ^v ^v ^v ^v ~e ^v ^v ^v ^v ^v ^v ^v ^v .. "
+               "^v ^v ^v ~3 ~c ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v .. {8 "
+               "^v ^v ~3 ~c ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v .. {4 {{ "
+               "^v ^v ~~ ^v ^v ^v ^. ^. ^v ^v ^v ^v ^v .. .. {8 {8 {c ^. "
+               "^v ^v ~a ~5 ^v ^. ^. ^. ^v ^v ^v ^v .. {8 {c {{ ^. ^. ^. "
+               "^v ^v ^v ~e ^v ^v ^. ^. ^v ^v ^v .. {c {{ ^. ^. ^. ^^ ^^ "
+               "^. ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v {4 {{ ^. ^. ^^ ^^ ^^ ^^ "
+               "^. ^. ^v ^v ^v ^v ^v ^v ^v ^v ^v {4 {{ ^. ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^. ^. ^v ^v ^v ^v ^v ^v ^v .. {c ^. ^. ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^. ^. ^v ^v ^v ^v ^v {8 {4 {{ ^. ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^. ^. ^. ^v ^v ^v {4 {{ {6 ^. ^. ^^ ^^ ^^ ^^ ^^ ^^ "
+  )
+    nil ;;entrances
+   (put (spawn-pt 'sea-serpent) 8 7)
+   (put (mk-ambient-sound 'sound-wind) 9 9)
+ )
+
+(mk-place-music p_griffin_peak_n 'ml-outdoor-adventure)
+
+;; Note: Griffin Peak is a copy of the South Face, but with different mountain
+;; visibility to give the player the illusion that he has climbed up to the top
+;; and is now looking down on the path he trod to get here. Object placement
+;; will vary at runtime and may break the illusion, but try to initialize
+;; object placement the same at the start of play.
+(mk-19x19-town
+ 'p_griffin_peak "Griffin Peak" nil
+ (list
+               "^. ^. ^. ^. ^v ^v ^v ^v {2 .. {4 ^v ^v ^v ^v ^. ^. ^. ^. "
+               "^. ^. ^. ^v ^v ^v ^v ^v {2 .. {4 ^v ^v ^v ^v ^. ^. ^. ^. "
+               "^. ^. ^. ^v ^v ^v ^v bb .. .. .. bb ^v ^v ^v ^v ^. ^. ^. "
+               "^. ^. ^v ^v ^v ^v bb .. dd .. dd .. bb ^v ^v ^v ^v ^. ^. "
+               "^. ^v ^v ^v ^v bb .. dd dd dd .. dd .. bb ^v ^v ^v ^. ^. "
+               "^v ^v ^v ^v ^v .. dd dd dd dd dd dd dd .. ^v ^v ^v ^v ^. "
+               "^v ^v ^v ^v ^v bb dd dd dd dd dd dd dd bb ^v ^v ^v ^v ^v "
+               "^v ^v ^v ^v ^v .. dd .. dd dd dd dd dd .. ^v ^v ^v ^v ^v "
+               "{5 ^v ^v ^v ^v bb .. dd dd dd dd dd .. bb ^v ^v ^v ^v {3 "
+               "{4 {{ ^v ^v ^v ^v bb .. dd .. dd .. bb ^v ^v ^v ^v {{ {2 "
+               ".. {1 {5 ^v ^v ^v ^v bb .. dd .. bb ^v ^v ^v ^v {{ {3 .. "
+               "^v .. .. {5 ^v ^v ^v ^v ^v bb ^v ^v ^v ^v ^v ^v {3 .. ^v "
+               "^v ^v .. {4 {{ ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v {{ {2 .. ^v "
+               "^v ^v ^v .. {5 ^v ^v ^v ^v ^v ^v ^v ^v ^v {3 {9 .. .. ^v "
+               "^v ^v ^v .. .. {1 {5 ^v ^v ^v ^v ^v ^v {3 {c {C bb .. ^v "
+               "^v ^v ^v {8 bb .. {4 {{ ^v ^v ^v {{ {3 {4 {{ bb .. .. ^v "
+               "^v ^v {4 {{ {2 .. .. {1 {1 {1 {1 {1 .. .. {1 .. .. bb ^v "
+               "^v ^v ^v {1 ^v ^v ^v .. .. .. .. .. ^v ^v ^v ^v ^v ^v ^v "
+               "^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v ^v "
+  )
+    nil ;;entrances
+ (put (mk-key t_brundegardt_tower_4_key) 9 9)
+(put (kern-mk-obj t_spell_book_force_magick_winds 1) 9 10)
+ (put (spawn-pt 'griffin-chick) 8 5)
+ (put (spawn-pt 'griffin-chick) 10 5)
+ (put (spawn-pt 'griffin-chick) 8 7)
+ (put (spawn-pt 'griffin-chick) 10 7)
+ (put (spawn-pt 'griffin) 9 6)
+ (put (mk-ambient-sound 'sound-wind) 9 9)
+ )
+
+(mk-place-music p_griffin_peak 'ml-outdoor-adventure)
+
+;; random loot corpses
+(put-random-stuff p_griffin_peak
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (or (eqv? (kern-place-get-terrain loc)
+                              t_dirt)
+                        (eqv? (kern-place-get-terrain loc)
+                              t_grass)))
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  20)
+
+(block-teleporting 
+ p_griffin_peak
+ (list
+  "x# x# x# x# x# x# x# x# .. .. .. x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# .. .. .. x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# bb .. .. .. bb x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# bb .. dd .. dd .. bb x# x# x# x# x# x# "
+  "x# x# x# x# x# bb .. dd dd dd .. dd .. bb x# x# x# x# x# "
+  "x# x# x# x# x# .. dd dd dd dd dd dd dd .. x# x# x# x# x# "
+  "x# x# x# x# x# bb dd dd dd dd dd dd dd bb x# x# x# x# x# "
+  "x# x# x# x# x# .. dd .. dd dd dd dd dd .. x# x# x# x# x# "
+  "x# x# x# x# x# bb .. dd dd dd dd dd .. bb x# x# x# x# x# "
+  "x# x# x# x# x# x# bb .. dd .. dd .. bb x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# bb .. dd .. bb x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# bb x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  "x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# x# "
+  ))
+                   
+
+;;----------------------------------------------------------------------------
+;; Assemble the lower levels into a dungeon complex
+(mk-dungeon-level 
+ (list nil           p_cave_shrine     )
+ (list p_brundegardt p_brundegardt_keep p_tunnel_turn p_black_canal p_tunnels p_wide_chasm p_brundegardt_tower_1)
+ )
+
+;;----------------------------------------------------------------------------
+;; Assemble the top levels into a complex
+(mk-dungeon-level
+ (list nil                   nil              p_griffin_peak_ne)
+ (list p_brundegardt_tower_4 p_griffin_peak_s p_griffin_peak_se)
+ )
+
+;; Manually paste together the final spiral of griffin peak
+(kern-place-set-neighbor west p_griffin_peak_ne p_griffin_peak_n)
+(kern-place-set-neighbor south p_griffin_peak_n p_griffin_peak)
diff --git a/worlds/haxima-1.002/camping-map.scm b/worlds/haxima-1.002/camping-map.scm
new file mode 100644 (file)
index 0000000..ef66439
--- /dev/null
@@ -0,0 +1,50 @@
+;;----------------------------------------------------------------------------
+;; Camping map
+;;----------------------------------------------------------------------------
+(kern-mk-map 
+ 'm_campsite 7 7 pal_expanded
+ (list
+  ".. .. bb bb bb .. .."
+  ".. .. .. .. .. .. .."
+  "bb .. .. .. .. .. bb"
+  "bb .. .. && .. .. bb"
+  "bb .. .. .. .. .. bb"
+  ".. .. .. .. .. .. .."
+  ".. .. bb bb bb .. .."  
+  ))
+
+;;----------------------------------------------------------------------------
+;; Camping proc - run every turn when player is camping in the wilderness
+;;  kplayer = player party (kernel object pointer)
+;;   kplace = camping place
+;;----------------------------------------------------------------------------
+(define (camping-proc kplayer kplace)
+  (if (> (kern-dice-roll "1d20") 1)
+      (let ((loc (kern-place-get-location kplace)))
+        (define (nearest a b)
+          (if (null? a)
+              b
+              (if (<= (kern-get-distance (kern-obj-get-location a) loc) 
+                      (kern-get-distance (kern-obj-get-location b) loc)) 
+                  a 
+                  b)))
+        (define (willattack? a)
+          (and (is-hostile? kplayer a)
+               (can-pathfind? a loc)))
+        (define (choose-npc-party)
+          (foldr nearest
+                 nil
+                 (filter willattack?
+                         (kern-place-get-beings (loc-place loc)))))
+        (let ((kparty (choose-npc-party))) 
+          (if (not (null? kparty))
+              (begin
+                (if (loc-8-adjacent? (kern-obj-get-location kplayer)
+                                     (kern-obj-get-location kparty))
+                    (kern-ambush-while-camping kparty kplace)
+                    ;; Have the party actually move, so if they are in a
+                    ;; vehicle, then when the ambush is over the vehicle will
+                    ;; be in the proper location on the wilderness map.
+                    (pathfind kparty (kern-obj-get-location kplayer)))))))))
+
+(kern-add-hook 'camping_turn_start_hook 'camping-proc)
diff --git a/worlds/haxima-1.002/cannon.wav b/worlds/haxima-1.002/cannon.wav
new file mode 100644 (file)
index 0000000..10c4eb3
Binary files /dev/null and b/worlds/haxima-1.002/cannon.wav differ
diff --git a/worlds/haxima-1.002/cast-ui.scm b/worlds/haxima-1.002/cast-ui.scm
new file mode 100644 (file)
index 0000000..0a5348d
--- /dev/null
@@ -0,0 +1,585 @@
+;; ui-target-char -- return the first available object for which 'pred' returns
+;; true at a user-specified location on the map
+(define (ui-target origin range pred)
+  (define (select-from seq)
+    (cond ((null? seq) 
+           nil)
+          (else (car seq))))
+  (let ((coords (kern-ui-target origin range)))
+    (cond ((null? coords) nil)
+          (else (select-from (filter pred (kern-get-objects-at coords)))))))
+
+(define (ui-get-direction)
+  (kern-ui-direction))
+
+(define (ui-get-adjacent origin pred)
+  (define (select-from seq)
+    (cond ((null? seq) 
+           (kern-print "Nothing!\n") 
+           nil)
+          (else
+           (car seq))))
+  (let ((dir (ui-get-direction)))
+    (if (null? dir) nil
+        (select-from (filter pred (kern-get-objects-at (loc-offset origin dir)))))))
+
+(define (ui-waitkey)
+  (kern-ui-waitkey))
+
+(define (mk-ifc-query signal)
+  (lambda (kobj) (kobj-can? kobj signal)))
+
+(define (neighbors loc)
+  (let ((place (car loc))
+        (x (cadr loc))
+        (y (caddr loc)))
+    (list (list place x (- y 1))
+          (list place x (+ y 1))
+          (list place (- x 1) y)
+          (list place (+ x 1) y))))
+
+(define (get-target-kchar caster range)
+  (let ((loc (get-target-loc caster range)))
+    (if (null? loc)
+        nil
+        (get-being-at loc))))
+
+;;--------------------------------------------------------------
+;; Need to sort this stuff out
+;;--------------------------------------------------------------
+
+(define (cast-field-spell caster field-type)
+  (let ((coords (kern-ui-target (kern-obj-get-location caster) 1)))
+    (cond ((null? coords) nil)
+          (else
+           (kern-obj-put-at (kern-mk-obj field-type 1) coords)))))
+
+(define (cast-teleport-spell caster dir)
+  (let ((coords (loc-offset (kern-obj-get-location caster) dir)))
+    (cond ((null? coords) (kern-print "You sense nothing there!\n"))
+          ((not (passable? coords caster)) (kern-print "You sense it is impassable!\n"))
+          (else (kern-obj-relocate caster coords nil)))))
+
+(define (cast-signal-spell caster signal target)
+  (cond ((null? target) result-no-target)
+        (else 
+         ((kobj-ifc target) signal target caster)
+         result-ok
+         )))
+
+(define (cast-bimodal caster proc)
+  (define (cast-it target)
+    (cond ((null? target) result-no-target)
+          (else (proc target))))
+  (let ((loc (kern-obj-get-location caster)))
+  (if (kern-place-is-wilderness? (loc-place loc))
+      (cast-it (kern-ui-select-party-member))
+      (cast-it (ui-target loc 2 obj-is-char?)))))
+  
+(define (user-cast-spell-on-party-member caster proc)
+  (define (cast-it target)
+    (cond ((null? target) result-no-target)
+          (else (proc caster target)
+                result-ok)))
+  (let ((loc (kern-obj-get-location caster)))
+  (if (kern-place-is-wilderness? (loc-place loc))
+      (cast-it (kern-ui-select-party-member))
+      (cast-it (ui-target loc 2 obj-is-char?)))))
+         
+(define (user-cast-ranged-targeted-spell kchar range proc)
+  (let ((ktarg (get-target-kchar kchar range)))
+    (if (null? ktarg)
+        result-no-target
+        (begin
+          (proc kchar ktarg)
+          result-ok))))  
+         
+(define (cast-ui-target-party-member caster range)
+       (let ((loc (kern-obj-get-location caster)))
+               (if (kern-place-is-wilderness? (loc-place loc))
+                       (kern-ui-select-party-member)
+                       (ui-target loc range obj-is-char?))))
+          
+(define (cast-ui-target-char caster range)
+       (let ((loc (get-target-loc caster range)))
+               (if (null? loc)
+                       nil
+                       (get-being-at loc))))
+                       
+(define (cast-ui-target-any caster range checkproc)
+       (ui-target (kern-obj-get-location caster)
+               range
+               checkproc))
+
+(define (cast-ui-dospell target effect caster power)
+  (cond ((null? target) result-no-target)
+        ((kern-in-los? (kern-obj-get-location caster) (kern-obj-get-location target))
+         ;; note in this case we should let the effect procedure determine the
+         ;; result (fixme: need to go through and ensure all the powers return
+         ;; a result-* codee)
+         (effect caster target power))
+        (else
+         (kern-log-msg "Not in LOS!")
+         result-no-target)))
+
+
+(define (cast-ui-dospell-loc target effect caster power)
+       (cond ((null? target) result-no-target)
+               ((kern-in-los? (kern-obj-get-location caster) target)
+                       (effect caster target power))
+               (else
+                       (kern-log-msg "Not in LOS!")
+                       result-no-target)))
+
+(define (cast-ui-dospell-nolos target effect caster power)
+       (if (null? target)
+               (begin 
+                       result-no-target
+                       )
+               (begin
+                       (effect caster target power)
+                       result-ok)))
+                       
+                       
+                       
+(define (cast-ui-basic-member-spell effect caster power)
+       (cast-ui-dospell
+               (cast-ui-target-party-member caster 2)
+               effect caster power))
+               
+(define (cast-ui-basic-ranged-spell effect caster range power)
+       (cast-ui-dospell
+               (cast-ui-target-char caster range)
+               effect caster power))
+
+(define (cast-ui-ranged-loc effect caster range power)
+       (cast-ui-dospell-loc
+               (kern-ui-target (kern-obj-get-location caster) range)
+               effect caster power))
+               
+(define (cast-ui-ranged-loc-nolos effect caster range power)
+       (cast-ui-dospell-nolos
+               (kern-ui-target (kern-obj-get-location caster) range)
+               effect caster power))
+               
+(define (cast-ui-ranged-any effect caster range power targetcheck)
+       (cast-ui-dospell
+               (cast-ui-target-any caster range targetcheck)
+               effect caster power))
+               
+(define (cast-ui-field effect caster range power)
+       (let ((target (kern-ui-target (kern-obj-get-location caster) range)))
+               (cond ((null? target) result-no-target)
+                       ((not (terrain-ok-for-field? target)) result-no-effect)
+                       ((kern-in-los? (kern-obj-get-location caster) target)
+                               (effect caster target power)
+                               result-ok)
+                       (else 
+                               (kern-log-msg "Not in LOS!")
+                               result-no-target))))    
+
+(define (cast-ui-wall effect caster range power)
+       (let ((target (kern-ui-target (kern-obj-get-location caster) range)))
+               (cond ((null? target) result-no-target)
+                       ((not (kern-in-los? (kern-obj-get-location caster) target)) (kern-log-msg "Not in LOS!") result-no-target)
+                       (else 
+                               (let ((targetb (kern-ui-target (kern-obj-get-location caster) range)))
+                                       (cond ((and (not (null? targetb)) (not (kern-in-los? (kern-obj-get-location caster) target))) (kern-log-msg "Not in LOS!") result-no-target)
+                                               (else
+                                                       (effect caster target (if (null? targetb) target targetb) power)
+                                                       result-ok
+                                               ))
+                               )))
+       ))
+
+(define (cast-ui-template-loc effect caster template power)
+  (cast-ui-dospell-loc
+   (kern-ui-target-generic (kern-obj-get-location caster)
+                           (kern-obj-get-location caster) ;; fixme: cursor-loc
+                           template
+                           nil ;; fixme: suggested-locs
+                           nil ;; fixme: cursor-move-cb
+                           nil ;; fixme: cursor-select-cb
+                           nil ;; fixme: gob
+                           )
+   effect caster power))
+
+(define (cast-ui-party-spell effect caster power)
+  (let ((party (kern-char-get-party caster)))
+    (if (null? party) 
+        (effect caster caster power)
+        (foldr (lambda (final-result target)
+                 (let ((result (effect caster target power)))
+                   (if (= result-ok final-result)
+                       final-result
+                       result)))
+               result-no-effect
+               (kern-party-get-members party)))))
+
+;;----------------------------------------------------------------------------
+;; First Circle
+;;----------------------------------------------------------------------------
+
+(define (an-nox caster)
+       (cast-ui-basic-member-spell powers-cure-poison
+               caster (occ-ability-whitemagic caster)))
+
+(define (an-zu  caster)
+       (cast-ui-basic-member-spell powers-awaken
+               caster (occ-ability-whitemagic caster)))
+
+(define (grav-por caster)
+       (cast-ui-basic-ranged-spell powers-magic-missile
+               caster 
+               (powers-magic-missile-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+(define (in-lor caster)
+       (powers-light caster caster (occ-ability-whitemagic caster))
+       result-ok)
+
+(define (an-xen-bet  caster)
+  (powers-spider-calm caster caster (occ-ability-whitemagic caster))
+  result-ok)
+
+(define (mani caster)
+       (cast-ui-basic-member-spell powers-heal
+               caster (occ-ability-whitemagic caster)))
+               
+;todo currently only checks topmost item
+(define (wis-sanct caster)
+  (cast-ui-ranged-any powers-detect-traps
+                      caster 1 (ceiling (/ (+ (occ-ability-whitemagic caster)
+                                              (occ-ability-thief caster))
+                                           2))
+                      (lambda (kobj)
+                        (and (kern-obj-is-visible? kobj)
+                             (handles? kobj 'get-traps)))
+                      ))
+
+;todo currently only checks topmost item
+(define (an-sanct-ylem caster)
+  (cast-ui-ranged-any powers-disarm-traps
+                      caster 1 (ceiling (/ (+ (occ-ability-whitemagic caster)
+                                              (occ-ability-thief caster))
+                                           2))
+                      (lambda (kobj)
+                        (and (kern-obj-is-visible? kobj)
+                             (handles? kobj 'rm-traps)))
+                      ))
+       
+(define (ylem-an-ex  caster)
+       (cast-ui-ranged-loc powers-web caster
+               (powers-web-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+               
+(define (bet-ylem-hur caster)
+       (cast-ui-ranged-loc powers-smoke-field caster
+               (powers-smoke-range (occ-ability-whitemagic caster))
+               (occ-ability-whitemagic caster)))
+       
+       
+;;----------------------------------------------------------------------------
+;; Second Circle
+;;----------------------------------------------------------------------------
+(define (an-sanct  caster)
+       (cast-ui-ranged-any powers-unlock
+                            caster 1 (ceiling (/ (+ (occ-ability-whitemagic caster)
+                                                    (occ-ability-thief caster))
+                                                 2))
+                            (mk-ifc-query 'unlock)))
+
+(define (sanct  caster)
+       (cast-ui-ranged-any powers-lock
+               caster 1 (occ-ability-whitemagic caster)
+               (mk-ifc-query 'lock)))
+               
+(define (sanct-nox  caster)
+       (cast-ui-basic-member-spell powers-protect-vs-poison
+               caster (occ-ability-whitemagic caster)))
+
+(define (an-xen-corp caster)
+       (powers-turn-undead caster nil (occ-ability-blackmagic caster))
+       result-ok)
+
+(define (in-wis caster)
+  (powers-locate caster nil nil)
+  result-ok)
+
+(define (in-bet-xen  caster)
+  (let ((power (occ-ability-whitemagic caster)))
+    (cond ((< power 7) (powers-summon-insect caster caster power))
+          ((< power 8) (powers-summon-rat caster caster power))
+          (else (powers-summon-bat caster caster power)))
+    result-ok))
+
+(define (rel-hur  caster)
+  (let ((dir (ui-get-direction)))
+    (cond ((or (null? dir)
+               (= here dir))
+           result-no-target)
+          (else 
+           (powers-wind-change caster dir (occ-ability-whitemagic caster))
+           result-ok
+           ))))
+
+(define (in-nox-por  caster)
+       (cast-ui-basic-ranged-spell powers-poison
+               caster 
+               (powers-poison-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+  
+(define (bet-flam-hur caster)
+       (cast-ui-ranged-loc-nolos powers-cone-flamespray
+               caster 
+               4
+               (occ-ability-blackmagic caster)))
+               
+(define (xen-zu caster)
+       (cast-ui-basic-ranged-spell powers-sleep-target
+               caster 
+               (powers-sleep-target-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+;;----------------------------------------------------------------------------
+;; Third Circle
+;;----------------------------------------------------------------------------
+(define (in-flam-grav caster)
+  (cast-ui-wall powers-field-fire-wall caster (powers-field-range (occ-ability-whitemagic caster)) (occ-ability-whitemagic caster)))
+
+(define (in-nox-grav  caster)
+  (cast-ui-wall powers-field-poison-wall caster (powers-field-range (occ-ability-whitemagic caster)) (occ-ability-whitemagic caster)))
+
+(define (in-zu-grav  caster)
+  (cast-ui-wall powers-field-sleep-wall caster (powers-field-range (occ-ability-whitemagic caster)) (occ-ability-whitemagic caster)))
+  
+(define (vas-flam  caster)
+       (cast-ui-ranged-loc powers-fireball caster
+               (powers-fireball-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+(define (vas-lor  caster)
+       (powers-great-light caster caster (occ-ability-whitemagic caster))
+       result-ok)
+
+(define (in-flam-sanct caster)
+       (cast-ui-basic-member-spell powers-protect-vs-fire
+                       caster (occ-ability-whitemagic caster)))
+
+(define (in-nox-sanct caster)
+       (cast-ui-basic-member-spell powers-protect-vs-poison
+                       caster (occ-ability-whitemagic caster)))
+
+(define (vas-an-nox caster)
+  (cast-ui-party-spell powers-cure-poison
+                       caster (occ-ability-whitemagic caster)))
+
+(define (an-ort-xen caster)
+       (cast-ui-basic-member-spell powers-dispel-magic
+               caster (occ-ability-whitemagic caster)))
+
+;;----------------------------------------------------------------------------
+;; Fourth Circle
+;;----------------------------------------------------------------------------
+(define (an-grav  caster)
+       (cast-ui-ranged-any powers-dispel-field
+               caster 1 (occ-ability-whitemagic caster)
+               is-field?))
+               
+;leaving alone at the moment (not used)
+(define (uus-por  caster)
+  (cast-teleport-spell caster up))
+
+;leaving alone at the moment (not used)
+(define (des-por  caster)
+  (cast-teleport-spell caster down))
+
+(define (in-sanct-grav  caster)
+  (cast-ui-wall powers-field-energy-wall caster (powers-field-range (occ-ability-whitemagic caster)) (occ-ability-whitemagic caster)))
+
+(define (in-sanct  caster)
+       (powers-protect caster caster (occ-ability-whitemagic caster))
+               result-ok)
+
+(define (wis-quas  caster)
+       (powers-reveal caster caster (occ-ability-blackmagic caster))
+       result-ok)
+
+;; bet-por -- single character blink
+(define (bet-por caster)
+       (cast-ui-ranged-loc powers-blink caster
+               (powers-blink-range (occ-ability-whitemagic caster))
+               (occ-ability-whitemagic caster)))
+               
+(define (vas-sanct-nox  caster)
+       (powers-protect-vs-poison-all caster caster (occ-ability-whitemagic caster))
+               result-ok)
+
+(define (ort-grav  caster)
+       (cast-ui-ranged-loc powers-lightning caster
+               (powers-lightning-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+               
+;;----------------------------------------------------------------------------
+;; Fifth Circle
+;;----------------------------------------------------------------------------
+(define (in-ex-por  caster)
+       (cast-ui-ranged-any powers-unlock-magic
+               caster 1 (occ-ability-whitemagic caster)
+               (mk-ifc-query 'magic-unlock)))
+
+(define (an-ex-por  caster)
+       (cast-ui-ranged-any powers-lock-magic
+               caster 1 (occ-ability-whitemagic caster)
+               (mk-ifc-query 'magic-lock)))
+
+(define (in-zu  caster)
+        (powers-sleep-area caster caster (occ-ability-blackmagic caster)))
+
+(define (vas-mani  caster)
+       (cast-ui-basic-member-spell powers-great-heal
+               caster (occ-ability-whitemagic caster)))
+               
+(define (rel-tym  caster)
+       (powers-quickness caster caster (occ-ability-whitemagic caster))
+       result-ok)
+       
+
+(define (kal-xen caster)
+  (let ((power (occ-ability-whitemagic caster)))
+    (cond ((< power 9) (powers-summon-snake caster caster power))
+          ((< power 10) (powers-summon-spider caster caster power))
+          (else (powers-summon-wolf caster caster power)))
+    result-ok))
+       
+;; ----------------------------------------------------------------------------
+;; Sixth Circle
+;; ----------------------------------------------------------------------------
+(define (in-an  caster) 
+       (powers-negate-magic caster caster (occ-ability-whitemagic caster))
+       result-ok)
+
+(define (in-rel-por caster)
+       (cast-ui-ranged-any powers-telekinesis
+               caster
+               (powers-telekinesis-range (occ-ability-whitemagic caster))
+               (occ-ability-whitemagic caster)
+               kern-obj-is-mech?))
+
+(define (wis-an-ylem caster) 
+       (powers-xray caster caster (occ-ability-whitemagic caster))
+       result-ok)
+
+(define (an-xen-ex  caster)
+       (cast-ui-basic-ranged-spell powers-charm
+               caster 
+               (powers-charm-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+(define (rel-xen-quas caster)
+  (cast-ui-basic-ranged-spell powers-beastly-illusion
+                              caster 
+                              (powers-charm-range (occ-ability-blackmagic caster))
+                              (occ-ability-blackmagic caster))
+  )
+
+(define (in-vas-por-ylem  caster)
+       (powers-tremor caster caster (occ-ability-blackmagic caster))
+       result-ok)
+
+(define (quas-an-wis  caster)
+       (powers-confuse caster caster (occ-ability-blackmagic caster))
+       result-ok)
+
+;; vas-uus-ylem -- special spell which raises a sunken ship
+(define (vas-uus-ylem caster)
+       (cast-ui-ranged-loc powers-raise-lost-area caster
+               1 (occ-ability-whitemagic caster)))
+
+;; vas-por -- whole party blink
+(define (vas-por caster)
+       (cast-ui-ranged-loc powers-blink-party caster
+               (powers-blink-party-range (occ-ability-whitemagic caster))
+               (occ-ability-whitemagic caster)))
+
+;; ----------------------------------------------------------------------------
+;; Seventh Circle
+;; ----------------------------------------------------------------------------
+
+(define (in-nox-hur  caster)
+       (cast-ui-ranged-loc-nolos powers-cone-poison
+               caster 
+               (powers-cone-basic-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+(define (in-zu-hur  caster)
+       (cast-ui-ranged-loc-nolos powers-cone-sleep
+               caster 
+               (powers-cone-basic-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+(define (in-quas-corp  caster)
+       (powers-fear caster caster (occ-ability-blackmagic caster))
+       result-ok)
+
+(define (in-quas-wis  caster)
+       (powers-view caster caster (occ-ability-whitemagic caster))
+       result-ok)
+
+(define (sanct-lor  caster)
+       (cast-ui-basic-member-spell powers-invisibility
+                       caster (occ-ability-whitemagic caster)))
+
+(define (in-quas-xen  caster)
+       (cast-ui-basic-ranged-spell powers-clone
+               caster 
+               (powers-clone-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+;; ----------------------------------------------------------------------------
+;; Eighth Circle
+;; ----------------------------------------------------------------------------
+
+(define (in-flam-hur caster)
+       (cast-ui-ranged-loc-nolos powers-cone-fire
+               caster 
+               (+ 2 (powers-cone-basic-range (occ-ability-blackmagic caster)))
+               (occ-ability-blackmagic caster)))
+
+(define (in-vas-grav-corp  caster)
+       (cast-ui-ranged-loc-nolos powers-cone-energy
+               caster 
+               (powers-cone-basic-range (occ-ability-blackmagic caster))
+               (occ-ability-blackmagic caster)))
+
+(define (an-tym  caster)
+       (powers-timestop caster caster (occ-ability-whitemagic caster))
+       result-ok)
+
+(define (kal-xen-corp caster)
+       (powers-summon-undead caster caster (occ-ability-blackmagic caster))
+       result-ok)
+
+(define (xen-corp  caster)
+       (let ((range (+ 1 (floor (/ (occ-ability-blackmagic caster) 3)))))
+       (user-cast-ranged-targeted-spell caster range cast-kill-proc)))
+
+(define (in-mani-corp  caster)
+       (cast-ui-dospell-nolos
+               (kern-ui-select-party-member)
+                       powers-resurrect caster (occ-ability-whitemagic caster)))
+                       
+(define (vas-rel-por  caster)
+       (let* ((loc (kern-obj-get-location caster))
+                       (range (if 
+                               (kern-place-is-wilderness? (loc-place loc))
+                               1
+                               2)))
+               (cast-ui-ranged-loc powers-gate-travel
+                       caster 
+                       range
+                       (occ-ability-whitemagic caster))))
+       
+(define (kal-xen-nox caster)
+       (powers-summon-slime caster caster (occ-ability-whitemagic caster))
+       result-ok)
diff --git a/worlds/haxima-1.002/chanticleer.scm b/worlds/haxima-1.002/chanticleer.scm
new file mode 100644 (file)
index 0000000..cd5651c
--- /dev/null
@@ -0,0 +1,304 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Trigrave"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_chant
+               (list 0  0  trigrave-east-west-road   "drunk")
+               (list 2  0  trigrave-chants-bed       "sleeping")
+               (list 12 0  trigrave-tavern-hall      "working")
+               (list 23 0  trigrave-east-west-road   "drunk")               
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (chant-mk) (list 0))
+(define (chant-get-gold knpc) (car (kobj-gob-data knpc)))
+(define (chant-has-gold? knpc) (> (chant-get-gold knpc) 0))
+(define (chant-set-gold! knpc amount) 
+  (if (>= amount 0)
+      (set-car! (kobj-gob-data knpc) 
+                amount)))
+(define (chant-dec-gold! knpc) (chant-set-gold! knpc 
+                                                (- (chant-get-gold knpc)
+                                                   1)))
+
+;; ----------------------------------------------------------------------------
+;; Chanticleer
+;;
+;; Chanticleer is a roaming bard who spends most of his time in Trigrave. He's
+;; a confident, easy-going fellow who is also an unstoppable showman. He
+;; possesses a great deal of knowledge about the region, loves rumours and
+;; gossip, has friends in low and high places (uncluding the reclusive
+;; Enchanter) and is probably a spy for *somebody* but it isn't clear who.
+;;
+;; ----------------------------------------------------------------------------
+(define (chant-song knpc kpc)
+  (if (isdrunk? knpc)
+      (say knpc "All together now! Row, row, row your boat! [Hee hee hee!]")
+      (begin
+        (say knpc "A thousand songs wait caged behind the bars of my dry "
+             "throat! Perhaps a little coin to whet the pipes? [He looks at "
+             "you expectantly. Do you give him some gold?]")
+        (if (kern-conv-get-yes-no? kpc)
+            ;; yes - give chant some gold
+            (let ((amount (kern-conv-get-amount)))
+              (display "amount=")(display amount)(newline)
+              (cond ((= 0 amount) 
+                     (say knpc "An imaginary song then, for your imaginary "
+                          "gold! [He pretends to play his lute]"))
+                    ((< amount 2)
+                     (say knpc "Yes... I see. Here goes:\n"
+                          "There was a Wanderer oh so cheap\n"
+                          "He wanted all his gold to keep\n"
+                          "And when he mocked poor Chanticleer\n"
+                          "The sound of discord filled his ear!\n"
+                          " [He strikes a loud, brash, chord and bows]"))
+                    (else
+                     (say knpc "That will fill my yearning mug! "
+                          "Now, of what would you hear? Of Fen, Forest "
+                          "or Forgotten places?")
+                     (chant-set-gold! knpc amount))))
+            ;; no -- don't give him some gold
+            (say knpc "A sober bard doesn't do anybody any good!")))))
+
+(define (chant-fen knpc kpc)
+  (if (isdrunk? knpc)
+      (say knpc "Nazzty place! [Hic]")
+      (if (not (chant-has-gold? knpc))
+          (chant-song knpc kpc)
+          (begin
+            (chant-dec-gold! knpc)
+            (say knpc 
+                 "THE FENS\n"
+                 "\n"
+                 "  If you like...\n"
+                 "  biting flies, and farting bogs,\n"
+                 "  dismal skies, man-sized frogs,\n"
+                 "  evil altars, muck-filled boots,\n"
+                 "  mislaid rangers (wary of strangers),\n"
+                 "  trackless wastes,\n"
+                 "  lichs, wraiths,\n"
+                 "  and skeletal warriors, too...\n"
+                 "  then, my friend,\n"
+                 "  to the northern Fen!\n"
+                 "  For that's the place for you.\n")))))
+
+(define (chant-forest knpc kpc)
+  (if (isdrunk? knpc)
+      (say knpc "Run, Forest, run! [Hee-hee]")
+      (if (not (chant-has-gold? knpc))
+          (chant-song knpc kpc)
+          (begin
+            (chant-dec-gold! knpc)
+            (say knpc 
+                 "THE EASTERN WOODS\n"
+                 "\n"
+                 "The woods are lovely, dark and deep\n"
+                 "and always hungry, too!\n"
+                 "They've eaten many travelers\n"
+                 "and gulped a king or two.\n"
+                 "\n"
+                 "There goblins lurk and bandits hide\n"
+                 "and giant spiders drool,\n"
+                 "So if you go there don't forget\n"
+                 "to bring a slower fool!\n"
+                 )))))
+
+(define (chant-forgotten knpc kpc)
+  (if (isdrunk? knpc)
+      (say knpc "I don't remember! [he weeps with laughter]")
+      (if (not (chant-has-gold? knpc))
+          (chant-song knpc kpc)
+          (begin
+            (chant-dec-gold! knpc)
+            (say knpc 
+                 "LOST HALLS\n"
+                 "\n"
+                 "Delving ever deeper,\n"
+                 "They woke the ancient sleeper,\n"
+                 "You know the tale\n"
+                 "(The moral's stale)\n"
+                 "So I won't bore you with detail!\n"
+                 "\n"
+                 "[stops playing] If you simply MUST go investigate, "
+                 "search the southern coast.")
+                (if (null? (quest-data-getvalue 'questentry-rune-l 'know-hall))
+                       (quest-data-update-with 'questentry-rune-l 'approx-hall 1 (quest-notify nil))
+               )
+                ))))
+
+(define (chant-thie knpc kpc)
+  (if (isdrunk? knpc)
+      (say knpc 
+           "Hey diddle riddle,\n"
+           "You're in the middle!\n"
+           "When Kalcifax jumped through moon\n"
+           "The Necromage laughed to see such sport\n"
+           "And the Thief ran away with the Rune!")
+      (say knpc "So Enchy has you looking too? The thief must have avoided this "
+           "town, but travelers may have crossed his path. Ask Gwen.")))
+
+(define (chant-man knpc kpc)
+  (if (isdrunk? knpc)
+      (begin
+        (say knpc "HEY! Can you keep a zecret?")
+        (if (yes? knpc)
+            (begin
+              (say knpc "The MAN haz a zecret cave. You know where it iz?")
+              (if (yes? kpc)
+                  (say knpc "Me too! [Hee-hee!]")
+                  (say knpc "The mountain at [" 
+                       (loc-x the-mans-hideout-loc) " " 
+                       (loc-y the-mans-hideout-loc) 
+                       "] izn't really a mountain! Go zurprize him!")))
+            (say knpc "Me neither! [He snorts]")))
+      (say knpc "The MAN? I don't know anything about the MAN. Why are you asking me?")))
+
+(define chant-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default 
+               (lambda (knpc kpc) 
+                 (if (isdrunk? knpc)
+                     (say knpc "I's drunk... [hic]")
+                     (say knpc "I am at a loss."))))
+       (method 'hail 
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "[Saluting drunkenly] Hail to the cheese!")
+                     (say knpc "Well met, my fine fellow!"))))
+       (method 'bye 
+               (lambda (knpc kpc) 
+                 (if (isdrunk? knpc)
+                 (say knpc "Buhhhh-bye [snicker]")
+                 (say knpc "May the road kiss your feet!"))))
+       (method 'job 
+               (lambda (knpc kpc) 
+                 (if (isdrunk? knpc)
+                     (say knpc "[Overdramatically, he points to his eyes, "
+                          "then his ears, then makes a zipping motion on his "
+                          "mouth, nods sagely and winks]")
+                     (say knpc "I am a very vessel of wit and song!"))))
+       (method 'name 
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "Chantibard! [He tries to bow but falls down]")
+                     (say knpc "Chanticleer the Bard, at your service "
+                          "[He bows and flourishes]"))))
+       (method 'join 
+               (lambda (knpc kpc) 
+                 (if (isdrunk? knpc)
+                     (say knpc "Join you for a drink? "
+                          "I thought you'd never azzk!")
+                     (say knpc "Some bards adventure, others are wise. "
+                          "I am among the latter."))))
+
+       (method 'chan
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "[Hic!] Whooze that maudlin, drunken fool,\n"
+                          "Who plaize the tung like beast made man...")
+                     (say knpc "\n"
+                          "\n"
+                          " Who is that wise, enchanting bard,\n"
+                          " Who plays the lute like song made flesh\n"
+                          " And tells tales Fate herself would tell\n"
+                          " If Fate could only lie so well?"))))
+       (method 'earl
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "e's furgotten mor' 'an I'll ever know!")
+                     (say knpc 
+                          "Our distinguished shopkeeper...\n"
+                          "\n"
+                          " There once was a master of flame\n"
+                          " As a warmage he gathered great fame\n"
+                          " But as you can tell\n"
+                          " He tried a bad spell\n"
+                          " And now can't remember his name!\n"
+                          ))))
+
+       (method 'ench
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "Enchy! Sits in his comfy tower, giving "
+                          "orders, while Chant has to make the rounds!")
+                     (say knpc 
+                          "My travels sometimes take me to the "
+                          "Enchanter's Tower."))))
+       (method 'gwen
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "[He leans in close and whispers loudly] "
+                          "Ever seen a witch carry a sword?")
+                     (say knpc
+                          "Ah, our mysterious innkeeper...\n"
+                          "\n"
+                          " When the gray dove is weeping\n"
+                          " And the whole world is sleeping\n"
+                          " When ghosts rise like mist from the sea\n"
+                          " The owl in the moonlight\n"
+                          " Inquires of the still night\n"
+                          " The question we all ask of she!\n"))))
+       (method 'fen chant-fen)
+       (method 'fore chant-forest)
+       (method 'forg chant-forgotten)
+       (method 'jim
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "A knight turned inside out! [Burp!]")
+                     (say knpc
+                          "Ha! Here's a bit of gossip!\n"
+                          "\n"
+                          " Full fell and grim\n"
+                          " the righteous Jim,\n"
+                          " His armour slicked in gore,\n"
+                          " Slew his master on the field,\n"
+                          " Scratched the emblem from his shield\n"
+                          " And fled that cursed shore."
+                          ))))
+       (method 'roun
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "Azzright! I watches the roads, "
+                          "watching for them...")
+                     (say knpc "What a strange thing to inquire about!"))))
+       (method 'song chant-song)
+       (method 'them
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "[Hissing] THEM! The Enemy of the Wise! Shhh!")
+                     (say knpc "[Looking at you with mock suspicion] "
+                          "Are you sure you're not paranoid?"))))
+       (method 'thie chant-thie)
+       
+       (method 'towe
+               (lambda (knpc kpc)
+                 (if (isdrunk? knpc)
+                     (say knpc "Deprezzing place!")
+                     (say knpc
+                          "It watches the Fen to the north, "
+                          "but if you're thinking of going there, "
+                          "know that the Enchanter does not like visitors!"))))
+
+       (method 'wit
+               (lambda (knpc kpc)
+                 (say knpc "Well, gossip really. Give me a name, I'll give "
+                      "you the dirt.")))
+       (method 'lost
+               (lambda (knpc kpc)
+                 (say knpc "Well, I wouldn't be a bard if I didn't know a song about the fabled Lost Halls!")))
+       (method 'man chant-man)
+       (method 'wrog chant-man)
+       ))
diff --git a/worlds/haxima-1.002/charset.png b/worlds/haxima-1.002/charset.png
new file mode 100644 (file)
index 0000000..ca1e399
Binary files /dev/null and b/worlds/haxima-1.002/charset.png differ
diff --git a/worlds/haxima-1.002/chester.scm b/worlds/haxima-1.002/chester.scm
new file mode 100644 (file)
index 0000000..28b24d6
--- /dev/null
@@ -0,0 +1,184 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Glasdrin.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_ches
+               (list 0  0  gc-bed       "sleeping")
+               (list 7  0  ghg-s3       "eating")
+               (list 8  0  gas-counter "working")
+               (list 11 0  ghg-s3       "eating")
+               (list 12 0  gas-counter "working")
+               (list 18 0  ghg-s3       "eating")
+               (list 19 0  ghg-hall     "idle")
+               (list 21 0  gc-bed       "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (ches-mk) (list 'townsman))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Chester is a burly weaponsmith who lives in Glasdrin.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (ches-hail knpc kpc)
+  (say knpc "[You meet an enormous man with arms like tree trunks] "
+       "Hail, warrior!"))
+
+(define (ches-default knpc kpc)
+  (say knpc "'Tis beyond my ken."))
+
+(define (ches-name knpc kpc)
+  (say knpc "I'm Chester, of the Axe and Shield. "
+       "You look like a serious character, "
+       "in need of some serious weaponry. "
+       "Perhaps I can interest you in something?")
+  (if (kern-conv-get-yes-no? kpc)
+      (ches-trade knpc kpc)))
+
+(define (ches-join knpc kpc)
+  (say knpc "Nay, friend, somebody has to keep you adventurers provisioned!"))
+
+(define (ches-job knpc kpc)
+  (say knpc "I sell the finest weapons and armor in the land. "
+       "Care to have a look?")
+       (if (kern-conv-get-yes-no? kpc)
+           (ches-trade knpc kpc)
+           (say knpc "As you like it. You'll find none better, "
+                "I assure you.")))
+
+(define (ches-bye knpc kpc)
+  (say knpc "Farewell, and tell your friends about my shop!"))
+
+(define ches-catalog
+  (list
+   (list t_staff            20 "Equip your mages with staffs so they can feel useful.")
+   (list t_dagger           65 "Always keep an extra dagger or two in your boots.")
+   (list t_mace             80 "The mace is a fine weapon for crushing skulls and breaking bones.")
+   (list t_axe              85 "That axe is just the thing for splitting shields.")
+   (list t_sword            85 "The sword is the workhorse of the fighting class.")
+   (list t_2H_axe           90 "You'll mow down your enemies like grass with my two-handed axes.")
+   (list t_2H_sword        100 "Ah yes, my personal favorite is the mighty the two-handed sword.")
+   (list t_morning_star    105 "Your foes will give you plenty of room when you whip out a morning star.")
+   (list t_halberd         150 "With the halberd your back ranks can reinforce your front.")
+   
+   (list t_sling            50 "If you have any children a sling will make a fine starter weapon.")
+   (list t_spear            15 "The spear is quite popular with goblins and other savages.")
+
+   (list t_self_bow        120 "These little bows are perfect for hunting small animals.")
+   (list t_bow             200 "The rangers like to skulk about in the woods with bows like this.")
+   (list t_arrow             1 "If you don't wish to face your enemies in manly combat, be sure to carry plenty of arrows.")
+   
+   (list t_crossbow        380 "When your enemies flee from your blade, drop them with a crossbow.")
+   (list t_hvy_crossbow    600 "When besieged, the manly warrior turns to one of these beauties.")
+   (list t_bolt              1 "The Glasdrin militia demands the best arms, and I am their sole supplier for bolts.")
+   
+   (list t_leather_helm     50 "The light helm is perfect for any pencil-necked wrogues in your party.")
+   (list t_chain_coif      100 "The chain coif will protect your neck without obstructing your vision.")
+   (list t_iron_helm       150 "With an iron helm you can charge head first into the thickest melee.")
+   (list t_armor_leather   150 "Leather armour won't slow you down, but it only gives minimal protection.")
+   (list t_armor_chain     330 "Chain is the preferred armour of paladins, and they know their stuff.")
+   (list t_armor_plate    1000 "With plate armour you will be invincible in battle.")
+   
+   (list t_shield           30 "A sturdy shield will save you from craven foes who shoot from afar.")
+   
+   (list t_spiked_helm     250 "The best defense is a good offense! This spiked helm will prove my point. No pun intended.")
+   (list t_spiked_shield   250 "With the spiked shield you practically don't need a weapon.")
+   ))
+
+(define ches-merch-msgs
+  (list "Come by the Axe and Shield when I'm working, and I'll ply you with the best weapons and armor money can buy between 9:00AM and 6:00PM."
+        "Come have a look at my armory!" ;; buy
+        "I'll offer you some trade-in value on your used arms." ;; sell
+        "I equip the finest warriors in the land. What can I do for you?" ;; trade
+        "Now go bash some skulls! And come back when you need an upgrade." ;; sold-something
+        "Your equipment is looking a bit shabby, you should reconsider." ;; sold-nothing
+        "Now you should buy something to replace that old junk." ;; bought-something
+        "I was only trying to help. I don't think anyone else will want that rubbish." ;; bought-nothing
+        "Now you're ready to storm Gintspar!" ;; traded-something
+        "Browse all you like." ;; traded-nothing
+        ))
+
+;; Trade...
+(define (ches-trade knpc kpc) (conv-trade knpc kpc "trade" ches-merch-msgs ches-catalog))
+(define (ches-buy knpc kpc) (conv-trade knpc kpc "buy" ches-merch-msgs ches-catalog))
+(define (ches-sell knpc kpc) (conv-trade knpc kpc "sell" ches-merch-msgs ches-catalog))
+
+;; Paladins...
+(define (ches-pala knpc kpc)
+  (say knpc "I served several tours with the paladins, but that's no way "
+       "to make a fortune, so I retired and opened my shop."))
+
+;; Townspeople...
+(define (ches-glas knpc kpc)
+  (say knpc "Not a bad town. Business is good here, "
+       "with the paladins and all."))
+
+(define (ches-ange knpc kpc)
+  (say knpc "Nice-looking woman. But I prefer them a bit more wild.")) 
+
+(define (ches-patc knpc kpc)
+  (say knpc "I've never been sick, but word is he's a good healer."))
+
+(define (ches-jess knpc kpc)
+  (say knpc "Now there's a fine piece of woman flesh! "
+       "Too bad about that scar, "
+       "but in the dark it's all the same, eh?"))
+
+(define ches-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default ches-default)
+       (method 'hail ches-hail)
+       (method 'bye ches-bye)
+       (method 'job ches-job)
+       (method 'name ches-name)
+       (method 'join ches-join)
+       
+       ;; trade
+       (method 'trad ches-trade)
+       (method 'buy ches-buy)
+       (method 'sell ches-sell)
+
+       ;; paladin
+       (method 'pala ches-pala)
+
+       ;; town & people
+       (method 'glas ches-glas)
+       (method 'ange ches-ange)
+       (method 'patc ches-patc)
+       (method 'jess ches-jess)
+
+       ))
+
+(define (mk-chester)
+  (bind 
+   (kern-mk-char 'ch_chester         ; tag
+                 "Chester"           ; name
+                 sp_human            ; species
+                 oc_warrior          ; occ
+                 s_townsman          ; sprite
+                 faction-glasdrin         ; starting alignment
+                 5 0 2               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'ches-conv          ; conv
+                 sch_ches            ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_mace)
+                                     (list 1 t_armor_chain))) ; container
+                 nil ;;  readied
+                 )
+   (ches-mk)))
diff --git a/worlds/haxima-1.002/clothes.png b/worlds/haxima-1.002/clothes.png
new file mode 100644 (file)
index 0000000..3fa6fb2
Binary files /dev/null and b/worlds/haxima-1.002/clothes.png differ
diff --git a/worlds/haxima-1.002/combat-maps.scm b/worlds/haxima-1.002/combat-maps.scm
new file mode 100644 (file)
index 0000000..c38f116
--- /dev/null
@@ -0,0 +1,1057 @@
+;; ----------------------------------------------------------------------------
+;; combat-maps.scm - terrain combat maps
+;;
+;; Pre: terrain.scm, palette.scm
+;; ----------------------------------------------------------------------------
+
+(kern-mk-map 
+ 'm_forest_combat ;; tag
+ 19               ;; width
+ 19               ;; height;
+ pal_expanded     ;; palette
+ (list
+               ".. .. .. .. tb || || || || tt || || || || td .. .. .. .. "
+               ".. .. .. .. bb || || || tc t& ta || || || bb .. .. .. .. "
+               ".. .. tC tb || || || tc t# .. t% ta || || || td tA .. .. "
+               ".. .. t7 bb || || tt tB .. .. .. tD tt || || bb t7 .. .. "
+               "t7 bb || || || || || t5 tA .. tC t3 || || || || || bb t7 "
+               "|| || || || || || || || tt tt tt || || || || || || || || "
+               "|| || || tt || || || || || || || || || || || tt || || || "
+               "|| || tc t& ta || || || bb tt tt || || || tc t& ta || || "
+               "|| tc t# .. t% tt || tt tt tt tt bb || tt t# .. t% ta || "
+               "tt tB .. .. .. tt || tt tt tt tt tt || tt .. .. .. tD tt "
+               "|| t5 tA .. tC tt || bb tt tt tt tt || tt tA .. tC t3 || "
+               "|| || t5 tE t3 || || || tt tt bb || || || t5 tE t3 || || "
+               "|| || || tt || || || || || || || || || || || tt || || || "
+               "|| || || || || || || || tt tt tt || || || || || || || || "
+               "te bb || || || || || tc t# .. t% ta || || || || || bb te "
+               ".. .. te bb || || tt tB .. .. .. tD tt || || bb te .. .. "
+               ".. .. t% tb || || || t5 tA .. tC t3 || || || td t# .. .. "
+               ".. .. .. .. bb || || || t5 tE t3 || || || bb .. .. .. .. "
+               ".. .. .. .. tb || || || || tt || || || || td .. .. .. .. "  ))
+
+(mk-combat-map
+ 'm_tree_combat
+               "|# || || || || || tt t5 tA .. .. tb tt tt tt || || || |% "
+               "|| || || || || || || tt t5 tA .. t% ta tt tt || || || || "
+               "|| || || tt tt || || tt tt t5 .. .. t% ta tt tt || || || "
+               "|| || tt tt tt tt tt tt tt tc .. .. .. t% tt tt tt || || "
+               "tt tt tt tt tc t# .. t% te t# .. .. .. .. ta tt tt || || "
+               "tt tt tc t# .. .. .. .. .. .. .. .. .. .. t% tt || || || "
+               "tt tc t# .. .. .. .. .. .. tC t3 t5 .. .. .. tt || || tt "
+               "te t# .. .. .. .. t3 t5 tE t3 tt tc .. .. tC tt tt tt tc "
+               ".. .. .. .. .. .. ta tt tt tt tt tB .. .. tb tt tt tc t# "
+               ".. tC t3 t5 tA .. t% ta tt tt tt t5 tA .. t% ta tc t# .. "
+               "tC t3 tt tt td .. .. tD tt tt tt tt t5 .. .. .. .. .. .. "
+               "t3 tt tt tt t# .. .. t3 tt tc t& ta tc .. .. .. .. tC t7 "
+               "tt || || tt .. .. .. ta tc t# .. .. .. .. .. .. tC t3 tt "
+               "|| || || tt tA .. .. .. .. .. .. .. .. .. .. tC t3 tt tt "
+               "|| || tt tt t5 .. .. .. .. tC t7 tA .. tC t3 tt tt tt tt "
+               "|| || tt tt tt tA .. .. .. t3 tt tt tt tt tt tt tt || || "
+               "|| || || tt tt t5 tA .. .. ta tt tt || || tt tt || || || "
+               "|| || || || tt tt t5 tA .. t% ta tt || || || || || || || "
+               "|A || || || tt tt tt td .. .. t% ta tt || || || || || |C "
+)
+
+(mk-combat-map 
+ 'm_grass_combat2
+               "t3 tt tt tt tt td .. .. .. .. .. .. .. .. .. tb tt tt t5 "
+               "tt tt tt tc tB .. .. .. .. .. .. t3 tt t5 tA t% tt tt tt "
+               "tt tt tt bb t3 tt tt td .. .. .. ta tt tt t5 bb tt tt tt "
+               "tt tt tt tt tc t# .. .. .. .. .. .. t% ta tt tt tt tt tt "
+               "tt t# bb tt t# tC tf tA .. .. tC tf tA t% tt tt bb t% te "
+               "tt .. tC tt .. tf bb tf .. .. tf bb tf .. tt tt tA .. .. "
+               "te .. t3 tc .. t% tf t# .. .. t% tf t# .. ta tt tt t5 .. "
+               ".. .. te t# .. .. .. .. .. .. .. .. .. .. t% ta tt tc .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tC tf tA .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf bb tf .. .. tC tf tA .. .. .. .. .. "
+               ".. .. tb td tA .. t% tf t# .. .. tf bb tf .. t3 t5 tA .. "
+               ".. .. .. bb t7 tA .. .. .. .. .. t% tf tB tC tt tt tt t5 "
+               "t7 tA tC t3 tt t5 tA .. .. .. .. .. tD t3 tt tt tt tt tt "
+               "tt tt tt tt tt tt t5 tA .. .. .. tC t3 tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt t5 .. .. .. t3 tc bb tt tt bb tt tt "
+               "tt tt tt tt tt bb t% te .. .. .. tt t# .. tt tt tt tt tt "
+               "tt tt tt tt tt tA .. .. .. .. .. te .. tC tt tt tt tt tt "
+               "ta tt tt tt tt tt td .. .. .. .. .. .. tb tt tt tt tt tc "
+ )
+
+(kern-mk-map 
+ 'm_hill_combat   ;; tag
+ 19               ;; width
+ 19               ;; height;
+ pal_expanded     ;; palette
+ (list
+               "^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ {{ {3 .. .. .. .. .. {5 {{ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ {{ {{ {a .. .. .. .. .. {c {{ {{ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ {{ {{ {{ {{ {a .. .. .. {c {{ {{ {{ {{ ^^ ^^ ^^ "
+               "^^ ^^ {{ {{ ^^ ^^ {{ {{ {a .. {c {{ {{ ^^ ^^ {{ {{ ^^ ^^ "
+               "{{ {{ {{ {{ ^^ ^^ ^^ {{ {{ {6 {{ {{ ^^ ^^ ^^ {{ {{ {{ {{ "
+               "{{ {3 {5 {{ {{ ^^ ^^ {{ {3 {8 {5 {{ ^^ ^^ {{ {{ {3 {5 {{ "
+               "{1 .. .. {5 {{ {{ {{ {3 {c {{ {a {5 {{ {{ {{ {3 .. .. {1 "
+               ".. .. .. .. {5 {{ {3 {c {{ {{ {{ {a {5 {{ {3 .. .. .. .. "
+               ".. .. .. .. .. {9 {4 {{ {{ ^^ {{ {{ {2 {9 .. .. .. .. .. "
+               ".. .. .. .. {c {{ {a {d {{ {{ {{ {3 {c {{ {a .. .. .. .. "
+               "{8 .. .. {c {{ {{ {{ {{ {7 {{ {3 {c {{ {{ {{ {a .. .. {8 "
+               "{{ {a {c {{ {{ ^^ ^^ {{ {a {1 {c {{ ^^ ^^ {{ {{ {a {c {{ "
+               "{{ {{ {{ {{ ^^ ^^ ^^ {{ {{ {6 {{ {{ ^^ ^^ ^^ {{ {{ {{ {{ "
+               "^^ ^^ {{ {{ ^^ ^^ {{ {{ {3 .. {5 {{ {{ ^^ ^^ {{ {{ ^^ ^^ "
+               "^^ ^^ ^^ {{ {{ {{ {{ {3 .. .. .. {5 {{ {{ {{ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ {{ {{ {3 .. .. .. .. .. {5 {{ {{ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ {{ {a .. .. .. .. .. {c {{ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+  ))
+
+(kern-mk-map 
+ 'm_trail_0_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tf .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_1_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_2_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_3_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. .. tf .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. t7 "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. te "
+    ))
+
+(kern-mk-map 
+ 'm_trail_4_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. tf .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_5_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_6_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_7_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_8_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. tf .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+    ))
+
+(kern-mk-map 
+ 'm_trail_9_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+    ))
+
+(kern-mk-map 
+ 'm_trail_a_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+    ))
+
+(kern-mk-map 
+ 'm_trail_b_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "tf .. .. .. .. .. .. .. /f /f /f .. .. .. .. tf .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. t3 t5 .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. ta tc .. .. .. .. .. /f /f /f tf .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. .. tf .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+    ))
+
+(kern-mk-map 
+ 'm_trail_c_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. tC t7 tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tb tt td .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t% te t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+               ".. .. .. .. .. .. .. tC t7 tA .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. tb tt td .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. t% te t# .. .. .. .. .. .. .. tC t7 "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t3 tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ta tc "
+    ))
+
+(kern-mk-map 
+ 'm_trail_d_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. tC t7 tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tb tt td .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t% te t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+               ".. .. .. .. .. .. .. tC t7 tA .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. tb tt td .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. t% te t# .. .. .. .. .. .. .. tC t7 "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t3 tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ta tc "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+    ))
+
+(kern-mk-map 
+ 'm_trail_e_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. tC t7 tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tb tt td .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t% te t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+               ".. .. .. .. .. .. .. tC t7 tA .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. tb tt td .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. t% te t# .. .. .. .. .. .. .. tC t7 "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t3 tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ta tc "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. tf .. .. .. .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. te bb te .. .. .. .. .. .. .. .. .. .. .. .. .. tC t7 "
+               ".. t% tf t# .. .. .. .. .. .. .. tf .. .. .. .. .. tb tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. t% te "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+    ))
+    
+(kern-mk-map 
+ 'm_trail_combat_base  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. .. t3 t5 .. .. .. .. .. .. bb .. .. "
+               ".. t3 tt t5 t# .. .. .. ta tc .. .. .. t3 t5 .. .. .. .. "
+               ".. te tt te .. .. .. .. .. .. .. .. .. ta tc .. .. t3 t5 "
+               ".. t% te t# .. .. .. .. .. .. .. tf .. .. .. .. .. tt tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ta tc "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. tf .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. t3 t5 .. .. .. "
+               ".. .. .. tb t5 tA .. .. /f /f /f .. .. .. ta tc .. .. .. "
+               "tf .. .. t% tt t5 .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. ta tc .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. bb .. .. .. .. .. .. .. bb .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. t7 t7 tA .. .. .. "
+               ".. .. .. .. .. .. tf .. t3 t5 .. .. .. t7 t7 t7 .. .. .. "
+               ".. t3 t5 tA .. .. .. .. ta tc .. .. .. t7 bb t7 .. .. .. "
+               ".. ta tt td .. .. .. .. .. .. .. .. .. t% t7 t7 .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+    ))   
+(kern-mk-map 
+ 'm_trail_combat_road  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. bb .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. t3 tt t5 t# .. .. .. /f /f /f .. bb t3 t5 .. .. .. .. "
+               ".. te tt te .. .. .. .. /f /f /f .. .. ta tc .. .. t3 t5 "
+               ".. t% te t# .. .. .. .. /f /f /f tf .. .. .. .. .. tt tt "
+               ".. .. bb .. .. .. bb .. /f /f /f .. .. bb .. .. bb ta tc "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               "/f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f /f "
+               ".. bb .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. bb .. /f /f /f .. .. .. .. .. bb .. .. "
+               ".. .. bb .. .. .. .. .. /f /f /f .. bb .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. t7 t7 tA .. .. .. "
+               ".. .. .. .. .. .. tf .. /f /f /f .. .. t7 t7 t7 .. .. .. "
+               ".. t3 t5 tA .. .. .. .. /f /f /f .. .. t7 bb t7 .. .. .. "
+               ".. ta tt td .. .. bb .. /f /f /f .. bb t% t7 t7 .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. tf "
+    ))    
+    
+(kern-mk-map 
+ 'm_trail_combat_roadend  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. tf .. .. .. .. .. "
+               ".. .. tC tf tA .. .. .. .. /f .. .. .. .. .. .. .. .. .. "
+               ".. tC t7 bb tf .. .. .. /f .. /f .. .. .. .. .. bb .. .. "
+               ".. t3 tt t5 t# .. .. .. .. /f /f .. .. t3 t5 .. .. .. .. "
+               ".. te tt te .. .. .. .. .. /f .. .. .. ta tc .. .. t3 t5 "
+               ".. t% te t# .. .. .. .. /f .. .. .. .. .. .. .. .. tt tt "
+               ".. .. .. .. .. .. .. .. .. /f /f .. .. .. .. .. .. ta tc "
+               ".. .. .. .. .. .. .. .. /f /f /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. /f .. /f /f /f /f /f /f .. .. /f .. .. .. .. "
+               ".. /f .. /f .. /f .. /f /f /f /f .. /f /f .. /f .. /f .. "
+               ".. .. /f .. .. .. /f .. /f /f /f /f /f .. /f .. /f .. .. "
+               ".. .. .. .. .. .. .. .. /f .. /f .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. /f /f .. .. .. .. .. .. .. .. .. "
+               ".. .. bb .. .. .. .. .. .. /f .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. /f .. .. t7 t7 tA .. .. .. "
+               ".. .. .. .. .. .. tf .. .. /f .. .. .. t7 t7 t7 .. .. .. "
+               ".. t3 t5 tA .. .. .. .. .. /f .. .. .. t7 bb t7 .. .. .. "
+               ".. ta tt td .. .. .. .. .. .. /f .. .. t% t7 t7 .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. tf "
+    ))     
+    
+
+(kern-mk-map 
+ 'm_bridge_WE_combat  ;; tag
+ 19                 ;; width
+ 19                 ;; height;
+ pal_expanded       ;; palette
+ (list
+               "tt tt tt t5 ~~ -- __ __ __ __ __ __ __ __ __ -- ~~ t3 tt "
+               "tt tt tt tL ~~ -- __ __ __ __ __ __ __ __ -- -- ~c tt tt "
+               "tt tt tt ~3 ~~ -- __ __ __ __ __ __ __ __ -- ~~ tG tt tt "
+               "tt tt tt ~2 -- __ -- -- -- -- -- -- -- __ -- ~4 tt tt tt "
+               "ta tt tc ~2 -- -- -- ~~ ~~ ~8 ~~ ~~ -- -- -- ~4 ta tt tc "
+               ".. .. .. ~2 -- -- ~~ ~c ~# .. ~% ~a ~~ -- -- ~4 .. .. .. "
+               ".. .. .. ~2 -- ~~ ~~ ~# t3 tt t5 ~% ~~ ~~ ~~ ~4 .. .. .. "
+               ".. oo .. ~2 ~~ oo ~~ .. te oo te .. ~~ oo ~~ ~4 .. oo .. "
+               "/f ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee /f "
+               "/f ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee /f "
+               "/f ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee /f "
+               ".. oo .. ~2 ~~ oo ~~ .. t7 oo t7 .. ~~ oo ~~ ~4 .. oo .. "
+               ".. .. .. ~2 ~~ ~~ ~~ ~A ta tt tc ~C ~~ ~~ ~~ ~4 .. .. .. "
+               ".. .. .. ~2 -- -- ~~ ~5 ~A .. ~C ~3 ~~ -- -- ~4 .. .. .. "
+               "t3 tt t5 ~2 -- -- -- ~~ ~~ ~1 ~~ ~~ -- -- -- ~4 .. .. .. "
+               "tt tt tt ~2 -- __ -- -- -- -- -- -- -- __ -- ~4 t3 tt t5 "
+               "tt tt tt ~a ~~ -- __ __ __ __ __ __ __ __ -- ~~ tJ tt tt "
+               "tt tt tt tH ~~ -- __ __ __ __ __ __ __ __ -- -- ~5 tt tt "
+               "tt tt tt tc ~~ -- __ __ __ __ __ __ __ __ __ -- ~~ ta tt "
+    ))
+
+(mk-combat-map
+ 'm_bridge_NS_combat
+               "tt tt tt tt tt td .. .. /f /f /f .. .. tb tt tt tt tt tt "
+               "ta tt tt tt tc t# .. oo ee ee ee oo .. t% ta tt tt tt tc "
+               ".. .. .. .. .. .. .. .. ee ee ee .. .. .. .. .. .. .. .. "
+               "~1 ~1 ~1 ~1 ~1 ~1 ~1 ~~ ee ee ee ~~ ~1 ~1 ~1 ~1 ~1 ~1 ~1 "
+               "-- -- -- -- -- -- -- -- ee ee ee -- -- -- -- -- -- -- -- "
+               "__ __ __ __ -- -- -- oo ee ee ee oo -- -- -- __ __ __ __ "
+               "__ __ __ -- -- ~~ ~~ ~~ ee ee ee ~~ ~~ ~~ -- -- __ __ __ "
+               "__ __ __ -- ~~ ~c ~# .. ee ee ee .. ~% ~a ~~ -- __ __ __ "
+               "__ __ __ -- ~~ ~# t3 td ee ee ee tb t5 ~% ~~ -- __ __ __ "
+               "__ __ __ -- ~4 .. tt oo ee ee ee oo tt .. ~2 -- __ __ __ "
+               "__ __ __ -- ~~ ~A ta td ee ee ee tb tc ~C ~~ -- __ __ __ "
+               "__ __ __ -- ~~ ~5 ~A .. ee ee ee .. ~C ~3 ~~ -- __ __ __ "
+               "__ __ __ -- -- ~~ ~~ ~~ ee ee ee ~~ ~~ ~~ -- -- __ __ __ "
+               "__ __ __ __ -- -- -- oo ee ee ee oo -- -- -- __ __ __ __ "
+               "-- -- -- -- -- -- -- -- ee ee ee -- -- -- -- -- -- -- -- "
+               "~8 ~8 ~8 ~8 ~8 ~8 ~8 ~~ ee ee ee ~~ ~8 ~8 ~8 ~8 ~8 ~8 ~8 "
+               ".. .. .. .. .. .. .. .. ee ee ee .. .. .. .. .. .. .. .. "
+               "t3 tt tt tt t5 tA .. oo ee ee ee oo .. tC t3 tt tt tt t5 "
+               "tt tt tt tt tt td .. .. /f /f /f .. .. tb tt tt tt tt tt "
+)
+
+(mk-combat-map
+ 'm_lava_bridge_NS_combat
+               "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ /f /f /f {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ {{ {{ pp ,, ,, ,, pp {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               "{{ {{ {{ {{ {{ {{ {{ {D ,, ,, ,, {B {{ {{ {{ {{ {{ {{ {{ "
+               "!! !! !! !! !! !! !! !! ,, ,, ,, !! !! !! !! !! !! !! !! "
+               "!! !! !! !! !! !! !! !! ,, ,, ,, !! !! !! !! !! !! !! !! "
+               "!_ !_ !_ !_ !! !! !! pp ,, ,, ,, pp !! !! !! !_ !_ !_ !_ "
+               "!_ !_ !_ !! !! !! !! !! ,, ,, ,, !! !! !! !! !! !_ !_ !_ "
+               "!_ !_ !_ !! !! !c {# {% ,, ,, ,, {# {% !a !! !! !_ !_ !_ "
+               "!_ !_ !_ !! !! {# {{ ^^ ,, ,, ,, ^^ {{ {% !! !! !_ !_ !_ "
+               "!_ !_ !_ !! !! {{ ^^ pp ,, ,, ,, pp ^^ {{ !! !! !_ !_ !_ "
+               "!_ !_ !_ !! !! {A {{ ^^ ,, ,, ,, ^^ {{ {C !! !! !_ !_ !_ "
+               "!_ !_ !_ !! !! !5 {A {C ,, ,, ,, {A {C !3 !! !! !_ !_ !_ "
+               "!_ !_ !_ !! !! !! !! !! ,, ,, ,, !! !! !! !! !! !_ !_ !_ "
+               "!_ !_ !_ !_ !! !! !! pp ,, ,, ,, pp !! !! !! !_ !_ !_ !_ "
+               "!! !! !! !! !! !! !! !! ,, ,, ,, !! !! !! !! !! !! !! !! "
+               "!! !! !! !! !! !! !! !! ,, ,, ,, !! !! !! !! !! !! !! !! "
+               "{{ {{ {{ {{ {{ {{ {{ {D ,, ,, ,, {B {{ {{ {{ {{ {{ {{ {{ "
+               "^^ ^^ ^^ ^^ ^^ {{ {{ pp ,, ,, ,, pp {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ /f /f /f {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+)
+
+(mk-combat-map
+ 'm_bog_combat
+               "t3 tt tt t5 .. %b %% %% ~b ~1 ~d %% %% %d .. t3 tt tt t5 "
+               "tt tt tt tt tA .. %% %% %% ~e %% %% %% .. tC tt tt tt tt "
+               "tt tt tt tt t5 .. %a %% %% %% %% %% %c .. t3 tt tt tt tt "
+               "ta tt tt tt tt tA .. %% %% %% %% %% .. tC tt tt tt tt tc "
+               ".. t% ta tt tt t5 .. %% %% %% %% %% .. t3 tt tt tc t# .. "
+               "%7 .. .. t% ta tc .. %% ~3 ~9 ~5 %% .. ta tc t# .. .. %7 "
+               "%% %% %5 .. .. .. .. %% ~6 %% ~a ~5 .. .. .. .. %3 %% %% "
+               "%% %% %% %% %% %% ~3 ~9 ~c %% %% ~6 %% %% %% %% %% %% %% "
+               "~7 %% %% %% %% ~3 ~c %% %% %% %% ~a ~9 ~5 %% %% %% %% ~7 "
+               "~2 ~d %% %% %% ~6 %% %% %% %% %% %% %% ~6 %% %% %% ~b ~4 "
+               "~e %% %% %% %% ~a ~9 ~5 %% %% %% %% ~3 ~c %% %% %% %% ~e "
+               "%% %% %% %% %% %% %% ~6 %% %% ~3 ~9 ~c %% %% %% %% %% %% "
+               "%% %% %c .. .. .. .. ~a ~5 %% ~6 %% .. .. .. .. %a %% %% "
+               "%e .. .. tC t3 t5 .. %% ~a ~9 ~c %% .. t3 t5 tA .. .. %e "
+               ".. tC t3 tt tt tc .. %% %% %% %% %% .. ta tt tt t5 tA .. "
+               "t3 tt tt tt tt t# .. %% %% %% %% %% .. t% tt tt tt tt t5 "
+               "tt tt tt tt tc .. %3 %% %% %% %% %% %5 .. ta tt tt tt tt "
+               "tt tt tt tt t# .. %% %% %% ~7 %% %% %% .. t% tt tt tt tt "
+               "ta tt tt tc .. %b %% %% ~b ~8 ~d %% %% %d .. ta tt tt tc "
+ )
+
+(mk-combat-map
+ 'm_mountain_combat
+ "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ {{ {{ {{ {{ {{ {{ ^^ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ "
+ "^^ ^^ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ ^^ ^^ "
+ "^^ {{ {{ ^^ {{ {{ {{ ^^ {{ ^^ {{ ^^ {{ {{ {{ ^^ {{ {{ ^^ "
+ "^^ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ ^^ "
+ "^^ {{ {{ ^^ {{ {{ {{ ^^ {{ ^^ {{ ^^ {{ {{ {{ ^^ {{ {{ ^^ "
+ "^^ ^^ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ ^^ ^^ "
+ "^^ ^^ ^^ {{ {{ {{ {{ {{ {{ ^^ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+ "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+)
+
+(mk-combat-map
+ 'm_shore_combat
+  "-- -- -- -- -- -- ~~ ~~ ~~ -- -- -- -- -- ~~ ~~ -- -- -- "
+  "~~ ~~ -- -- -- -- -- -- -- -- -- -- ~~ ~~ ~~ ~~ -- -- ~~ "
+  "~~ ~~ ~~ ~~ -- -- -- -- -- -- ~~ ~~ ~~ ~~ ~~ -- -- ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- ~~ ~~ ~~ ~~ -- -- -- ~~ ~~ "
+  "~~ ~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- -- -- ~~ ~~ ~~ "
+  "~~ ~~ -- -- -- ~~ ~~ -- -- -- -- -- -- -- -- -- -- -- ~~ "
+  "~~ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ~~ "
+  "-- ~~ -- -- -- -- -- ~~ -- -- ~~ ~~ ~~ -- ~~ ~~ ~~ ~~ -- "
+  "-- -- -- -- -- -- -- -- ~~ -- ~~ ~~ ~~ ~~ ~~ ~~ ~~ -- -- "
+  "-- -- -- ~~ -- ~~ -- -- -- -- ~~ -- -- ~~ ~~ -- -- ~~ ~~ "
+  "-- -- ~~ ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- -- -- -- ~~ ~~ "
+  "-- -- ~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- ~~ ~~ ~~ ~~ "
+  "-- -- -- -- ~~ ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- -- -- ~~ "
+  "-- ~~ -- -- -- -- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- "
+  "~~ ~~ -- -- -- -- -- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ -- "
+  "-- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- ~~ ~~ ~~ ~~ ~~ -- "
+  "-- ~~ -- -- -- ~~ ~~ ~~ ~~ -- -- -- ~~ ~~ ~~ ~~ -- -- -- "
+  "-- ~~ -- -- -- -- -- -- -- -- -- -- ~~ -- ~~ -- -- -- -- "
+  "-- -- -- -- -- -- -- ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- -- "
+)
+
+(mk-combat-map
+ 'm_water_combat
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+)
+
+(mk-combat-map
+ 'm_void_combat
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+  "*. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. *. "
+
+)
+
+(mk-combat-map
+ 'm_lava_combat
+       ".. .. .. {8 .. !3 !5 .. .. .. .. {8 {4 {{ {{ {2 {4 {{ {2 "
+       "!3 !5 {4 {{ {2 !! !! .. .. !f {4 {{ {2 {5 {C !3 !! !! !5 "
+       "!! !! .. bb !! !! !! !! !5 .. .. bb !! !! !! !_ !_ !! !! "
+       "!a !! !! !! !! !! !! !! !! !! !! !! !! !_ !_ !! !! !! !c "
+       "{# {% !a !! !_ !! {4 {% !a !! !! !! !! !! !! !! .. .. .. "
+       "{{ {{ {2 !! !_ !! !5 {1 {4 {{ {{ {a !a !! !! !! .. .. {8 "
+       "{5 {{ {2 !! !_ !! !c .. {4 {{ ^^ {{ {2 {8 !! !! .. {4 {{ "
+       ".. {9 !3 !! !_ !! .. {8 {4 {{ {{ {{ {6 {{ !a !! !5 .. {1 "
+       "{4 {C !! !_ !! !c {4 {{ {2 {1 {1 {1 {4 {{ {2 !a !! bb .. "
+       ".. !3 !! !_ !! {# {2 {1 .. .. {8 .. .. {1 .. .. !! .. .. "
+       "!3 !! !! !! !! {1 .. bb {8 {4 {{ {a !b !5 .. {8 !! !5 .. "
+       "!a !c {& !a !! !5 {4 {{ {{ !f {{ {{ {2 !e {4 {{ !! !! !5 "
+       ".. .. {1 .. !a !! .. {5 {{ {2 {1 {1 .. .. .. {1 !! !_ !! "
+       ".. !7 .. .. {8 !a !5 .. {1 .. .. .. .. !3 !! !! !! !! !c "
+       ".. !a bb {4 {{ {a !a !5 .. !3 !! !! !! !! !! !! !! !c .. "
+       "{4 {{ {2 .. {5 {{ {2 !! !! !! !! !c {# {2 .. !! !! .. .. "
+       "!3 !! !! !5 {4 {{ {2 !! !! !! !c .. {1 .. {8 !a !! !! !5 "
+       "!a !! !! !! !5 {1 .. !! !c {# {2 .. !f {4 {{ {{ {2 !a !c "
+       ".. {4 {{ {2 !a !! !! !c .. {1 .. .. .. .. {5 {{ {6 {{ {2 "
+)
+
+(define (combat-off-to-dst off)
+       (if (< off 0)
+               0
+               off)
+       )
+       
+(define (combat-off-to-src off)
+       (if (< off 0)
+               (- off)
+               0
+               )
+       )
+       
+(define (combat-off-to-src-max total off)
+       (if (< off 0)
+               total
+               (- total off)
+               )
+       )
+       
+(define (combat-off-to-len total off)
+       (if (< off 0)
+               (+ total off)
+               (- total off)
+               )
+       )
+       
+(define (combat-off-dst-pos total off pos)
+       (let ((opos (+ off pos)))
+               (cond ((> opos total) total)
+                               ((< opos 0) 0)
+                               (else opos))
+       ))
+       
+
+(define (combat-map-basic place map-tag off-x off-y)
+       (let* ((wid (kern-place-get-width place))
+                       (hgt (kern-place-get-height place)))
+               (kern-blit-map (kern-place-get-terrain-map place)
+                       (combat-off-to-dst off-x) (combat-off-to-dst off-y)
+                       (eval map-tag)
+                       (combat-off-to-src off-x) (combat-off-to-src off-y)
+                       (combat-off-to-len wid off-x) (combat-off-to-len hgt off-y))    
+       ))
+
+(define (combat-map-basic-handler map-tag)
+       (lambda (place our_terrain other_terrain off_x off_y map_x map_y)
+               (combat-map-basic place map-tag off_x off_y)
+               (mk-place-music place 'ml-travelling)
+               ))                      
+               
+(define combat-map-road-handler
+       (lambda (place our_terrain other_terrain off_x off_y map_x map_y)
+               (let* ((wid (kern-place-get-width place))
+                               (hgt (kern-place-get-height place))
+                               (min-y (combat-off-to-src off_y))
+                               (min-x (combat-off-to-src off_x))
+                               (max-y (combat-off-to-src-max hgt off_y))
+                               (max-x (combat-off-to-src-max wid off_x))
+                               (dstmap (kern-place-get-terrain-map place))
+                               )
+                       (mk-place-music place 'ml-travelling)
+                       (define (combat-blit-road-part targ-list srcmap x1 x2 y1 y2)
+                               (if (and (in-list? our_terrain targ-list)
+                                               (>= y2 min-y)
+                                               (>= x2 min-x)
+                                               (<= y1 max-y)
+                                               (<= x1 max-x))
+                                               (begin
+                                       (kern-blit-map dstmap
+                                               (combat-off-dst-pos wid off_x x1) (combat-off-dst-pos hgt off_y y1)
+                                               srcmap
+                                               (max x1 min-x) (max y1 min-y)
+                                               (- (min x2 max-x) (max x1 min-x))
+                                               (- (min y2 max-y) (max y1 min-y))
+                                               ))
+                               ))
+                               
+                       (kern-blit-map dstmap 
+                               (combat-off-to-dst off_x) (combat-off-to-dst off_y)
+                               m_trail_combat_base
+                               min-x min-y 
+                               (combat-off-to-len wid off_x) (combat-off-to-len hgt off_y))
+                       ;;north part
+                       (combat-blit-road-part
+                               (list t_trail_4 t_trail_5 t_trail_6 t_trail_7 t_trail_8 t_trail_9 t_trail_a t_trail_b)
+                               m_trail_combat_road
+                               6 13 0 8)
+                       ;;west part
+                       (combat-blit-road-part
+                               (list t_trail_1 t_trail_2 t_trail_5 t_trail_6 t_trail_9 t_trail_a t_trail_d t_trail_e)
+                               m_trail_combat_road
+                               0 8 6 13)
+                       ;;south part
+                       (combat-blit-road-part
+                               (list t_trail_0 t_trail_1 t_trail_2 t_trail_3 t_trail_4 t_trail_5 t_trail_6 t_trail_7)
+                               m_trail_combat_road
+                               6 13 11 20)
+                       ;;east part
+                       (combat-blit-road-part
+                               (list t_trail_0 t_trail_1 t_trail_4 t_trail_5 t_trail_8 t_trail_9 t_trail_c t_trail_d)
+                               m_trail_combat_road
+                               11 20 6 13)
+                       ;;north end
+                       (combat-blit-road-part
+                               (list t_trail_3)
+                               m_trail_combat_roadend
+                               6 13 0 8)
+                       ;;west end
+                       (combat-blit-road-part
+                               (list t_trail_c)
+                               m_trail_combat_roadend
+                               0 8 6 13)
+                       ;;south end
+                       (combat-blit-road-part
+                               (list t_trail_b)
+                               m_trail_combat_roadend
+                               6 13 11 20)
+                       ;;east end
+                       (combat-blit-road-part
+                               (list t_trail_e)
+                               m_trail_combat_roadend
+                               11 20 6 13)
+       ))
+       )
+       
+(map (lambda (kter)
+       (kern-terrain-set-combat-handler kter combat-map-road-handler))
+       (list t_trail_0 t_trail_1 t_trail_2 t_trail_3
+       t_trail_4 t_trail_5 t_trail_6 t_trail_7
+       t_trail_8 t_trail_9 t_trail_a t_trail_b
+       t_trail_c t_trail_d t_trail_e t_trail_f)
+)
+       
+
+(kern-terrain-set-combat-handler t_bridge_WE  (combat-map-basic-handler 'm_bridge_WE_combat))
+(kern-terrain-set-combat-handler t_bridge_NS  (combat-map-basic-handler 'm_bridge_NS_combat))
+(kern-terrain-set-combat-handler t_lava_bridge_NS (combat-map-basic-handler 'm_lava_bridge_NS_combat))
+
+(define (combat-map-list target-map terrains)
+       (let ((handler (combat-map-basic-handler target-map)))
+       (map (lambda (kter)
+               (kern-terrain-set-combat-handler kter handler))
+               terrains
+       )))
+       
+(combat-map-list 'm_grass_combat2
+       (list 
+       t_grass
+       t_grassw_ne t_grassw_nw t_grassw_es t_grassw_ws
+       t_grassw_nwe t_grassw_nes t_grassw_nws t_grassw_wes
+       t_grassw_c
+       t_hilledge_n t_hilledge_w t_hilledge_nw t_hilledge_e
+       t_hilledge_ne t_hilledge_we t_hilledge_nwe t_hilledge_s
+       t_hilledge_ns t_hilledge_ws t_hilledge_nws t_hilledge_es
+       t_hilledge_nes t_hilledge_wes t_hilledge_c
+       t_grassv_ne t_grassv_nw t_grassv_es t_grassv_ws
+       t_grassv_nwe t_grassv_nes t_grassv_nws t_grassv_wes
+       t_grasst_nw t_grasst_ne t_grasst_nwe t_grasst_ws
+       t_grasst_nws t_grasst_es t_grasst_nes t_grasst_wes
+       t_grasst_c
+       )) 
+
+(combat-map-list 'm_water_combat
+       (list 
+       t_wshore_n t_wshore_w t_wshore_nw t_wshore_e
+       t_wshore_ne t_wshore_we t_wshore_nwe t_wshore_s
+       t_wshore_ns t_wshore_ws t_wshore_nws t_wshore_es
+       t_wshore_nes t_wshore_wes t_wshore_c
+       t_dshore_n t_dshore_w t_dshore_nw t_dshore_e
+       t_dshore_ne t_dshore_we t_dshore_nwe t_dshore_s
+       t_dshore_ns t_dshore_ws t_dshore_nws t_dshore_es
+       t_dshore_nes t_dshore_wes t_dshore_c
+       ))      
+
+(combat-map-list 'm_tree_combat
+       (list
+       t_trees
+       t_treew_ne t_treew_nw t_treew_es t_treew_ws
+       t_treew_nwe t_treew_nes t_treew_nws t_treew_wes
+       t_treew_c
+       t_trees_nw t_trees_ne t_trees_nwe t_trees_ws
+       t_trees_nws t_trees_es t_trees_nes t_trees_wes
+       t_trees_c
+       ))        
+
+(combat-map-list 'm_hill_combat
+       (list
+       t_hills
+       t_hillw_ne t_hillw_nw t_hillw_es t_hillw_ws 
+       t_hillw_nwe  t_hillw_nes t_hillw_nws t_hillw_wes 
+       t_hillw_c  
+       t_hilli_ne t_hilli_nw t_hilli_es t_hilli_ws 
+       t_hilli_nwe t_hilli_nes t_hilli_nws t_hilli_wes 
+       t_hilli_c 
+       t_hillv_ne t_hillv_nw t_hillv_es t_hillv_ws 
+       t_hillv_nwe t_hillv_nes t_hillv_nws t_hillv_wes
+       ))       
+
+(combat-map-list 'm_mountain_combat
+       (list 
+       t_mountains
+       t_mountw_ne t_mountw_nw t_mountw_es t_mountw_ws 
+       t_mountw_nwe t_mountw_nes t_mountw_nws t_mountw_wes 
+       t_mountw_c 
+       t_mountg_ne t_mountg_nw t_mountg_es t_mountg_ws 
+       t_mountg_nwe t_mountg_nes t_mountg_nws t_mountg_wes 
+       t_mountg_c 
+       t_mountv_ne t_mountv_nw t_mountv_es t_mountv_ws  
+       t_mountv_nwe t_mountv_nes t_mountv_nws t_mountv_wes
+       ))
+
+(combat-map-list 'm_bog_combat
+       (list
+       t_bog
+       t_bog_nw t_bog_ne t_bog_nwe t_bog_ws 
+       t_bog_nws t_bog_es t_bog_nes t_bog_wes 
+       t_bog_c 
+       ))      
+
+(combat-map-list 'm_forest_combat
+       (list
+       t_forest t_forest_d t_forest_l
+       t_forestg_ne t_forestg_nw t_forestg_es t_forestg_ws
+       t_forestg_nwe t_forestg_nes t_forestg_nws t_forestg_wes
+       ))
+
+(combat-map-list 'm_void_combat
+       (list
+       t_voids_n t_voids_w t_voids_nw t_voids_e 
+       t_voids_ne t_voids_we t_voids_nwe t_voids_s 
+       t_voids_ns t_voids_ws t_voids_nws t_voids_es 
+       t_voids_nes t_voids_wes t_voids_c 
+       t_void t_stars t_chasm
+       ))
+
+(combat-map-list 'm_lava_combat
+       (list
+       t_lava_n t_lava_w t_lava_nw t_lava_e 
+       t_lava_ne t_lava_we t_lava_nwe t_lava_s 
+       t_lava_ns t_lava_ws t_lava_nws t_lava_es 
+       t_lava_nes t_lava_wes t_lava_c
+       t_lava
+       ))
+       
+(combat-map-list 'm_shore_combat
+       (list
+       t_shore_n t_shore_w t_shore_nw t_shore_e
+       t_shore_ne t_shore_we t_shore_nwe t_shore_s
+       t_shore_ns t_shore_ws t_shore_nws t_shore_es
+       t_shore_nes t_shore_wes t_shore_c
+       t_shoals
+       ))
diff --git a/worlds/haxima-1.002/containers.scm b/worlds/haxima-1.002/containers.scm
new file mode 100644 (file)
index 0000000..2811a85
--- /dev/null
@@ -0,0 +1,446 @@
+;;----------------------------------------------------------------------------
+;; Containers - objects that contain stuff
+;;----------------------------------------------------------------------------
+;;----------------------------------------------------------------------------
+;; Local Procedures
+;;----------------------------------------------------------------------------
+(define (mk-contents . contents)
+  (filter notnull? contents))
+
+(define (roll-100 prob)
+  (>= prob (modulo (random-next) 100)))
+
+(define (roll-to-add prob dice type)
+  (if (roll-100 prob)
+      (list (kern-dice-roll dice) type)
+      nil))
+
+;;----------------------------------------------------------------------------
+;; Corpse -- not really a container, if you search it then it sort of acts like
+;; opening a container
+;;----------------------------------------------------------------------------
+(define (corpse-mk loot)
+  (list loot))
+(define (corpse-loot corpse) (car corpse))
+(define (corpse-set-loot! corpse val) (set-car! corpse val))
+(define (corpse-loot-entry-q loot) (car loot))
+(define (corpse-loot-entry-type loot) (eval (cadr loot)))
+
+(define (corpse-search kobj)
+  (let* ((corpse (kobj-gob-data kobj))
+         (loot (corpse-loot corpse)))
+    (if (not (null? loot))
+        (let ((loc (kern-obj-get-location kobj)))
+          (map (lambda (entry) 
+                 (kern-obj-put-at (kern-mk-obj (corpse-loot-entry-type entry)
+                                               (corpse-loot-entry-q entry))
+                                  loc))
+               loot)
+          (corpse-set-loot! corpse nil)))))
+
+(define corpse-ifc
+  (ifc nil
+       (method 'search corpse-search)))
+
+(mk-obj-type 't_corpse "corpse" s_corpse layer-item corpse-ifc)
+
+(define (mk-corpse) 
+  (bind (kern-mk-obj t_corpse 1)
+        (corpse-mk nil)))
+
+;; mk-corpse2 -- loot: a list of (quantity type) lists
+(define (mk-corpse2 loot)
+  (bind (kern-mk-obj t_corpse 1)
+        (corpse-mk loot)))
+
+(define (mk-corpse-with-loot)
+  (mk-corpse2 (mk-quoted-treasure-list (+ 1(modulo (random-next)
+                                                   3)))))
+
+;;----------------------------------------------------------------------------
+;; This next section is an experimental new container type. It attempts to
+;; bypass the kernel's built-in Container class and implement everything in the
+;; script as a normal kernel Object that responds to the 'open signal the same
+;; way a kernel Container would respond to the open command.
+;;
+;; This currently works. The next step is to implement the ability to add (and
+;; remove or disable) traps on a container. The means of doing so will be
+;; implemented here in the script, so the kernel won't need to know about
+;; trapped containers when this all works, and the kernel's Container class can
+;; be stripped back to a basic Inventory class.
+
+;; Define the gob structure and procedures. The contents should be a single
+;; quoted list, for example:
+;;
+;;   '((t_sword 1)
+;;     (t_arrow 5)
+;;     (t_torch 2)))
+;;
+;; Using the quotes is not only cleaner in the declarations, it automatically
+;; ensures that the contents are safe to save and reload as part of the gob
+;; because they are stored in the gob merely as symbols.
+;;
+;; Each container has a (often empty) list of traps. See traps.scm for details
+;; of trap implementations. When traps are attached to a container, the type of
+;; trap is specified, and an instance of that type is added to the list.yn
+;;
+(define (mk-container contents sprites-tag)
+  (list 'container 
+        contents 
+        nil ;; traps
+        #f  ;; destroyed?
+        sprites-tag
+        #f  ;; locked?
+        #f  ;; magic-locked?
+        nil ;; key-tag
+        ))
+(define (is-container? gob) (eq? (car gob) 'container))
+
+(define (container-contents gob) (cadr gob))
+(define (container-set-contents! gob val) (set-car! (cdr gob) val))
+
+(define (container-traps gob) (caddr gob))
+(define (container-set-traps! gob traps) (set-car! (cdr (cdr gob)) traps))
+(define (container-add-trap! gob trap-type)
+  (container-set-traps! gob
+                        (cons (mk-trap (eval trap-type))
+                              (container-traps gob))))
+
+(define (container-destroyed? gob) (cadddr gob))
+(define (container-destroy! gob) (set-car! (cdddr gob) #t))
+
+(define (container-sprites gob) (eval (list-ref gob 4)))
+
+(define (container-locked? gob) (list-ref gob 5))
+(define (container-set-locked! gob val) (set-car! (list-tail gob 5) val))
+
+(define (container-magic-locked? gob) (list-ref gob 6))
+(define (container-set-magic-locked! gob val) (set-car! (list-tail gob 6) val))
+
+(define (container-key gob) (list-ref gob 7))
+(define (container-set-key! gob ktype) (set-car! (list-tail gob 7) ktype))
+(define (container-needs-key? gob) (not (null? (container-key gob))))
+(define (container-key-fits? gob ktype)
+  (let ((key (safe-eval (container-key gob))))
+    (and (not (null? key))
+         (eqv? key ktype))))
+
+;; For now always false, since they destroy themselves on open. Might change
+;; some day...
+(define (container-open? gob) #f)
+
+
+(define (content-type content) (cadr content))
+(define (content-quantity content) (car content))
+
+;; This is the heart of the implementation. This procedure runs when the
+;; container object gets the 'open signal, which is sent by the kernel in
+;; response to the player's o)pen command followed by selection of this
+;; object. It expects kobj to be a kernel object which is bound to a container
+;; gob following the above format (the constructors further down illustrate how
+;; to create such an object).
+;;
+;; Opening the container creates objects based on the types and quantities
+;; listed in the container's content list and deposits these objects on the
+;; ground where the container is. Then it removes the container, which likely
+;; results in its destruction.
+;;
+;; Before opening this applies all the traps attached to the container. Note
+;; that the self-destruct trap, as currently implemented, does not work as
+;; expected, because it relies on the removal of the container from the map as
+;; a means of destroying it; and that is not sufficient here.
+(define (kcontainer-open kobj kchar)
+  (let ((container (kobj-gob-data kobj))
+        (loc (kern-obj-get-location kobj))
+        )
+
+    (cond 
+     ((container-magic-locked? container)
+      (kern-log-msg "Magically locked!\n")
+      #f)
+     ((container-locked? container)
+      (kern-log-msg "Locked!\n")
+      #f)
+     (else
+
+      ;; Applying traps can destroy both kobj and kchar
+      (kern-obj-inc-ref kobj)
+      (kern-obj-inc-ref kchar)
+      
+      ;; Apply traps (see trap.scm for trap-trigger)
+      (map (lambda (trap)
+             (trap-trigger trap kobj kchar))
+           (container-traps container))
+      
+      (cond ((container-destroyed? container)
+             nil)
+            (else
+             ;; Spill contents
+             (map (lambda (content)
+                    (let ((newobj (kern-mk-obj (eval (content-type content))
+                                               (content-quantity content))))
+                      (kern-obj-put-at newobj loc)))
+                  (container-contents container))
+             
+             ;; Remove the container from the map
+             (kern-obj-remove kobj)
+             ))
+      
+      
+      ;; Done with references
+      (kern-obj-dec-ref kobj)
+      (kern-obj-dec-ref kchar)
+      ))))
+
+(define (kcontainer-add-trap kobj trap-sym)
+  (container-add-trap! (kobj-gob-data kobj)
+                       trap-sym))
+
+(define (kcontainer-get-traps kobj)
+  (container-traps (kobj-gob-data kobj)))
+
+(define (kcontainer-rm-traps kobj)
+  (container-set-traps! (kobj-gob-data kobj) nil))
+
+(define (kcontainer-self-destruct kobj)
+  (let ((container (kobj-gob-data kobj)))
+    (container-set-contents! container nil)
+    (container-destroy! container)
+    (kern-obj-remove kobj)
+    ))
+
+(define (kcontainer-search kobj kchar)
+  ;; Searching can trigger traps, which can destroy both kobj and kchar
+  (kern-obj-inc-ref kobj)
+  (kern-obj-inc-ref kchar)
+  (kern-log-begin "Searching chest...")
+  (let ((container (gob kobj)))
+    (if (foldr (lambda (detected? trap)
+                 (trap-search trap kobj kchar)
+                 (if (trap-tripped? trap)
+                     (container-set-traps! container
+                                           (filter (lambda (trap2)
+                                                     (not (equal? trap trap2)))
+                                                   (container-traps container))))
+                 (or detected? (trap-detected? trap)))
+               #f
+               (container-traps container))
+        (kern-log-end "Trap detected!")
+        (kern-log-end "No traps detected!")
+        ))
+  ;; Done with references
+  (kern-obj-dec-ref kobj)
+  (kern-obj-dec-ref kchar)
+  )
+
+(define (kcontainer-describe kcontainer count)
+  (let ((container (gob kcontainer)))
+    (kern-log-continue "a ")
+    (if (container-magic-locked? container)
+        (kern-log-continue "magically locked, "))
+    (if (container-locked? container)
+        (if (container-needs-key? container)
+            (kern-log-continue "locked (with a key), ")
+            (kern-log-continue "padlocked, ")))
+    (if (container-open? container)
+        (kern-log-continue "open container ")
+        (kern-log-continue "closed container "))
+    (kern-log-continue "(")
+    (if (foldr (lambda (described? trap)
+                 (cond ((trap-detected? trap)
+                        (if described?
+                            (kern-log-continue ", "))
+                        (kern-log-continue (trap-name trap))
+                        (if (trap-tripped? trap)
+                            (kern-log-continue "[disarmed]"))
+                        #t)
+                       (else 
+                        described?)))
+               #f
+               (container-traps container))
+        (kern-log-continue " trap(s) detected")
+        (kern-log-continue "no traps detected")
+        )
+    (kern-log-continue ")")
+    ))
+
+(define (container-get-sprite container)
+  (list-ref (container-sprites container)
+            (let ((index (if (container-magic-locked? container)
+                             (if (container-locked? container)
+                                 3 ;; magic locked & locked
+                                 2 ;; magic locked
+                                 )
+                             (if (container-locked? container)
+                                 1 ;; locked
+                                 0 ;; normal
+                                 ))))
+              (println "sprite-index: " index)
+              index)))
+
+(define (kcontainer-update-sprite kcontainer)
+  (kern-obj-set-sprite kcontainer (container-get-sprite (gob kcontainer)))
+  )
+
+(define (kcontainer-lock kcontainer khandler)
+  (let ((container (gob kcontainer)))
+    (println "container-lock: " container)
+    (cond ((container-open? container) (kern-log-msg "Not closed!\n") #f)
+          ((container-locked? container) (kern-log-msg "Already locked!\n") #f)
+          (else
+           (container-set-locked! container #t)
+           (kcontainer-update-sprite kcontainer)
+           #t))))
+
+(define (kcontainer-unlock kcontainer khandler)
+  (let ((container (gob kcontainer)))
+    (cond ((container-open? container) (kern-log-msg "Not closed!\n") #f)
+          ((not (container-locked? container)) (kern-log-msg "Not locked!\n") #f)
+          ((container-needs-key? container) (kern-log-msg "Needs the key!\n") #f)
+          (else
+           (container-set-locked! container #f)
+           (kcontainer-update-sprite kcontainer)
+           #t))))
+
+(define (kcontainer-magic-lock kcontainer khandler)
+  (let ((container (gob kcontainer)))
+    (cond ((container-open? container) (kern-log-msg "Not closed!\n") #f)
+          ((container-magic-locked? container) 
+           (kern-log-msg "Already magically locked!\n") #f)
+          (else
+           (container-set-magic-locked! container #t)
+           (kcontainer-update-sprite kcontainer)
+           #t))))
+
+(define (kcontainer-magic-unlock kcontainer khandler)
+  (let ((container (gob kcontainer)))
+    (println "container-magic-unlock: " container)
+    (cond ((container-open? container) (kern-log-msg "Not closed!\n") #f)
+          ((not (container-magic-locked? container)) 
+           (kern-log-msg "Not magically locked!\n") #f)
+          (else
+           (container-set-magic-locked! container #f)
+           (kcontainer-update-sprite kcontainer)
+           #t))))
+
+(define (kcontainer-use-key kcontainer key-type)
+  (let ((container (gob kcontainer)))
+    (println "container-use-key: " container)
+    (cond ((container-open? container) (kern-log-msg "Not closed!"))
+          ((not (container-key-fits? container key-type)) (kern-log-msg "Key won't fit!"))
+          ((container-locked? container)
+           (container-set-locked! container #f)
+           (kcontainer-update-sprite kcontainer)
+           )
+          (else
+           (container-set-locked! container #t)
+           (kcontainer-update-sprite kcontainer)
+           ))))
+
+(define (kcontainer-lock-with-key kcontainer ktype)
+  (let ((container (gob kcontainer)))
+    (println "container-lock-with-key: " container " " ktype)
+    (cond ((container-open? container) (kern-log-msg "Not closed!"))
+          ((container-locked? container) (kern-log-msg "Already locked!"))
+          (else
+           (container-set-key! container ktype)
+           (container-set-locked! container #t)
+           (kcontainer-update-sprite kcontainer)
+           ))))
+  
+(define (kcontainer-get-unlock-dc kcontainer)
+  (let ((val (container-locked? (gob kcontainer))))
+    ;; make it backwards-compatible for old saved games where the value is a bool
+    (if (number? val)
+        val
+        (if val dc-normal 0))))
+
+(define (kcontainer-get-magic-unlock-dc kcontainer)
+  (let ((val (container-magic-locked? (gob kcontainer))))
+    ;; make it backwards-compatible for old saved games where the value is a bool
+    (if (number? val)
+        val
+        (if val dc-normal 0))))
+
+;; This interface binds the 'open signal to our open procedure above.
+(define container-ifc
+  (ifc '()
+       (method 'open kcontainer-open)
+       (method 'add-trap kcontainer-add-trap)
+       (method 'get-traps kcontainer-get-traps)
+       (method 'rm-traps kcontainer-rm-traps)
+       (method 'self-destruct kcontainer-self-destruct)
+       (method 'search kcontainer-search)
+       (method 'describe kcontainer-describe)
+
+       (method 'lock kcontainer-lock)
+       (method 'unlock kcontainer-unlock)
+       (method 'magic-lock kcontainer-magic-lock)
+       (method 'magic-unlock kcontainer-magic-unlock)
+       (method 'use-key kcontainer-use-key)
+       (method 'get-unlock-dc kcontainer-get-unlock-dc)
+       (method 'get-magic-unlock-dc kcontainer-get-magic-unlock-dc)
+
+       ))
+
+;; This constructor makes new types of objects that conform to the container
+;; interface above. An example of usage is below, where I make a new chest
+;; type.
+(define (mk-container-type tag name sprite)
+  (mk-obj-type tag name sprite layer-mechanism container-ifc))
+
+;; Test it out. First, make a new chest type.
+(mk-container-type 't_chest "chest" s_chest)
+
+;; Define a constructor for an object of the new chest type. Example usage:
+;;
+;; (put (mk-chest2 '((1 t_sword)
+;;                   (5 t_arrow)
+;;                   (2 t_torch)))
+;;      5 8)
+;;
+;; * Note the use of a quoted list.
+;;
+(define chest-sprites (list s_chest
+                            s_locked_chest
+                            s_magic_chest
+                            s_magic_locked_chest)
+  )
+
+(define (mk-chest trap contents)
+  (let ((kchest (bind (kern-mk-obj t_chest 1)
+                      (mk-container contents 'chest-sprites))))
+    (if (not (null? trap))
+        (container-add-trap! (kobj-gob-data kchest) trap))
+    kchest))
+
+(define (chest-add-trap kobj trap)
+  (container-add-trap! (kobj-gob-data kobj) trap))
+
+;; mk-treasure-chest -- returns a chest with 1-10 random object types
+(define (mk-treasure-chest)
+  (mk-chest nil
+            (mk-quoted-treasure-list (+ 1
+                                        (modulo (random-next) 
+                                                9)))))
+
+;;----------------------------------------------------------------------------
+;; Animal corpse
+;;
+;; This does not really belong here, since it is not a container, but rather an
+;; object that implements the 'butcher interface.
+
+;; This procedure must take two args and return a boolean in order to fit into
+;; the skills yusage framework.
+(define (animal-corpse-butcher kobj kactor)
+  (kern-obj-put-at (kern-mk-obj t_food 1) (kern-obj-get-location kobj))
+  (kern-obj-remove kobj)
+  #t
+  )
+
+(define animal-corpse-ifc
+  (ifc nil
+       (method 'butcher animal-corpse-butcher)
+       ))
+
+(mk-obj-type 't_animal_corpse "animal corpse" s_corpse layer-item animal-corpse-ifc)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/conv.scm b/worlds/haxima-1.002/conv.scm
new file mode 100644 (file)
index 0000000..ff11d21
--- /dev/null
@@ -0,0 +1,581 @@
+;;----------------------------------------------------------------------------
+;; Generic conversation
+;;----------------------------------------------------------------------------
+
+;; fundamentals
+(define (generic-hail knpc kpc)
+  (say knpc "Well met"))
+
+(define (generic-unknown knpc kpc)
+  (say knpc "I can't help you with that"))
+
+(define (generic-bye knpc kpc)
+  (say knpc "Farewell")
+  (kern-conv-end))
+
+(define (generic-join knpc kpc)
+  (say knpc "I cannot join you."))
+
+(define (generic-leav knpc kpc)
+  (cond ((is-player-party-member? knpc)
+         (cond ((is-only-living-party-member? knpc)
+                (say knpc "Maybe I should resurrect the Wanderer first... "
+                     "or sell his body parts to a thaumaturge, at least."))
+               (else
+                (say knpc "Do you want me to leave your party now?")
+                (cond ((yes? kpc)
+                       (cond ((kern-char-leave-player knpc)
+                              (say knpc "If you change your mind I'll be here waiting.")
+                              (kern-conv-end)
+                              )
+                             (else 
+                              (say knpc "I can't leave right now!"))))
+                      (else
+                       (say knpc "You made me nervous there for a minute."))))))
+         (else
+          (say knpc "I'm not a member of your party!"))))
+
+;; wise
+(define (basic-ench knpc kpc)
+  (say knpc "The Enchanter is the Wise Wizard. "
+       "He lives in a tower by the Fens, do you need directions?")
+  (quest-wise-subinit 'questentry-enchanter)
+  (quest-data-update 'questentry-enchanter 'general-loc 1)
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "Take the ladder down. You'll come out in Eastpass. "
+                    "The knights can help you from there."))
+              ((equal? kplace p_eastpass)
+               (say knpc "Take the road west to Trigrave and ask around there."))
+              ((equal? kplace p_trigrave)
+               (quest-data-update 'questentry-calltoarms 'directions 1)
+               (say knpc "Take the road north to The Fen."))
+              (else 
+               (say knpc "The Fens are somewhere in the northwest."))
+        ))))
+
+;; towns
+(define (basic-trig knpc kpc)
+  (say knpc "Trigrave is a small town in the west, "
+       "settled where two rivers meet."))
+
+(define (basic-gree knpc kpc)
+  (say knpc "Green Tower, home of the Rangers, lies deep in the Great Forest. "
+       "Do you need directions?")
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "Take the road east into the forest. "
+                    "Eventually it turns into a trail, follow it as best you can."))
+              ((equal? kplace p_eastpass)
+               (say knpc "Take the ladder down to Westpass and ask the Rangers there."))
+              ((equal? kplace p_trigrave)
+               (say knpc "Take the road east to the mountains and go through Eastpass. "
+                    "After that, you'll have to ask around."))
+              ((equal? kplace p_enchanters_tower)
+               (say knpc "Go south to Trigrave and ask there."))
+              ((equal? kplace p_oparine)
+               (say knpc "Take the road north to Trigrave and ask there."))
+              ((equal? kplace p_moongate_clearing)
+               (say knpc "Follow the road south to the junction, then travel east. "
+                    "When the road bends north keep going east into the woods."))
+              (else 
+               (say knpc "It's in the middle of the Great Forest."))
+              ))))
+
+(define (basic-bole knpc kpc)
+  (say knpc "The hamlet of Bole sits in a canyon in the mountains north of "
+       "the Great Wood. Do you need directions?")
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "It's northeast of here. Follow the mountains."))
+              ((equal? kplace p_eastpass)
+               (say knpc "Take the ladder down to Westpass and ask the Rangers there."))
+              ((equal? kplace p_trigrave)
+               (say knpc "Take the road east to the mountains and go through Eastpass. "
+                    "After that, you'll have to ask around."))
+              ((equal? kplace p_green_tower)
+               (say knpc "Go north through the forest until you hit the mountains, "
+                    "then follow them east a short while."))
+              ((equal? kplace p_enchanters_tower)
+               (say knpc "Go south to Trigrave and ask there."))
+              (else 
+               (say knpc "I think it's by the mountains north of the Great Wood."))
+              ))))
+              
+(define (basic-absa knpc kpc)
+  (say knpc "Absalot, a great and wicked city, was destroyed for its sins."))
+
+(define (basic-opar knpc kpc)
+  (say knpc "The city of Oparine can be found in the southwest by a "
+       "deep harbor. Do you need directions?")
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "Take the ladder down to Eastpass and follow the road west."))
+              ((equal? kplace p_eastpass)
+               (say knpc "Follow the road west."))
+              ((equal? kplace p_trigrave)
+               (say knpc "Follow the road west and south all the way to the sea."))
+              ((equal? kplace p_green_tower)
+               (say knpc "Follow the trail south and west to Westpass and ask the rangers when you get there."))
+              ((equal? kplace p_enchanters_tower)
+               (say knpc "Go south to Trigrave and ask there."))
+              ((equal? kplace p_glasdrin)
+               (say knpc "Take the road south."))
+              ((equal? kplace p_oparine)
+               (say knpc "Well, here you are already!"))
+              (else 
+               (say knpc "It's on the southern coast somewhere."))
+              ))))
+
+(define (basic-east knpc kpc)
+  (say knpc "Eastpass guards the eastern pass into the River Plain. Do you need directions?")
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "Take the ladder down, you'll come out in Eastpass."))
+              ((equal? kplace p_eastpass)
+               (say knpc "You're here already."))
+              ((equal? kplace p_trigrave)
+               (say knpc "Follow the road east and you'll run right into it."))
+              ((equal? kplace p_green_tower)
+               (say knpc "Travel west through the woods, then follow the road west to Westpass and ask there."))
+              ((equal? kplace p_enchanters_tower)
+               (say knpc "Go south to Trigrave and ask there."))
+              ((equal? kplace p_glasdrin)
+               (say knpc "Take the road south as far as you can and ask there."))
+              ((equal? kplace p_oparine)
+               (say knpc "Take the road north to Trigrave and ask there."))
+              (else 
+               (say knpc "It's by the mountains west of the Great Forest."))
+              ))))
+
+(define (basic-west knpc kpc)
+  (say knpc "Westpass guards the western pass into the Great Forest. Do you need directions?")
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "This is it."))
+              ((equal? kplace p_eastpass)
+               (say knpc "Take the ladder down and you'll come out in it."))
+              ((equal? kplace p_trigrave)
+               (say knpc "Follow the road east and ask in Eastpass."))
+              ((equal? kplace p_green_tower)
+               (say knpc "Travel west through the woods, then follow the road west."))
+              ((equal? kplace p_enchanters_tower)
+               (say knpc "Go south to Trigrave and ask there."))
+              ((equal? kplace p_glasdrin)
+               (say knpc "Take the road south as far as you can."))
+              ((equal? kplace p_oparine)
+               (say knpc "Take the road north to Trigrave and ask there."))
+              (else 
+               (say knpc "Follow the road east from Trigrave."))
+              ))))
+
+(define (basic-glas knpc kpc)
+  (say knpc "Glasdrin is the fortified city of the Paladins. Do you need directions?")
+  (if (yes? kpc)
+      (let ((kplace (get-place knpc)))
+        (cond ((equal? kplace p_westpass)
+               (say knpc "Follow the road east and north."))
+              ((equal? kplace p_eastpass)
+               (say knpc "Go east to Westpass and ask there."))
+              ((equal? kplace p_trigrave)
+               (say knpc "Go east to Eastpass and ask there."))
+              ((equal? kplace p_green_tower)
+               (say knpc "Go west through the woods until you hit the road, then follow it north."))
+              ((equal? kplace p_enchanters_tower)
+               (say knpc "Go east through the pass and follow the river."))
+              ((equal? kplace p_oparine)
+               (say knpc "Follow the road north to Trigave and ask there, or take a ship and follow the coastline all the way north."))
+              (else 
+               (say knpc "It's up near the northeast coast on an island."))
+              ))))
+
+(define (basic-fens knpc kpc)
+  (say knpc "The Fens are a swampy area in the northwest."))
+
+(define (basic-kurp knpc kpc)
+  (say knpc "Kurpolis is an ancient underground ruin. "
+       "The entrance is somewhere in the northern mountains."))
+
+(define (basic-lost knpc kpc)
+  (say knpc "The Lost Halls? I've only heard them mentioned in bard's songs. "
+       "I didn't know they really existed."))
+
+;; establishments
+(define (basic-whit knpc kpc)
+  (say knpc "The White Stag is in Green Tower."))
+
+;; quests
+(define (basic-thie knpc kpc)
+  (say knpc "No, I don't know anything about a thief."))
+
+(define (basic-rune knpc kpc)
+  (say knpc "I don't know much about runes. Try asking one of the Wise."))
+
+(define (basic-wise knpc kpc)
+       (say knpc "The Wise have great influence over affairs in the Shard. Do you want to know their names?")
+       (if (yes? kpc)
+               (begin
+                       (say knpc "There's the Enchanter, the Necromancer, the Alchemist, the MAN, the Engineer and the Warritrix.")
+                       (map quest-wise-subinit
+                               (list 'questentry-enchanter 'questentry-warritrix  'questentry-alchemist
+                                               'questentry-the-man 'questentry-engineer  'questentry-necromancer)
+                       )
+               )
+       ))
+
+(define (basic-shar knpc kpc)
+  (say knpc "The Shard is what we call our world.")
+  (quest-data-update 'questentry-whereami 'shard 1)
+  )
+
+(define (basic-peni knpc kpc)
+  (say knpc "The Peninsula is our little corner of the Shard."))
+
+(define (basic-warr knpc kpc)
+  (say knpc "The Warritrix is the Wise Warrior. If you're looking for her try Glasdrin.")
+  (quest-wise-subinit 'questentry-warritrix)
+  (quest-data-update 'questentry-warritrix 'general-loc 1)
+  )
+
+(define (basic-engi knpc kpc)
+  (say knpc "I've heard the Engineer is the greatest Wright in the land, "
+       "but I don't know much about him.")
+       (quest-wise-subinit 'questentry-engineer)
+       (quest-data-update 'questentry-engineer 'common 1)
+       )
+
+(define (basic-man knpc kpc)
+  (say knpc "The MAN is a master wrogue. Nobody knows where his hideout is. "
+       "It's rumoured that he travels in disguise.")
+       (quest-wise-subinit 'questentry-the-man)
+       (quest-data-update 'questentry-the-man 'common 1)
+       )
+
+(define (basic-alch knpc kpc)
+  (say knpc "The Alchemist is a Wise Wright who specializes in potions. "
+       "You'll find his shop in Oparine.")
+       (quest-wise-subinit 'questentry-alchemist)
+       (quest-data-update 'questentry-alchemist 'general-loc 1)
+       )
+
+(define (basic-necr knpc kpc)
+  (say knpc "The Necromancer is a Wise Wizard who specializes in death magic. "
+       "I've heard he lives in a hidden cave.")
+       (quest-wise-subinit 'questentry-necromancer)
+       (quest-data-update 'questentry-necromancer 'general-loc 1)
+       )
+
+(define (basic-drag knpc kpc)
+  (say knpc "Stories say a mighty dragon is terrorizing shipping on the "
+       "east coast."))
+
+(define (basic-fire knpc kpc)
+  (say knpc "The Fire Sea? That's a volcano on an island off the east coast."))
+
+(define basic-conv
+  (ifc '()
+       ;; fundamentals
+       (method 'hail generic-hail)
+       (method 'default generic-unknown)
+       (method 'bye generic-bye)
+       (method 'join generic-join)
+       (method 'leav generic-leav)
+       
+       ;; wise
+       (method 'ench basic-ench)
+       (method 'wise basic-wise)
+       (method 'warr basic-warr)
+       (method 'man basic-man)
+       (method 'engi basic-engi)
+       (method 'alch basic-alch)
+       (method 'necr basic-necr)
+
+       ;; towns & regions
+       (method 'absa basic-absa)
+       (method 'bole basic-bole)
+       (method 'gree basic-gree)
+       (method 'trig basic-trig)
+       (method 'lost basic-lost)
+       (method 'opar basic-opar)
+       (method 'fens basic-fens)
+       (method 'shar basic-shar)
+       (method 'peni basic-peni)
+       (method 'kurp basic-kurp)
+       (method 'glas basic-glas)
+       (method 'fire basic-fire)
+
+       ;; establishments
+       (method 'whit basic-whit)
+
+       ;; quests
+       (method 'thie basic-thie)
+       (method 'rune basic-rune)
+
+       ;; monsters
+       (method 'drag basic-drag)
+
+       ))
+
+;; Helper(s)
+(define (say knpc . msg) (kern-conv-say knpc msg))
+(define (yes? kpc) (kern-conv-get-yes-no? kpc))
+(define (no? kpc) (not (kern-conv-get-yes-no? kpc)))
+(define (reply? kpc) (kern-conv-get-reply kpc))
+(define (ask? knpc kpc . msg)
+  (kern-conv-say knpc msg)
+  (kern-conv-get-yes-no? kpc))
+(define (prompt-for-key)
+  (kern-log-msg "<Hit any key to continue>")
+  (kern-ui-waitkey))
+(define (meet msg)
+  (kern-log-msg msg))
+(define (get-gold-donation knpc kpc)
+  (let ((give (kern-conv-get-amount kpc))
+        (have (kern-player-get-gold)))
+    (cond ((> give have)
+           (say knpc "You don't have that much!")
+           0)
+          (else
+           (kern-player-set-gold (- have give))
+           give))))
+(define (get-food-donation knpc kpc)
+  (let ((give (kern-conv-get-amount kpc))
+        (have (kern-player-get-food)))
+    (cond ((> give have)
+           (say knpc "You don't have that much!")
+           0)
+          (else
+           (kern-player-set-food (- have give))
+           give))))
+(define (working? knpc)
+  (string=? "working" (kern-obj-get-activity knpc)))
+
+;; Not really an aside in the theatrical sense, this routine causes a party
+;; member to interject something into the conversation. kpc is the character
+;; being conversed with, mem-tag is either nil or the party member who should
+;; do the interjection. If mem-tag is nil then a party member (other than the
+;; speaker) will be chosen at random. msg is the text of the comment. If kpc is
+;; the only member of the party then the aside will not do anything.
+(define (aside kpc kchar-tag . msg)
+  ;;(println msg)
+  (if (null? kchar-tag)
+      (let ((members (filter (lambda (kchar)
+                               (not (eqv? kchar kpc)))
+                             (kern-party-get-members (kern-get-player)))
+                     ))
+        (if (not (null? members))
+            (let ((kchar (random-select members)))
+              (say kchar msg)
+              #t)
+            #f)
+        )
+      (if (in-player-party? kchar-tag)
+          (begin
+            (kern-conv-say (eval kchar-tag) msg)
+            #t)
+          #f)
+      ))
+         
+;;----------------------------------------------------------------------------
+;; Quests
+;;----------------------------------------------------------------------------
+(define (mk-quest) (list #f #f #f))
+(define (quest-offered? qst) (car qst))
+(define (quest-accepted? qst) (cadr qst))
+(define (quest-done? qst) (caddr qst))
+(define (quest-offered! qst val) (set-car! qst val))
+(define (quest-accepted! qst val) (set-car! (cdr qst) val))
+(define (quest-done! qst val) (set-car! (cddr qst) val))
+
+
+;;----------------------------------------------------------------------------
+;; Ranger Conversation
+;;----------------------------------------------------------------------------
+(define (ranger-ranger knpc kpc)
+  (say knpc "Rangers guard the borders between wilderness and "
+       "civilization. We patrol the frontier and give aid where we can to the "
+       "Wise."))
+
+(define (ranger-wise knpc kpc)
+  (say knpc "Rangers have an informal alliance with the Wise. They give us "
+       "aid and hospitality. In return we give them news. Sometimes we serve "
+       "them as messengers and scouts."))
+
+(define (ranger-join knpc kpc)
+  (cond ((has? kpc t_ranger_orders 1)
+         (say knpc "Let's see those orders... ok. Looks like we're partners "
+              "for a while.")
+         (take kpc t_ranger_orders 1)
+         (join-player knpc)
+         ;; NOTE: the following only permits one ranger at a time to join the
+         ;; player!
+         (kern-tag 'ch_ranger_merc knpc)
+         (give kpc t_arrow 20)
+         (kern-conv-end)
+         )
+        (else
+         (say knpc "Sorry, I've got to get back to my patrol."))))
+
+(define (ranger-band knpc kpc)
+  (say knpc "When men get in trouble with the law, they flee to the woods. "
+       "There are always bandits in the forest."))
+
+(define ranger-conv
+  (ifc basic-conv
+       (method 'join ranger-join)
+       (method 'rang ranger-ranger)
+       (method 'wise ranger-wise)
+       (method 'band ranger-band)
+       ))
+
+
+;; Knight conversation -- used by Lord Froederick's troops
+(define knight-conv basic-conv)
+
+;; Glasdrin
+(define (glasdrin-warr knpc kpc)
+  (if (player-found-warritrix?)
+      (say knpc "We all mourn her loss.")
+      (say knpc "The Warritrix is the most cunning warrior of the age. I'm not sure where she is right now, ask the Steward or Commander Jeffries.")
+       )
+       (quest-data-update 'questentry-warritrix 'general-loc 1)
+  )
+
+(define (glasdrin-stew knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "Her name of the Stewardess is a curse among us now. The new Steward is Valus, a former commander.")
+      (say knpc "The Steward is the keeper of the city and realms of Glasdrin. You can usually find her in the Citadel.")))
+
+(define (glasdrin-jeff knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "At best Jeffries failed in his duties as commander to protect those under his command. "
+           "At worst, he was an accomplice in the betrayal of the Warritrix. "
+           "Our new commander is Janice.")
+      (say knpc "Jeffries is the commander of the Glasdrin militia. He's usually at work in the Citadel.")
+      ))
+
+(define (glasdrin-kurp knpc kpc)
+         (say knpc "Take the bridge north across the river then follow the "
+              "mountains east and north into a canyon."))
+(define (glasdrin-cita knpc kpc)
+  (say knpc "The Citadel is the inner keep in the north part of the castle."))
+(define (glasdrin-ghol knpc kpc)
+  (say knpc "I seem to recall a man named Gholet was arrested for theft. You might check the Citadel's dungeon.")
+   (quest-data-update 'questentry-ghertie 'gholet-dungeon 1)
+   )
+(define (glasdrin-kurp knpc kpc)
+  (say knpc "The dungeon Kurpolis is where most of our troops are now. Follow the mountains west, you'll find the entrance in a canyon."))
+
+(define (glasdrin-glas knpc kpc)
+  (say knpc "Glasdrin is the city of the Paladins."))
+
+(define (glasdrin-pala knpc kpc)
+  (say knpc "The Paladins of Glasdrin are the greatest military force in the realm."))
+
+(define glasdrin-conv
+  (ifc basic-conv
+       (method 'warr glasdrin-warr)
+       (method 'stew glasdrin-stew)
+       (method 'jeff glasdrin-jeff)
+       (method 'kurp glasdrin-kurp)
+       (method 'cita glasdrin-cita)
+       (method 'ghol glasdrin-ghol)
+       (method 'kurp glasdrin-kurp)
+       (method 'glas glasdrin-glas)
+       (method 'pala glasdrin-pala)
+       (method 'jani 
+               (lambda (knpc kpc) 
+                 (if (player-stewardess-trial-done?)
+                      (say knpc "The military council has elected Janice to replace Jeffries as commander of the militia.")
+                      (say knpc "Jeffries is an able leader, but everyone knows that his assistant Janice has the brains."))))
+       (method 'valu
+               (lambda (knpc kpc)
+                 (if (player-stewardess-trial-done?)
+                     (say knpc "Valus was exonerated by the Stewardess's journal. "
+                          "It is a shame we ever believed such lies about him. "
+                          "We have elected him to be the new Steward.")
+                     (say knpc "Valus has been imprisoned for shameful indecency. "
+                          "It's a pity, really. He was a well-respected general."))))
+       ))
+
+;; Kurpolis
+(define kurpolis-conv
+  (ifc basic-conv
+       ))
+
+;; Green Tower
+(define (gt-gobl knpc kpc)
+  (say knpc "Since the goblin wars there's been an uneasy truce. Sometimes they trade here in town, but if you meet them in the forest be careful."))
+(define (gt-towe knpc kpc)
+  (say knpc "The tower that gives this town its name is now the Ranger headquarters."))
+(define (gt-ruin knpc kpc)
+  (say knpc "The old ruins are in the southwest corner of town."))
+(define (gt-band knpc kpc)
+  (say knpc "Ask Deric about bandits. "
+       "He's the one who should be dealing with them."))
+
+
+(define green-tower-conv
+  (ifc basic-conv
+       (method 'gree
+               (lambda (knpc kpc)
+                 (say knpc "Yes, this town gets its name from the old tower in its center.")))
+       (method 'gobl gt-gobl)
+       (method 'towe gt-towe)
+       (method 'ruin gt-ruin)
+       (method 'band gt-band)
+       ))
+
+;; Trigrave
+(define trigrave-conv
+  (ifc basic-conv
+       (method 'thie 
+               (lambda (knpc kpc) 
+                 (say knpc "I don't know anything about a thief. Ask Gwen, maybe a traveler told her something.")))                       
+       ))
+
+;;----------------------------------------------------------------------------
+;; Merchant
+
+;; Indices into the merchant message list
+(define merch-closed           0)
+(define merch-buy              1)
+(define merch-sell             2)
+(define merch-trade            3)
+(define merch-sold-something   4)
+(define merch-sold-nothing     5)
+(define merch-bought-something 6)
+(define merch-bought-nothing   7)
+(define merch-traded-something 8)
+(define merch-traded-nothing   9)
+
+(define (conv-trade knpc kpc menu msgs catalog)
+  (println "conv-trade: " (kern-obj-get-activity knpc))
+  ;;(println "conv-trade: " menu msgs catalog)
+  (if (and (not (string=? "working" (kern-obj-get-activity knpc)))
+           (not (null? (list-ref msgs merch-closed))))
+      (say knpc (list-ref msgs merch-closed) 
+           " I'm " (kern-obj-get-activity knpc) " right now.")
+      (cond ((string=? menu "buy")
+             (say knpc (list-ref msgs merch-buy))
+             (if (kern-conv-trade knpc kpc "buy" catalog)
+                 (say knpc (list-ref msgs merch-sold-something))
+                 (say knpc (list-ref msgs merch-sold-nothing))))
+            ((string=? menu "sell")
+             (say knpc (list-ref msgs merch-sell))
+             (if (kern-conv-trade knpc kpc "sell" catalog)
+                 (say knpc (list-ref msgs merch-bought-something))
+                 (say knpc (list-ref msgs merch-bought-nothing))))
+            (else
+             (say knpc (list-ref msgs merch-trade))
+             (if (kern-conv-trade knpc kpc "trade" catalog)
+                 (say knpc (list-ref msgs merch-traded-something))
+                 (say knpc (list-ref msgs merch-traded-nothing))))
+            )))
+
diff --git a/worlds/haxima-1.002/creatures.png b/worlds/haxima-1.002/creatures.png
new file mode 100644 (file)
index 0000000..4c2193f
Binary files /dev/null and b/worlds/haxima-1.002/creatures.png differ
diff --git a/worlds/haxima-1.002/crypt.scm b/worlds/haxima-1.002/crypt.scm
new file mode 100644 (file)
index 0000000..65ec415
--- /dev/null
@@ -0,0 +1,120 @@
+(kern-load "keep_crypt_mech.scm")
+
+(mk-dungeon-room
+ 'p_crypt "Crypt"
+ (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx ,, ,, ,, xx x! ,, ,, ,, x! xx ,, ,, ,, xx ,, xx "
+      "xx xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, xx "
+      "xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, xx "
+      "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, xx xx xx xx xx ?? xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx ,, xx xx xx .C .R .Y .P .T xx xx xx ,, xx xx xx "
+      "xx .. .. ,, .. .. xx xx xx x! xx xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx xx xx ,, xx xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx xx ,, ,, ,, xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx xx ,, ,, ,, xx xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. x! xx xx ,, xx xx x! .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx ,, ,, ,, ,, ,, xx .. .. ,, .. .. xx "
+      "xx .. .. ,, .. .. xx ,, ,, ,, ,, ,, xx .. .. ,, .. .. xx "
+      "xx .. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, .. .. xx "
+      "xx .. .. .. .. .. xx ,, ,, ,, ,, ,, xx .. .. .. .. .. xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+ ;; special mechanisms for turning corpses into skeletal warriors
+ (put (kern-tag 'kc_kcma (mk-kcm (mk-rect 1 9 5 9))) 0 0)
+ (put (kern-tag 'kc_kcmb (mk-kcm (mk-rect 13 9 5 9))) 0 0)
+
+ (put (mk-ladder-up 'p_green_tower_lower 17 1) 9 3)
+ (put (mk-ladder-down 'p_lich_tomb 9 16) 9 10)
+ ;; mundane mechs
+ (put (mk-locked-door) 6 3)
+ (put (mk-magic-locked-door) 12 3)
+ (put (mk-door) 6 7)
+ (put (mk-door) 12 7)
+ (put (mk-windowed-door) 15 8)
+ (put (mk-windowed-door) 3 8)
+ (put (kern-tag 'kc_pa (mk-connected-portcullis 'kc_kcma)) 6 16)
+ (put (kern-tag 'kc_pb (mk-connected-portcullis 'kc_kcmb)) 12 16)
+ (put (kern-tag 'kc_pc (mk-portcullis)) 9 13)
+ (put (mk-lever 'kc_pb) 4 2)
+ (put (mk-lever 'kc_pa) 14 2)
+ (put (mk-lever 'kc_pc) 17 1)
+ ;; corpses
+ (put (mk-corpse) 1  9)
+ (put (mk-corpse) 2  9)
+ (put (mk-corpse) 4  9)
+ (put (mk-corpse) 5  9)
+ (put (mk-corpse) 13 9)
+ (put (mk-corpse) 14 9)
+ (put (mk-corpse) 16 9)
+ (put (mk-corpse) 17 9)
+ (put (mk-corpse) 1  10)
+ (put (mk-corpse) 2  10)
+ (put (mk-corpse) 4  10)
+ (put (mk-corpse) 5  10)
+ (put (mk-corpse) 13 10)
+ (put (mk-corpse) 14 10)
+ (put (mk-corpse) 16 10)
+ (put (mk-corpse) 17 10)
+ (put (mk-corpse) 1  11)
+ (put (mk-corpse) 2  11)
+ (put (mk-corpse) 4  11)
+ (put (mk-corpse) 5  11)
+ (put (mk-corpse) 13 11)
+ (put (mk-corpse) 14 11)
+ (put (mk-corpse) 16 11)
+ (put (mk-corpse) 17 11)
+ (put (mk-corpse) 1  12)
+ (put (mk-corpse) 2  12)
+ (put (mk-corpse) 4  12)
+ (put (mk-corpse) 5  12)
+ (put (mk-corpse) 13 12)
+ (put (mk-corpse) 14 12)
+ (put (mk-corpse) 16 12)
+ (put (mk-corpse) 17 12)
+ (put (mk-corpse) 1  13)
+ (put (mk-corpse) 2  13)
+ (put (mk-corpse) 4  13)
+ (put (mk-corpse) 5  13)
+ (put (mk-corpse) 13 13)
+ (put (mk-corpse) 14 13)
+ (put (mk-corpse) 16 13)
+ (put (mk-corpse) 17 13)
+ (put (mk-corpse) 1  14)
+ (put (mk-corpse) 2  14)
+ (put (mk-corpse) 4  14)
+ (put (mk-corpse) 5  14)
+ (put (mk-corpse) 13 14)
+ (put (mk-corpse) 14 14)
+ (put (mk-corpse) 16 14)
+ (put (mk-corpse) 17 14)
+ (put (mk-corpse) 1  15)
+ (put (mk-corpse) 2  15)
+ (put (mk-corpse) 4  15)
+ (put (mk-corpse) 5  15)
+ (put (mk-corpse) 13 15)
+ (put (mk-corpse) 14 15)
+ (put (mk-corpse) 16 15)
+ (put (mk-corpse) 17 15)
+ (put (mk-corpse) 1  16)
+ (put (mk-corpse) 2  16)
+ (put (mk-corpse) 16 16)
+ (put (mk-corpse) 17 16)
+ (put (mk-corpse) 1  17)
+ (put (mk-corpse) 2  17)
+ (put (mk-corpse) 3  17)
+ (put (mk-corpse) 4  17)
+ (put (mk-corpse) 5  17)
+ (put (mk-corpse) 13 17)
+ (put (mk-corpse) 14 17)
+ (put (mk-corpse) 15 17)
+ (put (mk-corpse) 16 17)
+ (put (mk-corpse) 17 17)
+ )
+
+(mk-place-music p_crypt 'ml-creepy-area)
diff --git a/worlds/haxima-1.002/cursor.png b/worlds/haxima-1.002/cursor.png
new file mode 100644 (file)
index 0000000..4019ff4
Binary files /dev/null and b/worlds/haxima-1.002/cursor.png differ
diff --git a/worlds/haxima-1.002/damage.wav b/worlds/haxima-1.002/damage.wav
new file mode 100644 (file)
index 0000000..82c0f27
Binary files /dev/null and b/worlds/haxima-1.002/damage.wav differ
diff --git a/worlds/haxima-1.002/dank-cave.scm b/worlds/haxima-1.002/dank-cave.scm
new file mode 100644 (file)
index 0000000..a5b5e85
--- /dev/null
@@ -0,0 +1,43 @@
+;; Aka, reagent cave -- generate rare reagents here
+(mk-dungeon-room
+ 'p_dank_cave "Dank Cave"
+       (list
+               "rn rn rn rn rn rn rn rn r8 r8 r8 rn rn rn rn rn rn rn rn "
+               "rn rn rn rn r8 rn rn r4 .. .. .. r2 rn rn r8 rn rn rn rn "
+               "rn rn rn rc {{ ra rn rc {8 .. {8 ra rn rc {{ ra rn rn rn "
+               "rn rn rc {{ {{ {{ re {{ {{ {e {{ {{ re {{ {{ {{ ra rn rn "
+               "rn rc {{ {C %f {A {{ {{ {{ {{ {{ {{ {{ {C .! {A {{ ra rn "
+               "r4 {{ {{ %7 .! %3 %d {{ {{ r7 {{ {{ %b %% %% %5 {{ {{ r2 "
+               "r4 {{ {{ %a %% %c {# {{ rb rn rd {{ {% %a %% %c {{ {{ r2 "
+               "rn r5 {{ {% %e {# {{ {{ {{ re {{ {{ {{ {% %e {# {{ r3 rn "
+               "rn rn r5 {{ {{ {{ r7 {{ {{ {{ {{ {{ r7 {{ {{ {{ r3 rn rn "
+               "rn rn rn rd {{ rb rn rd {{ {{ {{ rb rn rd {{ rb rn rn rn "
+               "rn rn rc {{ {{ {{ re {{ {{ {{ {{ {{ re {{ {{ {{ ra rn rn "
+               "rn rc {{ {C %7 {A {{ {{ {{ r7 {{ {{ {{ {C %7 {A {{ ra rn "
+               "r4 {{ {{ %3 %% %d {A {{ rb rn rd {{ {C %3 %% %5 {{ {{ r2 "
+               "r4 {{ {{ %a %% .! %7 {A {{ re {{ {C %3 %% %% %c {{ {{ r2 "
+               "rn r5 {{ {% %a %% %% %d {{ {{ {{ %b %% .! %e {# {{ r3 rn "
+               "rn rn r5 {{ {% %a %c {# {{ r7 {{ {% %a %d {# {{ r3 rn rn "
+               "rn rn rn r5 {{ {{ {{ {{ r3 rn r5 {{ {{ {{ {{ r3 rn rn rn "
+               "rn rn rn rn r5 {{ {{ r3 rn rn rn r5 {{ {{ r3 rn rn rn rn "
+               "rn rn rn rn rn r1 r1 rn rn rn rn rn r1 r1 rn rn rn rn rn "
+       )
+
+ ;; reagents
+ (put (custom-pt 'grow-trig 'mandrake "1d5") 14 14)
+ (put (custom-pt 'grow-trig 'nightshade "1d5") 6 14)
+ (put (custom-pt 'grow-trig 'ginseng "1d5") 3 12)
+ (put (custom-pt 'grow-trig 'ginseng "1d5") 3 5)
+ (put (custom-pt 'grow-trig 'garlic "1d5") 15 5)
+ (put (custom-pt 'grow-trig 'garlic "1d5") 3 13)
+ (put (mk-ladder-up 'p_shamans_grove 14 11) 9 1)
+
+ ;; monsters
+ (put (spawn-pt 'gazer) 9 9)
+ (put (spawn-pt 'headless) 8 7)
+ (put (spawn-pt 'bat) 5 17)
+ (put (spawn-pt 'rat) 4 2)
+ (put (spawn-pt 'snake) 17 12)
+ )
+
+(mk-place-music p_dank_cave 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/demo.scm b/worlds/haxima-1.002/demo.scm
new file mode 100644 (file)
index 0000000..ddc02ef
--- /dev/null
@@ -0,0 +1,2180 @@
+;;----------------------------------------------------------------------------
+;; The very first line of any session file should be (load "naz.scm"). This
+;; bootstraps some procedures that we need to continue. This is the only place
+;; you should use 'load'. Every other place you want to load a file you should
+;; user 'kern-load'. 'kern-load' ensures that a saved session will be able to
+;; load the file, too.
+;;----------------------------------------------------------------------------
+(load "naz.scm")
+
+;; clone of game.scm ---------------------------------------------------------
+
+;; Setup progress bar stuff. The number 44 should be the total number of files
+;; we're going to load.
+(kern-progress-bar-start "Loading" 44)
+
+;; Wrap the original definition of (load ...) with one that advances the
+;; progress bar.
+(define original-load load)  
+(define (load file)
+  (kern-progress-bar-advance 1)
+  (original-load file)
+  )
+
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;; Slots
+(define slot-nil              0)
+(define slot-amulet           1)
+(define slot-ring             2)
+(define slot-gazer-helm       4)
+(define slot-weapon           8)
+(define slot-shield           8)
+(define slot-weapon-or-shield 8)
+(define slot-armor            16)
+(define slot-boot             32)
+(define slot-helm             64)
+
+;; Speeds  ;; TODO: move most of these into kern-intvars ?
+
+(define speed-human             50)  ;; typical AP/round for humans
+
+(define base-move-ap           50)  ;; this may not bear a neat relationship to speed-human
+(define default-weapon-rap      50)  ;; this may not bear a neat relationship to speed-human
+(define default-armour-apmod    2)  ;; this may not bear a neat relationship to speed-human
+
+(define base-skill-ap                  base-move-ap)  ;; this may not bear a neat relationship to speed-human
+(define base-spell-ap                  base-move-ap)  ;; this may not bear a neat relationship to speed-human
+
+;; AP costs of various actions which the kernal needs to know about:
+(kern-set-kern-intvar "AP_TOTAL:normal_human"    speed-human)
+
+(kern-set-kern-intvar "AP_COST:default"           speed-human)
+(kern-set-kern-intvar "AP_COST:search"            (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:get_item"          (* 0.34 speed-human))
+(kern-set-kern-intvar "AP_COST:drop_item"         (* 0.34 speed-human))
+(kern-set-kern-intvar "AP_COST:open_mechanism"    speed-human)
+(kern-set-kern-intvar "AP_COST:open_container"    speed-human)
+(kern-set-kern-intvar "AP_COST:handle_mechanism"  speed-human)
+(kern-set-kern-intvar "AP_COST:use_item"          speed-human)  ;; may be unused, per comment in cmd.c cmdUse()
+
+;; Normal mixing: 18 + (num_mixed * 12) + (spell_level * 12) AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_base"         (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_per_mix"      (* 2 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_per_level"    (* 2 speed-human))
+;; Attempt at non-existent spell: 3d18+6 AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_num"   3)
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_dice" (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_plus"  speed-human)
+;; Missing or additional ingredients: (2 * spell_level)d18+18 AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_num"    2)  ;; times spell Level
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_dice"  (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_plus"  (* 3 speed-human))
+
+;; These values are used by ctrl.c ctrl_attack_target() 
+;; to adjust weapon AP costs in the event of dual wielding.
+;; The dual weapon rules can thus be tweaked here...
+(kern-set-kern-intvar "AP_MULT12:second_wpn_attack"       6)  ;; AP cost * 6/12 for 2nd weapon attack if dual wpns used
+(kern-set-kern-intvar "AP_MULT12:third_plus_wpn_attack"   6)  ;; AP cost * 6/12 for 3rd+ weapon attacks, if 3+ weapons used
+(kern-set-kern-intvar "AP_THRESHOLD:multi_attack_overage" 0)  ;; attack sequence can continue if AP overage is not > 0
+
+(kern-set-kern-intvar "submerged_def_bonus" 10) ;; defense bonus for submerged critters
+
+;; ship speeds are better handled using mmodes/pclasses-
+;; it should only affect actual movement
+(define speed-ship            speed-human)  
+
+;; Action Point costs for various basic actions:
+;; are these used anywhere?
+;;(define ap-for-1H-melee-attack   9)
+;;(define ap-for-2H-melee-attack  12)
+
+;;(define ap-for-1H-thrown-attack 12)
+;;(define ap-for-2H-thrown-attack 18)
+
+;;(define ap-for-shooting-attack  12)
+
+;;(define ap-for-combat-spell      9)
+;;(define ap-to-use-scroll        12)
+
+
+;; Difficulty Classes
+(define dc-escape-ensnare  26)
+(define dc-escape-paralyze 16)
+
+;; Pmasks (keep them around until mechs are converted to use passability
+;; classes (see below))
+(define pmask-none   0)
+(define pmask-solid  1)
+(define pmask-land   2)
+(define pmask-water  4)
+(define pmask-shoals 8)
+(define pmask-bridge (+ pmask-land pmask-water pmask-shoals))
+(define pmask-all    (+ pmask-solid pmask-land pmask-water pmask-shoals))
+
+;; Passability Difficulty Levels 
+;;   (Note: 255 is well-known to the kernel to mean
+;;   "impassible" in the case of movement costs)
+(define fast        (* 0.66 base-move-ap))  ;; 0.66 (2/3)
+(define s-fast      (* 0.8 base-move-ap))  ;; 'slightly fast' 0.8
+(define norm        base-move-ap)  ;; 1.0
+(define s-hard      (* 1.5 base-move-ap))  ;; 1.5
+(define hard       (* 2 base-move-ap))  ;; 2.0
+(define v-hard     (* 3 base-move-ap))  ;; 3.0
+
+(define no-drop    100)  ;; special, used for dropability (not related to speed-human)
+(define cant      255)  ;; special
+
+;(define norm       50)  ;; 1.0
+;(define s-hard     75)  ;; 1.5
+;(define hard      100)  ;; 2.0
+;(define v-hard    150)  ;; 3.0
+;(define fast       30)  ;; 0.6
+;(define s-fast     40)  ;; 0.4
+;(define no-drop   100)  ;; 2.0
+;(define cant      255)  ;; 
+
+
+;; Passability classes
+(define pclass-none          0)
+(define pclass-grass         1)
+(define pclass-deep          2)
+(define pclass-shoals        3)
+(define pclass-mountains     4) ;; no ceiling
+(define pclass-wall          5) ;; has a ceiling
+(define pclass-trees         6)
+(define pclass-forest        7)
+(define pclass-hills         8)
+(define pclass-repel         9) ;; energy shield blocks all
+(define pclass-space         10)
+(define pclass-bridge        pclass-grass)
+(define pclass-road          pclass-grass)
+(define pclass-boulder       11) ;; no ceiling, smaller than mountain
+(define pclass-waterboulder  12) ;; worst case of boulder and water
+(define pclass-sludge        13)
+(define pclass-shallows      14)
+(define pclass-bars          15) ;; portcullis
+(define pclass-window        16) ;; separating from bars for shoot-but-not-crawl-through passability
+(define pclass-vmountains    17)
+(define pclass-canfloat      18) ;; avoids drowning
+(define pclass-canfly        19) ;; avoids ground based issues
+
+;; Movement modes
+(define mmodes
+  (list
+   (list 'mmode-walk      "walking"     0)
+   (list 'mmode-hover     "hovering"    1)
+   (list 'mmode-ship      "sailing"     2)
+   (list 'mmode-phase     "phasing"     3)
+   (list 'mmode-fly       "flying"      4)
+   (list 'mmode-skiff     "rowing"      5)
+   (list 'mmode-fish      "swimming"    6)
+   (list 'mmode-crawl     "crawling"    7) ;; spiders, can cross boulders
+   (list 'mmode-voidship  "sailing"     8)
+   (list 'mmode-ranger    "stalking"    9)
+   (list 'mmode-none      "stationary" 10)
+   (list 'mmode-wriggle   "wriggle"    11) ;; rogue special move
+   (list 'mmode-missile   "missile"    12)
+   (list 'mmode-fastfly   "flying"     13)
+   (list 'mmode-fastrun   "running"    14)
+   (list 'mmode-fastcrawl "crawling"   15)
+   (list 'mmode-smallobj  "smallobj"   16) ;; for determining dropability of small objects
+   (list 'mmode-largeobj  "largeobj"   17) ;; for determining dropability of big objects- basically, stuff that wont fit through bars/windows
+   (list 'mmode-field     "field"      18) ;; for determining dropability of fields
+   (list 'mmode-return    "return"     19) ;; return path for magic axe (for now assume it always returns)
+   (list 'mmode-cannon    "crawling"   20) ;; enhanced missile passibility for cannon shells
+   (list 'mmode-large     "striding"   21) ;; big critters
+))
+(map (lambda (mmode) (apply kern-mk-mmode mmode)) mmodes)
+
+(define mmode-jump mmode-fly)
+
+;; Movement cost table (optimized for cut to/paste from spreadsheet!)
+(kern-mk-ptable                                                                                                                                                                                                        
+       ;;      walk    hover   ship    phase   fly     skiff   fish    crawl   vship   rangr   none    wrigl   missl   f_fly   f_run   f_crawl sml_obj lrg_obj fields  return  cannon  striding                
+       (list   0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       )       ;; none
+       (list   norm    norm    cant    norm    norm    cant    cant    norm    cant    norm    cant    norm    0       fast    fast    fast    norm    norm    norm    0       0       norm    )       ;; grass/paving
+       (list   cant    cant    s-fast  cant    norm    v-hard  norm    cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       cant    )       ;; deep
+       (list   cant    s-hard  cant    cant    norm    norm    norm    cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       s-hard  )       ;; shoals
+       (list   cant    cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    95      s-fast  cant    cant    no-drop no-drop cant    0       90      cant    )       ;; mountains
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    cant    100     cant    cant    cant    cant    cant    cant    0       100     cant    )       ;; wall (w/ ceiling)
+       (list   hard    hard    cant    norm    norm    cant    cant    hard    cant    norm    cant    hard    10      fast    norm    norm    norm    norm    norm    0       7       hard    )       ;; trees
+       (list   v-hard  v-hard  cant    norm    norm    cant    cant    v-hard  cant    s-hard  cant    v-hard  30      fast    hard    hard    norm    norm    norm    0       20      v-hard  )       ;; forest
+       (list   v-hard  hard    cant    norm    norm    cant    cant    v-hard  cant    s-hard  cant    v-hard  7       fast    hard    hard    norm    norm    norm    0       5       hard    )       ;; hills/bog
+       (list   cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    100     cant    cant    cant    no-drop no-drop norm    0       100     cant    )       ;; energy fields
+       (list   cant    cant    cant    cant    norm    cant    cant    cant    norm    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       cant    )       ;; space
+       (list   cant    norm    cant    norm    norm    cant    cant    hard    cant    cant    cant    hard    10      fast    cant    norm    norm    norm    norm    0       4       norm    )       ;; boulder
+       (list   cant    hard    cant    cant    norm    cant    cant    hard    cant    cant    cant    hard    10      fast    cant    norm    norm    norm    no-drop 0       4       hard    )       ;; waterboulder
+       (list   cant    norm    hard    cant    norm    v-hard  v-hard  cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       norm    )       ;; sludge
+       (list   s-hard  norm    cant    norm    norm    norm    norm    s-hard  cant    norm    cant    cant    0       fast    norm    norm    cant    cant    no-drop 0       0       norm    )       ;; shallow sludge
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    v-hard  7       cant    cant    cant    norm    no-drop norm    0       7       cant    )       ;; bars (eg portcullis)
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    cant    30      cant    cant    cant    no-drop no-drop no-drop 0       25      cant    )       ;; window
+       (list   cant    cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    30      s-fast  cant    cant    no-drop no-drop no-drop 0       10      cant    )       ;; passlos mountains
+       (list   cant    v-hard  s-fast  cant    norm    cant    norm    cant    cant    cant    cant    cant    norm    norm    cant    cant    cant    cant    norm    norm    norm    v-hard  )       ;; float
+       (list   cant    hard    cant    cant    norm    hard    cant    cant    norm    cant    cant    cant    norm    norm    cant    cant    cant    cant    norm    norm    norm    cant    )       ;; fly
+)                                                                                                                                                                                                      
+;; Note that pclass 'missl' is using the value as a percentage chance 
+;; for a missile to be blocked by obscuring terrain, not as an AP cost
+
+
+;; Factions. The diplomacy table (which defines the relationship between
+;; factions) must be defined in the session file, because it changes over time.
+(define faction-none          0)
+(define faction-player        1)
+(define faction-men           2)
+(define faction-cave-goblin   3)
+(define faction-accursed      4)
+(define faction-monster       5)
+(define faction-troll         6)
+(define faction-spider        7)
+(define faction-outlaw        8)
+(define faction-gint          9)
+(define faction-demon         10)
+(define faction-forest-goblin 11)
+(define faction-num           12)
+(define faction-green-tower   faction-men)
+(define faction-glasdrin      faction-men)
+(define faction-oparine       faction-men)
+(define faction-trigrave      faction-men)
+(define faction-nixie         faction-monster)
+(define faction-prisoner      13)
+
+;; Layers (must match object.h)
+(define layer-none       0)
+(define layer-tfeat      1)
+(define layer-mechanism  2)
+(define layer-portal     3)
+(define layer-vehicle    4)
+(define layer-bed        5)
+(define layer-container  6)
+(define layer-item       7)
+(define layer-field      8)
+(define layer-being      9)
+(define layer-projectile 10)
+(define layer-crosshair  11)
+
+;; Contexts
+(define context-world 1)
+(define context-town  2)
+(define context-any      (+ context-town context-world))
+
+;; Damage/Immunity types (ordinal, not bitmasks)
+(define damage-none   0)
+(define damage-fire   1)
+(define damage-poison 2)
+(define damage-sleep  3)
+
+;; Damage amounts
+(define lava-damage 10)
+
+;; Directions (as returned by kern-ui-get-direction)
+(define northwest 0)
+(define north     1)
+(define northeast 2)
+(define west      3)
+(define here      4)
+(define east      5)
+(define southwest 6)
+(define south     7)
+(define southeast 8)
+(define up        9)
+(define down      10)
+
+(define opposite-dir (vector southeast south southwest
+                             east here west
+                             northeast north northwest
+                             down up))
+
+;; Player character bonuses
+(define pc-hp-off  25)
+(define pc-hp-gain 5)
+(define pc-mp-off  1)
+(define pc-mp-gain 1)
+
+;; NPC activities
+(define (isdrunk? knpc)
+  (string=? "drunk" (kern-obj-get-activity knpc)))
+(define (isworking? knpc)
+  (string=? "working" (kern-obj-get-activity knpc)))
+
+;; Prices
+(define base-scroll-cost 20) ;; gold pieces per level of scroll's spell
+(define reagent-price-mult 1) ;; global reagent price multiplier
+
+;; rather than trying to calculate appropriate hp/mp for
+;; characters, stick in a big number and let Character::new
+;; trim it as needed
+(define max-health 999999999)
+
+;; Some of the following are order-dependent
+(load "loc.scm")
+(load "kobj.scm")
+(load "ifc.scm")
+(load "sprite-sets.scm")
+(load "sprites.scm")
+
+(define s_altar (mk-composite-sprite (list s_grass s_altar_obj)))
+(define s_active_altar (mk-composite-sprite (list s_grass s_active_altar_obj)))
+(define s_overgrown_altar (mk-composite-sprite (list s_trees s_altar_obj)))
+
+(load "sounds.scm")
+(load "effects.scm")
+(load "terrains.scm")
+(load "fields.scm")
+;;(load "combat-maps.scm")
+
+;; Object types
+(load "objs.scm")
+;;(load "traps.scm")
+;;(load "pitfalls.scm")
+;;(load "landslide.scm")
+(load "containers.scm")
+(load "reagents.scm")
+(load "food.scm")
+(load "arms.scm")
+(load "powers.scm")
+(load "ability.scm")
+(load "cast-ui.scm")
+(load "spells.scm")
+(load "items.scm")
+;;(load "vehicles.scm")
+;;(load "beds.scm")
+(load "money.scm")
+(load "skills.scm")
+(load "occs.scm")
+(load "ai.scm")
+(load "species.scm")
+(load "conv.scm") ;; basic conversation
+(load "npc-types.scm")
+(load "spider.scm")
+;;(load "mimic.scm")
+;;(load "parties.scm")
+;;(load "jewelry.scm")
+(load "gate-guard.scm")
+
+;; Mechanism-like things
+(load "bim.scm")
+(load "step.scm")
+(load "monster-generator.scm")
+;;(load "wilderness-manager.scm")
+(load "terrain-to-ptype.scm")
+;;(load "edge-spawn.scm")
+;;(load "door.scm")
+;;(load "portcullis.scm")
+(load "hidden.scm")
+;;(load "lever.scm")
+(load "timer.scm")
+;;(load "tblit.scm")
+(load "portals.scm")
+(load "moongate.scm")
+;;(load "bridge.scm")
+;;(load "drawbridge.scm")
+;;(load "weather-vane.scm")
+;;(load "wind-bridge.scm")
+
+;; Astronomy
+(load "moon.scm")
+
+;; Miscellaneous crap
+(mk-obj-type 't_crosshair "crosshair" s_crosshair layer-crosshair nil)
+(kern-set-crosshair t_crosshair)
+(kern-set-frame s_frame_ulc
+                s_frame_urc
+                s_frame_llc
+                s_frame_lrc
+                s_frame_td
+                s_frame_tu
+                s_frame_tl
+                s_frame_tr
+                s_null
+                s_frame_horz
+                s_frame_vert
+                s_frame_endl
+                s_frame_endr)
+(kern-set-ascii ss_u4_charset 32)
+(kern-set-cursor ls_whirlpool)
+(kern-set-damage-sprite s_hit)
+(kern-add-query 'str_based_attack_query proc-stratt)
+(kern-add-query 'dex_based_attack_query proc-dexatt)
+(kern-add-query 'damage_bonus_query proc-stratt)
+(kern-add-query 'defense_bonus_query proc-dexdef)
+
+;; Setup the global effect sprites
+(kern-set-quicken-sprite s_quicken)
+(kern-set-time-stop-sprite s_time_stop)
+(kern-set-magic-negated-sprite s_magic_negated)
+(kern-set-reveal-sprite s_reveal)
+(kern-set-xray-vision-sprite s_xray_vision)
+
+(kern-init-random)
+
+(kern-progress-bar-finish)
+
+;; end clone of game.scm------------------------------------------------------
+
+
+
+(kern-load "runes.scm")
+
+(define logo-image (kern-image-load "haximatext.png"))
+(define yoff 7)
+(define xoff -3)
+
+;;----------------------------------------------------------------------------
+;; Time -- this needs to be set before loading any dungeon rooms
+;;----------------------------------------------------------------------------
+(define hour 12)
+(define minutes 00)
+(define time-in-minutes (+ (* hour 60) minutes))
+(define game-start-time (time-mk 0 0 0 0 hour minutes))
+
+(kern-set-clock 
+ 0 ; year
+ 0 ; month
+ 0 ; week
+ 0 ; day
+ hour  ; hour
+ minutes ; minutes
+ )
+
+;;----------------------------------------------------------------------------
+;; Gate Traveler
+;;----------------------------------------------------------------------------
+
+(define flee-gate (list #f))
+
+(define (traveler-goto-dest kchar dest)
+  (let (
+         (loc (kern-obj-get-location kchar))
+         )
+    (if (equal? loc dest)
+        (begin
+          (kern-obj-remove kchar)
+          (kern-map-repaint)
+          #t)
+        (begin
+          (pathfind kchar dest)))))
+          
+(define (traveler-dest kchar)
+       (let ((loc (kern-obj-get-location kchar)))
+               (if (car flee-gate)
+                       (loc-mk (loc-place loc) (+ xoff 20) (+ yoff  5))
+                       (cons 
+                               (loc-place loc) 
+                               (npcg-get-post (gob kchar))
+                       ))
+       ))
+
+(define (wizard-traveler-ai kchar)
+  (or (spell-sword-ai kchar)
+      (traveler-goto-dest kchar (traveler-dest kchar))))
+
+(define (normal-traveler-ai kchar)
+  (or (std-ai kchar)
+      (if (any-visible-hostiles? kchar)
+          #f
+          (traveler-goto-dest kchar (traveler-dest kchar)))))
+       
+;; these detect who kchar is friendly/hostile to, not vice-versa
+(define (all-demons-near kchar)
+  (filter (lambda (kobj) (eqv? (kern-char-get-species kobj) sp_demon))
+          (kern-place-get-beings (loc-place (kern-obj-get-location kchar)))))
+    
+(define (all-allies-near kchar)
+  (filter (lambda (kobj) (eqv? (kern-char-get-species kobj) sp_human))
+          (kern-place-get-beings (loc-place (kern-obj-get-location kchar)))))      
+             
+(define (wizard-defender-ai kchar)
+  (or (spell-sword-ai kchar)
+               (if (and (null? (all-demons-near kchar)) (> (kern-dice-roll "1d3") 2))
+                       (if (> (kern-dice-roll "1d3") 2)
+                       (traveler-goto-dest kchar (traveler-dest kchar))
+                       #t
+               )
+               #f)))
+
+(define (normal-defender-ai kchar)
+  (or (std-ai kchar)
+      (if (and (null? (all-demons-near kchar)) (> (kern-dice-roll "1d3") 2))
+       (if (> (kern-dice-roll "1d3") 2)
+               (traveler-goto-dest kchar (traveler-dest kchar))
+               (begin 
+                       (kern-obj-dec-ap kchar base-move-ap)
+                       #t
+               )
+          )
+          #f)))
+
+(define (traveler-exit kchar)
+  (let* ((loc (kern-obj-get-location kchar))
+         (dest (loc-mk (loc-place loc) (+ xoff 20) (+ yoff  5)))
+       )
+    (traveler-goto-dest kchar dest)
+  ))
+
+(define (seek-loot kchar)
+  (let ((loot-list 
+         (filter (mk-ifc-query 'get)
+                 (kern-place-get-objects (loc-place (kern-obj-get-location kchar))))
+         ))
+    (if (not (null? loot-list))
+        (let* ((targetloot (nearest-obj kchar loot-list)))
+          (if (< (kern-get-distance (kern-obj-get-location kchar) (kern-obj-get-location targetloot)) 2)
+              (begin 
+                (kern-obj-remove targetloot)
+                (kern-map-repaint)
+                #t
+                )
+              (pathfind kchar (kern-obj-get-location targetloot))
+              ))
+        #f
+        )
+    ))
+    
+(define (beggar-exit kchar)
+  (or (seek-loot kchar)
+      (traveler-exit kchar))
+    ) 
+    
+(define (erratic-traveler-ai kchar)
+  (or (std-ai kchar)
+     (if (> (kern-dice-roll "1d5") 1)
+               (if (> (kern-dice-roll "1d3") 1)
+               (traveler-goto-dest kchar (traveler-dest kchar))
+               (begin
+                       (kern-obj-dec-ap kchar base-move-ap)
+                       #t
+               )
+       )
+       #f)))
+          
+(define (traveler-mk kplace)
+  (let* ((wizard-sprites (list s_black_mage s_old_mage s_plain_mage s_cloaked_female s_companion_wizard s_red_wizard s_lady s_silas s_companion_druid))
+         (warrior-sprites (list s_avatar s_wanderer s_companion_fighter s_companion_paladin s_brigand))
+         (wrogue-sprites (list s_companion_bard s_companion_tinker s_companion_ranger s_ranger s_brigandess s_old_ranger))
+         (info (random-select (list (list 'wizard 'wizard-traveler-ai wizard-sprites) 
+                                    (list 'paladin 'normal-traveler-ai warrior-sprites)
+                                    (list 'tinker 'normal-traveler-ai wrogue-sprites)
+                                    (list 'ranger 'normal-traveler-ai wrogue-sprites)
+                                    )))
+         (path (random-select (list 
+                               (list (loc-mk kplace (+ xoff 20) (+ yoff  4)) (list  (+ xoff 9) (+ yoff  5)) #f)
+                               (list (loc-mk kplace (+ xoff 20) (+ yoff  5)) (list  (+ xoff 9) (+ yoff  5)) #f)
+                               (list (loc-mk kplace (+ xoff 20) (+ yoff  6)) (list  (+ xoff 9) (+ yoff  5)) #f)
+
+                               (list (loc-mk kplace (+ xoff 10) (+ yoff  4)) (list  (+ xoff 20)(+ yoff  4)) #t)
+                               (list (loc-mk kplace (+ xoff 10) (+ yoff  5)) (list  (+ xoff 20)(+ yoff  5)) #t)
+                               (list (loc-mk kplace (+ xoff 10) (+ yoff  6)) (list  (+ xoff 20)(+ yoff  6)) #t)
+                               )))
+         (kchar (mk-npc (car info) 9))
+         )
+    (npcg-set-post! (gob kchar) (cadr path))
+    (kern-char-set-ai kchar (cadr info) kchar)
+    (kern-obj-set-sprite kchar (random-select (caddr info)))
+    (kern-obj-put-at kchar (car path))
+    (kern-map-repaint)
+    (kern-sleep 20)
+    kchar))
+
+(define (defender-mk ctype aitype kplace postx posty)
+       (let ((kchar (mk-npc ctype 9)))
+               (npcg-set-post! (gob kchar) (list postx posty))
+          (kern-char-set-ai kchar aitype)
+       (kern-obj-put-at kchar (loc-mk kplace postx posty))
+       (kern-map-repaint)
+      (kern-sleep 20)
+       kchar           
+       ))
+    
+;;----------------------------------------------------------------------------
+;; Wise
+;;----------------------------------------------------------------------------
+(define (wait-ai kchar)
+  #t)
+
+(define (wise-enter-ai kchar)
+  (let* ((wise (gob kchar))
+         (loc (kern-obj-get-location kchar))
+         (dest (cons (loc-place loc) (npcg-get-post wise)))
+         )
+    (if (equal? loc dest)
+        (let ((kmgr (car (npcg-get-subgob wise))))
+          ;; Tell the mgr this one is in position and switch it over to waiting
+          ;; mode.
+          (scene-mgr-incr-num-wise-in-pos! (gob kmgr))
+          (kern-char-set-ai kchar 'wait-ai)
+          #t)
+        (pathfind kchar dest))))
+
+(define (wise-exit-ai kchar)
+  (let* ((wise (gob kchar))
+         (loc (kern-obj-get-location kchar))
+         (dest (cons (loc-place loc) 
+                     (npcg-get-post wise)))
+         )
+    (if (equal? loc dest)
+        (let ((kmgr (car (npcg-get-subgob wise))))
+          (kern-obj-remove kchar)
+          (kern-map-repaint)
+          (scene-mgr-incr-num-wise-in-pos! (gob kmgr))
+          #t)
+        (begin
+          (pathfind kchar dest)))))
+
+(define (wise-mk kplace n kmgr)
+  (let* ((kchar (mk-npc 'wizard 9))
+         (info (list-ref (list 
+                         (list (list (+ xoff 20) (+ yoff 4)) (list  3 11) s_black_mage)
+                         (list (list (+ xoff 20) (+ yoff 5)) (list  3 13) s_old_mage)
+                         (list (list (+ xoff 20) (+ yoff 6)) (list  5  9) s_plain_mage)
+                         (list (list (+ xoff 20) (+ yoff 4)) (list  5 15) s_cloaked_female)
+                         (list (list (+ xoff 20) (+ yoff 5)) (list  7 15) s_companion_wizard)
+                         (list (list (+ xoff 20) (+ yoff 6)) (list  7  9) s_red_wizard)
+                         (list (list (+ xoff 20) (+ yoff 4)) (list  9 11) s_lady)
+                         (list (list (+ xoff 20) (+ yoff 5)) (list  9 13) s_silas)
+                              )
+                        n))
+         (enter-pos (cons kplace (car info)))
+         (altar-pos (cadr info))
+        )
+    (kern-char-set-ai kchar 'wise-enter-ai)
+    (npcg-set-post! (gob kchar) altar-pos)    
+
+    ;; Save the kmgr object in the gob so the wise can notify it when they are
+    ;; in position. Also remember the entrance position so they can pathfind
+    ;; back.
+    (npcg-set-subgob! (gob kchar) (cons kmgr (car info)))
+    (kern-obj-set-sprite kchar (caddr info))
+    (kern-obj-put-at kchar enter-pos)
+    (kern-map-repaint)
+    (kern-sleep 20)
+    kchar))
+
+;;----------------------------------------------------------------------------
+;; Special Object Types
+;;----------------------------------------------------------------------------
+(define portal-ifc
+  (ifc '()
+       (method 'step (lambda (kportal kobj) 
+                       ;;(println "portal-step")
+                       ;;(kern-map-flash 100)
+                       (kern-obj-remove kobj)
+                       ))
+       ))
+(mk-obj-type 't_portal "Portal" s_blackgate_full layer-mechanism portal-ifc)
+
+;;----------------------------------------------------------------------------
+;; Scene Manager
+;;----------------------------------------------------------------------------
+(define (scene-mgr-mk) (list 'scene-mgr 0 0 0 '() 0 0))
+(define (scene-mgr-state gob) (list-ref gob 1))
+(define (scene-mgr-set-state! gob val) (set-car! (list-tail gob 1) val))
+(define (scene-mgr-advance-state! gob) 
+  (set-car! (list-tail gob 1) (+ 1 (scene-mgr-state gob)))
+  (scene-mgr-set-pause! gob 0)
+  )
+(define (scene-mgr-get-num-demons gob) (list-ref gob 2))
+(define (scene-mgr-set-num-demons! gob val) (set-car! (list-tail gob 2) val))
+(define (scene-mgr-incr-num-demons! gob) (set-car! (list-tail gob 2) (+ 1 (scene-mgr-get-num-demons gob))))
+(define (scene-mgr-get-num-travelers gob) (list-ref gob 3))
+(define (scene-mgr-set-num-travelers! gob val) (set-car! (list-tail gob 3) val))
+(define (scene-mgr-incr-num-travelers! gob) (set-car! (list-tail gob 3) (+ 1 (scene-mgr-get-num-travelers gob))))
+
+(define (scene-mgr-get-wise gob) (list-ref gob 4))
+(define (scene-mgr-get-num-wise gob) (length (scene-mgr-get-wise gob)))
+(define (scene-mgr-add-wise! gob kwise) (set-car! (list-tail gob 4) (cons kwise (scene-mgr-get-wise gob))))
+
+(define (scene-mgr-get-num-wise-in-pos gob) (list-ref gob 5))
+(define (scene-mgr-set-num-wise-in-pos! gob val) (set-car! (list-tail gob 5) val))
+(define (scene-mgr-incr-num-wise-in-pos! gob) (set-car! (list-tail gob 5) (+ 1 (scene-mgr-get-num-wise-in-pos gob))))
+(define (scene-mgr-get-pause gob) (list-ref gob 6))
+(define (scene-mgr-set-pause! gob val) (set-car! (list-tail gob 6) val))
+(define (scene-mgr-incr-pause! gob) (set-car! (list-tail gob 6) (+ 1 (scene-mgr-get-pause gob))))
+
+(define (scene-mgr-intro-travelers-phase kobj)
+  ;;(println "scene-mgr-intro-travelers-phase")
+  (let* ((smgr (kobj-gob-data kobj))
+         (n (scene-mgr-get-num-travelers smgr))
+         )
+    (define (put-traveler)
+      ;;(println "put-traveler")
+      (traveler-mk (loc-place (kern-obj-get-location kobj)))
+      (scene-mgr-incr-num-travelers! smgr)
+      )
+    (cond ((< n 10) 
+           (if (> (kern-dice-roll "1d10") 9)
+               (put-traveler)))
+          (else
+           (if (> (kern-dice-roll "1d5") 4)
+           (scene-mgr-advance-state! smgr))))
+    ))
+
+(define (scene-mgr-intro-demons-phase kobj)
+  ;;(println "scene-mgr-intro-demons-phase")
+  (let* ((smgr (kobj-gob-data kobj))
+         (n (scene-mgr-get-num-demons smgr))
+         )
+    (define (put-demon dir)
+      (let ((kdemon (mk-npc 'demon 9)))
+        (kern-char-set-ai kdemon 'std-ai)
+        ;;(kern-map-flash 1000)
+        (kern-obj-put-at kdemon 
+                         (loc-offset (mk-loc (loc-place (kern-obj-get-location kobj)) (+ xoff 9)  (+ yoff 5))
+                                     dir)))
+    
+      (scene-mgr-incr-num-demons! smgr)
+              (kern-map-repaint)
+                 (kern-sleep 20)
+      )
+    (cond ((= n 0) 
+                       (set-car! flee-gate #t)
+           (kern-add-reveal 1000)
+           (put-demon west))
+          ((= n 1) (put-demon east))
+          ((= n 2) (put-demon south))
+          ((= n 3) (put-demon north))
+          ((= n 4) ;; second wave
+               (if (> (kern-dice-roll "1d7") 6)
+                       (put-demon west)
+               )
+          )
+          ((= n 5) (put-demon east))
+          ((= n 6) (put-demon south))
+          ((= n 7) (put-demon north))
+          (else
+           (scene-mgr-advance-state! smgr)))
+    ))
+          
+(define (scene-mgr-wait-for-no-demons-phase kobj)
+  (if (null? (all-demons-near (kern-get-player)))
+                       (if (> (kern-dice-roll "1d7") 6)
+               (scene-mgr-advance-state! (gob kobj)))
+                       (if (< (length (all-allies-near (kern-get-player))) 3)
+                               (let ((kplace (loc-place (kern-obj-get-location kobj))))
+                                       (defender-mk 'ranger 'normal-defender-ai kplace (+ xoff 20) (+ yoff  5))
+                                       (defender-mk 'paladin 'normal-defender-ai kplace (+ xoff 20) (+ yoff  6))
+                                       (if (> (kern-dice-roll "1d4") 3)
+                                               (defender-mk 'wizard 'wizard-defender-ai kplace (+ xoff 20) (+ yoff  4))
+                                               (defender-mk 'paladin 'normal-defender-ai kplace (+ xoff 20) (+ yoff  4))
+                                       )
+                               ))
+      ))
+
+(define (scene-mgr-intro-wise kobj)
+  ;;(println "scene-mgr-intro-wise")
+  (let* ((smgr (kobj-gob-data kobj))
+         (n (scene-mgr-get-num-wise smgr))
+         )
+    (cond ((< n 8) 
+                       (if (or (> n 6) (> (kern-dice-roll "1d4") 3))
+           (scene-mgr-add-wise! smgr (wise-mk (loc-place (kern-obj-get-location kobj)) n kobj))
+           ))
+          (else
+           (scene-mgr-advance-state! smgr)))
+    )
+  )
+
+(define (scene-mgr-wait-for-wise kobj)
+  ;;(println "scene-mgr-wait-for-wise")
+  (let ((smgr (gob kobj)))
+    (if (= 8 (scene-mgr-get-num-wise-in-pos smgr))
+      (scene-mgr-advance-state! smgr))))
+
+(define (scene-mgr-close-gate kobj)
+  ;;(println "scene-mgr-close-gate")
+  
+  (define (drop-rune krune loc)
+    (kern-obj-put-at krune loc)
+    (kern-place-set-terrain loc t_active_altar)
+    )
+
+  (define (drop-all-runes)
+    (let ((kplace (loc-place (kern-obj-get-location kobj))))
+      (drop-rune (kern-tag 'rune_k (kern-mk-obj t_rune_k 1)) (loc-mk kplace  4   8))
+      (drop-rune (kern-tag 'rune_p (kern-mk-obj t_rune_p 1)) (loc-mk kplace  8   8))
+      (drop-rune (kern-tag 'rune_s (kern-mk-obj t_rune_s 1)) (loc-mk kplace 10  10))
+      (drop-rune (kern-tag 'rune_c (kern-mk-obj t_rune_c 1)) (loc-mk kplace 10  14))
+      (drop-rune (kern-tag 'rune_f (kern-mk-obj t_rune_f 1)) (loc-mk kplace  8  16))
+      (drop-rune (kern-tag 'rune_w (kern-mk-obj t_rune_w 1)) (loc-mk kplace  4  16))
+      (drop-rune (kern-tag 'rune_d (kern-mk-obj t_rune_d 1)) (loc-mk kplace  2  14))
+      (drop-rune (kern-tag 'rune_l (kern-mk-obj t_rune_l 1)) (loc-mk kplace  2  10))
+      )
+    (kern-map-repaint)
+    )
+
+  (define (close-portal)
+    (map (lambda (stage)
+           ;; The last sprite in the sequence is null, and if we set the portal's
+           ;; sprite to null it will fall back on the sprite of its object type,
+           ;; which is a fully-open gate, so catch that as a special case.
+           (cond ((not (null? (stage-sprite stage)))
+                  (kern-obj-set-sprite portal (stage-sprite stage))
+                  (kern-obj-set-light portal (stage-light stage))
+                  (kern-map-repaint)
+                  (kern-sleep 125))))
+         (reverse blackgate-stages))
+    (kern-obj-remove portal)
+    (kern-map-repaint)
+    )
+  
+  (kern-log-msg "VAS AN EX REL POR!")
+  ;; we need a better rumbling thunder/ earthquake type noise
+  (kern-sound-play sound-lightning)
+  (shake-map 15)
+  (kern-map-flash 1000)
+  (drop-all-runes)
+  (close-portal)
+
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-pause kobj delay)
+  ;; Keep the sprites animating during pauses.
+  (kern-map-repaint)
+  (let ((smgr (gob kobj)))
+    (if (>= (scene-mgr-get-pause smgr) delay)
+        (scene-mgr-advance-state! (gob kobj))
+        (scene-mgr-incr-pause! smgr))))
+
+(define (scene-mgr-pickup-runes kobj)
+  ;;(println "scene-mgr-pickup-runes")
+  (for-each (lambda (krune)
+              (kern-obj-remove krune)
+              (kern-map-repaint)
+              (kern-sleep 100)
+              ;; Delay changing back the altar so the player can see that it is
+              ;; the altar glowing, not the rune.
+              (kern-place-set-terrain (kern-obj-get-location krune) t_altar)
+              )
+            (list rune_s rune_w rune_p rune_d rune_f rune_k rune_c rune_l))
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-exit-wise kobj)
+  ;;(println "scene-mgr-exit-wise")
+  (map (lambda (kwise)
+         (let ((wise (gob kwise)))
+           ;;(println "post:" (cdr (npcg-get-subgob wise)))
+           (npcg-set-post! wise (cdr (npcg-get-subgob wise)))
+           (kern-char-set-ai kwise 'wise-exit-ai)))
+       (scene-mgr-get-wise (gob kobj)))
+  (scene-mgr-set-num-wise-in-pos! (gob kobj) 0)
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-exit-guards kobj)
+  ;;(println "scene-mgr-exit-guards") 
+  (map (lambda (kchar)
+               (if (not (is-player-party-member? kchar))
+           (kern-char-set-ai kchar 'traveler-exit)))
+       (kern-place-get-beings (loc-place (kern-obj-get-location kobj))))
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-wait-for-exits kobj)
+  ;;(println "scene-mgr-wait-for-guards")
+  (if (< (length (all-allies-near (kern-get-player))) 2)
+       (scene-mgr-advance-state! (gob kobj)))
+  )
+  
+(define (scene-mgr-exit-beggar kobj)
+  ;; This is a hack to keep the camera centered on the beggar's location (and
+  ;; thus the whole scene within the vision radius) while allowing the beggar
+  ;; to go pick up the loot and then exit. The party member beggar's sprite is
+  ;; changed to nil, making him invisible, then a new npc beggar is cloned.
+  (let ((kcharn (mk-npc 'ranger 9)))
+    (kern-obj-set-sprite kcharn s_beggar)
+    (kern-char-set-ai kcharn 'beggar-exit)
+    (kern-obj-put-at kcharn (kern-obj-get-location (kern-get-player)))
+   )
+  (map (lambda (kchar)
+               (if (is-player-party-member? kchar)
+           (kern-obj-set-sprite kchar nil)))
+       (kern-place-get-beings (loc-place (kern-obj-get-location kobj))))
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-start-days-pass kobj)
+  (kern-log-msg "Days pass...")
+  (set-car! flee-gate #f)
+  (let ((kplace (loc-place (kern-obj-get-location kobj))))
+    (define (wolf-mk from-loc to-xy)
+      (let ((kchar (mk-npc 'wolf 9)))
+        (npcg-set-post! (gob kchar) to-xy)
+        (kern-char-set-ai kchar 'erratic-traveler-ai)
+        (kern-obj-put-at kchar from-loc)
+        (kern-map-repaint)
+                 (kern-sleep 20)        
+        ))
+    (wolf-mk (loc-mk kplace 1 14) (list 17 7))
+    )
+  (kern-map-repaint)
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-end-days-pass kobj)
+  (if (null? (filter (lambda (kobj)
+                       (not (is-player-party-member? kobj)))
+                     (kern-place-get-beings (loc-place (kern-obj-get-location kobj)))))
+      (scene-mgr-advance-state! (gob kobj))
+      ))
+
+(define (scene-mgr-years-pass kobj)
+  (kern-log-msg "Then years...")
+  (let ((kplace (loc-place (kern-obj-get-location kobj))))
+    (define (mk-troll loc)
+      (let ((kchar (mk-npc 'troll 9)))
+        (kern-char-set-ai kchar 'wait-ai)
+        (kern-obj-put-at kchar loc)
+        ))
+    (kern-blit-map (kern-place-map kplace) 0 0
+                   (kern-mk-map
+                    nil     19 19 pal_expanded
+                    (list
+                     "000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 "
+                     "019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 "
+                     "038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 "
+                     "057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 "
+                     "076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 "
+                     "095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 "
+                     "fg fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fi "
+                                                       "fj t. |. t. t. tc .. .. ta t. t. |. |. |. tL __ t. |. fl "
+                                                       "fj |. t. tc ar .. .. .. ar t% t. |. t. t. _3 _c t. t. fl "
+                                                       "fj t. tc t# .. .. .. .. .. .. ta t. t. t. _2 tG t. t. fl "
+                                                       "fj tc ar .. .. .. bb .. .. .. ar |. t. tc _2 ta t. t. fl "
+                                                       "fj |. .. .. bb dd dd dd .. .. .. ta tc t# ee ee dd .. fl "
+                                                       "fj t. .. .. dd dd && dd dd .. .. dd dd ee ee dd dd dd fl "
+                                                       "fj t. .. .. .. dd dd dd .. .. .. t7 tA ee __ ee .. dd fl "
+                                                       "fj t. ar .. .. .. .. bb .. .. ar t. t. t5 __ t3 t. t. fl "
+                                                       "fj t. t5 tA .. .. .. .. .. .. t3 |. t. t5 _2 tJ |. t. fl "
+                                                       "fj t. t. t5 ar .. .. .. ar tC t. t. t. t. _a _5 t. |. fl "
+                                                       "fj t. t. |. t5 .. t7 .. t3 |. |. t. t. t. tH __ t. |. fl "
+                     "fm fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fo " 
+                     ))
+                   0 0 19 19)
+    (mk-troll (loc-mk kplace 5 12))
+    (mk-troll (loc-mk kplace 7 12))
+    )
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-end-years-pass kobj)
+  (println "end-years-pass")
+  (let ((trolls (filter 
+                 (lambda (kobj)
+                   (not (is-player-party-member? kobj)))
+                 (kern-place-get-beings (loc-place (kern-obj-get-location kobj))))))
+    (for-each kern-obj-remove trolls))
+  (kern-map-repaint)
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+
+(define (scene-mgr-ages-pass kobj)
+  (kern-log-msg "Then ages...")
+  (let ((kplace (loc-place (kern-obj-get-location kobj))))
+    (kern-blit-map (kern-place-map kplace) 0 0
+                   (kern-mk-map
+                    nil     19 19 pal_expanded
+                    (list
+                     "000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 "
+                     "019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 "
+                     "038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 "
+                     "057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 "
+                     "076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 "
+                     "095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 "
+                     "fg fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fi "
+                                                       "fj |. |. |. t. |. |. |. t. |. |. |. |. tc %% __ _c %% fl "
+                                                       "fj |. t. t. ar t. |. t. at t. t. |. |. %3 _3 _c %c .. fl "
+                                                       "fj |. t. t. t. t. t. |. t. |. t. t. t. %a _e %c tC t3 fl "
+                                                       "fj t. at t. tc t# bb t% ta t. at t. t. .. %% .. t3 |. fl "
+                                                       "fj |. t. t. bb .. .. .. t% ta t. |. tc tA %% .. ta |. fl "
+                                                       "fj |. |. t. .. .. {f .. .. tD t. tB tD ta gg .. tD t. fl "
+                                                       "fj |. t. t. tA .. .. .. tC t3 t. t. t5 t# %% .. t3 |. fl "
+                                                       "fj t. at t. t5 tA .. bb t3 t. at t. t. .. %% .. ta |. fl "
+                                                       "fj |. t. |. t. t. t. t. t. |. t. |. t. tA %e .. t% t. fl "
+                                                       "fj |. |. t. at t. t. t. ar t. |. |. |. t5 .. %7 .. |. fl "
+                                                       "fj |. |. |. t. |. |. |. t. |. |. t. |. t. .. %% .. |. fl "                     
+                     "fm fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fo "
+                     ))
+                   0 0 19 19)
+    (define (deer-mk from-loc to-xy)
+      (let ((kchar (mk-npc 'wolf 9)))
+        (npcg-set-post! (gob kchar) to-xy)
+        (kern-obj-set-sprite kchar s_deer)
+        (kern-char-set-ai kchar 'erratic-traveler-ai)
+        (kern-obj-put-at kchar from-loc)
+        (kern-map-repaint)
+        (kern-sleep 20)
+      )
+      )
+    (deer-mk (loc-mk kplace 5 7) (list 12 17))
+    (deer-mk (loc-mk kplace 3 7) (list 13 17))
+    )
+  (kern-map-repaint)
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+(define (scene-mgr-ages-passed kobj)
+  (let ((kplace (loc-place (kern-obj-get-location kobj))))
+  )
+  (kern-map-repaint)
+  (scene-mgr-advance-state! (gob kobj))
+  )
+
+
+
+(define (scene-mgr-conclude kobj)
+  (kern-log-msg "Until what was closed and locked by magic has been forgotten.")
+  (let ((kplace (loc-place (kern-obj-get-location kobj))))
+    (kern-blit-map (kern-place-map kplace) 0 0
+                   (kern-mk-map
+                    nil     19 19 pal_expanded
+                    (list
+                     "000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 "
+                     "019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 "
+                     "038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 "
+                     "057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 "
+                     "076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 "
+                     "095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 "
+                     "fg fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fi "
+                                                       "fj |. |. |. t. |. |. |. t. |. t. .. %% %% %% %% %c .. fl "
+                                                       "fj |. |. t. at t. |. t. at t. t. tA %a %% %% %% .. t3 fl "
+                                                       "fj |. t. t. t. |. |. |. t. |. t. t5 tA %a %% %c tC t. fl "
+                                                       "fj t. at t. |. |. bb |. |. t. at t. t5 .. %% .. t3 |. fl "
+                                                       "fj |. t. |. bb te .. ta |. |. t. |. t. .. %% .. ta |. fl "
+                                                       "fj |. |. |. t5 tB {f tD t. |. |. |. ta %b gg %d tD t. fl "
+                                                       "fj |. t. |. |. t5 tE tb |. |. t. |. t. .. %% .. t3 |. fl "
+                                                       "fj t. at t. |. |. t5 bb |. t. at t. t. .. gg .. ta |. fl "
+                                                       "fj |. t. |. t. |. |. |. t. |. t. |. t. tA gg %5 t% t. fl "
+                                                       "fj |. |. t. at t. |. t. at t. |. |. |. t5 .. gg .. t. fl "
+                                                       "fj |. |. |. t. |. |. |. t. |. |. |. |. t. .. gg .. t. fl "
+                     "fm fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fo "
+                     ))
+                   0 0 19 19)
+    (let ((kchar (mk-npc 'giant-spider 9)))
+      (kern-obj-put-at  kchar (loc-mk kplace 6 12))
+      (kern-char-set-ai kchar 'wait-ai)
+      )
+    (kern-obj-put-at (kern-mk-obj F_web_perm 1) (loc-mk kplace 5 12))
+    (kern-obj-put-at (kern-mk-obj F_web_perm 1) (loc-mk kplace 6 10))
+    (kern-obj-put-at (kern-mk-obj F_web_perm 1) (loc-mk kplace 6 11))
+    (kern-obj-put-at (kern-mk-obj F_web_perm 1) (loc-mk kplace 6 12))
+    (kern-obj-put-at (kern-mk-obj F_web_perm 1) (loc-mk kplace 6 13))
+    (kern-obj-put-at (kern-mk-obj F_web_perm 1) (loc-mk kplace 7 12))
+    (kern-obj-put-at (kern-mk-obj t_corpse 1) (loc-mk kplace 7 12))
+    )
+  (kern-map-repaint)
+  (scene-mgr-advance-state! (gob kobj))
+  )
+  
+(define (scene-mgr-exec kobj) 
+  (let* ((smgr (kobj-gob-data kobj))
+         (state (scene-mgr-state smgr)))
+    (cond ((= 0 state) (scene-mgr-intro-travelers-phase kobj))
+          ((= 1 state) (scene-mgr-intro-demons-phase kobj))
+          ((= 2 state) (scene-mgr-wait-for-no-demons-phase kobj)) 
+          ((= 3 state) (scene-mgr-pause kobj 10))
+          ((= 4 state) (scene-mgr-intro-wise kobj))
+          ((= 5 state) (scene-mgr-wait-for-wise kobj))
+          ((= 6 state) (scene-mgr-pause kobj 10))
+          ((= 7 state) (scene-mgr-close-gate kobj))
+          ((= 8 state) (scene-mgr-pause kobj 10))
+          ((= 9 state) (scene-mgr-pickup-runes kobj))
+          ((= 10 state) (scene-mgr-pause kobj 10))
+          ((= 11 state) (scene-mgr-exit-wise kobj))
+          ((= 12 state) (scene-mgr-wait-for-wise kobj))
+          ((= 13 state) (scene-mgr-exit-guards kobj))
+          ((= 14 state) (scene-mgr-wait-for-exits kobj))
+          ((= 15 state) (scene-mgr-exit-beggar kobj))
+          ((= 16 state) (scene-mgr-wait-for-exits kobj))
+          ((= 17 state) (scene-mgr-pause kobj 10))
+          ((= 18 state) (scene-mgr-start-days-pass kobj))
+          ((= 19 state) (scene-mgr-pause kobj 10))
+          ((= 20 state) (scene-mgr-end-days-pass kobj))
+          ((= 21 state) (scene-mgr-years-pass kobj))
+          ((= 22 state) (scene-mgr-pause kobj 20))
+          ((= 23 state) (scene-mgr-end-years-pass kobj))
+          ((= 24 state) (scene-mgr-ages-pass kobj))
+          ((= 25 state) (scene-mgr-pause kobj 20))
+          ((= 26 state) (scene-mgr-end-years-pass kobj))
+          ((= 27 state) (scene-mgr-conclude kobj))
+          ((= 28 state) (scene-mgr-pause kobj 20))
+          (else
+           (kern-end-game)
+           )
+          (else
+           ))
+    ))
+
+(define scene-mgr-ifc
+  (ifc nil
+       (method 'exec scene-mgr-exec)))
+
+(mk-obj-type 't_scene_mgr nil nil layer-none scene-mgr-ifc)
+
+(define (mk-scene-mgr)
+  (bind (kern-obj-set-visible (kern-mk-obj t_scene_mgr 1) #f)
+        (scene-mgr-mk)
+        ))
+
+;;----------------------------------------------------------------------------
+;; Haxima Logo & Frame Terrain
+;;----------------------------------------------------------------------------
+(kern-mk-sprite-set 'ss_hl 32 32 6 19 0 0  "haximatext.png")
+(kern-mk-sprite-set 'ss_gf 32 32 3  3 0 0  "gold_frame.png")
+
+(kern-mk-sprite 's_hl_0 ss_hl 1 0 #f 0)
+(kern-mk-sprite 's_hl_1 ss_hl 1 1 #f 0)
+(kern-mk-sprite 's_hl_2 ss_hl 1 2 #f 0)
+(kern-mk-sprite 's_hl_3 ss_hl 1 3 #f 0)
+(kern-mk-sprite 's_hl_4 ss_hl 1 4 #f 0)
+(kern-mk-sprite 's_hl_5 ss_hl 1 5 #f 0)
+(kern-mk-sprite 's_hl_6 ss_hl 1 6 #f 0)
+(kern-mk-sprite 's_hl_7 ss_hl 1 7 #f 0)
+(kern-mk-sprite 's_hl_8 ss_hl 1 8 #f 0)
+(kern-mk-sprite 's_hl_9 ss_hl 1 9 #f 0)
+(kern-mk-sprite 's_hl_10 ss_hl 1 10 #f 0)
+(kern-mk-sprite 's_hl_11 ss_hl 1 11 #f 0)
+(kern-mk-sprite 's_hl_12 ss_hl 1 12 #f 0)
+(kern-mk-sprite 's_hl_13 ss_hl 1 13 #f 0)
+(kern-mk-sprite 's_hl_14 ss_hl 1 14 #f 0)
+(kern-mk-sprite 's_hl_15 ss_hl 1 15 #f 0)
+(kern-mk-sprite 's_hl_16 ss_hl 1 16 #f 0)
+(kern-mk-sprite 's_hl_17 ss_hl 1 17 #f 0)
+(kern-mk-sprite 's_hl_18 ss_hl 1 18 #f 0)
+(kern-mk-sprite 's_hl_19 ss_hl 1 19 #f 0)
+(kern-mk-sprite 's_hl_20 ss_hl 1 20 #f 0)
+(kern-mk-sprite 's_hl_21 ss_hl 1 21 #f 0)
+(kern-mk-sprite 's_hl_22 ss_hl 1 22 #f 0)
+(kern-mk-sprite 's_hl_23 ss_hl 1 23 #f 0)
+(kern-mk-sprite 's_hl_24 ss_hl 1 24 #f 0)
+(kern-mk-sprite 's_hl_25 ss_hl 1 25 #f 0)
+(kern-mk-sprite 's_hl_26 ss_hl 1 26 #f 0)
+(kern-mk-sprite 's_hl_27 ss_hl 1 27 #f 0)
+(kern-mk-sprite 's_hl_28 ss_hl 1 28 #f 0)
+(kern-mk-sprite 's_hl_29 ss_hl 1 29 #f 0)
+(kern-mk-sprite 's_hl_30 ss_hl 1 30 #f 0)
+(kern-mk-sprite 's_hl_31 ss_hl 1 31 #f 0)
+(kern-mk-sprite 's_hl_32 ss_hl 1 32 #f 0)
+(kern-mk-sprite 's_hl_33 ss_hl 1 33 #f 0)
+(kern-mk-sprite 's_hl_34 ss_hl 1 34 #f 0)
+(kern-mk-sprite 's_hl_35 ss_hl 1 35 #f 0)
+(kern-mk-sprite 's_hl_36 ss_hl 1 36 #f 0)
+(kern-mk-sprite 's_hl_37 ss_hl 1 37 #f 0)
+(kern-mk-sprite 's_hl_38 ss_hl 1 38 #f 0)
+(kern-mk-sprite 's_hl_39 ss_hl 1 39 #f 0)
+(kern-mk-sprite 's_hl_40 ss_hl 1 40 #f 0)
+(kern-mk-sprite 's_hl_41 ss_hl 1 41 #f 0)
+(kern-mk-sprite 's_hl_42 ss_hl 1 42 #f 0)
+(kern-mk-sprite 's_hl_43 ss_hl 1 43 #f 0)
+(kern-mk-sprite 's_hl_44 ss_hl 1 44 #f 0)
+(kern-mk-sprite 's_hl_45 ss_hl 1 45 #f 0)
+(kern-mk-sprite 's_hl_46 ss_hl 1 46 #f 0)
+(kern-mk-sprite 's_hl_47 ss_hl 1 47 #f 0)
+(kern-mk-sprite 's_hl_48 ss_hl 1 48 #f 0)
+(kern-mk-sprite 's_hl_49 ss_hl 1 49 #f 0)
+(kern-mk-sprite 's_hl_50 ss_hl 1 50 #f 0)
+(kern-mk-sprite 's_hl_51 ss_hl 1 51 #f 0)
+(kern-mk-sprite 's_hl_52 ss_hl 1 52 #f 0)
+(kern-mk-sprite 's_hl_53 ss_hl 1 53 #f 0)
+(kern-mk-sprite 's_hl_54 ss_hl 1 54 #f 0)
+(kern-mk-sprite 's_hl_55 ss_hl 1 55 #f 0)
+(kern-mk-sprite 's_hl_56 ss_hl 1 56 #f 0)
+(kern-mk-sprite 's_hl_57 ss_hl 1 57 #f 0)
+(kern-mk-sprite 's_hl_58 ss_hl 1 58 #f 0)
+(kern-mk-sprite 's_hl_59 ss_hl 1 59 #f 0)
+(kern-mk-sprite 's_hl_60 ss_hl 1 60 #f 0)
+(kern-mk-sprite 's_hl_61 ss_hl 1 61 #f 0)
+(kern-mk-sprite 's_hl_62 ss_hl 1 62 #f 0)
+(kern-mk-sprite 's_hl_63 ss_hl 1 63 #f 0)
+(kern-mk-sprite 's_hl_64 ss_hl 1 64 #f 0)
+(kern-mk-sprite 's_hl_65 ss_hl 1 65 #f 0)
+(kern-mk-sprite 's_hl_66 ss_hl 1 66 #f 0)
+(kern-mk-sprite 's_hl_67 ss_hl 1 67 #f 0)
+(kern-mk-sprite 's_hl_68 ss_hl 1 68 #f 0)
+(kern-mk-sprite 's_hl_69 ss_hl 1 69 #f 0)
+(kern-mk-sprite 's_hl_70 ss_hl 1 70 #f 0)
+(kern-mk-sprite 's_hl_71 ss_hl 1 71 #f 0)
+(kern-mk-sprite 's_hl_72 ss_hl 1 72 #f 0)
+(kern-mk-sprite 's_hl_73 ss_hl 1 73 #f 0)
+(kern-mk-sprite 's_hl_74 ss_hl 1 74 #f 0)
+(kern-mk-sprite 's_hl_75 ss_hl 1 75 #f 0)
+(kern-mk-sprite 's_hl_76 ss_hl 1 76 #f 0)
+(kern-mk-sprite 's_hl_77 ss_hl 1 77 #f 0)
+(kern-mk-sprite 's_hl_78 ss_hl 1 78 #f 0)
+(kern-mk-sprite 's_hl_79 ss_hl 1 79 #f 0)
+(kern-mk-sprite 's_hl_80 ss_hl 1 80 #f 0)
+(kern-mk-sprite 's_hl_81 ss_hl 1 81 #f 0)
+(kern-mk-sprite 's_hl_82 ss_hl 1 82 #f 0)
+(kern-mk-sprite 's_hl_83 ss_hl 1 83 #f 0)
+(kern-mk-sprite 's_hl_84 ss_hl 1 84 #f 0)
+(kern-mk-sprite 's_hl_85 ss_hl 1 85 #f 0)
+(kern-mk-sprite 's_hl_86 ss_hl 1 86 #f 0)
+(kern-mk-sprite 's_hl_87 ss_hl 1 87 #f 0)
+(kern-mk-sprite 's_hl_88 ss_hl 1 88 #f 0)
+(kern-mk-sprite 's_hl_89 ss_hl 1 89 #f 0)
+(kern-mk-sprite 's_hl_90 ss_hl 1 90 #f 0)
+(kern-mk-sprite 's_hl_91 ss_hl 1 91 #f 0)
+(kern-mk-sprite 's_hl_92 ss_hl 1 92 #f 0)
+(kern-mk-sprite 's_hl_93 ss_hl 1 93 #f 0)
+(kern-mk-sprite 's_hl_94 ss_hl 1 94 #f 0)
+(kern-mk-sprite 's_hl_95 ss_hl 1 95 #f 0)
+(kern-mk-sprite 's_hl_96 ss_hl 1 96 #f 0)
+(kern-mk-sprite 's_hl_97 ss_hl 1 97 #f 0)
+(kern-mk-sprite 's_hl_98 ss_hl 1 98 #f 0)
+(kern-mk-sprite 's_hl_99 ss_hl 1 99 #f 0)
+(kern-mk-sprite 's_hl_100 ss_hl 1 100 #f 0)
+(kern-mk-sprite 's_hl_101 ss_hl 1 101 #f 0)
+(kern-mk-sprite 's_hl_102 ss_hl 1 102 #f 0)
+(kern-mk-sprite 's_hl_103 ss_hl 1 103 #f 0)
+(kern-mk-sprite 's_hl_104 ss_hl 1 104 #f 0)
+(kern-mk-sprite 's_hl_105 ss_hl 1 105 #f 0)
+(kern-mk-sprite 's_hl_106 ss_hl 1 106 #f 0)
+(kern-mk-sprite 's_hl_107 ss_hl 1 107 #f 0)
+(kern-mk-sprite 's_hl_108 ss_hl 1 108 #f 0)
+(kern-mk-sprite 's_hl_109 ss_hl 1 109 #f 0)
+(kern-mk-sprite 's_hl_110 ss_hl 1 110 #f 0)
+(kern-mk-sprite 's_hl_111 ss_hl 1 111 #f 0)
+(kern-mk-sprite 's_hl_112 ss_hl 1 112 #f 0)
+(kern-mk-sprite 's_hl_113 ss_hl 1 113 #f 0)
+
+(kern-mk-sprite 's_gf_nw ss_gf 1 0 #f 0)
+(kern-mk-sprite 's_gf_n  ss_gf 1 1 #f 0)
+(kern-mk-sprite 's_gf_ne ss_gf 1 2 #f 0)
+(kern-mk-sprite 's_gf_w  ss_gf 1 3 #f 0)
+(kern-mk-sprite 's_gf_c  ss_gf 1 4 #f 0)
+(kern-mk-sprite 's_gf_e  ss_gf 1 5 #f 0)
+(kern-mk-sprite 's_gf_sw ss_gf 1 6 #f 0)
+(kern-mk-sprite 's_gf_s  ss_gf 1 7 #f 0)
+(kern-mk-sprite 's_gf_se ss_gf 1 8 #f 0)
+
+(kern-mk-terrain 't_hl_0 "logo" pclass-wall s_hl_0 trn 0 nil)
+(kern-mk-terrain 't_hl_1 "logo" pclass-wall s_hl_1 trn 0 nil)
+(kern-mk-terrain 't_hl_2 "logo" pclass-wall s_hl_2 trn 0 nil)
+(kern-mk-terrain 't_hl_3 "logo" pclass-wall s_hl_3 trn 0 nil)
+(kern-mk-terrain 't_hl_4 "logo" pclass-wall s_hl_4 trn 0 nil)
+(kern-mk-terrain 't_hl_5 "logo" pclass-wall s_hl_5 trn 0 nil)
+(kern-mk-terrain 't_hl_6 "logo" pclass-wall s_hl_6 trn 0 nil)
+(kern-mk-terrain 't_hl_7 "logo" pclass-wall s_hl_7 trn 0 nil)
+(kern-mk-terrain 't_hl_8 "logo" pclass-wall s_hl_8 trn 0 nil)
+(kern-mk-terrain 't_hl_9 "logo" pclass-wall s_hl_9 trn 0 nil)
+(kern-mk-terrain 't_hl_10 "logo" pclass-wall s_hl_10 trn 0 nil)
+(kern-mk-terrain 't_hl_11 "logo" pclass-wall s_hl_11 trn 0 nil)
+(kern-mk-terrain 't_hl_12 "logo" pclass-wall s_hl_12 trn 0 nil)
+(kern-mk-terrain 't_hl_13 "logo" pclass-wall s_hl_13 trn 0 nil)
+(kern-mk-terrain 't_hl_14 "logo" pclass-wall s_hl_14 trn 0 nil)
+(kern-mk-terrain 't_hl_15 "logo" pclass-wall s_hl_15 trn 0 nil)
+(kern-mk-terrain 't_hl_16 "logo" pclass-wall s_hl_16 trn 0 nil)
+(kern-mk-terrain 't_hl_17 "logo" pclass-wall s_hl_17 trn 0 nil)
+(kern-mk-terrain 't_hl_18 "logo" pclass-wall s_hl_18 trn 0 nil)
+(kern-mk-terrain 't_hl_19 "logo" pclass-wall s_hl_19 trn 0 nil)
+(kern-mk-terrain 't_hl_20 "logo" pclass-wall s_hl_20 trn 0 nil)
+(kern-mk-terrain 't_hl_21 "logo" pclass-wall s_hl_21 trn 0 nil)
+(kern-mk-terrain 't_hl_22 "logo" pclass-wall s_hl_22 trn 0 nil)
+(kern-mk-terrain 't_hl_23 "logo" pclass-wall s_hl_23 trn 0 nil)
+(kern-mk-terrain 't_hl_24 "logo" pclass-wall s_hl_24 trn 0 nil)
+(kern-mk-terrain 't_hl_25 "logo" pclass-wall s_hl_25 trn 0 nil)
+(kern-mk-terrain 't_hl_26 "logo" pclass-wall s_hl_26 trn 0 nil)
+(kern-mk-terrain 't_hl_27 "logo" pclass-wall s_hl_27 trn 0 nil)
+(kern-mk-terrain 't_hl_28 "logo" pclass-wall s_hl_28 trn 0 nil)
+(kern-mk-terrain 't_hl_29 "logo" pclass-wall s_hl_29 trn 0 nil)
+(kern-mk-terrain 't_hl_30 "logo" pclass-wall s_hl_30 trn 0 nil)
+(kern-mk-terrain 't_hl_31 "logo" pclass-wall s_hl_31 trn 0 nil)
+(kern-mk-terrain 't_hl_32 "logo" pclass-wall s_hl_32 trn 0 nil)
+(kern-mk-terrain 't_hl_33 "logo" pclass-wall s_hl_33 trn 0 nil)
+(kern-mk-terrain 't_hl_34 "logo" pclass-wall s_hl_34 trn 0 nil)
+(kern-mk-terrain 't_hl_35 "logo" pclass-wall s_hl_35 trn 0 nil)
+(kern-mk-terrain 't_hl_36 "logo" pclass-wall s_hl_36 trn 0 nil)
+(kern-mk-terrain 't_hl_37 "logo" pclass-wall s_hl_37 trn 0 nil)
+(kern-mk-terrain 't_hl_38 "logo" pclass-wall s_hl_38 trn 0 nil)
+(kern-mk-terrain 't_hl_39 "logo" pclass-wall s_hl_39 trn 0 nil)
+(kern-mk-terrain 't_hl_40 "logo" pclass-wall s_hl_40 trn 0 nil)
+(kern-mk-terrain 't_hl_41 "logo" pclass-wall s_hl_41 trn 0 nil)
+(kern-mk-terrain 't_hl_42 "logo" pclass-wall s_hl_42 trn 0 nil)
+(kern-mk-terrain 't_hl_43 "logo" pclass-wall s_hl_43 trn 0 nil)
+(kern-mk-terrain 't_hl_44 "logo" pclass-wall s_hl_44 trn 0 nil)
+(kern-mk-terrain 't_hl_45 "logo" pclass-wall s_hl_45 trn 0 nil)
+(kern-mk-terrain 't_hl_46 "logo" pclass-wall s_hl_46 trn 0 nil)
+(kern-mk-terrain 't_hl_47 "logo" pclass-wall s_hl_47 trn 0 nil)
+(kern-mk-terrain 't_hl_48 "logo" pclass-wall s_hl_48 trn 0 nil)
+(kern-mk-terrain 't_hl_49 "logo" pclass-wall s_hl_49 trn 0 nil)
+(kern-mk-terrain 't_hl_50 "logo" pclass-wall s_hl_50 trn 0 nil)
+(kern-mk-terrain 't_hl_51 "logo" pclass-wall s_hl_51 trn 0 nil)
+(kern-mk-terrain 't_hl_52 "logo" pclass-wall s_hl_52 trn 0 nil)
+(kern-mk-terrain 't_hl_53 "logo" pclass-wall s_hl_53 trn 0 nil)
+(kern-mk-terrain 't_hl_54 "logo" pclass-wall s_hl_54 trn 0 nil)
+(kern-mk-terrain 't_hl_55 "logo" pclass-wall s_hl_55 trn 0 nil)
+(kern-mk-terrain 't_hl_56 "logo" pclass-wall s_hl_56 trn 0 nil)
+(kern-mk-terrain 't_hl_57 "logo" pclass-wall s_hl_57 trn 0 nil)
+(kern-mk-terrain 't_hl_58 "logo" pclass-wall s_hl_58 trn 0 nil)
+(kern-mk-terrain 't_hl_59 "logo" pclass-wall s_hl_59 trn 0 nil)
+(kern-mk-terrain 't_hl_60 "logo" pclass-wall s_hl_60 trn 0 nil)
+(kern-mk-terrain 't_hl_61 "logo" pclass-wall s_hl_61 trn 0 nil)
+(kern-mk-terrain 't_hl_62 "logo" pclass-wall s_hl_62 trn 0 nil)
+(kern-mk-terrain 't_hl_63 "logo" pclass-wall s_hl_63 trn 0 nil)
+(kern-mk-terrain 't_hl_64 "logo" pclass-wall s_hl_64 trn 0 nil)
+(kern-mk-terrain 't_hl_65 "logo" pclass-wall s_hl_65 trn 0 nil)
+(kern-mk-terrain 't_hl_66 "logo" pclass-wall s_hl_66 trn 0 nil)
+(kern-mk-terrain 't_hl_67 "logo" pclass-wall s_hl_67 trn 0 nil)
+(kern-mk-terrain 't_hl_68 "logo" pclass-wall s_hl_68 trn 0 nil)
+(kern-mk-terrain 't_hl_69 "logo" pclass-wall s_hl_69 trn 0 nil)
+(kern-mk-terrain 't_hl_70 "logo" pclass-wall s_hl_70 trn 0 nil)
+(kern-mk-terrain 't_hl_71 "logo" pclass-wall s_hl_71 trn 0 nil)
+(kern-mk-terrain 't_hl_72 "logo" pclass-wall s_hl_72 trn 0 nil)
+(kern-mk-terrain 't_hl_73 "logo" pclass-wall s_hl_73 trn 0 nil)
+(kern-mk-terrain 't_hl_74 "logo" pclass-wall s_hl_74 trn 0 nil)
+(kern-mk-terrain 't_hl_75 "logo" pclass-wall s_hl_75 trn 0 nil)
+(kern-mk-terrain 't_hl_76 "logo" pclass-wall s_hl_76 trn 0 nil)
+(kern-mk-terrain 't_hl_77 "logo" pclass-wall s_hl_77 trn 0 nil)
+(kern-mk-terrain 't_hl_78 "logo" pclass-wall s_hl_78 trn 0 nil)
+(kern-mk-terrain 't_hl_79 "logo" pclass-wall s_hl_79 trn 0 nil)
+(kern-mk-terrain 't_hl_80 "logo" pclass-wall s_hl_80 trn 0 nil)
+(kern-mk-terrain 't_hl_81 "logo" pclass-wall s_hl_81 trn 0 nil)
+(kern-mk-terrain 't_hl_82 "logo" pclass-wall s_hl_82 trn 0 nil)
+(kern-mk-terrain 't_hl_83 "logo" pclass-wall s_hl_83 trn 0 nil)
+(kern-mk-terrain 't_hl_84 "logo" pclass-wall s_hl_84 trn 0 nil)
+(kern-mk-terrain 't_hl_85 "logo" pclass-wall s_hl_85 trn 0 nil)
+(kern-mk-terrain 't_hl_86 "logo" pclass-wall s_hl_86 trn 0 nil)
+(kern-mk-terrain 't_hl_87 "logo" pclass-wall s_hl_87 trn 0 nil)
+(kern-mk-terrain 't_hl_88 "logo" pclass-wall s_hl_88 trn 0 nil)
+(kern-mk-terrain 't_hl_89 "logo" pclass-wall s_hl_89 trn 0 nil)
+(kern-mk-terrain 't_hl_90 "logo" pclass-wall s_hl_90 trn 0 nil)
+(kern-mk-terrain 't_hl_91 "logo" pclass-wall s_hl_91 trn 0 nil)
+(kern-mk-terrain 't_hl_92 "logo" pclass-wall s_hl_92 trn 0 nil)
+(kern-mk-terrain 't_hl_93 "logo" pclass-wall s_hl_93 trn 0 nil)
+(kern-mk-terrain 't_hl_94 "logo" pclass-wall s_hl_94 trn 0 nil)
+(kern-mk-terrain 't_hl_95 "logo" pclass-wall s_hl_95 trn 0 nil)
+(kern-mk-terrain 't_hl_96 "logo" pclass-wall s_hl_96 trn 0 nil)
+(kern-mk-terrain 't_hl_97 "logo" pclass-wall s_hl_97 trn 0 nil)
+(kern-mk-terrain 't_hl_98 "logo" pclass-wall s_hl_98 trn 0 nil)
+(kern-mk-terrain 't_hl_99 "logo" pclass-wall s_hl_99 trn 0 nil)
+(kern-mk-terrain 't_hl_100 "logo" pclass-wall s_hl_100 trn 0 nil)
+(kern-mk-terrain 't_hl_101 "logo" pclass-wall s_hl_101 trn 0 nil)
+(kern-mk-terrain 't_hl_102 "logo" pclass-wall s_hl_102 trn 0 nil)
+(kern-mk-terrain 't_hl_103 "logo" pclass-wall s_hl_103 trn 0 nil)
+(kern-mk-terrain 't_hl_104 "logo" pclass-wall s_hl_104 trn 0 nil)
+(kern-mk-terrain 't_hl_105 "logo" pclass-wall s_hl_105 trn 0 nil)
+(kern-mk-terrain 't_hl_106 "logo" pclass-wall s_hl_106 trn 0 nil)
+(kern-mk-terrain 't_hl_107 "logo" pclass-wall s_hl_107 trn 0 nil)
+(kern-mk-terrain 't_hl_108 "logo" pclass-wall s_hl_108 trn 0 nil)
+(kern-mk-terrain 't_hl_109 "logo" pclass-wall s_hl_109 trn 0 nil)
+(kern-mk-terrain 't_hl_110 "logo" pclass-wall s_hl_110 trn 0 nil)
+(kern-mk-terrain 't_hl_111 "logo" pclass-wall s_hl_111 trn 0 nil)
+(kern-mk-terrain 't_hl_112 "logo" pclass-wall s_hl_112 trn 0 nil)
+(kern-mk-terrain 't_hl_113 "logo" pclass-wall s_hl_113 trn 0 nil)
+
+(kern-mk-terrain 't_gf_nw "frame" pclass-wall s_gf_nw trn 0 nil)
+(kern-mk-terrain 't_gf_n  "frame" pclass-wall s_gf_n  trn 0 nil)
+(kern-mk-terrain 't_gf_ne "frame" pclass-wall s_gf_ne trn 0 nil)
+(kern-mk-terrain 't_gf_w  "frame" pclass-wall s_gf_w  trn 0 nil)
+(kern-mk-terrain 't_gf_c  "frame" pclass-wall s_gf_c  trn 0 nil)
+(kern-mk-terrain 't_gf_e  "frame" pclass-wall s_gf_e  trn 0 nil)
+(kern-mk-terrain 't_gf_sw "frame" pclass-wall s_gf_sw trn 0 nil)
+(kern-mk-terrain 't_gf_s  "frame" pclass-wall s_gf_s  trn 0 nil)
+(kern-mk-terrain 't_gf_se "frame" pclass-wall s_gf_se trn 0 nil)
+
+(kern-mk-terrain 't_overgrown_altar "altar" pclass-boulder s_overgrown_altar trn 0 nil)
+
+;; define our own palette to include the logo terrain
+(kern-mk-palette 'pal_expanded
+  (list
+    ;; NOTE: "x#" is reserved for blocking mechanisms, see block-teleporting in
+    ;; naz.scm
+    (list  "xx"   t_wall)               ;; "wall"
+    (list  "__"   t_deep)               ;; "deep water"
+    (list  "_!"   t_sunlit_deep)               ;; "deep water"
+    (list  "~*"   t_blendable_shoals)            ;; "shallow water"
+    (list  "_s"   t_sludge)
+    (list  "~s"   t_shallow_sludge)
+    (list  "dd"   t_dirt)
+    (list  "gg"   t_gravel)
+       
+    (list  "%%"   t_bog)                ;; "bog"
+    (list  ".."   t_grass)              ;; "grass"
+    (list  ".!"   t_sunlit_grass)              ;; "grass"
+    (list  "t."   t_trees_v)            ;; "trees (transparent)"
+    (list  "tt"   t_trees)              ;; "trees"
+    (list  "t|"   t_trees_d)            ;; "trees denser"
+
+    (list  "||"   t_forest)             ;; "forest"
+    (list  "|X"   t_forest_d)           ;; "forest (denser)"
+    (list  "|t"   t_forest_l)           ;; "forest (lighter)"
+    (list  "|."   t_forest_v)           ;; "forest (non-LOS-blocking)"
+    (list  "|v"   t_forest_b)           ;; "forest (totally LOS-blocking)"
+
+    (list  "{{"   t_hills)              ;; "hills"
+
+    (list  "^^"   t_mountains)          ;; "mountains"
+    (list  "^."   t_mountains_v)        ;; "mountains" (non-LOS-blocking)
+    (list  "^v"   t_mountains_b)        ;; "mountains" (below player)
+    (list  "^~"   t_fake_mountains)
+
+    (list  ",,"   t_flagstones)         ;; "flagstones"
+    (list  "~,"   t_inv_wall)
+    (list  "d,"   t_doorway)
+    (list  "cc"   t_cobblestone)        ;; "cobblestone"
+    (list  "ee"   t_deck)               ;; "deck"
+    (list  "oo"   t_mast)               ;; "mast"
+    (list  "ff"   t_fire_terrain)       ;; "fire"
+    (list  "!!"   t_lava)               ;; "lava"
+    (list  "~!"   t_fake_lava)
+    (list  "!_"   t_deep_lava)
+    (list  "&&"   t_fireplace)          ;; "fireplace"
+
+    (list  "x."   t_wall_v)             ;; "wall"  (non-LOS-blocking)
+    (list  "~x"   t_fake_wall)
+
+    (list  "**"   t_stars)              ;; "stars"
+       (list  "*."   t_void)
+    (list  "??"   t_secret_door)        ;; "secret door"
+    (list  "pp"   t_pillar)             ;; "pillar"
+    (list  "~p"   t_false_pillar)
+    (list  "bb"   t_boulder)            ;; "boulder"
+    (list  "b~"   t_water_rocks)        ;; "boulder" in water
+       
+    (list  "rr"   t_wall_rock)          ;; "rock wall"
+    (list  "r."   t_wall_rock_v)        ;; "rock wall"  (non-LOS-blocking)
+    (list  "~r"   t_fake_wall_rock)     ;; "rock wall"  (fake)
+
+    (list  "WW"   t_ships_wheel)        ;; "ship's wheel"
+    (list  "x!"   t_wall_torch)         ;; "wall torch"
+    (list  "##"   t_ship_hull)          ;; "ship's hull"
+    (list  "#>"   t_ship_hull2)          ;; "ship's hull (LOS-blocking)"
+
+    (list  ".A"   t_a)                  ;; "an A"
+    (list  ".B"   t_b)                  ;; "a B"
+    (list  "?B"   t_fake_b)                  ;; "a B"
+    (list  ".C"   t_c)                  ;; "a C"
+    (list  ".D"   t_d)                  ;; "a D"
+    (list  ".E"   t_e)                  ;; "an E"
+    (list  ".F"   t_f)                  ;; "an F"
+    (list  ".G"   t_g)                  ;; "a G"
+    (list  ".H"   t_h)                  ;; "an H"
+    (list  ".I"   t_i)                  ;; "an I"
+    (list  ".J"   t_j)                  ;; "a J"
+    (list  ".K"   t_k)                  ;; "a K"
+    (list  ".L"   t_l)                  ;; "an L"
+    (list  ".M"   t_m)                  ;; "an M"
+    (list  ".N"   t_n)                  ;; "an N"
+    (list  ".O"   t_o)                  ;; "an O"
+    (list  "~O"   t_fake_o)
+    (list  ".P"   t_p)                  ;; "a P"
+    (list  ".Q"   t_q)                  ;; "a Q"
+    (list  ".R"   t_r)                  ;; "an R"
+    (list  ".S"   t_s)                  ;; "an S"
+    (list  ".T"   t_t)                  ;; "a T"
+    (list  ".U"   t_u)                  ;; "a U"
+    (list  ".V"   t_v)                  ;; "a V"
+    (list  ".W"   t_w)                  ;; "a W"
+    (list  ".X"   t_x)                  ;; "an X"
+    (list  ".Y"   t_y)                  ;; "a Y"
+    (list  ".Z"   t_z)                  ;; "a Z"
+
+    (list  ",A"   t_rune_a)             ;; "a rune"
+    (list  ",B"   t_rune_b)             ;; "a rune"
+    (list  ",C"   t_rune_c)             ;; "a rune"
+    (list  ",D"   t_rune_d)             ;; "a rune"
+    (list  ",E"   t_rune_e)             ;; "a rune"
+    (list  ",F"   t_rune_f)             ;; "a rune"
+    (list  ",G"   t_rune_g)             ;; "a rune"
+    (list  ",H"   t_rune_h)             ;; "a rune"
+    (list  ",I"   t_rune_i)             ;; "a rune"
+    (list  ",J"   t_rune_j)             ;; "a rune"
+    (list  ",K"   t_rune_k)             ;; "a rune"
+    (list  ",L"   t_rune_l)             ;; "a rune"
+    (list  ",M"   t_rune_m)             ;; "a rune"
+    (list  ",N"   t_rune_n)             ;; "a rune"
+    (list  ",O"   t_rune_o)             ;; "a rune"
+    (list  ",P"   t_rune_p)             ;; "a rune"
+    (list  ",Q"   t_rune_q)             ;; "a rune"
+    (list  ",R"   t_rune_r)             ;; "a rune"
+    (list  ",S"   t_rune_s)             ;; "a rune"
+    (list  ",T"   t_rune_t)             ;; "a rune"
+    (list  ",U"   t_rune_u)             ;; "a rune"
+    (list  ",V"   t_rune_v)             ;; "a rune"
+    (list  ",W"   t_rune_w)             ;; "a rune"
+    (list  ",X"   t_rune_x)             ;; "a rune"
+    (list  ",Y"   t_rune_y)             ;; "a rune"
+    (list  ",Z"   t_rune_z)             ;; "a rune"
+    (list  ";T"   t_rune_th)            ;; "a rune"
+    (list  ";E"   t_rune_ee)            ;; "a rune"
+    (list  ";N"   t_rune_ng)            ;; "a rune"
+    (list  ";A"   t_rune_ea)            ;; "a rune"
+    (list  ";S"   t_rune_st)            ;; "a rune"
+    (list  ";D"   t_rune_dot)           ;; "a rune"
+
+    (list  "@@"   t_counter_2x1_c)      ;; "counter"
+    (list  "[["   t_counter_2x1_w)      ;; "counter"
+    (list  "]]"   t_counter_2x1_e)      ;; "counter"
+
+    (list  "++"   t_ankh)               ;; "ankh"
+    (list  "+s"   t_statue)               ;; "ankh"
+    (list  "aa"   t_altar)              ;; "altar"
+    (list  "ar"   t_rune_altar)              ;; "altar"
+    (list  "a!"   t_active_altar)              ;; "altar"
+    (list  "at"   t_overgrown_altar)              ;; "altar"
+    (list  "<<"   t_leftwing)           ;; "castle wall"
+    (list  ">>"   t_rightwing)          ;; "castle wall"
+    (list  "w+"   t_arrow_slit)         ;; "arrow slit"
+    (list  "ws"   t_window_in_stone)    ;; "window"
+    (list  "wr"   t_window_in_rock)     ;; "window"
+    
+    (list  "=="   t_bridge_WE)          ;; "east-west bridge"
+    (list  "=|"   t_bridge_NS)          ;; "east-west bridge"
+    (list  "=!"   t_lava_bridge_NS)
+    (list  "vv"   t_chasm)              ;; "chasm"
+
+    (list "sE" t_equip_sign)
+    (list "sA" t_weapon_sign)
+    (list "sH" t_healer_sign)
+    (list "sT" t_tavern_sign)
+    (list "sI" t_inn_sign)
+    (list "sP" t_alchemy_sign)
+    (list "sR" t_magic_sign)
+    (list "sS" t_str_sign)
+    (list "sD" t_dex_sign)
+    (list "sW" t_wis_sign)
+       
+       ;; blended terrains (mostly terrain + corner of something else)
+       
+       (list  "/0"   t_trail_0)            ;; "trail"
+    (list  "/1"   t_trail_1)            ;; "trail"
+    (list  "/2"   t_trail_2)            ;; "trail"
+    (list  "/3"   t_trail_3)            ;; "trail"
+    (list  "/4"   t_trail_4)            ;; "trail"
+    (list  "/5"   t_trail_5)            ;; "trail"
+    (list  "/6"   t_trail_6)            ;; "trail"
+    (list  "/7"   t_trail_7)            ;; "trail"
+    (list  "/8"   t_trail_8)            ;; "trail"
+    (list  "/9"   t_trail_9)            ;; "trail"
+    (list  "/a"   t_trail_a)            ;; "trail"
+    (list  "/b"   t_trail_b)            ;; "trail"
+    (list  "/c"   t_trail_c)            ;; "trail"
+    (list  "/d"   t_trail_d)            ;; "trail"
+    (list  "/e"   t_trail_e)            ;; "trail"
+    (list  "/f"   t_trail_f)            ;; "trail"
+       
+       (list  "~~" t_shoals)     ;; shallow + land
+    (list  "~1" t_shore_n)
+    (list  "~2" t_shore_w)
+    (list  "~3" t_shore_nw)
+    (list  "~4" t_shore_e)
+    (list  "~5" t_shore_ne)
+    (list  "~6" t_shore_we)
+    (list  "~7" t_shore_nwe)
+    (list  "~8" t_shore_s)
+    (list  "~9" t_shore_ns)
+    (list  "~a" t_shore_ws)
+    (list  "~b" t_shore_nws)
+    (list  "~c" t_shore_es)
+    (list  "~d" t_shore_nes)
+    (list  "~e" t_shore_wes)
+    (list  "~f" t_shore_c)
+       
+    (list  "--" t_shallow)            ;; water + land
+    (list  "-1" t_wshore_n)
+    (list  "-2" t_wshore_w)
+    (list  "-3" t_wshore_nw)
+    (list  "-4" t_wshore_e)
+    (list  "-5" t_wshore_ne)
+    (list  "-6" t_wshore_we)
+    (list  "-7" t_wshore_nwe)
+    (list  "-8" t_wshore_s)
+    (list  "-9" t_wshore_ns)
+    (list  "-a" t_wshore_ws)
+    (list  "-b" t_wshore_nws)
+    (list  "-c" t_wshore_es)
+    (list  "-d" t_wshore_nes)
+    (list  "-e" t_wshore_wes)
+    (list  "-f" t_wshore_c)
+       
+       (list  "_1" t_dshore_n)        ;; deep water + land
+    (list  "_2" t_dshore_w)
+    (list  "_3" t_dshore_nw)
+    (list  "_4" t_dshore_e)
+    (list  "_5" t_dshore_ne)
+    (list  "_6" t_dshore_we)
+    (list  "_7" t_dshore_nwe)
+    (list  "_8" t_dshore_s)
+    (list  "_9" t_dshore_ns)
+    (list  "_a" t_dshore_ws)
+    (list  "_b" t_dshore_nws)
+    (list  "_c" t_dshore_es)
+    (list  "_d" t_dshore_nes)
+    (list  "_e" t_dshore_wes)
+    (list  "_f" t_dshore_c)
+       
+       (list  "*1" t_voids_n)             ;; void + land
+    (list  "*2" t_voids_w)
+    (list  "*3" t_voids_nw)
+    (list  "*4" t_voids_e)
+    (list  "*5" t_voids_ne)
+    (list  "*6" t_voids_we)
+    (list  "*7" t_voids_nwe)
+    (list  "*8" t_voids_s)
+    (list  "*9" t_voids_ns)
+    (list  "*a" t_voids_ws)
+    (list  "*b" t_voids_nws)
+    (list  "*c" t_voids_es)
+    (list  "*d" t_voids_nes)
+    (list  "*e" t_voids_wes)
+    (list  "*f" t_voids_c)
+       
+       (list  "{1" t_hilledge_n)          ;; grass + hills
+    (list  "{2" t_hilledge_w)
+    (list  "{3" t_hilledge_nw)
+    (list  "{4" t_hilledge_e)
+    (list  "{5" t_hilledge_ne)
+    (list  "{6" t_hilledge_we)
+    (list  "{7" t_hilledge_nwe)
+    (list  "{8" t_hilledge_s)
+    (list  "{9" t_hilledge_ns)
+    (list  "{a" t_hilledge_ws)
+    (list  "{b" t_hilledge_nws)
+    (list  "{c" t_hilledge_es)
+    (list  "{d" t_hilledge_nes)
+    (list  "{e" t_hilledge_wes)
+    (list  "{f" t_hilledge_c)
+       
+    (list  "%3" t_bog_nw)              ;; bog + land
+    (list  "%5" t_bog_ne)
+    (list  "%7" t_bog_nwe)
+    (list  "%a" t_bog_ws)
+    (list  "%b" t_bog_nws)
+    (list  "%c" t_bog_es)
+    (list  "%d" t_bog_nes)
+    (list  "%e" t_bog_wes)
+    (list  "%f" t_bog_c)
+
+    (list  "t3" t_trees_nw)               ;; trees + grass
+    (list  "t5" t_trees_ne)
+    (list  "t7" t_trees_nwe)
+    (list  "ta" t_trees_ws)
+    (list  "tb" t_trees_nws)
+    (list  "tc" t_trees_es)
+    (list  "td" t_trees_nes)
+    (list  "te" t_trees_wes)
+    (list  "tf" t_trees_c)
+
+       (list  "t#" t_grasst_nw)             ;; grass + trees
+    (list  "t%" t_grasst_ne)
+    (list  "t&" t_grasst_nwe)
+    (list  "tA" t_grasst_ws)
+    (list  "tB" t_grasst_nws)
+    (list  "tC" t_grasst_es)
+    (list  "tD" t_grasst_nes)
+    (list  "tE" t_grasst_wes)
+    (list  "tF" t_grasst_c)
+       
+       (list  "~#" t_grassw_nw)           ;; grass + water
+    (list  "~%" t_grassw_ne)
+    (list  "~&" t_grassw_nwe)
+    (list  "~A" t_grassw_ws)
+    (list  "~B" t_grassw_nws)
+    (list  "~C" t_grassw_es)
+    (list  "~D" t_grassw_nes)
+    (list  "~E" t_grassw_wes)
+    (list  "~F" t_grassw_c)
+       
+       (list  "{#" t_hilli_nw)             ;; hills + grass
+    (list  "{%" t_hilli_ne)
+    (list  "{&" t_hilli_nwe)
+    (list  "{A" t_hilli_ws)
+    (list  "{B" t_hilli_nws)
+    (list  "{C" t_hilli_es)
+    (list  "{D" t_hilli_nes)
+    (list  "{E" t_hilli_wes)
+    (list  "{F" t_hilli_c)
+       
+       (list  "|#" t_forestg_nw)          ;; forest + grass
+    (list  "|%" t_forestg_ne)
+    (list  "|&" t_forestg_nwe)
+    (list  "|A" t_forestg_ws)
+    (list  "|B" t_forestg_nws)
+    (list  "|C" t_forestg_es)
+    (list  "|D" t_forestg_nes)
+    (list  "|E" t_forestg_wes)
+
+       (list  "tG" t_treew_nw)            ;; trees + water
+    (list  "tH" t_treew_ne)
+    (list  "tI" t_treew_nwe)
+    (list  "tJ" t_treew_ws)
+    (list  "tK" t_treew_nws)
+    (list  "tL" t_treew_es)
+    (list  "tM" t_treew_nes)
+    (list  "tN" t_treew_wes)
+    (list  "tO" t_treew_c)
+       
+       (list  "{G" t_hillw_nw)            ;; hills + water
+    (list  "{H" t_hillw_ne)
+    (list  "{I" t_hillw_nwe)
+    (list  "{J" t_hillw_ws)
+    (list  "{K" t_hillw_nws)
+    (list  "{L" t_hillw_es)
+    (list  "{M" t_hillw_nes)
+    (list  "{N" t_hillw_wes)
+    (list  "{O" t_hillw_c)     
+       
+       (list  "{g" t_hillv_nw)           ;; hills + void
+    (list  "{h" t_hillv_ne)
+    (list  "{i" t_hillv_nwe)
+    (list  "{j" t_hillv_ws)
+    (list  "{k" t_hillv_nws)
+    (list  "{l" t_hillv_es)
+    (list  "{m" t_hillv_nes)
+    (list  "{n" t_hillv_wes)   
+       
+       (list  ".g" t_grassv_nw)          ;; grass + void
+    (list  ".h" t_grassv_ne)
+    (list  ".i" t_grassv_nwe)
+    (list  ".j" t_grassv_ws)
+    (list  ".k" t_grassv_nws)
+    (list  ".l" t_grassv_es)
+    (list  ".m" t_grassv_nes)
+    (list  ".n" t_grassv_wes)
+       
+       (list  "^g" t_mountv_nw)        ;; mounts + void
+    (list  "^h" t_mountv_ne)
+    (list  "^i" t_mountv_nwe)
+    (list  "^j" t_mountv_ws)
+    (list  "^k" t_mountv_nws)
+    (list  "^l" t_mountv_es)
+    (list  "^m" t_mountv_nes)
+    (list  "^n" t_mountv_wes)  
+       
+       (list  "^3" t_mountg_nw)     ;; mounts + grass
+    (list  "^5" t_mountg_ne)
+    (list  "^7" t_mountg_nwe)
+    (list  "^a" t_mountg_ws)
+    (list  "^b" t_mountg_nws)
+    (list  "^c" t_mountg_es)
+    (list  "^d" t_mountg_nes)
+    (list  "^e" t_mountg_wes)
+    (list  "^f" t_mountg_c)    
+       
+       (list  "^G" t_mountw_nw)        ;; mounts + water
+    (list  "^H" t_mountw_ne) 
+    (list  "^I" t_mountw_nwe)
+    (list  "^J" t_mountw_ws)
+    (list  "^K" t_mountw_nws)
+    (list  "^L" t_mountw_es)
+    (list  "^M" t_mountw_nes)
+    (list  "^N" t_mountw_wes)
+    (list  "^O" t_mountw_c)    
+       
+    (list  "!3" t_lava_nw)        ;; lava + land
+    (list  "!5" t_lava_ne)
+    (list  "!6" t_lava_we)
+    (list  "!7" t_lava_nwe)
+    (list  "!a" t_lava_ws)
+    (list  "!b" t_lava_nws)
+    (list  "!c" t_lava_es)
+    (list  "!d" t_lava_nes)
+    (list  "!e" t_lava_wes)
+    (list  "!f" t_lava_c)
+    
+    (list      "#=" t_rail_ew)
+    (list      "#|" t_rail_ns)
+    (list      "#a" t_bulwark_n)
+    (list      "#b" t_bulwark_w)
+    (list      "#c" t_bulwark_e)
+    (list      "#d" t_bulwark_s)
+    (list      "#A" t_bulwark_v_n)
+    (list      "#B" t_bulwark_v_w)
+    (list      "#C" t_bulwark_v_e)
+    (list      "#D" t_bulwark_v_s)
+    (list      "#e" t_bulwark_w_nw)
+    (list      "#f" t_bulwark_w_ne)
+    (list      "#g" t_bulwark_w_sw)
+    (list      "#h" t_bulwark_w_se)
+    (list      "#E" t_bulwark_d_nw)
+    (list      "#F" t_bulwark_d_ne)
+    (list      "#G" t_bulwark_d_sw)
+    (list      "#H" t_bulwark_d_se)  
+    (list      "#i" t_bulwark_v_nw)
+    (list      "#j" t_bulwark_v_ne)
+    (list      "#k" t_bulwark_v_sw)
+    (list      "#l" t_bulwark_v_se)
+    (list      "#I" t_bulwark_x_nw)
+    (list      "#J" t_bulwark_x_ne)
+    (list      "#K" t_bulwark_x_sw)
+    (list      "#L" t_bulwark_x_se)
+    (list      "#s" t_bulwark_x_ns)
+    (list      "#r" t_bulwark_x_ew)    
+  
+    (list      "#m" t_tank_l)
+    (list      "#M" t_tank_d)
+    (list      "#n" t_tank_nw)
+    (list      "#o" t_tank_ne)
+    (list      "#p" t_tank_sw)
+    (list      "#q" t_tank_se)  
+    (list      "#N" t_tank_d_nw)
+    (list      "#O" t_tank_d_ne)
+    (list      "#P" t_tank_d_sw)
+    (list      "#Q" t_tank_d_se) 
+      
+    (list      "<n" t_stair_un)
+    (list      "<s" t_stair_us)
+    (list      "<w" t_stair_uw)
+    (list      "<e" t_stair_ue)
+    
+    (list      "rn" t_nat_rock)
+    (list      "r1" t_nat_rock_n)
+    (list      "r2" t_nat_rock_w)
+    (list      "r3" t_nat_rock_nw)
+    (list      "r4" t_nat_rock_e)
+    (list      "r5" t_nat_rock_ne)
+    (list      "r6" t_nat_rock_we)
+    (list      "r7" t_nat_rock_nwe)
+    (list      "r8" t_nat_rock_s)
+    (list      "r9" t_nat_rock_ns)
+    (list      "ra" t_nat_rock_ws)
+    (list      "rb" t_nat_rock_nws)
+    (list      "rc" t_nat_rock_es)
+    (list      "rd" t_nat_rock_nes)
+    (list      "re" t_nat_rock_wes)
+    (list      "rf" t_nat_rock_nwes)
+    (list      "r~" t_fake_wall_nrock)   
+
+    (list "000" t_hl_0)
+    (list "001" t_hl_1)
+    (list "002" t_hl_2)
+    (list "003" t_hl_3)
+    (list "004" t_hl_4)
+    (list "005" t_hl_5)
+    (list "006" t_hl_6)
+    (list "007" t_hl_7)
+    (list "008" t_hl_8)
+    (list "009" t_hl_9)
+    (list "010" t_hl_10)
+    (list "011" t_hl_11)
+    (list "012" t_hl_12)
+    (list "013" t_hl_13)
+    (list "014" t_hl_14)
+    (list "015" t_hl_15)
+    (list "016" t_hl_16)
+    (list "017" t_hl_17)
+    (list "018" t_hl_18)
+    (list "019" t_hl_19)
+    (list "020" t_hl_20)
+    (list "021" t_hl_21)
+    (list "022" t_hl_22)
+    (list "023" t_hl_23)
+    (list "024" t_hl_24)
+    (list "025" t_hl_25)
+    (list "026" t_hl_26)
+    (list "027" t_hl_27)
+    (list "028" t_hl_28)
+    (list "029" t_hl_29)
+    (list "030" t_hl_30)
+    (list "031" t_hl_31)
+    (list "032" t_hl_32)
+    (list "033" t_hl_33)
+    (list "034" t_hl_34)
+    (list "035" t_hl_35)
+    (list "036" t_hl_36)
+    (list "037" t_hl_37)
+    (list "038" t_hl_38)
+    (list "039" t_hl_39)
+    (list "040" t_hl_40)
+    (list "041" t_hl_41)
+    (list "042" t_hl_42)
+    (list "043" t_hl_43)
+    (list "044" t_hl_44)
+    (list "045" t_hl_45)
+    (list "046" t_hl_46)
+    (list "047" t_hl_47)
+    (list "048" t_hl_48)
+    (list "049" t_hl_49)
+    (list "050" t_hl_50)
+    (list "051" t_hl_51)
+    (list "052" t_hl_52)
+    (list "053" t_hl_53)
+    (list "054" t_hl_54)
+    (list "055" t_hl_55)
+    (list "056" t_hl_56)
+    (list "057" t_hl_57)
+    (list "058" t_hl_58)
+    (list "059" t_hl_59)
+    (list "060" t_hl_60)
+    (list "061" t_hl_61)
+    (list "062" t_hl_62)
+    (list "063" t_hl_63)
+    (list "064" t_hl_64)
+    (list "065" t_hl_65)
+    (list "066" t_hl_66)
+    (list "067" t_hl_67)
+    (list "068" t_hl_68)
+    (list "069" t_hl_69)
+    (list "070" t_hl_70)
+    (list "071" t_hl_71)
+    (list "072" t_hl_72)
+    (list "073" t_hl_73)
+    (list "074" t_hl_74)
+    (list "075" t_hl_75)
+    (list "076" t_hl_76)
+    (list "077" t_hl_77)
+    (list "078" t_hl_78)
+    (list "079" t_hl_79)
+    (list "080" t_hl_80)
+    (list "081" t_hl_81)
+    (list "082" t_hl_82)
+    (list "083" t_hl_83)
+    (list "084" t_hl_84)
+    (list "085" t_hl_85)
+    (list "086" t_hl_86)
+    (list "087" t_hl_87)
+    (list "088" t_hl_88)
+    (list "089" t_hl_89)
+    (list "090" t_hl_90)
+    (list "091" t_hl_91)
+    (list "092" t_hl_92)
+    (list "093" t_hl_93)
+    (list "094" t_hl_94)
+    (list "095" t_hl_95)
+    (list "096" t_hl_96)
+    (list "097" t_hl_97)
+    (list "098" t_hl_98)
+    (list "099" t_hl_99)
+    (list "100" t_hl_100)
+    (list "101" t_hl_101)
+    (list "102" t_hl_102)
+    (list "103" t_hl_103)
+    (list "104" t_hl_104)
+    (list "105" t_hl_105)
+    (list "106" t_hl_106)
+    (list "107" t_hl_107)
+    (list "108" t_hl_108)
+    (list "109" t_hl_109)
+    (list "110" t_hl_110)
+    (list "111" t_hl_111)
+    (list "112" t_hl_112)
+    (list "113" t_hl_113)
+
+    (list "fg" t_gf_nw)
+    (list "fh" t_gf_n )
+    (list "fi" t_gf_ne)
+    (list "fj" t_gf_w )
+    (list "fk" t_gf_c )
+    (list "fl" t_gf_e )
+    (list "fm" t_gf_sw)
+    (list "fn" t_gf_s )
+    (list "fo" t_gf_se)
+  )
+) ;; palette pal_expanded
+
+;;----------------------------------------------------------------------------
+;; Places
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_demo_scene 19 19 pal_expanded
+
+       (list
+               "000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 "
+               "019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 "
+               "038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 "
+               "057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 "
+               "076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 "
+               "095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 "
+               "fg fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fh fi "
+               "fj t. t. t# .. .. .. .. .. .. t% ta t. t. tc __ t. t. fl "
+               "fj t. t# .. ar .. .. .. ar .. .. t% t. t. _3 _c t. t. fl "
+               "fj t# .. .. .. .. .. .. .. .. .. .. ta tc _2 tG t. t. fl "
+               "fj .. ar .. .. .. .. .. .. .. ar .. .. .. __ .. .. .. fl "
+               "fj .. .. .. .. dd dd dd .. .. .. .. dd ee ee ee dd dd fl "
+               "fj .. .. .. dd dd {f dd dd dd dd dd dd ee ee ee dd dd fl "
+               "fj .. .. .. .. dd dd dd .. .. .. .. dd ee ee ee dd dd fl "
+               "fj .. ar .. .. .. .. .. .. .. ar .. .. .. __ .. .. .. fl "
+               "fj tA .. .. .. .. .. .. .. .. .. .. t3 t5 _2 tJ t. t. fl "
+               "fj t. tA .. ar .. .. .. ar .. .. tC t. t. _a _5 t. t. fl "
+               "fj t. t. tA .. .. .. .. .. .. tC t3 t. t. t5 __ t. t. fl "
+               "fm fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fn fo "
+       )
+ )
+
+(kern-mk-place
+ 'p_demo_scene   ; tag
+ "Demo Scene"    ; name
+ nil             ; sprite
+ m_demo_scene    ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil             ; subplaces
+ nil             ; neighbors
+
+ (list ; objects
+ (put (guard-pt 'halberdier)   15 10)
+ (put (guard-pt 'halberdier)   15 14)
+ (put (guard-pt 'crossbowman) 13 10)
+ (put (guard-pt 'crossbowman) 13 14)
+ (put (mk-monman) 0 0)
+ (put (mk-scene-mgr) 0 0)
+ (put (kern-tag 'portal (kern-mk-obj t_portal 1)) 6  12)
+ )
+ (list 'on-entry-to-dungeon-room) ; hooks
+ nil ;; edge entrances
+)
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;
+;; Make an invisible, passive character for the player party, because there has
+;; to be a player party to get the camera on the scene, and the player party
+;; has to have at least one living member. Yes, this is a blatant hack.
+;;----------------------------------------------------------------------------
+
+(define (passive-ai kchar)
+       (kern-char-set-hp kchar max-health) ; functionally immortal, in case of stray fireballs
+       (kern-map-repaint)
+       (kern-sleep 75)
+      #t)
+  
+(let ((kchar (kern-mk-char 
+              'ch_wanderer
+              "John the Mute"       ; name
+              sp_human              ; species
+              oc_wanderer           ; occ
+              s_beggar    ; sprite
+              faction-player        ; starting alignment
+              5 5 5                ; str/int/dex
+              9999                                                     ; functionally immortal, in case of stray fireballs
+              pc-hp-gain
+              pc-mp-off
+              pc-mp-gain
+              max-health 0 max-health 0 1  ; hp/xp/mp/AP_per_turn/lvl
+              #f                    ; dead
+              nil                   ; conv
+              nil                   ; sched
+              'passive-ai           ; special ai
+              nil                   ; container
+              nil                   ; readied
+              )))
+  (kern-char-set-ai kchar 'passive-ai)
+  )
+;;----------------------------------------------------------------------------
+;; Player Party
+;;----------------------------------------------------------------------------
+(kern-mk-player
+ 'player                     ; tag
+ s_wanderer         ; sprite
+ "Walk"                      ; movement description
+ sound-walking               ; movement sound
+ 1                           ; food
+ 0                           ; gold
+ (* 60 60 5)                 ; turns to next meal (5 hours)
+ nil                         ; formation
+ nil                         ; campsite map
+ nil                         ; campsite formation
+ nil                         ; vehicle
+ ;; inventory
+ (kern-mk-inventory nil)
+ nil ;; party members (should be nil for initial load file)
+ )
+
+(kern-party-add-member player ch_wanderer)
+
+;;----------------------------------------------------------------------------
+;; Astronomy
+;;----------------------------------------------------------------------------
+(kern-mk-astral-body
+ 'sun              ; tag
+ "Fyer (the sun)"  ; name
+ 1                 ; relative astronomical distance 
+ 1                 ; minutes per phase (n/a for sun)
+ (/ (* 24 60) 360) ; minutes per degree
+ 0                 ; initial arc
+ 0                 ; initial phase
+ '()               ; script interface
+ ;; phases:
+ (list 
+  (list s_sun 255 "full")
+  )
+ )
+
+;;----------------------------------------------------------------------------
+;; Lumis is the source gate, which means it opens the source moongates on its
+;; phases. We designate this by using the source-moon-ifc as its ifc.
+;;
+;; Note: the arc and phase are calculated to give the moon the right orientation
+;; with respect to phase vs sun position
+;;----------------------------------------------------------------------------
+(mk-moon 'lumis  ; tag
+         "Lumis" ; name
+         5       ; hours per phase
+         60      ; hours per revolution
+         22      ; initial arc
+         0       ; initial phase
+         'source-moon-ifc ; ifc
+         ;; gates (moons are fixed at 8 phases in mk-moon):
+         (list 'mg-1 'mg-2 'mg-3 'mg-4
+               'mg-5 'mg-6 'mg-7 'mg-8
+               )
+         "yellow")
+
+;;----------------------------------------------------------------------------
+;; Ord is the destination gate, which means its phase decides the destination
+;; when the player steps through a moongate. We designate this by giving it a
+;; nil ifc. Note that its gates do not need to be listed in the same order as
+;; Lumis. In fact, they don't even need to be the same set of gates.
+;;
+;; Note: the arc and phase are calculated to give the moon the right orientation
+;; with respect to phase vs sun position
+;;----------------------------------------------------------------------------
+(mk-moon 'ord    ; tag
+         "Ord"   ; name
+         9       ; hours per phase
+         36      ; hours per revolution
+         67     ; initial arc
+         7       ; initial phase
+         nil     ; ifc
+         ;; gates (moons are fixed at 8 phases in mk-moon):
+         (list 'mg-1 'mg-2 'mg-3 'mg-4
+               'mg-5 'mg-6 'mg-7 'mg-8
+               )
+         "blue")
+
+;; ----------------------------------------------------------------------------
+;; The diplomacy table. Each entry defines the attitude of the row to the
+;; column. Note that attitudes are not necessarily symmetric. Negative values
+;; are hostile, positive are friendly.
+;;
+;; Note: factions should always be allied with themselves in order for
+;; summoning AI to work properly.
+;;       
+;; Formatted for spreadsheet
+;; ----------------------------------------------------------------------------
+(kern-mk-dtable                                                                                                                                        
+       ;;      non     pla     men     cgb     acc     mon     tro     spd     out     gnt     dem     fgb     prs                     
+       (list   2       0       0       0       -1      -2      -2      -2      0       -2      -2      0       0       )       ;;      none
+       (list   0       2       2       -1      -2      -2      -2      -2      -2      2       -2      -2      2       )       ;;      player
+       (list   -1      2       2       -1      -2      -2      -2      -2      -2      -2      -2      -2      2       )       ;;      men
+       (list   -1      2       -2      2       -1      -2      0       -2      -2      -1      -2      -2      0       )       ;;      cave goblin
+       (list   -1      2       -1      -1      2       -2      -1      -1      -2      -1      -2      -2      0       )       ;;      accursed
+       (list   -2      2       -2      -2      -2      2       -2      0       -2      0       -2      0       0       )       ;;      monsters
+       (list   -2      2       -2      0       -1      -2      2       -2      -2      -1      -2      -1      0       )       ;;      hill trolls
+       (list   -2      2       -2      -2      -1      0       -2      2       -2      -1      -2      0       0       )       ;;      wood spiders
+       (list   0       2       -2      -2      -2      -2      -2      -2      2       -2      -2      -1      0       )       ;;      outlaws
+       (list   -2      2       -2      -1      -1      0       -1      -1      -2      2       -2      -1      0       )       ;;      gint
+       (list   -2      2       -2      -2      -2      -2      -2      -2      -2      -2      2       -2      0       )       ;;      demon
+       (list   0       2       -2      -2      -2      0       -2      0       -1      -1      -2      2       0       )       ;;      forest goblin
+       (list   0       2       2       0       0       0       0       0       0       0       0       0       2       )       ;;      prisoners
+)                                                                                                                                      
+
+(define (simple-start kplayer)
+  (kern-obj-put-at kplayer (list p_demo_scene (+ xoff 14)  (+ yoff 3)))
+       (kern-map-center-camera (mk-loc p_demo_scene (+ xoff 10)  (+ yoff 5)))
+
+        (kern-char-set-control-mode ch_wanderer "auto")
+
+  ;; Do this to initialize the map viewer's active view, and to replace the
+  ;; splash screen with the scene.
+  (kern-map-repaint)
+  )
+
+(kern-add-hook 'new_game_start_hook 'simple-start)
diff --git a/worlds/haxima-1.002/demon-gate.scm b/worlds/haxima-1.002/demon-gate.scm
new file mode 100644 (file)
index 0000000..da78b43
--- /dev/null
@@ -0,0 +1,124 @@
+(kern-load "nossifer.scm")
+
+;; constants
+(define demon-gate-x 6)
+(define demon-gate-y 9)
+
+;; demon gate gob
+(define (mk-demon-gate-gob) (list 8 #f #f))
+(define (demon-gate-unlock gob) (set-car! gob (- (car gob) 1)))
+(define (demon-gate-completely-unlocked? gob) (= (car gob) 0))
+(define (demon-gate-opened? gob) (cadr gob))
+(define (demon-gate-opened! gob) (set-car! (cdr gob) #t))
+(define (end-game-played? gob) (caddr gob))
+(define (end-game-played! gob) (set-car! (cddr gob) #t))
+
+
+;; demon gate procs
+(define (summon-nossifer kplace)
+  (kern-log-msg "SOMETHING EMERGES")
+  (let ((knpc (mk-nossifer)))
+    (kern-obj-put-at knpc
+                     (mk-loc kplace
+                             demon-gate-x
+                             demon-gate-y))
+    (kern-map-repaint)
+    (kern-sleep 2000)
+    (kern-conv-begin knpc)
+  ))
+
+(define (open-demon-gate kplace)
+  (let* ((loc (mk-loc kplace
+                      demon-gate-x
+                      demon-gate-y))
+         (gate (mk-moongate nil))
+         (stages (list (list '()                       0)
+                       (list s_blackgate_quarter        32)
+                       (list s_blackgate_half           64)
+                       (list s_blackgate_three_quarters 96)
+                       (list s_blackgate_full           128))))
+    (kern-map-flash 100)
+    (kern-sleep 2000)
+    (kern-log-msg "A DARK GATE OPENS")
+    (kern-obj-put-at gate loc)
+    (moongate-animate gate stages)
+    (kern-sleep 2000)
+    (summon-nossifer kplace)
+    (kern-obj-remove gate)
+    ))
+
+
+(define (demon-gate-on kgate kchar)
+  (let ((dgate (gob kgate)))
+    (demon-gate-unlock dgate)))
+
+(define (nossifer-vanquished?)
+  (= 0 (num-hostiles (kern-get-player))))
+
+(define (end-game)
+  (kern-map-flash 1000)
+  (kern-map-repaint)
+  (kern-log-msg "**************************")
+  (kern-sleep 2000)
+  (kern-log-msg "Nossifer and his minions are defeated.")
+  (kern-sleep 2000)
+  (kern-log-msg "The Demon Gate is closed.")
+  (kern-sleep 2000)
+  (kern-log-msg "Will it open again?")
+  (kern-sleep 2000)
+  (kern-log-msg "Is the Wanderer trapped on the Shard forever?")
+  (kern-sleep 2000)
+  (kern-log-msg "Is he, perhaps, a Wanderer no more?")
+  (kern-sleep 2000)
+  (kern-log-msg "Is it time he became...")
+  (kern-sleep 4000)
+  (kern-log-msg "...a Conquerer?")
+  (kern-sleep 2000)
+  (kern-log-msg "Find out in Haxima II: Conquerer")
+  (kern-log-msg "**************************")
+
+  (kern-log-msg "*** CONGRATULATIONS ***")
+  (kern-log-msg "You have finished the game!")
+  (kern-log-msg "Press any key to exit.")
+  (kern-ui-waitkey)
+
+  (kern-end-game)
+  )
+
+(define (demon-gate-exec kgate)
+       (let ((dgate (gob kgate)))
+               (if (and (not (end-game-played? dgate))
+                               (demon-gate-opened? dgate)
+                               (nossifer-vanquished?))
+                       (begin
+                               (end-game)
+                               (end-game-played! dgate)
+                       ))
+               (println (demon-gate-completely-unlocked? dgate) " "
+                                       (demon-gate-opened? dgate) " " (nossifer-vanquished?))
+               (if (and (demon-gate-completely-unlocked? dgate)
+                               (not (demon-gate-opened? dgate)))
+                       (begin
+                               (open-demon-gate (get-place kgate))
+                               (demon-gate-opened! dgate)
+                       )
+               )
+       ))
+        
+
+;; demon gate type ifc
+(define demon-gate-ifc
+  (ifc '()
+       (method 'on demon-gate-on)
+       (method 'exec demon-gate-exec)
+       ))
+
+;; demon gate type
+(mk-obj-type 't_demon_gate nil nil layer-none demon-gate-ifc)
+
+;; demon gate ctor
+(define (mk-demon-gate)
+  (kern-tag 'demon-gate
+            (bind (kern-obj-set-ignore-time-stop (kern-mk-obj t_demon_gate 1)
+                                                 #t)
+                  (mk-demon-gate-gob))))
diff --git a/worlds/haxima-1.002/dennis.scm b/worlds/haxima-1.002/dennis.scm
new file mode 100644 (file)
index 0000000..d9a3819
--- /dev/null
@@ -0,0 +1,140 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define dennis-lvl 3)
+(define dennis-species sp_human)
+(define dennis-occ oc_wright)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Old Absalot.
+;;----------------------------------------------------------------------------
+(define dennis-bed oa-bed2)
+(define dennis-mealplace oa-tbl1)
+(define dennis-workplace oa-slaves)
+(define dennis-leisureplace oa-dining-hall)
+(kern-mk-sched 'sch_dennis
+               (list 0  0 dennis-bed          "sleeping")
+               (list 7  0 dennis-mealplace    "eating")
+               (list 8  0 dennis-workplace    "working")
+               (list 12 0 dennis-mealplace    "eating")
+               (list 13 0 dennis-workplace    "working")
+               (list 18 0 dennis-mealplace    "eating")
+               (list 19 0 dennis-leisureplace "idle")
+               (list 22 0 dennis-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (dennis-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Dennis is an acolyte of the Accursed, who lives in Old Absalot.
+;; He is somewhat naive, but not yet wholly corrupt.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (dennis-hail knpc kpc)
+  (say knpc "Hello."))
+
+(define (dennis-default knpc kpc)
+  (say knpc "I don't know about that sort of thing."))
+
+(define (dennis-name knpc kpc)
+  (say knpc "I'm Dennis."))
+
+(define (dennis-join knpc kpc)
+  (say knpc "[He scoffs] I don't think so, wayfarer."))
+
+(define (dennis-job knpc kpc)
+  (say knpc "I am a student of Master Silas."))
+
+(define (dennis-bye knpc kpc)
+  (say knpc "Goodbye."))
+
+;; Tier 2
+(define (dennis-stud knpc kpc)
+  (say knpc "Master Silas teaches that by focusing my will, and by sacrificing things which impede my progess, I can achieve anything I desire. Or, at least, I will be able to once I have mastered the ways of the Accursed."))
+
+(define (dennis-accu knpc kpc)
+  (say knpc "The Accursed are misunderstood. It is not evil to pursue one's desires, it is good! Why can't our enemies see that?"))
+
+(define (dennis-enem knpc kpc)
+  (say knpc "The butchers of Glasdrin and that old fool the Enchanter have more blood on their hands than anyone!"))
+
+(define (dennis-ways knpc kpc)
+  (say knpc "The ways of the Accursed are revealed to students in phases. At each phase, an acolyte gains more power. To advance to the next phase the student must master the rites and perform a suitable sacrifice."))
+
+(define (dennis-sacr knpc kpc)
+  (say knpc "The sacrificial rites are secret. I cannot speak of them with an uninitiate like yourself."))
+
+(define (dennis-powe knpc kpc)
+  (say knpc "Power unimaginable awaits those who have the will to grasp it."))
+
+(define (dennis-sila knpc kpc)
+  (say knpc "Master Silas is a powerful wizard and a wise teacher."))
+
+(define (dennis-absa knpc kpc)
+  (say knpc "Those fools destroyed Absalot, thinking we were there! But they didn't know about Old Absalot, a city beneath the city."))
+
+(define (dennis-old knpc kpc)
+  (say knpc "I can't help but feel awed when I walk among these ruins. But they are a bit creepy. The ancients had some strange beliefs!"))
+
+(define (dennis-sele knpc kpc)
+  (say knpc "[He blushes] If you know what's good for you, you will stay away from her!")
+  (kern-conv-end)
+  )
+
+(define dennis-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default dennis-default)
+       (method 'hail dennis-hail)
+       (method 'bye dennis-bye)
+       (method 'job dennis-job)
+       (method 'name dennis-name)
+       (method 'join dennis-join)
+       
+       (method 'sele dennis-sele)
+       (method 'stud dennis-stud)
+       (method 'teac dennis-stud)
+       (method 'accu dennis-accu)
+       (method 'enem dennis-enem)
+       (method 'ways dennis-ways)
+       (method 'sacr dennis-sacr)
+       (method 'powe dennis-powe)
+       (method 'sila dennis-sila)
+       (method 'absa dennis-absa)
+       (method 'old dennis-old)
+       ))
+
+(define (mk-dennis)
+  (bind 
+   (kern-mk-char 
+    'ch_dennis           ; tag
+    "Dennis"             ; name
+    dennis-species         ; species
+    dennis-occ              ; occ
+    s_townsman     ; sprite
+    faction-men      ; starting alignment
+    0 1 0            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    dennis-lvl
+    #f               ; dead
+    'dennis-conv         ; conv
+    sch_dennis           ; sched
+    'spell-sword-ai              ; special ai
+    nil              ; container
+    (list t_staff)              ; readied
+    )
+   (dennis-mk)))
diff --git a/worlds/haxima-1.002/deric.scm b/worlds/haxima-1.002/deric.scm
new file mode 100644 (file)
index 0000000..8065361
--- /dev/null
@@ -0,0 +1,304 @@
+;;----------------------------------------------------------------------------
+;; Sched
+;; 
+;; In Green Tower.
+;;----------------------------------------------------------------------------
+(define (mk-zone x y w h) (list 'p_green_tower x y w h))
+(kern-mk-sched 'sch_deric
+               (list 0  0 (mk-zone 17  4  1   1)  "sleeping")
+               (list 6  0 (mk-zone 30 30  5   5)  "working")
+               (list 12  0 (mk-zone 52 54  1   1)  "eating")
+               (list 13  0 (mk-zone 30 30  5   5)  "working")
+               (list 18  0 (mk-zone 52 54  1   1)  "eating")
+               (list 19  0 (mk-zone 30 30  5   5)  "working")
+               (list 21  0 (mk-zone 13  2  4   4)  "idle")
+               (list 22  0 (mk-zone 17  4  1   1)  "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (deric-mk tell-secret?) (list tell-secret? (mk-quest)))
+(define (deric-tell-secret? deric) (car deric))
+(define (deric-set-tell-secret! deric) (set-car! deric #t))
+(define (deric-bandit-quest deric) (cadr deric))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Deric is a Captain of the Rangers in Green Tower.
+;;----------------------------------------------------------------------------
+
+(define (deric-name knpc kpc)
+  (say knpc "I am Captain Deric, commander of the Rangers, at your service."))
+
+(define (deric-job knpc kpc)
+  (say knpc "I command the Rangers, though I aspire to greater things. I "
+       "think I have proved myself quite well as a leader, but around here "
+       "you have to wait for someone to die before you get promoted!"))
+
+(define (deric-health knpc kpc)
+  (say knpc "I am the very definition of good health!"))
+
+(define (deric-rangers knpc kpc)
+  (say knpc "Right then! The Rangers are charged with keeping the peace in "
+       "the Great Wood. We enforce the law, keep an eye on the goblins, that "
+       "sort of thing. We're also charged with maintenance of the forest and "
+       "keeping the roads in and out clear. If I say so myself, we have done "
+       "an amazing job under my leadership. Thanks to the hard work of my "
+       "people, of course. Ahem."))
+
+(define (deric-two knpc kpc)
+  (say knpc "The upper level of the tower is mostly fortifications. The lower "
+       "level is where the council chamber, barracks, kitchen and other "
+       "facilities are. We also have a prison down there. Some think the "
+       "lower level is haunted."))
+
+(define (deric-haunted knpc kpc)
+  (say knpc "They say the lower level is haunted, and I for one have heard "
+       "some strange noises. They sound like they're coming from deep within "
+       "the walls - chanting, or shrieking. But I've never seen any ghosts. "
+       "And of course I am not afraid of such things!"))
+
+(define (deric-gen knpc kpc)
+  (say knpc "A splendid old chap, if a bit daft. He's a legend among the "
+       "Rangers for his efforts during the Goblin War, and one of the last "
+       "surviving veterans. Still looks to be in good shape physically, but "
+       "he's gone a bit native, if you know what I mean."))
+
+(define (deric-native knpc kpc)
+  (say knpc "Yes, he's adopted some of the habits of the Wood Folk - the "
+       "forest goblins. But I don't suspect him of conspiring against us - if "
+       "I did I would turn him in and perhaps get a promotion! But alas, 'tis "
+       "not the case."))
+
+(define (deric-shroom knpc kpc)
+  (say knpc "A nice old hag. Bit of a witch, but not any trouble. Keeps a "
+       "reagent shop in the northeast corner of town."))
+
+(define (deric-abe knpc kpc)
+  (say knpc "A queer young man. Queer as in strange, you know, not that "
+       "other... well, maybe... it's hard to say. Anyway, he studies the "
+       "ruins in the southwest corner. Working for the Royal Library or some "
+       "such."))
+
+
+(define (deric-tower knpc kpc)
+  (say knpc "Yes, the Tower itself which gives Green Tower its name is "
+       "located in the center of town. It is my command post and headquarters "
+       "for the Rangers. A fascinating building! Did you know it is built on "
+       "the ruins of an older tower?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Interesting, eh? Not that I'm an expert on such things. "
+           "You'd have to talk with old Abe, or perhaps Shroom, to learn "
+           "more.")
+      (say knpc "'Tis true! What is now the Tower was once only the central "
+           "spire of a very great structure that reached much higher! And "
+           "much lower as well, if young Abe is to be believed. Currently "
+           "there are only two stories.")))
+
+(define (deric-ambition knpc kpc)
+  (say knpc "Yes, I am quite ambitious and not afraid to admit it! No point "
+       "sneaking about when one is ambitious, it just makes people nervous. "
+       "I wouldn't do anything immoral to advance my position, of course, "
+       "I believe too firmly in the principles of our great society. Do you "
+       "have any ambitions?")
+  (if (kern-conv-get-yes-no? kpc)
+      (begin
+        (say knpc "Well, enough about you! I hope someday to be a Lord. "
+             "Do you think I have a chance?")
+        (if (kern-conv-get-yes-no? kpc)
+            (begin
+              (say knpc "I knew it! You know, I wasn't sure if I could trust "
+                   "you, but you're obviously a person of insight, so I'll "
+                   "let you in on a secret.")
+              (deric-set-tell-secret! (kobj-gob-data knpc)))
+            (say knpc "[laughing] I'm sorry if I must disagree! People of "
+                 "destiny are never appreciated by their fellows.")))
+      (say knpc "[sigh] So many people lead worthless, wasted lives. I'm glad "
+           "I'm not one of them!")))
+
+(define (deric-secret knpc kpc)
+  (if (deric-tell-secret? (kobj-gob-data knpc))
+      (say knpc "In the lower level of the Tower there is a hidden passage. "
+           "Go down the ladder and enter the southeast supply room. "
+           "On the east wall is a secret door! "
+           "I have no idea what it was for.")
+      (say knpc "Nothing I want to tell a stranger like you!")))
+
+(define (deric-afraid knpc kpc)
+  (say knpc "Of course not! Fear is the hobgoblin of little minds. "
+       "Or is it hobgoblins are the fear of little minds? "
+       "Damn, I can never remember that silly saying."))
+
+(define (deric-prison knpc kpc)
+  (say knpc "Yes. Very secure. We currently only have one prisoner, "
+       "a forest goblin we caught skulking around here. "
+       "A quite vicious-looking brute, I must say. "
+       "Not that I am afraid of him. Ahem."))
+
+(define (deric-gobl knpc kpc)
+  (say knpc "Sneaky fellows! Why, just the other day I caught one here in town and had him thrown into prison."))
+
+(define (deric-brute knpc kpc)
+  (say knpc "Very suspicious. He obviously did not come to trade, "
+       "for he carried no merchandise. And he speaks not a lick of Common. "
+       "In fact, he refuses to say anything! Well, some time spent "
+       "underground should loosen his tongue. I'll find out what he's "
+       "scheming."))
+
+(define (deric-default knpc kpc)
+  (say knpc "You must ask another of that!"))
+
+;; Scan the player party looking for mercs
+                         
+
+(define (deric-hail knpc kpc)
+
+  (define (get-ranger-merc)
+    (let ((mercs (filter (lambda (kchar)
+                           (kbeing-is-npc-type? kchar 'ranger))
+                         (kern-party-get-members (kern-get-player)))))
+      (cond ((null? mercs) nil)
+            (else
+           (car mercs)))))
+
+  (define (rm-ranger-merc)
+    (let ((kmerc (get-ranger-merc)))
+      (if (not (null? kmerc))
+          (begin
+            (prompt-for-key)
+            (say knpc "I'll need to re-assign that ranger to a patrol.")
+            (kern-char-leave-player kmerc)
+            ))))
+
+  (cond ((in-player-party? 'ch_nate)
+         (say knpc "I see you have apprehended the bandit leader! "
+              "Deliver him downstairs to the jailer and I will give you the "
+              "reward.")
+         (rm-ranger-merc)
+         (quest-data-update-with 'questentry-bandits 'captured-nate-and-talked-to-deric 1 (quest-notify nil))
+         )        
+        ((has? kpc t_prisoner_receipt 1)
+         (say knpc "Putting that bandit behind bars will look very good on my "
+              "record! Here is your reward.")
+         (give-player-gold 100)
+         (kern-char-add-experience kpc 64)
+         (take kpc t_prisoner_receipt 1)
+         (quest-done! (deric-bandit-quest (kobj-gob-data knpc)) #t)
+         (rm-ranger-merc)
+         (quest-data-update-with 'questentry-bandits 'done 1 (grant-party-xp-fn 30))
+         (quest-data-complete 'questentry-bandits)
+         )
+        (else
+         (say knpc "Well met, indeed!")
+         )))
+
+(define (deric-bye knpc kpc)
+  (say knpc "Until next time"))
+
+(define (deric-thie knpc kpc)
+  (say knpc "Hm. The goblin brute we have locked up below may be a thief. But "
+       "he's been in our prison for some time. Now, our rangers did report "
+       "a lone man traveling north through the forest, but we know not "
+       "whence. The only thing to the north is Bole.")
+       (quest-data-update 'questentry-thiefrune 'tower 1)
+       (quest-data-update-with 'questentry-thiefrune 'bole 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+
+(define (deric-accu knpc kpc)
+  (say knpc "I assure you, my good man, there are no Accursed around here."))
+
+
+(define (deric-band knpc kpc)
+  (let ((quest (deric-bandit-quest (kobj-gob-data knpc))))
+    (cond ((quest-done? quest) 
+           (say knpc "I don't expect any more trouble from bandits since I "
+                "had their leader apprehended. "
+                "By you, of course. "
+                "But I had it done. "
+                "Ahem."))
+          ((quest-accepted? quest)
+           (say knpc "The bandits have a hideout somewhere in these "
+                "woods.  Keep searching! And bring me their leader "
+                "back alive.")
+           )
+          (else
+           (say knpc "So you've heard of our bandit problem. "
+                "Yes, they have a secret hideout somewhere in these woods. "
+                "I would have flushed them out long ago, "
+                "but I haven't the men to spare. You understand. ")
+           (prompt-for-key)
+           (say knpc
+                "Say, you seem like a plucky sort. "
+                "If you capture the bandit leader and bring him here I'll "
+                "gladly reward you for your trouble. What do you say?")
+           (if (yes? kpc)
+               (begin
+                 (quest-accepted! quest #t)
+                 (say knpc "Good! You may need some help. "
+                      "[He gives you a parchment]."
+                      "These orders will temporarily assign one of my Rangers "
+                      "to you. Just ask one to join your party.")
+                 (give kpc t_ranger_orders 1)
+                 (quest-data-update-with 'questentry-bandits 'talked-to-deric 1 (quest-notify nil))
+                 )
+               (say knpc "You'll never gain a reputation that way!")))
+          )))
+                       
+
+(define deric-conv
+  (ifc green-tower-conv
+       (method 'abe        deric-abe)
+       (method 'afra       deric-afraid)
+       (method 'ambi       deric-ambition)
+       (method 'aspi       deric-ambition)
+       (method 'band       deric-band)
+       (method 'brut       deric-brute)
+       (method 'bye        deric-bye)
+       (method 'comm       deric-rangers)
+       (method 'default    deric-default)
+       (method 'die        deric-ambition)
+       (method 'gen        deric-gen)
+       (method 'hail       deric-hail)
+       (method 'haun       deric-haunted)
+       (method 'heal       deric-health)
+       (method 'job        deric-job)
+       (method 'name       deric-name)
+       (method 'nati       deric-native)
+       (method 'pris       deric-prison)
+       (method 'prom       deric-ambition)
+       (method 'rang       deric-rangers)
+       (method 'secr       deric-secret)
+       (method 'shro       deric-shroom)
+       (method 'skul       deric-brute)
+       (method 'stor       deric-two)
+       (method 'thie       deric-thie)
+       (method 'towe       deric-tower)
+       (method 'two        deric-two)
+       (method 'gobl       deric-gobl)
+))                
+
+(define (mk-deric tag)
+  (bind 
+   (kern-mk-char tag                 ; tag
+                 "Deric"            ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_ranger_captain   ; sprite
+                 faction-men         ; starting alignment
+                 1 3 2               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 4  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'deric-conv        ; conv
+                 sch_deric          ; sched
+                 'townsman-ai        ;; special ai
+                 nil                 ; container
+                 (list  t_sword_2
+                                                t_armor_leather_2
+                                                t_leather_helm_2
+                                                )                  ; readied
+                 )
+   (deric-mk #f)))
diff --git a/worlds/haxima-1.002/disarm-trap.scm b/worlds/haxima-1.002/disarm-trap.scm
new file mode 100644 (file)
index 0000000..3a16e73
--- /dev/null
@@ -0,0 +1,100 @@
+;; ----------------------------------------------------------------------------
+;; Disarm Trap skill
+;; ----------------------------------------------------------------------------
+
+;; Runs the 'disarm-trap' task. kchar is the person doing the task, ktarg is
+;; the object the traps are attached to. Only one trap is worked on per
+;; iteration. When there are no traps left the task is done. Each time in, we
+;; roll to see if the char is done with the next trap. If so, we roll to see if
+;; they succeed in disarming. If not, we trip the trap. Note that the
+;; trap-trigger procedure gives the char another chance to roll to avoid. The
+;; chief benefit of using the disarm skill is it gives an extra roll to avoid
+;; tripping the trap. The only other advantage is when the on-damage hooks are
+;; in place for tasks they will give the player a chance to abort before
+;; tripping any more traps. By comparison, when you search or open a door (for
+;; example) it will trip all the traps in sequence, which can do a lot of
+;; damage if there are multiple traps.
+(define (disarm-task kchar ktarg)
+  (let* (
+         (traps (filter (lambda (trap) 
+                          (and (trap-detected? trap) 
+                               (not (trap-tripped? trap))))
+                        (ifccall ktarg 'get-traps)))
+        )
+    ;; Check if any unprocessed traps remaining
+    (println "traps: " traps)
+    (cond ((null? traps) 
+           (kern-char-task-end kchar)
+           )
+          ((not (handles? ktarg 'rm-traps)) 
+           (kern-log-msg "Traps can't be removed!")
+           (kern-char-task-abort kchar)
+           )
+          (else
+           ;; Roll to complete the task (on the current trap)
+           (let* (
+                  (trap (car traps))
+                  (dc (trap-avoid-dc trap))
+                  (roll (kern-dice-roll "1d20"))
+                  (bonus (occ-thief-dice-roll kchar))
+                  )
+             (println "trap: " trap " dc: " dc " roll: " roll " bonus: " bonus)
+             (if (or 
+                  (= roll 20) 
+                  (> (+ roll bonus) (* 2 dc))
+                  )
+                 ;; Roll to succeed
+                 (let (
+                       (roll (kern-dice-roll "1d20"))
+                       (bonus (occ-thief-dice-roll kchar))
+                       )
+                   (println "roll2: " roll " bonus2: " bonus)
+                   (cond ((or 
+                           (= roll 20) 
+                           (> (+ roll bonus) dc)
+                           )
+                          ;; Success - disarm the trap
+                          (kern-log-msg (kern-obj-get-name kchar) " ^c+gdisarms^c- a " (trap-name trap) " trap!")
+                          (trap-set-tripped! trap #t)
+                          )
+                      (else
+                       ;; Failure - trip the trap (kchar will get another roll
+                       ;; to avoid the damage)
+                       (trap-trigger trap ktarg kchar)
+                       ))
+                   ;; Last trap just proceessed
+                   (if (= 1 (length traps))
+                       (kern-char-task-end kchar))
+                   )))))))
+                
+
+(define (skill-disarm-trap kactor)
+
+  ;; Called after the player has selected a target to disarm.
+  (define (cb kactor ktarg power)
+    (let (
+          (traps (filter (lambda (trap) 
+                           (and (trap-detected? trap) 
+                                (not (trap-tripped? trap))))
+                         (ifccall ktarg 'get-traps)))
+          )
+      ;; Check if there are any unprocessed traps
+      (println "traps: " traps)
+      (cond ((null? traps) 
+             result-no-effect
+             )
+            (else
+             ;; Start a task to disarm the traps
+             (kern-char-task-begin kactor "disarming a trap" 'disarm-task ktarg)
+             result-ok
+             ))))
+
+  ;; fixme: only checks topmost item.
+  (cast-ui-ranged-any cb
+                      kactor 
+                      1
+                      (occ-ability-thief kactor)
+                      (lambda (kobj)
+                        (and (kern-obj-is-visible? kobj)
+                             (handles? kobj 
+                                       'rm-traps)))))
diff --git a/worlds/haxima-1.002/dog_9.wav b/worlds/haxima-1.002/dog_9.wav
new file mode 100644 (file)
index 0000000..ff2314c
Binary files /dev/null and b/worlds/haxima-1.002/dog_9.wav differ
diff --git a/worlds/haxima-1.002/door.scm b/worlds/haxima-1.002/door.scm
new file mode 100644 (file)
index 0000000..b1e4187
--- /dev/null
@@ -0,0 +1,376 @@
+;;----------------------------------------------------------------------------
+;; Doors
+(define door-state-closed       0)
+(define door-state-open         1)
+(define door-state-locked       2)
+(define door-state-magic-locked 3)
+
+(define (mk-door-state sprite opacity pclass)
+  (list sprite opacity pclass))
+(define (door-state-sprite ds) (car ds))
+(define (door-state-opacity ds) (cadr ds))
+(define (door-state-pclass ds) (caddr ds))
+
+(define (mk-door-states closed open locked magic-locked)
+  (list closed open locked magic-locked))
+
+;; Define the door gob structure and procedures.
+(define (door-mk open? timeout port active? locked? magic-locked? type)
+  (list open? timeout port active? locked? magic-locked? type nil nil))
+(define (door-open? door) (car (gob-data door)))
+(define (door-timeout door) (cadr (gob-data door)))
+(define (door-port door) (list-ref (gob-data door) 2))
+(define (door-active? door) (list-ref (gob-data door) 3))
+(define (door-locked? door) (list-ref (gob-data door) 4))
+(define (door-magic-locked? door) (list-ref (gob-data door) 5))
+(define (door-states door) (eval (list-ref (gob-data door) 6)))
+(define (door-traps door) (list-ref (gob-data door) 7))
+(define (door-trapped? door) (not (null? (door-traps door))))
+(define (door-key door) (list-ref (gob-data door) 8))
+(define (door-needs-key? door) (not (null? (door-key door))))
+(define (door-key-fits? door ktype)
+  (let ((key (safe-eval (door-key door))))
+    (and (not (null? key))
+         (eqv? key ktype))))
+
+(define (door-set-open door val) (set-car! (gob-data door) val))
+(define (door-set-timeout! door time) (set-car! (cdr (gob-data door)) time))
+(define (door-set-port! door port) (set-car! (cddr (gob-data door)) port))
+(define (door-set-active! door val) (set-car! (cdddr (gob-data door)) val))
+(define (door-set-locked! door val) (set-car! (cddddr (gob-data door)) val))
+(define (door-set-magic-locked! door val)
+  (list-set-ref! (gob-data door) 5 val))
+(define (door-set-traps! door val) (list-set-ref! (gob-data door) 7 val))
+(define (door-add-trap! door trap-type)
+  (door-set-traps! door (cons (mk-trap (eval trap-type))
+                              (door-traps door))))
+(define (door-set-key! door key-type-tag) 
+  (list-set-ref! (gob-data door) 8 key-type-tag))
+
+(define (door-send-signal kdoor sig)
+  (let ((door (kobj-gob kdoor)))
+    (if (not (door-active? door))
+        (begin
+          (let ((port (door-port door)))
+            (door-set-active! door #t)
+            (if (not (null? port))
+                (begin
+                  ((kobj-ifc (eval port)) sig (eval port) kdoor)))
+            (door-set-active! door #f))))))
+
+(define (door-update-kstate kdoor)
+  (define (update state-no)
+    (let ((state (list-ref (door-states (kobj-gob kdoor)) state-no)))
+      (kern-obj-set-sprite kdoor (door-state-sprite state))
+      (kern-obj-set-opacity kdoor (door-state-opacity state))
+      (kern-obj-set-pclass kdoor (door-state-pclass state))))
+  (let ((door (kobj-gob kdoor)))
+    (cond ((door-magic-locked? door) (update door-state-magic-locked))
+          ((door-locked? door)       (update door-state-locked))
+          ((door-open? door)         (update door-state-open))
+          (else                      (update door-state-closed))))
+  (kern-map-set-dirty)
+  kdoor)
+
+(define (door-trip-traps kdoor kchar)
+  (let ((door (kobj-gob kdoor))
+        )
+    (kern-obj-inc-ref kdoor)
+    (kern-obj-inc-ref kchar)
+    (map (lambda (trap)
+           (trap-trigger trap kdoor kchar))
+         (door-traps door))
+    (door-set-traps! door nil)
+    (kern-obj-dec-ref kdoor)
+    (kern-obj-dec-ref kchar)))
+
+(define (door-open kdoor khandler) 
+  (let ((door (kobj-gob kdoor)))
+    (cond 
+     ((door-magic-locked? door)
+      (kern-log-msg "Magically locked!\n")
+      #f)
+     ((door-locked? door)
+      (kern-log-msg "Locked!\n")
+      #f)
+     ((door-trapped? door)
+      (door-trip-traps kdoor khandler)
+      (door-open kdoor khandler)
+      )
+      (else
+       (door-set-open door #t)
+       (door-set-timeout! door 10)
+       (door-update-kstate kdoor)
+       (door-send-signal kdoor 'open)
+       #t))))
+  
+(define (door-close kdoor khandler)
+  ;;(display "door-close")(newline)
+  (if (not (occupied? (kern-obj-get-location kdoor)))
+      (let ((door (kobj-gob kdoor)))
+        (door-set-open door #f)
+        (door-set-timeout! door 0)
+        (door-update-kstate kdoor)
+        (door-send-signal kdoor 'close)
+        #t)))
+
+(define (door-lock kdoor khandler)
+  (let ((door (kobj-gob kdoor)))
+    ;;(display "door-lock:")(display door)(newline)
+    (cond ((door-open? door) (kern-log-msg "Not closed!\n") #f)
+          ((door-locked? door) (kern-log-msg "Already locked!\n") #f)
+          (else
+           (door-set-locked! door #t)
+           (door-update-kstate kdoor)
+           #t))))
+
+(define (door-unlock kdoor khandler)
+  (let ((door (kobj-gob kdoor)))
+    ;;(display "door-unlock:")(display door)(newline)
+    (cond ((door-open? door) (kern-log-msg "Not closed!\n") #f)
+          ((not (door-locked? door)) (kern-log-msg "Not locked!\n") #f)
+          ((door-needs-key? door) (kern-log-msg "Needs the key!\n") #f)
+          (else
+           (door-set-locked! door #f)
+           (door-update-kstate kdoor)
+           #t))))
+
+(define (door-magic-lock kdoor khandler)
+  (let ((door (kobj-gob kdoor)))
+    ;;(display "door-magic-lock:")(display door)(newline)
+    (cond ((door-open? door) (kern-log-msg "Not closed!\n") #f)
+          ((door-magic-locked? door) 
+           (kern-log-msg "Already magically locked!\n") #f)
+          (else
+           (door-set-magic-locked! door #t)
+           (door-update-kstate kdoor)
+           #t))))
+
+(define (door-magic-unlock kdoor khandler)
+  (let ((door (kobj-gob kdoor)))
+    ;;(display "door-magic-unlock:")(display door)(newline)
+    (cond ((door-open? door) (kern-log-msg "Not closed!\n") #f)
+          ((not (door-magic-locked? door)) 
+           (kern-log-msg "Not magically locked!\n") #f)
+          (else
+           (door-set-magic-locked! door #f)
+           (door-update-kstate kdoor)
+           #t))))
+
+(define (door-handle kdoor khandler)
+  (let ((door (kobj-gob kdoor)))
+    (if (door-open? door) 
+        (door-close kdoor khandler)
+        (door-open kdoor khandler))))
+
+(define (door-exec kdoor)
+  (let ((door (kobj-gob kdoor)))
+    (if (door-open? door)
+        (let ((timeout (door-timeout door)))
+          (cond ((> timeout 1) (door-set-timeout! door (- timeout 1)))
+                ((= timeout 1) (door-close kdoor '())))))))
+
+
+(define (door-connect kobj kto-tag)
+  (let ((door (kobj-gob kobj)))
+    (door-set-port! door kto-tag)))
+
+(define (door-add-trap kdoor trap-sym)
+  (let ((door (kobj-gob kdoor)))
+    (door-add-trap! door trap-sym)))
+  
+(define (door-get-traps kdoor)
+  (door-traps (kobj-gob kdoor)))
+
+(define (door-rm-traps kdoor)
+  (let ((door (kobj-gob kdoor)))
+    (door-set-traps! door nil)))
+
+(define (door-use-key kdoor key-type)
+  (let ((door (kobj-gob kdoor)))
+    (cond ((door-open? door) (kern-log-msg "Not closed!"))
+          ((not (door-key-fits? door key-type)) (kern-log-msg "Key won't fit!"))
+          ((door-locked? door)
+           (door-set-locked! door #f)
+           (door-update-kstate kdoor))
+          (else
+           (door-set-locked! door #t)
+           (door-update-kstate kdoor)))))
+
+(define (door-search kdoor kchar)
+  (kern-log-begin "Searching door...")
+  (let ((door (kobj-gob kdoor)))
+    (if (foldr (lambda (detected? trap)
+                 (trap-search trap kdoor kchar)
+                 (if (trap-tripped? trap)
+                     (door-set-traps! door
+                                      (filter (lambda (trap2)
+                                                (not (equal? trap trap2)))
+                                              (door-traps door))))
+                 (or detected? (trap-detected? trap)))
+               #f
+               (door-traps door))
+        (kern-log-end "Trap detected!")
+        (kern-log-end "No traps detected!")
+        )))
+
+(define (door-describe kdoor count)
+  (let ((door (kobj-gob kdoor)))
+    (kern-log-continue "a ")
+    (if (door-magic-locked? door)
+        (kern-log-continue "magically locked, "))
+    (if (door-locked? door)
+        (if (door-needs-key? door)
+            (kern-log-continue "locked (with a key), ")
+            (kern-log-continue "padlocked, ")))
+    (if (door-open? door)
+        (kern-log-continue "open door ")
+        (kern-log-continue "closed door "))
+    (kern-log-continue "(")
+    (if (foldr (lambda (described? trap)
+                 (cond ((trap-detected? trap)
+                        (if described?
+                            (kern-log-continue ", "))
+                        (kern-log-continue (trap-name trap))
+                        (if (trap-tripped? trap)
+                            (kern-log-continue "[disarmed]"))
+                        #t)
+                       (else described?)))
+               #f
+               (door-traps door))
+        (kern-log-continue " trap(s) detected")
+        (kern-log-continue "no traps detected")
+        )
+    (kern-log-continue ")")
+    ))
+
+(define (door-get-unlock-dc kdoor)
+  (let ((val (door-locked? (kobj-gob kdoor))))
+    ;; make it backwards-compatible for old saved games where the value is a bool
+    (if (number? val)
+        val
+        (if val dc-normal 0))))
+
+(define (door-get-magic-unlock-dc kdoor)
+  (let ((val (door-magic-locked? (kobj-gob kdoor))))
+    ;; make it backwards-compatible for old saved games where the value is a bool
+    (if (number? val)
+        val
+        (if val dc-normal 0))))
+
+(define door-ifc
+  (ifc '()
+       (method 'exec door-exec)
+       (method 'handle door-handle)
+       (method 'open door-open)
+       (method 'close door-close)
+       (method 'init door-update-kstate)
+       (method 'connect door-connect)
+       (method 'lock door-lock)
+       (method 'unlock door-unlock)
+       (method 'magic-lock door-magic-lock)
+       (method 'magic-unlock door-magic-unlock)
+       (method 'add-trap door-add-trap)
+       (method 'get-traps door-get-traps)
+       (method 'rm-traps door-rm-traps)
+       (method 'use-key door-use-key)
+       (method 'search door-search)
+       (method 'describe door-describe)
+       (method 'get-unlock-dc door-get-unlock-dc)
+       (method 'get-magic-unlock-dc door-get-magic-unlock-dc)
+       ))
+
+;; Create the kernel "door" type
+(mk-obj-type 't_door "door" s_stone_arch layer-mechanism 
+             door-ifc)
+
+(define (door-state-factory
+                               arch-sprite door-sprite magic-sprite
+                               open-opacity closed-opacity
+                               open-pclass closed-pclass)
+       (mk-door-states
+               (mk-door-state (mk-composite-sprite (list arch-sprite door-sprite))
+                                       closed-opacity closed-pclass)
+               (mk-door-state arch-sprite      open-opacity open-pclass)
+               (mk-door-state (mk-composite-sprite (list arch-sprite door-sprite s_door_lock))
+                                       closed-opacity closed-pclass)
+               (mk-door-state (mk-composite-sprite (list arch-sprite door-sprite s_door_magiclock))
+                                       closed-opacity closed-pclass)
+       ))
+
+;; Types for common door types
+(define solid-wood-door-in-stone
+       (door-state-factory
+                       s_stone_arch s_door_wood s_door_magiclock
+                       #f #t
+                       pclass-none pclass-wall))
+
+(define windowed-wood-door-in-stone
+       (door-state-factory
+                       s_stone_arch s_door_windowed s_door_magiclock
+                       #f #f
+                       pclass-none pclass-window))
+
+(define solid-wood-door-in-rock
+       (door-state-factory
+                       s_rock_arch s_door_wood s_door_magiclock
+                       #f #t
+                       pclass-none pclass-wall))
+
+(define windowed-wood-door-in-rock
+       (door-state-factory
+                       s_rock_arch s_door_windowed s_door_magiclock
+                       #f #f
+                       pclass-none pclass-window))
+   
+;;----------------------------------------------------------------------------
+;; mk-door -- make and initialize a door object
+;;
+;; Used by the startup scripts when creating new doors.
+;;
+;;          type: one of the door state sets listed above
+;;        locked: true iff door starts out locked
+;;  magic-locked: true iff door starts out magically locked
+;;  connected-to: nil, or the tag of an object the door forwards signals to
+;;----------------------------------------------------------------------------
+(define (mk-door-full type locked? magic-locked? connected-to)
+  (bind (kern-mk-obj t_door 1)
+        (door-mk #f 0 connected-to #f locked? magic-locked? type)))
+
+;; Backward-compatible curried constructors
+(define (mk-door) (mk-door-full 'solid-wood-door-in-stone #f #f nil))
+(define (mk-door-in-rock) (mk-door-full 'solid-wood-door-in-rock #f #f nil))
+(define (mk-locked-door) (mk-door-full 'solid-wood-door-in-stone #t #f nil))
+(define (mk-locked-door-in-rock) (mk-door-full 'solid-wood-door-in-rock #t #f nil))
+(define (mk-connected-door tag) (mk-door-full 'solid-wood-door-in-stone #f #f tag))
+(define (mk-windowed-door) (mk-door-full 'windowed-wood-door-in-stone #f #f nil))
+(define (mk-windowed-door-in-rock) (mk-door-full 'windowed-wood-door-in-rock #f #f nil))
+(define (mk-magic-locked-door) (mk-door-full 'solid-wood-door-in-stone #f #t nil))
+(define (mk-locked-windowed-door) 
+  (mk-door-full 'windowed-wood-door-in-stone #t #f nil))
+(define (mk-locked-windowed-door-in-rock) 
+  (mk-door-full 'windowed-wood-door-in-rock #t #f nil))
+
+(define (lock-door-with-key kdoor key-type-tag)
+  (lock-door kdoor nil)
+  (door-set-key! (kobj-gob kdoor) key-type-tag)
+  )
+    
+
+;; Add a trap to a door
+(define (trap-door kdoor trap-tag)
+  (ifccall kdoor 'add-trap trap-tag)
+  kdoor
+  )
+  
+(mk-obj-type 't_archway_rock "archway" s_rock_arch layer-mechanism 
+             nil)
+
+(mk-obj-type 't_archway_stone "archway" s_stone_arch layer-mechanism 
+             nil)
+        
+(define (mk-archway-rock) (kern-mk-obj t_archway_rock 1))
+
+(define (mk-archway-stone) (kern-mk-obj t_archway_rock 1))
+
+
diff --git a/worlds/haxima-1.002/doris.scm b/worlds/haxima-1.002/doris.scm
new file mode 100644 (file)
index 0000000..bfad286
--- /dev/null
@@ -0,0 +1,196 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Green Tower.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_doris
+               (list 0  0  doris-bed "sleeping")
+               (list 8  0  white-stag-counter "working"))
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (doris-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Doris is the female innkeeper of the White Stag Lodge in Green Tower.
+;;----------------------------------------------------------------------------
+(define (doris-name kdoris kplayer)
+  (say kdoris "Hi, I'm Doris, innkeeper of the White Stag Lodge."))
+
+(define (doris-default)
+  (say kdoris "Let me think... nope, can't help you there."))
+
+(define (doris-join kdoris kplayer)
+  (say kdoris "[laughing] No thanks! I've got my hands full with the lodge."))
+
+(define (doris-doris knpc kpc)
+  (say knpc "Yep. That's me."))
+
+(define (doris-trade knpc kpc)
+  (let ((door (eval 'white-stag-door))
+        (price 15))
+    ;; is the room still open?
+    (if (not (door-locked? (kobj-gob door)))
+        ;; yes - remind player
+        (say knpc "Your room is still open, silly! You can use it as long as "
+             "you're in town.")
+        ;; no - ask if player needs a room
+        (begin
+          (say knpc "My room is " price " gold. I'll unlock the door and you "
+               "can use it for as long as you are in town. Agreed?")
+          (if (kern-conv-get-yes-no? kpc)
+              ;; yes - player agrees to the price
+              (let ((gold (kern-player-get-gold)))
+                ;; does player have enough gold?
+                (if (>= gold price)
+                    ;; yes - player has enough gold
+                    (begin
+                      (kern-player-set-gold (- gold price))
+                      (say knpc "Very well. Take the west passage. First room "
+                           "at the end of the hall.")
+                      (send-signal knpc door 'unlock)
+                      (kern-conv-end)
+                      )
+                    ;; no - player does not have enouvh gold)
+                    (say knpc "Seems you're short of funds. Why don't you "
+                         "walk around and kill things until you loot enough "
+                         "corpses? Or whatever you bold adventurers do. [She "
+                         "smiles a bit too sweetly]")))
+              ;; no - player does not want the room
+              (say knpc "Maybe some other time, then"))))))
+
+(define (doris-lodge knpc kpc)
+  (say knpc "Yep. It's all mine. It used to belong to my Daddy, God rest his "
+       "soul. Most of my customers are local folk, woodsman or travellers "
+       "wandering through."))
+
+(define (doris-daddy knpc kpc)
+  (say knpc "Daddy hunted and trapped his way to a small fortune then he "
+       "built this lodge. When he died, I got the lodge."))
+
+(define (doris-local knpc kpc)
+  (say knpc "The people here are varied, odd and secretive. They are also "
+       "trustworthy, competent and interesting. You will not find better "
+       "friends or worse enemies then the ones you make here."))
+
+(define (doris-woodsman knpc kpc)
+  (say knpc "Hunters, lumberjacks and foragers usually pass through here if "
+       "they are in the area. Wealthier sport hunters from the city take "
+       "lodging here, but usually those who work in the woods camp in the "
+       "woods. They come here for a bit of drink, company and a decent meal."))
+
+(define (doris-travelers knpc kpc)
+  (say knpc "Yes, folk like yourself."))
+
+(define (doris-gen knpc kpc)
+  (say knpc "An old goblin-fighter. Something of a local legend. You can "
+       "find him pottering around in the woods, and he usually stops in at "
+       "night for a drink."))
+
+(define (doris-deric knpc kpc)
+  (say knpc "Yes, Deric. Well, if you've met Deric then you know Deric. He's "
+       "competent enough but doesn't want to spend his life in the obscurity "
+       "of a frontier post."))
+
+(define (doris-shroom knpc kpc)
+  (say knpc "Some say she is a witch, and that she knows some goblin magic. "
+       "She certainly is handy when anyone falls ill. She often takes her "
+       "meals here."))
+
+(define (doris-abe knpc kpc)
+  (say knpc "Some kind of scholar from Glasdrin. He spends all his time "
+       "studying the ruins. Bookish fellow."))
+
+(define (doris-abigail knpc kpc)
+  (say knpc "She was orphaned, so I adopted her. I always wanted a child, "
+       "but that was not to be. I worry about her future... I know she "
+       "belongs among her own kind but I can't bear the thought of losing "
+       "her."))
+
+(define (doris-goblins knpc kpc)
+  (say knpc "They trade with the townsfolk, I even have one as a customer "
+       "from time-to-time. But they are forbidden by law to enter cities in "
+       "large numbers, so they're always outnumbered. Most of them are hasty "
+       "to conclude their business and get back into the woods."))
+
+(define (doris-orphaned knpc kpc)
+  (say knpc "Shroom brought her to me when she was just a baby. Said she "
+       "found her in the woods besides her dead parents. I don't know what - "
+       "or who - killed them, Shroom wouldn't say. Perhaps I don't want to "
+       "know."))
+
+(define (doris-hail knpc kpc)
+  (say knpc "Welcome to the White Stag"))
+
+(define (doris-bye knpc kpc)
+  (say knpc "Come back anytime"))
+
+(define (doris-default knpc kpc)
+  (say knpc "Can't help you there"))
+
+(define (doris-thie knpc kpc)
+  (say knpc "I haven't had any odd guests lately. Check with Deric, who gets "
+       "reports from ranger patrols. And Gen may have seen something in his "
+       "wanderings, too."))
+
+(define (doris-band knpc kpc)
+  (say knpc "Travelers have been complaining about them! "
+       "I wish Deric would do something, they're bad for business!"))
+
+(define doris-conv
+  (ifc green-tower-conv
+       (method 'band      doris-band)
+       (method 'hail      doris-hail)
+       (method 'bye       doris-bye)
+       (method 'default   doris-default)
+       (method 'name      doris-name)
+       (method 'room      doris-trade)
+       (method 'defa      doris-default)
+       (method 'job       doris-trade)
+       (method 'join      doris-join)
+       (method 'dori      doris-doris)
+       (method 'buy       doris-trade)
+       (method 'innk      doris-trade)
+       (method 'whit      doris-lodge)
+       (method 'stag      doris-lodge)
+       (method 'lodg      doris-lodge)
+       (method 'dadd      doris-daddy)
+       (method 'loca      doris-local)
+       (method 'wood      doris-woodsman)
+       (method 'trav      doris-travelers)
+       (method 'gen       doris-gen)
+       (method 'deri      doris-deric)
+       (method 'shro      doris-shroom)
+       (method 'abe       doris-abe)
+       (method 'abig      doris-abigail)
+       (method 'orph      doris-orphaned)
+       (method 'gobl      doris-goblins)
+       (method 'thie      doris-thie)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-doris tag)
+  (bind 
+   (kern-mk-char tag                 ; tag
+                 "Doris"             ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_townswoman   ; sprite
+                 faction-men         ; starting alignment
+                 0 1 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 2  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'doris-conv         ; conv
+                 sch_doris           ; sched
+                 'townsman-ai        ; special ai
+                 nil                 ; container
+                 (list t_dagger)     ; readied
+                 )
+   (doris-mk)))
diff --git a/worlds/haxima-1.002/douglas.scm b/worlds/haxima-1.002/douglas.scm
new file mode 100644 (file)
index 0000000..5054ef3
--- /dev/null
@@ -0,0 +1,138 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the Entrance to Kurpolis.
+;;----------------------------------------------------------------------------
+(define doug-bed ke-bed1)
+(define doug-mealplace ke-tbl1)
+(define doug-workplace ke-hall)
+(define doug-leisureplace ke-dine)
+(kern-mk-sched 'sch_doug
+               (list 0  0 doug-bed          "sleeping")
+               (list 11 0 doug-mealplace    "eating")
+               (list 12 0 doug-workplace    "working")
+               (list 18 0 doug-mealplace    "eating")
+               (list 19 0 doug-leisureplace "idle")
+               (list 24 0 doug-workplace    "working")               
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (doug-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Douglas is the Commander of the First Kurpolis Garrison,
+;; stationed at the Entrance to Kurpolis, guarding the Goblin Kingdoms level.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (doug-hail knpc kpc)
+  (say knpc "[You meet a grim paladin] Welcome to hell's doorstep, traveler.")
+  (if (and (in-player-party? 'ch_mesmeme)
+           (is-alive? ch_mesmeme))
+      (begin
+        (say knpc "[He points at Mesmeme] Are you taking that to the dungeon?")
+        (if (yes? kpc)
+            (say knpc "It's on the third level, below Paladin's Hold. "
+                 "But I don't think a prison will hold a gazer, "
+                 "it would be better to slay it.")
+            (say knpc "I've never seen a tame one. Beware it doesn't betray you.")))))
+
+(define (doug-default knpc kpc)
+  (say knpc "I cannot help you with that."))
+
+(define (doug-name knpc kpc)
+  (say knpc "I am Captain Douglas, commander of the First Kurpolis Garrison."))
+
+(define (doug-join knpc kpc)
+  (say knpc "And desert my post? I think not, and don't be asking my troopers, or I'll have you expelled back to the surface."))
+
+(define (doug-job knpc kpc)
+  (say knpc "I command this Garrison."))
+
+(define (doug-bye knpc kpc)
+  (say knpc "Be careful when traveling the deeps."))
+
+;; Special
+(define (doug-garr knpc kpc)
+  (say knpc "Glasdrin keeps this garrison here to suppress the monsters of Kurpolis. There's a second garrison deeper down."))
+
+(define (doug-mons knpc kpc)
+  (say knpc "At this level you find mostly goblins and trolls. Occasionally something worse comes up from the deeps."))
+
+(define (doug-gobl knpc kpc)
+  (say knpc "The cave goblins dominate this level. They are savage but ill-equipped. "
+       "There is also a grotto where you can find some forest goblins who are usually not as hostile. "
+       "The forest and cave goblins do not get along, which helps keep them under control."))
+
+(define (doug-trol knpc kpc)
+  (say knpc "The filthy creatures have a cave beyond the goblin village. "
+       "We clean them out from time to time but they just come back. "
+       "Sometimes I swear the rocks themselves must be giving birth to trolls."))
+
+(define (doug-wors knpc kpc)
+  (say knpc "The worst I've ever seen? The gazer. It had a clutch of slaves, some of them paladins. Men I once knew. [He shudders and turns away]")
+  (kern-conv-end)
+  )
+
+(define (doug-kurp knpc kpc)
+  (say knpc "Kurpolis is a breeding ground for monsters. We can't wipe them out, but we can keep a lid on things."))
+
+(define (doug-seco knpc kpc)
+  (say knpc "To get to the Second Garrison go east from here to the crossroads, then south and take the ladder down."))
+
+(define (doug-gaze knpc kpc)
+  (say knpc "A gazer is a creature from a nightmare. The old ones have the power to enslave other beings and force them to fight on their behalf."))
+
+(define doug-conv
+  (ifc kurpolis-conv
+
+       ;; basics
+       (method 'default doug-default)
+       (method 'hail doug-hail)
+       (method 'bye doug-bye)
+       (method 'job doug-job)
+       (method 'name doug-name)
+       (method 'join doug-join)
+
+       (method 'garr doug-garr)
+       (method 'mons doug-mons)
+       (method 'gobl doug-gobl)
+       (method 'trol doug-trol)
+       (method 'wors doug-wors)
+       (method 'kurp doug-kurp)
+       (method 'hell doug-kurp)
+       (method 'door doug-kurp)
+       (method 'seco doug-seco)
+       (method 'gaze doug-gaze)
+       ))
+
+(define (mk-douglas)
+  (bind 
+   (kern-mk-char 'ch_douglas        ; tag
+                 "Douglas"           ; name
+                 sp_human            ; species
+                 oc_warrior          ; occ
+                 s_companion_paladin ; sprite
+                 faction-men         ; starting alignment
+                 2 2 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 4  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'doug-conv         ; conv
+                 sch_doug           ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 (list t_armor_chain
+                       t_chain_coif
+                       t_sword
+                       ))         ; readied
+   (doug-mk)))
diff --git a/worlds/haxima-1.002/drawbridge.scm b/worlds/haxima-1.002/drawbridge.scm
new file mode 100644 (file)
index 0000000..54167dd
--- /dev/null
@@ -0,0 +1,28 @@
+;; Accessors - a drawbridge gob is simply its sprite in the 'on state
+(define (drawbridge-sprite-tag drawbridge) 
+  (display "drawbridge-sprite-tag drawbridge:")(display drawbridge)(newline)
+  drawbridge)
+
+;; Extend the bim interface to support the 'signal message
+(define (drawbridge-state on? kobj)
+  (let* ((bim (gob-data (kobj-gob kobj))))
+    (if on?
+        (state-mk (drawbridge-sprite-tag (bim-members bim)) #f pclass-bridge 0)
+        (state-mk nil #f pclass-none   0))))
+
+(define drawbridge-ifc
+  (ifc bim-ifc
+       (method 'signal bim-toggle)
+       (method 'state drawbridge-state)
+       ))
+
+;; Make a kernel drawbridge type
+(mk-obj-type 'TF_drawbridge "drawbridge" nil layer-tfeat drawbridge-ifc)
+
+;; Define a constructor
+(define (mk-drawbridge dir)
+  (case dir
+    ((north south) (bind (kern-mk-obj TF_drawbridge 1) 
+                         (bim-mk #f '() 's_ns_bridge)))
+    (else          (bind (kern-mk-obj TF_drawbridge 1) 
+                         (bim-mk #f '() 's_ew_bridge)))))
diff --git a/worlds/haxima-1.002/earl.scm b/worlds/haxima-1.002/earl.scm
new file mode 100644 (file)
index 0000000..57d2e3c
--- /dev/null
@@ -0,0 +1,111 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Trigrave"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_earl
+               (list 0  0  trigrave-earls-bed        "sleeping")
+               (list 5  0  trigrave-tavern-table-3a  "eating")
+               (list 6  0  trigrave-earls-counter    "working")
+               (list 12 0  trigrave-tavern-table-3a  "eating")
+               (list 13 0  trigrave-earls-counter    "working")
+               (list 18 0  trigrave-tavern-table-3a  "eating")
+               (list 19 0  trigrave-tavern-hall      "idle")
+               (list 20 0  trigrave-earls-room       "idle")
+               (list 21 0  trigrave-earls-bed        "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (earl-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Earl is a merchant, and will trade with the player if he's at work. 
+;; ...(removed some text which seems to have come from Jim.scm)...
+;;----------------------------------------------------------------------------
+(define earl-merch-msgs
+  (list "Come by my shop when I'm open. It's the Dry Goods store in the southwest corner, open from 6:00AM to 6:00PM."
+        "Here's what I have in stock right now."
+        "Well, ok, let me see what you have to offer."
+        "Step right up to the counter."
+        "Tell 'em you got it at Earl's."
+        "Just window-shopping? All right."
+        "I'll put this in the back and clean it up later."
+        "Come back later when you've got something else to offer, then."
+        "Finished already? Suit yourself."
+        "Let me know if there's anything else."
+   ))
+
+(define earl-catalog
+  (list
+   (list t_torch               5 "You don't want to run out of torches at the bottom of a dungeon.")
+   (list t_sling              50 "The sling is just the thing for cheapskates who don't want to buy ammo.")
+   (list t_staff              25 "A mage without a staff is like a dog without a bark.")
+   
+   (list t_heal_potion        22 "You want to keep plenty of these in your emergency kit.")
+   (list t_cure_potion        22 "Headed north? You'll want some of these when travelling the Fens.")
+   (list t_mana_potion        22 "This is just the thing when you're in a spot where you can't camp and your mages are exhausted.")
+   
+   (list t_arrow               1 "If you've got a bow then you can't have too many arrows.")
+   (list t_bolt                1 "I've got the least expensive bolts anywhere around.")
+   (list t_smoke_bomb          3 "Just throw these smoke bombs at enemy archers and they won't be able to see you.")
+   
+   (list t_shovel             50 "When you find that buried treasure you'll want a shovel to dig it up.")
+   (list t_pick               50 "A pick is essential for busting up boulders that block your path.")
+   
+   (list t_sextant           500 "You can figure your location anywhere in the wilderness with one of these without wasting any reagents or scrolls.")
+   (list t_chrono            300 "This little timepiece is invaluable when there aren't any clocks around.")
+   (list t_grease             23 "Wrogues seem to like this stuff. I'm afraid to ask why.")
+   ))
+
+(define (earl-trade knpc kpc) (conv-trade knpc kpc "trade" earl-merch-msgs earl-catalog))
+
+(define earl-conv
+  (ifc trigrave-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "I forgot.")))
+       (method 'hail (lambda (knpc kpc) (say knpc "Welcome, stranger.")))
+       (method 'bye (lambda (knpc kpc) (say knpc "Oh, were we talking? Bye.")))
+       (method 'job (lambda (knpc kpc) (say knpc "I keep the store. Need something?")
+                            (if (kern-conv-get-yes-no? kpc)
+                                (earl-trade knpc kpc)
+                                (say knpc "Okay."))))
+       (method 'name (lambda (knpc kpc) (say knpc "[He thinks for a minute] Earl! That's it!")))
+       (method 'buy (lambda (knpc kpc) (conv-trade knpc kpc "buy"  earl-merch-msgs earl-catalog)))
+       (method 'sell (lambda (knpc kpc) (conv-trade knpc kpc "sell"  earl-merch-msgs earl-catalog)))
+       (method 'trad earl-trade)
+       (method 'join (lambda (knpc kpc) (say knpc "You're too late! I forgot all my spells.")))
+
+       (method 'batt
+               (lambda (knpc kpc)
+                 (say knpc "Yep. I fought with Lord Calvin against the "
+                      "Goblin Horde!")))
+       (method 'calv
+               (lambda (knpc kpc)
+                 (say knpc "Now there was a warlord! Calvin conquered "
+                      "everything from the Gray Sea to the Northern Rim!")))
+       (method 'hord
+               (lambda (knpc kpc)
+                 (say knpc "In those days the Goblins were united under one "
+                      "chieftain, and threatened the whole Peninsula! By the "
+                      "time Lord Calvin was done with them they were scattered "
+                      "and hiding in the hills. They've never recovered!")))
+       (method 'mage
+               (lambda (knpc kpc)
+                 (say knpc "I've forgotten all my magic. I even lost my wand! "
+                      "I once knew spells that would slay whole armies.")))
+       (method 'spel
+               (lambda (knpc kpc) 
+                 (say knpc "I was a battle mage once. Long ago.")))
+       (method 'thie
+               (lambda (knpc kpc)
+                 (say knpc "I saw a stranger fleeing west! No, south! No... Oh, drat, I can't remember.")))
+       ))
diff --git a/worlds/haxima-1.002/eastpass.scm b/worlds/haxima-1.002/eastpass.scm
new file mode 100644 (file)
index 0000000..0cb2bef
--- /dev/null
@@ -0,0 +1,38 @@
+(mk-tower
+ 'p_eastpass "Eastpass"
+       (list
+               ".. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. {5 {{ {{ {{ {{ xx ,, xx {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. {4 {{ {{ {{ {{ w+ ,, w+ {5 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. .. {1 {1 {1 {1 xx ,, xx .. {1 {5 {{ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. .. .. .. xx xx xx ,, xx xx xx {4 {{ {{ ^^ ^^ ^^ ^^ "
+               ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. {5 {{ {{ ^^ ^^ ^^ "
+               ".. .. .. .. .. x! ,, ,, ,, ,, ,, x! .. .. {5 {{ {{ ^^ ^^ "
+               ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. .. .. {5 {{ {{ ^^ "
+               ".. .. .. .. .. ,, ,, ,, ,, ,, ,, ,, .. .. .. .. {d {{ ^^ "
+               ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. .. .. {c {{ {{ ^^ "
+               ".. .. .. .. .. x! ,, ,, ,, ,, ,, x! .. .. {4 {{ {{ ^^ ^^ "
+               ".. .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. .. {c {{ ^^ ^^ ^^ "
+               ".. .. .. .. .. xx xx xx ,, xx xx xx .. {c {{ {{ ^^ ^^ ^^ "
+               ".. .. .. .. .. .. .. xx ,, xx .. .. {c {{ {{ ^^ ^^ ^^ ^^ "
+               ".. .. .. {8 {8 {8 {8 w+ ,, w+ {8 {c {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               ".. .. {c {{ {{ {{ {{ xx ,, xx {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. {4 {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               ".. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+       )
+       nil
+ (put (mk-ladder-down 'p_westpass 4 14) 14 9)
+ (put (mk-windowed-door) 11 9)
+ (put (mk-windowed-door)  5 9)
+
+ (put (guard-pt 'knight)  7 8)
+ (put (guard-pt 'knight)  9 10)
+ (put (guard-pt 'squire)  7 10)
+ (put (guard-pt 'squire)  9 8)
+
+ (put (spawn-pt 'bandit) 3 8)
+ (put (spawn-pt 'bandit) 4 9)
+ )
+
+(mk-place-music p_eastpass 'ml-castle)
diff --git a/worlds/haxima-1.002/edge-spawn.scm b/worlds/haxima-1.002/edge-spawn.scm
new file mode 100644 (file)
index 0000000..879e50a
--- /dev/null
@@ -0,0 +1,54 @@
+
+(define (edge-spawn-exec kwm)
+
+  ;;(println "edge-spawn-exec")
+
+  (define (get-ptype loc)
+    (println "get-ptype:" loc)
+    (terrain-to-ptype (kern-place-get-terrain loc)
+                      (mean-player-party-level)))
+
+  (define (try-to-spawn-at loc)
+    (let ((ptype (get-ptype loc)))
+      ;;(println " try-to-spawn-at:ptype=" ptype)
+      (if (not (null? ptype))
+          (let ((kparty (ptype-generate ptype)))
+            ;; note: must put the party on the map (thus giving it a refcount)
+            ;; before setting ttl
+            ;; FIXME: what if loc is invalid? will put-at fail? will ttl then crash?
+            (kern-obj-put-at kparty loc)
+            (kern-obj-set-ttl kparty 50)
+            ))))
+
+  (define (pick-edge-tile)
+    (let* ((ww 9)
+           (wh 9)
+           (ploc (kern-obj-get-location (kern-get-player)))
+           (kplace (loc-place ploc))
+           (x (loc-x ploc))
+           (y (loc-y ploc)))
+      (case (modulo (random-next) 4)
+        ((0) (random-loc kplace (- x ww) (- y wh) (+ 1 (* 2 ww)) 1)) ; north
+        ((1) (random-loc kplace (- x ww) (+ y wh) (+ 1 (* 2 ww)) 1)) ; south
+        ((2) (random-loc kplace (+ x ww) (- y wh) 1 (+ 1 (* 2 wh)))) ; east
+        ((3) (random-loc kplace (- x ww) (- y wh) 1 (+ 1 (* 2 wh)))) ; west
+        )))
+
+  (define (roll-to-spawn?) 
+    (>= (modulo (random-next) 100) 98))
+
+  (if (and (kern-place-is-wilderness? (loc-place (kern-obj-get-location (kern-get-player))))
+           (roll-to-spawn?))
+      (try-to-spawn-at (pick-edge-tile)))
+
+  )
+
+(define edge-spawn-ifc
+  (ifc nil
+       (method 'exec edge-spawn-exec)))
+
+(mk-obj-type 't_edge_spawn nil nil layer-none edge-spawn-ifc)
+
+(define (mk-edge-spawn-generator)
+  (kern-obj-set-visible (kern-mk-obj t_edge_spawn 1) #f)
+  )
diff --git a/worlds/haxima-1.002/edward.scm b/worlds/haxima-1.002/edward.scm
new file mode 100644 (file)
index 0000000..4d59f7c
--- /dev/null
@@ -0,0 +1,211 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define edward-start-lvl 4)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; In the dungeons below Green Tower.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_edward
+               (list 0  0  gtl-jailor-bed "sleeping")
+               (list 7  0  gtl-jail       "working" )
+               (list 21 0  gtl-jailor-bed "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (edward-mk) (list #f #f))
+(define (edward-met? gob) (car gob))
+(define (edward-meet! gob) (set-car! gob #t))
+(define (edward-has-nate? gob) (cadr gob))
+(define (edward-has-nate! gob) (set-car! (cdr gob) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Edward is a old blind man, serving as the jailor 
+;; in the dungeons below Green Tower.
+;;----------------------------------------------------------------------------
+(define (edward-hail knpc kpc)
+  (meet "You meet a pale old man whose eyes are milky white.")
+  (let ((edward (kobj-gob-data knpc)))
+    (cond ((not (edward-met? edward))
+           (say knpc "Who goes there?")
+           (reply? kpc)
+           (edward-meet! edward)
+           (say knpc "I don't know you. Are you hear to make a jail-break?")
+           (if (yes? kpc)
+               (say knpc "Well get on with it! I'm too old to stop you.")
+               (say knpc "That's a relief. I'd have no-one to talk to.")
+               )
+           )
+          (else
+           (say knpc "Welcome back. I remember your footfalls.")
+           ))))
+
+(define (edward-give-nate knpc kpc)
+  (say knpc "Are you delivering a prisoner?")
+  (cond ((yes? kpc)
+         (cond ((is-only-living-party-member? ch_nate)
+                (say knpc "Turn yourself in if you like, "
+                     "but get rid of that dead body first! "
+                     "This isn't a morgue.")
+                )
+               (else
+                (say knpc "Oh, good. More company. [He takes Nate into custody and "
+                     "locks him in a cell]")
+                (kern-char-leave-player ch_nate)
+                (kern-obj-relocate ch_nate (mk-loc p_green_tower_lower 9 10) nil)
+                (prompt-for-key)
+                (say knpc "Here's your receipt, in case the Captain wants it.")
+                (give (kern-get-player) t_prisoner_receipt 1)
+                (edward-has-nate! (kobj-gob-data knpc))
+                (quest-data-update-with 'questentry-bandits 'nate-given-to-jailor 1 (quest-notify nil))                
+                )))
+        (else
+         (say knpc "Hokay. [He gives Nate a look, then shrugs]")
+         )))
+
+(define (edward-pris knpc kpc)
+  (cond ((in-player-party? 'ch_nate) (edward-give-nate knpc kpc))
+        (else
+         (let ((edward (kobj-gob-data knpc)))
+           (if (edward-has-nate? edward)
+               (say knpc "I've got a forest goblin and that fellow you brought in.")
+               (say knpc "I've just got a forest goblin right now. "
+                    "He and I can't understand each other, "
+                    "but that doesn't stop us from swapping stories."))))
+        ))
+
+(define (edward-gobl knpc kpc)
+  (say knpc "I'm not afraid of them. They never done me no harm."))
+
+(define (edward-stor knpc kpc)
+  (say knpc "Have you heard the one about Will-o-the-Woods?")
+  (cond ((no? kpc)
+         (say knpc "Will-o-the-Woods was a spirit that used to haunt these woods, "
+              "in the old days when the gates worked and the gods were honored. ")
+         (prompt-for-key kpc)
+         (say knpc "If a pretty maiden ventured into the woods alone, "
+              "he would appear as a handsome woodsman or ranger, "
+              "and entice her back to his sacred grove. "
+              "There, he would turn her into a tree. ")
+         (prompt-for-key kpc)
+         (say knpc "That's how the Great Wood got its beginning, in his grove. "
+              "And that's why you find so many haunted trees in the woods even to this day.")
+         )
+        (else
+         (say knpc "No one knows what become of Will-o-the-Woods. "
+              "Passed into legend like the other gods, I suppose.")
+         )))
+
+(define (edward-gate knpc kpc)
+  (say knpc "I don't know anything about them. They used to work, that's all I know."))
+
+(define (edward-gods knpc kpc)
+  (say knpc "It's not a good idea to talk about the old gods. "
+       "Folks might think us Accursed if they were to overhear."))
+
+(define (edward-accu knpc kpc)
+  (say knpc "The Accursed seek power from the old gods... and other things. "
+       "I've had a few in my jail."))
+
+(define (edward-talk knpc kpc)
+  (say knpc "The prisoners are the only ones I can talk to down here."))
+
+(define (edward-blin knpc kpc)
+  (say knpc "The dark doesn't bother me. Neither does the light, for that matter. "
+       "It's all the same to me."))
+
+(define (edward-guar knpc kpc)
+  (say knpc "Truth be told, I'm not much of a guard."))
+
+(define (edward-jail knpc kpc)
+  (cond ((in-player-party? 'ch_nate) (edward-give-nate knpc kpc))
+        (else
+         (say knpc "I feed the prisoners and swap stories with them. "
+              "I'm supposed to guard them, too. Prevent escapes.")
+         )))
+
+(define edward-conv
+  (ifc ranger-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default 
+               (lambda (knpc kpc) 
+                 (say knpc "[He shrugs]")))
+       (method 'hail edward-hail)
+       (method 'bye 
+               (lambda (knpc kpc) 
+                 (say knpc "Watch your step in the dark!")))
+       (method 'job 
+               (lambda (knpc kpc) 
+                 (say knpc "I'm the jailor.")))
+       (method 'name 
+               (lambda (knpc kpc) 
+                 (say knpc "I am Edward. And you already told me your name.")))
+       (method 'join 
+               (lambda (knpc kpc) 
+                 (say knpc "Love to. [But he doesn't]")))
+       (method 'accu edward-accu)
+       (method 'blin edward-blin)
+       (method 'esca edward-guar)
+       (method 'gate edward-gate)
+       (method 'gobl edward-gobl)
+       (method 'god  edward-gods)
+       (method 'gods edward-gods)
+       (method 'guar edward-guar)
+       (method 'jail edward-jail)
+       (method 'old  edward-gods)
+       (method 'pris edward-pris)
+       (method 'stor edward-stor)
+       (method 'talk edward-talk)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-edward)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_edward ;;..........tag
+     "Edward" ;;.......name
+     sp_human ;;.....species
+     oc_ranger ;;.. .occupation
+     s_old_townsman ;;..sprite
+     faction-men ;;..faction
+     0 ;;...........custom strength modifier
+     0 ;;...........custom intelligence modifier
+     0 ;;...........custom dexterity modifier
+     0 ;;............custom base hp modifier
+     0 ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     edward-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'edward-conv ;;...conversation (optional)
+     sch_edward ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+
+     ;;..............container (and contents)
+     (mk-inventory
+      (list
+       (list 1 t_torch)
+       (list 1 t_dagger)
+       ))
+     (list t_armor_leather)                ; readied ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (edward-mk)))
diff --git a/worlds/haxima-1.002/effects.png b/worlds/haxima-1.002/effects.png
new file mode 100644 (file)
index 0000000..29d06e6
Binary files /dev/null and b/worlds/haxima-1.002/effects.png differ
diff --git a/worlds/haxima-1.002/effects.scm b/worlds/haxima-1.002/effects.scm
new file mode 100644 (file)
index 0000000..d5ed561
--- /dev/null
@@ -0,0 +1,1001 @@
+;; ----------------------------------------------------------------------------
+;; effects.scm - generic effects procedures used in multiple places
+;; ----------------------------------------------------------------------------
+
+;; Hook ids. These must agree with the kernel.
+(define start-of-turn-hook 0)
+(define add-hook-hook      1)
+(define on-damage-hook     2)
+(define keystroke-hook     3)
+(define nil-hook           4)
+(define on-death-hook      5)
+(define ready-equip-hook   6)
+(define unready-equip-hook 7)
+(define move-done-hook     8)
+(define attack-done-hook   9)
+(define cast-done-hook     10)
+(define drop-done-hook     11)
+(define yuse-done-hook     12)
+(define get-done-hook      13)
+(define handle-done-hook   14)
+(define open-done-hook     15)
+(define ready-done-hook    16)
+(define talk-done-hook     17)
+(define use-done-hook      18)
+(define mix-done-hook      19)
+(define kamp-start-hook    20)
+
+(define (mk-effect tag name sprite exec apply rm restart hook sym ddc cum dur)
+  (kern-mk-effect tag 
+                  name
+                  sprite
+                  exec 
+                  apply 
+                  rm 
+                  restart
+                  hook 
+                  ddc 
+                  cum 
+                  dur
+                  ))
+
+;; apply-time-scaled damage account for damaging effects applied at wilderness
+;; scale or when camping or loitering. At higher time scales I think it's not
+;; so nice to kill characters in one turn by applying the full damage for the
+;; time scale. However, you have to apply *some* extra damage or its
+;; incongruent.
+(define (time-scaled-damage-factor)
+  (if (> (kern-ticks-per-turn) 1)
+      10
+      1))
+
+(define (poison-exec fgob obj)
+  (if (obj-is-char? obj)
+      (kern-obj-apply-damage obj "poisoned" (* 1 (time-scaled-damage-factor)))))
+
+;; ------------------------------------------------------------------
+;; Accumulating duration effects support
+;; Should probably have a 'remove from list', but
+;; it might be a better way elsewhere anyway
+;; -------------------------------------------------------------------
+
+(define (effect-list-lookup-loop fxlist target)
+       (if (null? fxlist)
+               nil
+               (if (equal? (caar fxlist) target)
+                       (cadar fxlist)
+                       (effect-list-lookup-loop (tail fxlist) target)
+               )))
+               
+(define (effect-list-lookup fxlist target)
+       (let ((result (effect-list-lookup-loop (tail fxlist) target)))
+               (if (null? result)
+                       (car (cdr (car (tail (set-cdr! fxlist (append (list (list target (list 0))) (tail fxlist)))))))
+                       result
+               )))
+
+;; ----------------------------------------------------------------------------
+;; Poison & Disease Immunities
+;;
+;; These work by attaching an effect to the "add-hook-hook", which runs
+;; whenever any new effect is applied. If anything tries to apply a poison
+;; effect, for example, the poison immunity effect will catch it and block the
+;; application.
+;; ----------------------------------------------------------------------------
+(define (poison-immunity-exec fgob effect)
+  (if (eqv? effect ef_poison) #t #f))
+
+(define (disease-immunity-exec fgob effect)
+  (if (eqv? effect ef_disease) #t #f))
+
+(define (paralysis-immunity-exec fgob effect)
+  (if (eqv? effect ef_paralyze) #t #f))
+
+(define (charm-immunity-exec fgob effect)
+  (if (eqv? effect ef_charm) #t #f))
+
+(define (sleep-immunity-exec fgob effect)
+  (if (eqv? effect ef_sleep) #t #f))
+
+;; ----------------------------------------------------------------------------
+;; sleep
+;;
+;; The sleep effect is largely implemented in the kernel, and applies only to
+;; character types. It expires naturally when the character makes a saving
+;; throw. Note that this sleep effect is completely different than camping or
+;; resting, which is managed entirely by the kernel.
+;; ----------------------------------------------------------------------------
+(define (sleep-exec fgob kobj)
+  (if (not (obj-is-char? kobj))
+      (kern-obj-remove-effect kobj ef_sleep)
+      (let ((kchar kobj))
+        (if (> (kern-dice-roll "1d20")
+               19)
+            (begin
+              (kern-obj-remove-effect kchar ef_sleep)
+              (kern-char-set-sleep kchar #t) ;; shouldn't this be #f?
+              )))))
+    
+(define (sleep-reset fgob kobj)
+  (if (obj-is-char? kobj)
+     (kern-char-set-sleep kobj #t)))
+
+(define (sleep-rm fgob kobj)
+  (if (obj-is-char? kobj)
+      (kern-char-set-sleep kobj #f)))
+
+;; ----------------------------------------------------------------------------
+;; paralyze
+;;
+;; The paralyze effect rolls to expire each turn. If the roll fails, the
+;; character loses its turn. If it succeeds, the effect removes itself from the
+;; character. Treats a natural roll of 20 as success.
+;; ----------------------------------------------------------------------------
+(define (can-paralyze? kobj)
+  (and (obj-is-char? kobj)
+       (not (species-is-immune-to-paralyze? (kern-char-get-species kobj)))))
+
+(define (paralyze-apply fgob kobj)
+  (kern-log-msg (kern-obj-get-name kobj) " paralyzed!"))
+
+(define (paralyze-exec fgob kobj)
+  (if (not (obj-is-char? kobj))
+      (kern-obj-remove-effect kobj ef_paralyze)
+      (let ((kchar kobj)
+            (droll (kern-dice-roll "1d20")))
+        (if (or (= droll 20)
+                (> droll
+                   dc-escape-paralyze))
+            (begin
+              (kern-log-msg "Paralysis wears off of " (kern-obj-get-name kchar))
+              (kern-obj-remove-effect kchar ef_paralyze)
+              (if (is-player-party-member? kobj)
+                  (kern-char-set-player-controlled kobj #t))
+              #f)
+            (begin
+             (kern-log-msg "** " (kern-obj-get-name kchar) " remains paralyzed! **")
+              (kern-obj-set-ap kchar 0)
+              #f)))))
+
+
+(define (paralyze kobj)
+  (if (can-paralyze? kobj)
+      (begin
+        (kern-obj-add-effect kobj ef_paralyze nil)
+        (kern-char-set-player-controlled kobj #f)
+        )))
+
+;;----------------------------------------------------------------------------
+;; disease
+;;
+;; Drains life until victim is near death
+;;----------------------------------------------------------------------------
+(define (disease-exec fgob kobj)
+  (if (not (obj-is-char? kobj))
+      (kern-obj-remove-effect kobj ef_disease)
+      (let ((kchar kobj))
+        (let ((dmgroll (* (time-scaled-damage-factor) 
+                          (kern-dice-roll "1d5")))
+              (maxdmg (- (kern-char-get-hp kchar) 
+                         (kern-dice-roll "1d10"))))
+          (cond ((> dmgroll maxdmg)
+                 (kern-log-msg (kern-obj-get-name kchar) " fights off Disease")
+                 (kern-obj-apply-damage kchar "disease" maxdmg)
+                 (kern-obj-remove-effect kchar ef_disease)
+                 )
+                (else
+                 (kern-obj-apply-damage kchar "disease" dmgroll)))))))
+
+;; ----------------------------------------------------------------------------
+;; ensnare
+;;
+;; The ensnare effect rolls against a character's strength each turn. If the
+;; roll fails, the character loses its turn. If it succeeds, the effect removes
+;; itself from the character. Also treat a natural roll of 20 as success.
+;; ----------------------------------------------------------------------------
+(define (can-ensnare? kobj)
+  (and (obj-is-char? kobj)
+       (not (species-is-immune-to-ensnare? (kern-char-get-species kobj)))))
+
+(define (ensnare-apply fgob kobj)
+  (kern-log-msg (kern-obj-get-name kobj) " stuck in web!"))
+
+(define (ensnare-exec fgob kobj)
+  (println "ensnare-exec")
+  (if (not (can-ensnare? kobj))
+      (kern-obj-remove-effect ef_ensnare)
+      (let ((kchar kobj)
+            (droll (kern-dice-roll "1d20")))
+        ;; special case -- paralysis prevents struggling against the ensnare
+        (if (not (is-paralyzed? kchar))
+            (if (or (= droll 20)
+                    (> (+ (kern-char-get-strength kchar) 
+                          droll)
+                       dc-escape-ensnare))
+                (let ((loc (kern-obj-get-location kobj)))
+                  (kern-log-msg (kern-obj-get-name kchar) " breaks free of web!")
+                  (kern-obj-remove-effect kchar ef_ensnare)
+                  (map kern-obj-remove-web (find-object-types-at loc web-type))
+                  (map kern-obj-remove-web (find-object-types-at loc F_web_perm))
+                  #t)
+                (begin
+                  (kern-log-msg (kern-obj-get-name kchar) " struggles in the web!")
+                  (kern-obj-set-ap kchar 0)
+                  #f))))))
+
+(define (is-ensnared? kobj)
+  (in-list? ef_ensnare (kern-obj-get-effects kobj)))
+
+(define (ensnare kobj)
+  (if (can-ensnare? kobj)
+      (begin
+        (kern-obj-add-effect kobj ef_ensnare nil))))
+
+;; ----------------------------------------------------------------------------
+;; Stuck
+;;
+;; Like ensnare, but no webs involved, and the thiefly ability is used to roll
+;; free. This was added as a risk balance for the wriggle skill.
+;; ----------------------------------------------------------------------------
+(define (stuck-apply fgob kobj)
+  (kern-log-msg (kern-obj-get-name kobj) " stuck!"))
+
+(define (stuck-exec fgob kobj)
+  (cond ((check-roll dc-escape-stuck (occ-thief-dice-roll kobj))
+         (kern-log-msg (kern-obj-get-name kobj) " wriggles free!")
+         (kern-obj-remove-effect kobj ef_stuck)
+         #t
+         )
+        (else
+         (kern-log-msg (kern-obj-get-name kobj) " struggles!")
+         (kern-obj-set-ap kobj 0)
+         #f
+         )))
+
+(define (is-stuckd? kobj)
+  (in-list? ef_stuck (kern-obj-get-effects kobj)))
+
+(define (stuck kobj)
+  (if (can-stuck? kobj)
+      (begin
+        (kern-obj-add-effect kobj ef_stuck nil))))
+
+
+;;----------------------------------------------------------------------------
+;; poison immunity
+(define (has-poison-immunity? kobj)
+  (let ((effects (kern-obj-get-effects kobj)))
+    (or (in-list? ef_poison_immunity effects)
+        (in-list? ef_temporary_poison_immunity effects))))
+
+;;----------------------------------------------------------------------------
+;; fire immunity
+(define (has-fire-immunity? kobj)
+  (let ((effects (kern-obj-get-effects kobj)))
+    (or (in-list? ef_fire_immunity effects)
+        (in-list? ef_temporary_fire_immunity effects))))
+
+;;----------------------------------------------------------------------------
+;; magical kill immunity
+(define (has-magical-kill-immunity? kobj)
+  (let ((effects (kern-obj-get-effects kobj)))
+    (or (in-list? ef_magical_kill_immunity effects)
+        (in-list? ef_temporary_magical_kill_immunity effects))))
+
+(define (has-sleep-immunity? kobj)
+  (let ((effects (kern-obj-get-effects kobj)))
+    (or (in-list? ef_sleep_immunity effects)
+        (in-list? ef_temporary_sleep_immunity effects))))
+        
+(define (has-charm-immunity? kobj)
+  (let ((effects (kern-obj-get-effects kobj)))
+    (or (in-list? ef_charm_immunity effects)
+        (in-list? ef_temporary_charm_immunity effects))))
+
+;; ----------------------------------------------------------------------------
+;; light
+;;
+;; Light works by increasing the effected object's light value when the effect
+;; is applied, and decreasing it when the effect is removed. It does this in a
+;; two-step process. The first step is an effect which runs on the special
+;; ----------------------------------------------------------------------------
+
+(define temp-light-power (list 0))
+
+(define (temp-light-power-set power)
+       (set-car! temp-light-power power))
+
+(define (light-rm fgob kobj)
+  (kern-log-msg "Light spell wore off")
+  (kern-obj-dec-light kobj (caar fgob))
+  (temp-light-power-set (caar fgob)))
+
+(define (light-apply fgob kobj)
+       (kern-obj-inc-light kobj (caar fgob))
+       )
+
+;a function with a working power->time calculation would be nicer
+(define (light-effect-getdecr current)
+       (if (< current 300)
+               50
+               (if (< current 600)
+                       5
+                       (floor (/ current 20))
+       )))
+
+(define (light-dim power light-time current-time kobj)
+       (if (<= current-time light-time)
+               power
+               (let ((decrlight (light-effect-getdecr power)))
+                       (if (> decrlight power)
+                               0
+                               (light-dim (- power decrlight) (+ light-time 1) current-time kobj)
+                       ))))
+
+(define (light-exec fgob kobj)
+       (let* ((light-time (cadar fgob))
+               (current-time (kern-get-total-minutes))
+               (power (caar fgob))
+               (newpower (light-dim power light-time current-time kobj)))
+               (cond ((= newpower power) nil)
+                       ((<= newpower 0) (kern-obj-remove-effect kobj ef_light))
+                       (else
+                               (set-car! fgob (list newpower (kern-get-total-minutes)))
+                               (kern-obj-dec-light kobj (- power newpower))
+                               ))))
+
+(define (light-apply-new target power)
+       (temp-light-power-set 0)
+       (kern-log-enable #f)
+       (kern-obj-remove-effect target ef_light)
+       (kern-log-enable #t)
+       (let ((fxgob (list (list (+ power (car temp-light-power)) (kern-get-total-minutes)))))
+               (kern-obj-add-effect target ef_light fxgob)
+       ))
+       
+;; ----------------------------------------------------------------------------
+;; torchlight
+;;
+;; This is just like light but it's called out especially because it's
+;; vulnerable to the douse effect, where as normal light is not.
+;; ----------------------------------------------------------------------------
+(define torchlight-amount 1024)
+
+(define (torchlight-rm fgob kobj)
+  (kern-log-msg "A torch flickers out!")
+  (kern-obj-dec-light kobj torchlight-amount))
+
+(define (torchlight-apply fgob kobj)
+  (kern-obj-inc-light kobj torchlight-amount)
+  ;; Lighting up a torch will undo stealth mode
+  (kern-obj-remove-effect kobj ef_stealth)
+  )
+
+;; ----------------------------------------------------------------------------
+;; Weak light
+;;
+;; A silent, weak version of torchlight for NPCs.
+;; ----------------------------------------------------------------------------
+(define weaklight-amount 256)
+
+(define (weaklight-rm fgob kobj)
+  (kern-obj-dec-light kobj weaklight-amount))
+
+(define (weaklight-apply fgob kobj)
+  (kern-obj-inc-light kobj weaklight-amount))
+
+;; ----------------------------------------------------------------------------
+;; Protection
+;;
+;; Used by the In Sanct spell.
+;; ----------------------------------------------------------------------------
+(define (protection-rm fgob kobj)
+  (if (obj-is-char? kobj)
+      (kern-char-add-defense kobj -10)))
+
+(define (protection-apply fgob kobj)
+  (if (obj-is-char? kobj)
+      (kern-char-add-defense kobj 10)))
+
+;; ----------------------------------------------------------------------------
+;; Charm
+;;
+;; Used by the An Xen Ex spell.
+;; ----------------------------------------------------------------------------
+(define (charm-mk faction) (list faction))
+
+(define (charm-faction charm) (car charm))
+
+(define (charm-rm charm kchar)
+  (cond ((obj-is-char? kchar)
+         (kern-being-set-current-faction kchar (kern-being-get-base-faction kchar))
+         (if (is-player-party-member? kchar)
+             (kern-char-set-player-controlled kchar #t))
+         (kern-log-msg (kern-obj-get-name kchar) " recovers from charm!")
+        )))
+
+(define (charm-apply charm kchar)
+  (cond ((obj-is-char? kchar)
+         (kern-log-msg (kern-obj-get-name kchar) " is charmed!")
+         (kern-char-set-player-controlled kchar #f)
+         (kern-being-set-current-faction kchar (charm-faction charm))
+         )))
+
+;; ----------------------------------------------------------------------------
+;; Loot Drop
+;;
+;; Used to generate loot when an NPC is killed. The hook-fx given to the gob is
+;; executed when the effect runs, taking the unfortunate npc as its parm.
+;; ----------------------------------------------------------------------------
+(define (loot-drop-mk hook-fx . hook-fx-parms) (list 'loot-drop-gob hook-fx hook-fx-parms))
+
+(define (loot-drop-hook-fx gob) (cadr gob))
+(define (loot-drop-hook-fx-parms gob) (caddr gob))
+
+(define (loot-drop-exec fgob kobj)
+  (if (not (obj-is-char? kobj))
+      (kern-obj-remove-effect kobj ef_loot_drop)
+      (let ((kchar kobj))
+        (apply (eval (loot-drop-hook-fx fgob)) 
+               (cons kchar
+                     (loot-drop-hook-fx-parms fgob))))))
+
+;; ----------------------------------------------------------------------
+;; Generic death
+;; Just does some arbitary named closure
+;; (kern-obj-add-effect npc 
+;;           ef_generic_death
+;;           'a_closure_name)
+;; --------------------------------------------------------------------
+
+(define (generic-death-exec fgob kobj)
+  (if (not (obj-is-char? kobj))
+      (kern-obj-remove-effect kobj ef_loot_drop)
+      ((eval fgob) kobj)
+   ))      
+
+;; ----------------------------------------------------------------------------
+;; Invisibility
+;;
+;; Used by the Sanct Lor spell. Note: the kernel's kern-obj-set-visible proc
+;; increments/decrements a visibility counter, naturally handling cumulative
+;; invisibility effects.
+;; ----------------------------------------------------------------------------
+(define (invisibility-rm fgob kobj)
+  (kern-obj-set-visible kobj #t))
+
+(define (invisibility-apply fgob kobj)
+  (kern-obj-set-visible kobj #f))
+
+;; ----------------------------------------------------------------------------
+;; Stealth
+;;
+;; Used by the Stealth skill. Similar to invisibility, but it decrements MP on
+;; every turn. Also, on anything that involves movement it rolls to remove
+;; itself.
+;; ----------------------------------------------------------------------------
+(define (stealth-apply fgob kobj)
+  (kern-obj-set-visible kobj #f)
+  (map (lambda (x) (kern-obj-add-effect kobj x nil))
+       stealth-co-effects))
+
+;; Helper for the misc stealth effects
+(define (stealth-exec-generic kobj dc)
+  (let ((roll (kern-dice-roll "1d20"))
+        (bonus (occ-thief-dice-roll kobj))
+        (bonus2 (kern-char-get-level kobj))
+        )
+    ;;(println "stealth:" roll "+" bonus "+" bonus2 ">?" dc)
+    (if (< (+ roll bonus bonus2) dc)
+        (kern-obj-remove-effect kobj ef_stealth)
+        )))
+  
+(define (stealth-exec fgob kobj)
+  ;; hack -- add the yuse-done hook now instead of in stealth-apply
+  ;; application. Otherwise, as soon as the player y)uses stealth, the
+  ;; yuse-done hook immediately runs and potentially removes stealth mode.
+  (stealth-exec-generic kobj dc-nontrivial)
+  (if (not (has-effect? kobj ef_stealth_yuse))
+      (kern-obj-add-effect kobj ef_stealth_yuse nil))
+  )
+
+(define (stealth-rm fgob kobj)
+  (kern-obj-set-visible kobj #t)
+  (map (lambda (x) (kern-obj-remove-effect kobj x))
+       stealth-co-effects)
+  ;; And treat yuse as a special case
+  (kern-obj-remove-effect kobj ef_stealth_yuse)
+  (kern-log-msg (kern-obj-get-name kobj) " goes out of stealth mode!")
+  )
+
+;; At basic skill levels any movement will undo stealth mode. As the character
+;; advances its ability to remain hidden while moving increases naturally. With
+;; a DC of 16, An L3 wrogue with dexterity 10 will give itself away with
+;; movement about 50% of the time.
+(define (stealth-do-simple-exec fgob kobj)
+  (stealth-exec-generic kobj dc-nontrivial))
+
+(define (stealth-move-exec fgob kobj kplace x y)
+  (stealth-exec-generic kobj dc-normal))
+
+(define (stealth-do-challenging-exec fgob kobj)
+  (stealth-exec-generic kobj dc-challenging))
+
+(define (stealth-do-masterful-exec fgob kobj)
+  (stealth-exec-generic kobj dc-masterful))
+
+(define (stealth-attack-exec fgob kobj kweap ktarg)
+  (stealth-exec-generic kobj dc-challenging))
+
+(define (stealth-do-impossible-exec fgob kobj)
+  (kern-obj-remove-effect kobj ef_stealth))  
+
+;; ----------------------------------------------------------------------------
+;; Slime Split
+;;
+;; A special feature of the slime species. When a slime takes damage it rolls
+;; to clone itself.
+;; ----------------------------------------------------------------------------
+(define (split-gob-mk npc-type-tag) (list npc-type-tag))
+(define (split-gob-npc-type-tag gob) (car gob))
+
+(define (split-exec fgob kobj)
+  (let ((loc (kern-obj-get-location kobj)))
+    (if (not (kern-place-is-wilderness? (loc-place loc)))
+        (begin
+          ;; eight is too low
+          (if (> (kern-dice-roll "1d20") 10)
+              (let* (
+                                       (orighp (kern-char-get-hp kobj))
+                                       (orighproll (string-append "1d" (number->string (kern-char-get-max-hp kobj))))
+                                       (hurtclone (< (kern-dice-roll orighproll) orighp))
+                                       (origlevel (kern-char-get-level kobj))
+                                       (clonelevel 
+                                               (if (= origlevel 1)
+                                                       1
+                                                       (if hurtclone
+                                                               origlevel
+                                                               (- origlevel 1))))
+                                       (clone (mk-npc (split-gob-npc-type-tag fgob)
+                                   clonelevel)))
+                (kern-being-set-base-faction clone
+                                   (kern-being-get-base-faction kobj))
+                               (if hurtclone
+                                       (kern-char-set-hp clone orighp))
+                (kern-log-msg (kern-obj-get-name kobj) " divides!")
+                (kern-obj-put-at clone (pick-loc loc clone)))
+              )))))
+
+;; ----------------------------------------------------------------------------
+;; Grow Head
+;;
+;; A special feature of the hydra species. When a hydra takes damage it gains
+;; experience, accelerating its advancement.
+;; ----------------------------------------------------------------------------
+(define (grow-head-exec fgob kobj)
+  (if (obj-is-char? kobj)
+      (kern-char-add-experience kobj (kern-dice-roll "2d20"))))
+
+;; ----------------------------------------------------------------------------
+;; Spider Calm
+;;
+;; Used by the An Xen Bet spell to prevent spiders from attacking.
+;; ----------------------------------------------------------------------------
+(define (spider-calm-rm fgob kchar)
+  (kern-dtable-dec (kern-being-get-current-faction kchar)
+                   faction-spider)
+  (kern-log-msg (kern-obj-get-name kchar) " seems less friendly to spiders"))
+
+(define (spider-calm-apply fgob kchar)
+  (kern-dtable-inc (kern-being-get-current-faction kchar)
+                   faction-spider)
+  (kern-log-msg (kern-obj-get-name kchar) " makes spiders seem friendlier"))
+
+;;----------------------------------------------------------------------------
+;; Drunk
+;;
+;; Every keystroke at start-of-turn, roll to make the victim move in a random
+;; direction as if staggering. If roll succeeds end the victim's turn. Ending
+;; the turn prevents cumulative drinks from causing more than one "stagger" per
+;; turn.
+;;----------------------------------------------------------------------------
+(define (drunk-exec fgob kchar)
+  (if (> (kern-dice-roll "1d20") 16)
+      (if (stagger kchar)
+          (begin
+            (kern-log-msg (kern-obj-get-name kchar) " staggers!")
+            (end-turn kchar)))))
+
+(define (drunk-apply fgob kchar)
+  (kern-log-msg (kern-obj-get-name kchar) " feels tipsy!"))
+
+(define (drunk-rm fgob kchar)
+  (kern-log-msg (kern-obj-get-name kchar) " has a hangover!"))
+
+;;-----------------------------------------------------------------
+;; Graphics update
+;; for stuff that changes appearance with time
+;; requires update-gfx ifc
+;;-----------------------------------------------------------
+
+(define (update-graphics fgob kobj)
+       (if (kobj-can? kobj 'update-gfx)
+               (send-signal nil kobj 'update-gfx)
+       ))
+
+;;----------------------------------------------------------------------------
+;; Ready/Unready hooks
+;;----------------------------------------------------------------------------
+(define (uses-paper-doll? kobj)
+  (and (obj-is-char? kobj)
+       (eqv? (kern-char-get-species kobj)
+             sp_human)))
+
+(define (ktype-get-sprite ktype)
+  (let ((gob (kern-type-get-gob ktype)))
+    (if (null? gob)
+        nil
+        gob)))
+
+(define (rebuild-humanoid-sprite khum)
+  (re-mk-composite-sprite (cons (kern-sprite-strip-decorations 
+                                 (kern-obj-get-sprite khum))
+                                (filter notnull?
+                                        (map ktype-get-sprite
+                                             (kern-char-get-arms khum))))))
+
+(define (ready-equip fgob kobj karms slot)
+  (if (uses-paper-doll? kobj)
+      (begin
+        (kern-obj-set-sprite kobj (rebuild-humanoid-sprite kobj))
+        (kern-map-set-dirty))))
+
+(define (unready-equip fgob kobj karms slot)
+  (ready-equip fgob kobj karms slot))
+
+;; ----------------------------------------------------------------------------
+;; Cleanup tentacles (for sludge krakens when they die). Note that this is a
+;; hack, in that ALL tentacles in the current place are cleaned up, whether
+;; they "belong" to the dying sludge kraken or not.
+;; ----------------------------------------------------------------------------
+(define (cleanup-tentacles fgob kobj)
+  (map kern-char-kill
+       (filter is-sludge-tentacle?
+               (kern-place-get-beings (loc-place (kern-obj-get-location kobj))))))
+
+;; ----------------------------------------------------------------------------
+;; Unrest-Curses. These replace the normal camping proc with one that always creates
+;; an ambush. The 'fgob' of the effect is the tag of the npc party to
+;; generate. This is specified when the unrest-curse effect is added to the target.
+;; ----------------------------------------------------------------------------
+(define (unrest-camping-proc kplayer kplace fgob)
+  (println "unrest-camping-proc")
+  (kern-ambush-while-camping (mk-npc-party fgob) kplace)
+  (kern-ambush-while-camping (mk-npc-party fgob) kplace)
+  )
+
+(define (unrest-curse-apply fgob kobj)
+  (println "unrest-curse-apply " fgob)
+  (kern-add-hook 'camping_turn_start_hook 'unrest-camping-proc fgob)
+  )
+
+(define (unrest-curse-rm fgob kobj)
+  (println "unrest-curse-rm " fgob)
+  (kern-rm-hook 'camping_turn_start_hook 'unrest-camping-proc)
+  )
+
+(define (unrest-curse-apply-new ktarg party-tag)
+  (kern-obj-add-effect ktarg ef_unrest_curse party-tag)
+  )
+
+;; ----------------------------------------------------------------------------
+;; Effects Table
+;; ----------------------------------------------------------------------------
+
+;; Start-of-turn hooks
+(mk-effect 'ef_poison                 "Poison"        s_poison      'poison-exec nil                 nil              nil                 start-of-turn-hook "P" 0   #f  -1)
+(mk-effect 'ef_sleep                  "Sleep"         s_sleep       'sleep-exec  nil                 'sleep-rm        'sleep-reset        start-of-turn-hook "S" 0   #f  60)
+(mk-effect 'ef_light                  "Magical light" s_light       'light-exec  'light-apply        'light-rm        'light-apply        start-of-turn-hook "L" 0   #t  -2)
+(mk-effect 'ef_torchlight             "Torchlight"    s_torchlight  nil          'torchlight-apply   'torchlight-rm   'torchlight-apply   start-of-turn-hook "T" 0   #f  60)
+(mk-effect 'ef_weaklight              "Torchlight"    s_torchlight  nil          'weaklight-apply    'weaklight-rm    'weaklight-apply    start-of-turn-hook "T" 0   #f  60)
+(mk-effect 'ef_protection             "Protection"    s_protect     nil          'protection-apply   'protection-rm   'protection-apply   start-of-turn-hook "p" 0   #f  10)
+(mk-effect 'ef_charm                  "Charm"         s_charm       nil          'charm-apply        'charm-rm        'charm-apply        start-of-turn-hook "C" 0   #f   5)
+(mk-effect 'ef_invisibility           "Invisible"     s_invis       nil          'invisibility-apply 'invisibility-rm 'invisibility-apply start-of-turn-hook "N" 0   #t  10)
+(mk-effect 'ef_permanent_invisibility "Invisible"     s_invis       nil          'invisibility-apply 'invisibility-rm 'invisibility-apply start-of-turn-hook "N" 0   #t  -1)
+(mk-effect 'ef_spider_calm            "Spider calm"   s_spider_calm nil          'spider-calm-apply  'spider-calm-rm   nil                start-of-turn-hook ""  0   #f  60) 
+(mk-effect 'ef_disease                "Diseased"      s_disease    'disease-exec  nil                 nil              nil                start-of-turn-hook "D" 0   #f  -2)
+(mk-effect 'ef_graphics_update        nil             nil          'update-graphics nil               nil             'update-graphics    start-of-turn-hook ""  0   #f  -1)
+(mk-effect 'ef_stealth                "Stealth"       nil          'stealth-exec 'stealth-apply      'stealth-rm      'stealth-apply      start-of-turn-hook ""  0   #f  -1)
+
+;; Add-hook hooks
+(mk-effect 'ef_poison_immunity               "Poison immunity"    s_im_poison   'poison-immunity-exec    nil nil nil add-hook-hook "I" 0   #f  -1)
+(mk-effect 'ef_temporary_poison_immunity     "Poison immunity"    s_im_poison   'poison-immunity-exec    nil nil nil add-hook-hook "I" 0   #f  60)
+(mk-effect 'ef_disease_immunity              "Disease immunity"   s_im_disease  'disease-immunity-exec   nil nil nil add-hook-hook "E" 0   #f  -1)
+(mk-effect 'ef_temporary_disease_immunity    "Disease immunity"   s_im_disease  'disease-immunity-exec   nil nil nil add-hook-hook "E" 0   #f  60)
+(mk-effect 'ef_paralysis_immunity            "Paralysis immunity" s_im_paralyse 'paralysis-immunity-exec nil nil nil add-hook-hook "z" 0   #f  -1)
+(mk-effect 'ef_temporary_paralysis_immunity  "Paralysis immunity" s_im_paralyse 'paralysis-immunity-exec nil nil nil add-hook-hook "z" 0   #f  60)
+(mk-effect 'ef_charm_immunity                "Charm immunity"     s_im_charm    'charm-immunity-exec     nil nil nil add-hook-hook "c" 0   #f  -1)
+(mk-effect 'ef_temporary_charm_immunity      "Charm immunity"     s_im_charm    'charm-immunity-exec     nil nil nil add-hook-hook "c" 0   #f  60)
+(mk-effect 'ef_sleep_immunity                "Sleep immunity"     s_im_sleep    'sleep-immunity-exec     nil nil nil add-hook-hook "s" 0   #f  -1)
+(mk-effect 'ef_temporary_sleep_immunity      "Sleep immunity"     s_im_sleep    'sleep-immunity-exec     nil nil nil add-hook-hook "s" 0   #f  60)
+
+;; Nil hooks
+(mk-effect 'ef_fire_immunity                   "Fire immunity"       s_im_fire  nil nil nil nil nil-hook "F" 0 #f  -1)
+(mk-effect 'ef_temporary_fire_immunity         "Fire immunity"       s_im_fire  nil nil nil nil nil-hook "F" 0 #f  15)
+(mk-effect 'ef_magical_kill_immunity           "Magic kill immunity" s_im_death nil nil nil nil nil-hook "K" 0 #f  -1)
+(mk-effect 'ef_temporary_magical_kill_immunity "Magic kill immunity" s_im_death nil nil nil nil nil-hook "K" 0 #f  15)
+(mk-effect 'ef_fatigue                         "Fatigue"             s_unrest   nil nil nil nil nil-hook "F" 0 #f  1)
+(mk-effect 'ef_unrest_curse                    "Curse of Unrest"     s_unrest   nil 'unrest-curse-apply 'unrest-curse-rm 'unrest-curse-apply nil-hook "P" 0 #f  (* 60 24))
+
+;; Keystroke hooks
+(mk-effect 'ef_drunk    "Drunk"     s_drunk    'drunk-exec    'drunk-apply    'drunk-rm nil             keystroke-hook "A" 0 #t 60)
+(mk-effect 'ef_paralyze "Paralyzed" s_paralyse 'paralyze-exec 'paralyze-apply nil       'paralyze-apply start-of-turn-hook "Z" 0 #f 15)
+(mk-effect 'ef_ensnare  "Ensnared"  s_tangle   'ensnare-exec  'ensnare-apply  nil       'ensnare-apply  keystroke-hook "E" 0 #f 15)
+(mk-effect 'ef_stuck    "Stuck"     s_tangle   'stuck-exec    'stuck-apply    nil       'stuck-apply    keystroke-hook "E" 0 #f 15)
+
+;; On-damage hooks
+(mk-effect 'ef_split               "Split"          nil 'split-exec     nil nil nil             on-damage-hook ""  0 #f  -1)
+(mk-effect 'ef_grow_head           "XP from damage" nil 'grow-head-exec nil nil 'grow-head-exec on-damage-hook "H" 0 #f  -1)
+(mk-effect 'ef_temporary_grow_head "XP from damage" nil 'grow-head-exec nil nil 'grow-head-exec on-damage-hook "H" 0 #f  15)
+
+
+;; Ready-equip hooks
+(mk-effect 'ef_ready_equip nil nil 'ready-equip nil nil nil ready-equip-hook "" 0 #f -1)
+
+;; Unready-equip hooks
+(mk-effect 'ef_unready_equip nil nil 'unready-equip nil nil nil unready-equip-hook "" 0 #f -1)
+
+;; On-death hooks
+(mk-effect 'ef_loot_drop         nil nil 'loot-drop-exec    nil nil nil on-death-hook "" 0 #f -1)
+(mk-effect 'ef_cleanup_tentacles nil nil 'cleanup-tentacles nil nil nil on-death-hook "" 0 #f -1)
+(mk-effect 'ef_generic_death         nil nil 'generic-death-exec    nil nil nil on-death-hook "" 0 #f -1)
+
+;; Move-done hooks
+(mk-effect 'ef_stealth_move nil nil 'stealth-move-exec nil nil nil move-done-hook "" 0 #t -1)
+
+;; Attack-done hooks
+(mk-effect 'ef_stealth_attack nil nil 'stealth-attack-exec nil nil nil attack-done-hook "" 0 #t -1)
+
+;; Bunch of almost-generic co-effects for stealth
+(map (lambda (x)
+       (mk-effect (car x) nil nil (caddr x) nil nil nil (cadr x) "" 0 #t -1))
+     (list
+      (list 'ef_stealth_cast   cast-done-hook   'stealth-do-masterful-exec)
+      (list 'ef_stealth_yuse   yuse-done-hook   'stealth-do-masterful-exec)
+      (list 'ef_stealth_get    get-done-hook    'stealth-do-simple-exec)
+      (list 'ef_stealth_handle handle-done-hook 'stealth-do-challenging-exec)
+      (list 'ef_stealth_mix    mix-done-hook    'stealth-do-challenging-exec)
+      (list 'ef_stealth_open   open-done-hook   'stealth-do-challenging-exec)
+      (list 'ef_stealth_ready  ready-done-hook  'stealth-do-challenging-exec)
+      (list 'ef_stealth_drop   drop-done-hook   'stealth-do-simple-exec)
+      (list 'ef_stealth_use    use-done-hook    'stealth-do-simple-exec)
+      ))
+
+(define stealth-co-effects
+  (list
+   ef_stealth_move
+   ef_stealth_attack
+   ef_stealth_cast
+   ;; ef_stealth_yuse -- nope, needs to be a special case
+   ef_stealth_get
+   ef_stealth_handle
+   ef_stealth_mix
+   ef_stealth_open
+   ef_stealth_ready
+   ef_stealth_drop
+   ef_stealth_use  
+   ))
+
+;;----------------------------------------------------------------------------
+;; Effect Test Procedures
+;;----------------------------------------------------------------------------
+
+(define (has-effect? kobj kef)
+  (in-list? kef (kern-obj-get-effects kobj)))
+
+(define (is-poisoned? kobj)
+  (in-list? ef_poison (kern-obj-get-effects kobj)))
+
+(define (is-paralyzed? kobj)
+  (in-list? ef_paralyze (kern-obj-get-effects kobj)))
+
+(define (is-diseased? kobj)
+  (in-list? ef_disease (kern-obj-get-effects kobj)))
+
+(define (is-asleep? kobj)
+  (in-list? ef_sleep (kern-obj-get-effects kobj)))
+
+(define (is-charmed? kobj)
+  (in-list? ef_charm (kern-obj-get-effects kobj)))
+
+(define (is-invisible? kobj)
+  (in-list? ef_invisibility (kern-obj-get-effects kobj)))
+
+(define (is-disabled? kobj)
+  (let ((effects (kern-obj-get-effects kobj)))
+    (if (null? effects)
+        #f
+        (foldr (lambda (x effect)
+                 (or x
+                     (in-list? effect effects)))
+               #f
+               (list ef_paralyze ef_sleep ef_charm ef_ensnare)))))
+
+(define (not-disabled? kobj)
+  (not (is-disabled? kobj)))
+
+;; ----------------------------------------------------------------------------
+;; Effect Application Procedures
+;; ----------------------------------------------------------------------------
+
+;; Used by spells:
+(define (apply-poison obj)
+  (if (obj-is-char? obj)
+      (cond ((not (has-poison-immunity? obj))
+             (kern-log-msg (kern-obj-get-name obj) " poisoned!")
+             (kern-obj-add-effect obj ef_poison nil))
+            (else
+             (kern-log-msg (kern-obj-get-name obj) " immune to poison!"))))
+  obj)
+
+;; Used by species that are inherently immune:
+(define (apply-poison-immunity kobj)
+  (kern-obj-add-effect kobj ef_poison_immunity nil)
+  kobj)
+
+(define (apply-sleep kobj)
+  (cond ((and (obj-is-char? kobj)
+              (not (has-sleep-immunity? kobj)))
+         (kern-char-set-sleep kobj #t)
+         (kern-obj-add-effect kobj ef_sleep nil)))
+  kobj)
+
+(define (make-invisible kobj)
+  (kern-obj-add-effect kobj ef_permanent_invisibility nil)
+  kobj)
+
+(define (apply-acid kchar)
+  (if (obj-is-char? kchar)
+      (let ((arms (kern-char-get-arms kchar)))
+        (if (null? arms)
+            (kern-log-msg "Acid has no effect!")
+            (let ((ktype (random-select arms)))
+              (if (in-list? ktype arms-immune-to-acid)
+                  (kern-log-msg "Acid hits " (kern-type-get-name ktype) " but has no effect!")
+                  (begin
+                    (kern-log-msg "Acid dissolves 1 " (kern-type-get-name ktype) 
+                                  " held by " (kern-obj-get-name kchar))
+                    (kern-char-unready kchar ktype)
+                    (kern-obj-remove-from-inventory kchar ktype 1))))))))
+
+;; TODO: multiply damage by kern-ticks-per-turn?
+;;     TODO: define ifc for objects taking damage from fire
+(define (generic-burn obj dice)
+       (let ((damage (kern-dice-roll dice)))
+               (if (and (> damage 0)
+                               (or (not (kern-obj-is-being? obj))
+                                       (not (has-fire-immunity? obj))
+                       ))
+                       (begin
+                               (if (kern-obj-is-being? obj)
+                                       (begin
+                                       (kern-log-msg (kern-obj-get-name obj) " burned!")
+                                       (kern-obj-apply-damage obj "burning" damage)
+                                       )
+                       ))
+       )))
+
+(define (burn obj)
+  (generic-burn obj "2d3+2"))
+
+(define (great-burn obj)
+  (generic-burn obj "10d8+20"))
+
+;; fixme: what about the player party? probably not safe to just remove it from
+;; the map...
+;; player party seems to work fine. (sigh. another mighty adventurer bites the dust)
+(define (chasm-fall kobj)
+  (cond ((and (not (can-fly? kobj))
+              (not (is-abstract? kobj))
+              (or  (not (ship-at? (kern-obj-get-location kobj)))
+                       (not (kern-obj-is-being? kobj)))
+                         (not (and (obj-is-char? kobj) (kchar-in-vehicle? kobj)))
+              (eqv? pclass-space (kern-terrain-get-pclass (kern-place-get-terrain (kern-obj-get-location kobj)))))
+         (kern-log-msg (kern-obj-get-name kobj) " drops into the abyss!")
+         (if (obj-is-char? kobj)
+             (kern-char-kill kobj)
+             (kern-obj-remove kobj)))))
+
+(define (magical-kill obj)
+  (if (and (kern-obj-is-char? obj)
+           (not (has-magical-kill-immunity? obj)))
+      (kern-char-kill obj)))
+  
+
+(define (slip obj)
+  (let ((mmode (kern-obj-get-mmode obj)))
+    (if (eqv? mmode mmode-walk)
+        (if (< (kern-dice-roll "1d20") 5)
+            (let ((dir (kern-obj-get-dir obj)))
+              (if (not (and (= 0 (car dir))
+                            (= 0 (cadr dir))))
+                  (begin
+                    (kern-obj-move obj (- (car dir)) (- (cadr dir)))
+                    (kern-log-msg "Slipped!")
+                    (kern-obj-apply-damage obj "slipped" (kern-dice-roll "1d4")))))))))
+
+;; TODO: multiply damage by kern-ticks-per-turn?
+;; TODO: define ifc for objects taking damage from shock
+(define (apply-lightning obj)
+  (if (kern-obj-is-being? obj)
+               (begin
+       (kern-log-msg (kern-obj-get-name obj) " shocked!")
+                       (kern-obj-apply-damage obj "shocked" (kern-dice-roll "2d8")))
+       ))
+
+;; Drop a random temporary field on the object's location
+(define (apply-random-field kobj)
+  (kern-obj-put-at (kern-mk-obj (random-select (list  F_fire 
+                                                      F_poison 
+                                                      F_sleep 
+                                                      F_energy))
+                                1)
+                   (kern-obj-get-location kobj)))
+                   
+;; Prismatic -- pick a random effect. This isn't quite what I want, I'd rather
+;; go through the powers layer, but that requires me to know who my caster
+;; is. This was written to be used by a weapon like a prismatic wand, and the
+;; missile procedures don't get the user/caster as a parm (yet).
+(define (apply-prismatic kobj)
+  (if (or (not (kern-obj-is-being? kobj))
+          (contest-of-skill 8 (occ-ability-magicdef kobj)))
+      (let ((selection (random-select (list 'paralyze 
+                                            'apply-acid
+                                            'apply-poison
+                                            'burn
+                                            'slip
+                                            'apply-lightning
+                                            'apply-random-field
+                                            ))))
+        (apply (eval selection)
+               (list kobj)))))
+   
+                  
+
+;;----------------------------------------------------------------------------
+;; Misc stuff -- not sure where to put this
+(define (douse ktarg)
+  (kern-obj-remove-effect ktarg ef_torchlight))
+
+(define (wind-trap ktarg)
+  (kern-log-msg "A gust of wind!")
+  (douse ktarg)
+  #f ;; prevents removal of trigger
+  )
+
+  
+;;--------------------------------------------------------------------------
+;; Dispell Magic effects
+
+(define (effects-dispel-magic ktarg)
+       (map (lambda (effect)
+                       (kern-obj-remove-effect ktarg effect)
+                       )
+               (list
+                       ef_sleep
+                       ef_light
+                       ef_protection
+                       ef_charm
+                       ef_invisibility
+                       ef_spider_calm
+                       ef_temporary_poison_immunity
+                       ef_temporary_disease_immunity
+                       ef_temporary_paralysis_immunity
+                       ef_temporary_charm_immunity
+                       ef_temporary_sleep_immunity
+                       ef_temporary_fire_immunity
+                       ef_temporary_magical_kill_immunity
+                       ef_paralyze
+                       ef_temporary_grow_head
+               )
+       ))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/enchanter.scm b/worlds/haxima-1.002/enchanter.scm
new file mode 100644 (file)
index 0000000..50945e8
--- /dev/null
@@ -0,0 +1,496 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define enchanter-start-lvl 8)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Enchanter's Tower Ground Floor"
+;; 
+;; (The fact that he never visits the second floor of his own tower
+;; should serve as an incentive for us to eventually get multi-place
+;; schedules working  :-)
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_enchanter
+               (list 0  0  enchtwr-ench-bed        "sleeping")
+               (list 8  0  enchtwr-dining-room-2   "eating")
+               (list 9  0  enchtwr-hall            "idle")
+               (list 12 0  enchtwr-dining-room-2   "eating")
+               (list 13 0  enchtwr-hall            "idle")
+               (list 19 0  enchtwr-dining-room-2   "eating")
+               (list 20 0  enchtwr-bedroom-1       "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (enchanter-mk)
+  (list #f 
+        (mk-quest) ;; get stolen rune
+        (mk-quest) ;; learn the purpose of the runes
+        (mk-quest) ;; get all runes
+        (mk-quest) ;; open demon gate
+        ))
+(define (ench-met? gob) (car gob))
+(define (ench-first-quest gob) (cadr gob))
+(define (ench-second-quest gob) (caddr gob))
+(define (ench-quest gob n) (list-ref gob n))
+(define (ench-met! gob val) (set-car! gob val))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; The Enchanter is a powerful Mage, and one of the Wise.
+;; He lives in the Enchanter's Tower.
+;; He plays an important role in multiple stages of the main quest.
+;;----------------------------------------------------------------------------
+(define (ench-hail knpc kpc)
+  (let ((ench (gob knpc)))
+
+    ;; Fourth Quest -- open the demon gate
+    (define (check-fourth-quest)
+      (say knpc "Have you found the location of the Demon Gate?")
+      (if (yes? kpc)
+          (begin
+            (say knpc "And have you found the locks which the Rune-keys will open?")
+            (if (yes? kpc)
+                (say knpc "So you are just fooling around, wasting time. I see.")
+                (say knpc "I would expect them to appear as altars in a shrine. "
+                     "The shrine may be hidden, perhaps revealing itself with a "
+                     "password. Find and search the Accursed, "
+                     "they must have had a clue.")))
+          (say knpc "Search well the library at Absalot.")))
+
+    ;; Third Quest -- find all the Runes
+    (define (finish-third-quest)
+      (say knpc "You have found all the Runes! "
+           "Well, it couldn't have been all that hard. ")
+      (prompt-for-key)
+      (say knpc "I have one last task for you. "
+           "You must find the Demon Gate and re-open it. "
+           "Do you know where to find it?")
+      (if (yes? kpc)
+          (say knpc
+               "I don't know what you will face, "
+               "so prepare yourself well, "
+               "and take anyone foolish enough to join you. "
+               )
+          (say knpc "The Accursed must have some idea, "
+               "and the library of Absalot may yet hold some clue. "
+               "Search well.")
+          )
+      (quest-done! (ench-quest ench 3) #t)
+      (kern-char-add-experience kpc 100)
+      (quest-accepted! (ench-quest ench 4) #t)      
+      )
+
+    (define (check-third-quest)
+       (define (missing-only-s-rune?)
+               (all-in-inventory? kpc
+                         (filter (lambda (ktype)
+                                   (not (eqv? ktype t_rune_s)))
+                                 rune-types)))
+       (cond                    
+               ((missing-only-s-rune?)
+                       (say knpc "You appear to have found most of the Runes now.")
+               (prompt-for-key)
+               (say knpc "Hmmm.")
+               (prompt-for-key)
+               (say knpc "I hesitated to raise this before, but it may be within your abilities after all.")
+               (prompt-for-key)
+               (say knpc "We know that the Accursed also seek the runes. We should consider ourselves fortunate if only one has fallen into their clutches.")
+               (prompt-for-key)
+               (say knpc "You will need to seek it in the very lair of our enemies: the ruins of Absalot.")
+               (quest-data-assign-once 'questentry-rune-s)
+               )
+               
+               ((has-all-runes? kpc)
+          (finish-third-quest)
+          (say knpc "Return when you have found all the Runes. "
+               "Consult with the other Wise, they may have clues about where to find the Runes.")
+              ))
+              )
+
+    ;; Second Quest -- find out what the Runes are for
+    (define (second-quest-spurned)
+      (say knpc "It is the duty of all good men to stand up to evil. I "
+           "don't have time for sluggards or cynics. Now give me my rune, "
+           "take your reward and get out!")
+      (kern-obj-remove-from-inventory kpc t_rune_k 1)
+      (kern-obj-add-to-inventory knpc t_rune_k 1)
+      (quest-accepted! (ench-second-quest ench) #f)
+      (kern-conv-end))
+
+    (define (start-second-quest)
+      (quest-accepted! (ench-second-quest ench) #t)
+      (say knpc "Good! First, keep my rune, and guard it well. ")
+      (quest-data-update 'questentry-rune-k 'entrusted-with-rune 1)
+      (prompt-for-key)
+      (say knpc "Second, find the other Wise and ask them of the RUNE. "
+           "You might start with the Alchemist near Oparine. "
+           "Although obscenely greedy, "
+           "he has devoted his life to the acquisition of secrets.")
+      (quest-data-assign-once 'questentry-runeinfo)
+      (quest-wise-subinit 'questentry-alchemist)
+      (quest-wise-init)
+      (kern-conv-end)
+      )
+
+    (define (offer-second-quest-again)
+      (say knpc "You're back. Perhaps you've had an attack of conscience. "
+           "It happens to the worst of us. "
+           "Now, are you ready to help me thwart the Accursed?")
+      (if (kern-conv-get-yes-no? kpc)
+          (begin
+            (kern-obj-remove-from-inventory knpc t_rune_k 1)
+            (kern-obj-add-to-inventory kpc t_rune_k 1)
+            (start-second-quest))
+          (begin
+            (say knpc "Like a pig to the trough, "
+                 "a fool returns to his own folly. "
+                 "Go back to filling your belly!")
+            (kern-conv-end)))
+      )
+    
+    (define (finish-second-quest)
+      (say knpc "[He looks very grave] "
+           "So my Rune is one of eight keys to the Demon Gate. "
+           "Very well, you must find the rest. "
+           "The Accursed have a head start on us. "
+           "No doubt they already have some of the Runes. "
+           "When you have found all the Runes return to me.")
+      (quest-done! (ench-second-quest ench) #t)
+      (quest-data-update 'questentry-runeinfo 'abe 1)
+      (quest-data-update 'questentry-runeinfo 'keys 1)
+      (quest-data-update 'questentry-runeinfo 'gate 1)
+      (quest-data-update 'questentry-rune-k 'entrusted-with-rune 1)
+      (quest-data-update-with 'questentry-runeinfo 'done 1 (grant-party-xp-fn 30))
+      (quest-data-complete 'questentry-runeinfo)
+      ;; temporary setup- will require information gathering first when done
+      (prompt-for-key)
+      (quest-data-assign-once 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-k 'questentry-allrunes)
+      (quest-data-assign-once 'questentry-rune-k)
+      (quest-data-convert-subquest 'questentry-rune-c 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-d 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-l 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-p 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-s 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-w 'questentry-allrunes)
+      (quest-data-convert-subquest 'questentry-rune-f 'questentry-allrunes)
+      (quest-accepted! (ench-quest ench 3) #t)
+      )
+
+    (define (check-second-quest)
+      (say knpc "Have you learned what the Rune is for?")
+      (if (yes? kpc)
+          (begin
+            (say knpc "Well, what?")
+            (let ((reply (kern-conv-get-reply kpc)))
+              (if (or (equal? reply 'demo) (equal? reply 'gate) (equal? reply 'key))
+                  (finish-second-quest)
+                  (begin
+                    (say knpc "I don't think so. Have you asked all of the Wise about the ^c+mrune^c-?")
+                    (if (yes? kpc)
+                        (say knpc "Surely one of them must have given you some clue!")
+                        (say knpc "Seek them all."))))))
+          (say knpc "Ask all the Wise about the ^c+mrune^c-.")))
+
+    ;; First Quest -- find the stolen Rune
+    (define (finish-first-quest)
+      (say knpc "Ah, I see you've found my Rune at last!")
+      (kern-obj-add-gold kpc 200)
+               (quest-data-update-with 'questentry-thiefrune 'done 1 (grant-party-xp-fn 20))
+               (quest-data-complete 'questentry-thiefrune)
+      (say knpc "Perhaps your are not completely useless. "
+           "Did you encounter any... resistance?")      
+      (kern-conv-get-yes-no? kpc)
+      (say knpc "The Accursed were behind this theft. "
+           "We must find out what the Rune is for. "
+           "Will you help?")
+      (quest-offered! (ench-second-quest ench) #t)
+      (if (kern-conv-get-yes-no? kpc)
+          (start-second-quest)
+          (second-quest-spurned)))
+
+    (define (check-first-quest)
+      (if (in-inventory? kpc t_rune_k)
+          (finish-first-quest)
+          (say knpc "Hmph. I see you still haven't found my item yet!"
+               " [He mutters something about Wanderers and Rogues]")
+            ))
+    
+    ;; Main
+    (if (ench-met? ench)
+        (if (quest-done? (ench-quest ench 4))
+            (say knpc "Welcome, friend of the Wise")
+            (if (quest-accepted? (ench-quest ench 4))
+                (check-fourth-quest)
+                (if (quest-accepted? (ench-quest ench 3))
+                    (check-third-quest)
+                    (if (quest-offered? (ench-second-quest ench))
+                        (if (quest-accepted? (ench-second-quest ench))
+                            (check-second-quest)
+                            (offer-second-quest-again))
+                        (if (quest-accepted? (ench-first-quest ench))
+                            (check-first-quest)
+                            (say knpc "Yes, what is it this time?"))))))
+        (begin
+          (quest-data-update-with 'questentry-calltoarms 'talked 1 (quest-notify (grant-xp-fn 10)))
+          (kern-log-msg "This ageless mage looks unsurprised to see you.")
+          (say knpc "I was wondering when you would get here. "
+               "It took you long enough!")
+          (ench-met! ench #t)))))
+
+(define (ench-name knpc kpc)
+  (say knpc "I am known as the Enchanter."))
+
+(define (ench-job knpc kpc)
+  (say knpc "I help as I can in the struggle against evil."))
+
+(define (ench-default knpc kpc)
+  (say knpc "I cannot help you with that"))
+
+(define (ench-bye knpc kpc)
+  (say knpc "Beware the Accursed!"))
+
+(define (ench-join knpc kpc)
+  (say knpc "No, I belong here. Seek the Warritrix if you desire a powerful "
+       "companion."))
+
+
+(define (ench-warr knpc kpc)
+  (say knpc "The Warritrix is Wise and fierce, "
+       "and like yourself prone to Wandering. "
+       "In fact, at the moment I don't know where she is. "
+       "Try Glasdrin.")
+       (quest-wise-subinit 'questentry-warritrix)
+       (quest-data-update 'questentry-warritrix 'general-loc 1)
+       )
+
+(define (ench-wand knpc kpc)
+  (say knpc "Yes, I've met your type before. Unpredictable. "
+       "And as to whether you are good or evil, that depends upon you."))
+
+(define (ench-offer-first-quest knpc kpc)
+  (say knpc "I do not quibble over definitions of good and evil. "
+       "They are easily recognized when encountered. "
+       "Do you intend to do good while you are here?")
+  (if (kern-conv-get-yes-no? kpc)
+      ;; yes - player intends to do good
+      (begin
+        (say knpc "Then you will find me to be your ally. "
+             "But beware! Many who claim to be good are not, "
+             "or fail when put to the test. Are you ready to be tested?")
+        (if (kern-conv-get-yes-no? kpc)
+            ;; yes - player is ready to be tested
+            (begin
+              (say knpc "Very well. An item was recently stolen from me. "
+                   "I need someone to find the thief, "
+                   "recover the item and return it to me. Are you willing?")
+              (if (kern-conv-get-yes-no? kpc)
+                  ;; yes -- player is willing
+                  (begin
+                    (say knpc "Good! Rangers have tracked the thief to "
+                         "Trigrave. Go there and inquire about a ^c+mthief^c-.")
+                                                       (quest-data-assign-once 'questentry-thiefrune)
+                       (quest-data-complete 'questentry-calltoarms)
+                       ;; if you dont read the letter, you might not get the quest till now!
+                       (quest-data-assign-once 'questentry-calltoarms)
+                       (quest-data-update-with 'questentry-calltoarms 'done 1 (grant-xp-fn 10))
+                    (quest-accepted! (ench-first-quest (gob knpc)) #t)
+                    )
+                  ;; no -- player is not willing
+                  (say knpc "Perhaps I misjudged you.")))
+            ;; no -- player is not ready
+            (say knpc "It is not enough to speak of doing good, one cannot "
+                 "BE good without DOING good.")))
+      ;; no -- player does not intend to do good
+      (say knpc "We shall see. Evil men can do good without meaning to, "
+           "and men who would be callous find they can't ignore their "
+           "conscience.")))
+
+(define (ench-good knpc kpc)
+  (if (quest-accepted? (ench-first-quest (gob knpc)))
+      (say knpc "The wicked flee when no one pursues, but the righteous are "
+           "bold as dragons.")
+      (ench-offer-first-quest knpc kpc)))
+
+(define (ench-gate knpc kpc)
+  (say knpc "There are many gates in the land which connect to "
+       "one another and appear with the moons. "
+       "But the Shrine Gate is the only one I know of for certain that connects with "
+       "other worlds."))
+
+(define (ench-wise knpc kpc)
+  (say knpc "The Wise are the most powerful Warriors, Wizards, Wrights and "
+       "Wrogues in the land. Although they function to protect the Shard, "
+       "they are not all good."))
+
+(define (ench-accu knpc kpc)
+  (say knpc "The Accursed are an evil secret society, responsible for many "
+       "crimes and atrocities. With the destruction of Absalot I thought "
+       "they were finished. I was wrong. I fear now their number and "
+       "strength is greater than ever before."))
+
+(define (ench-moon knpc kpc)
+  (say knpc "Ask Kalcifax the Traveler of moongates. "
+       "She is quite the expert."))
+
+(define (ench-shri knpc kpc)
+  (say knpc "The Shrine Gate opens unpredictably, and only for a short time. "
+       "Those who enter never return, "
+       "and those who emerge are strangers and Wanderers like yourself."))
+
+(define (ench-rune knpc kpc)
+  (say knpc "The rune was passed to me by my master long ago. "
+       "He did not know what it was for, and for all my research I never "
+       "found its purpose, either. I decided it was an unimportant old relic. "
+       "Why else would it not be mentioned in any of the arcane tomes or "
+       "histories?"))
+
+(define (ench-wiza knpc kpc)
+  (say knpc "The Warrior, Wright and Wrogue all derive some power from their "
+       "knowledge of the physical world. But a Wizard's power comes from his "
+       "knowledge of the magical world."))
+
+(define (ench-know knpc kpc)
+  (say knpc "Just as a blind man cannot perceive colors, those without the "
+       "Inner Eye cannot perceive the forces of magic. But those who have "
+       "opened the Eye perceive causes and effects invisible to others."))
+
+(define (ench-wrog knpc kpc)
+  (say knpc "The Wisest of Wrogues is The MAN, who comes and goes as if on "
+       "the wind. If the MAN has a home, it is well-hidden. Ask around, "
+       "perhaps your inquiries will prompt a meeting.")
+       (quest-wise-subinit 'questentry-the-man)
+       (quest-data-update 'questentry-the-man 'common 1)
+       )
+
+(define (ench-wrig knpc kpc)
+  (say knpc "The Wisest Wright prefers to work in isolation. You may find him "
+       "if you are persistent, but not in any city. "
+       "Seek the mage Kalcifax, I think she knows the Engineer well.")
+       (quest-wise-subinit 'questentry-engineer)
+       (quest-data-update 'questentry-engineer 'kalcifax 1)
+       )
+
+(define (ench-necr knpc kpc)
+  (say knpc "The most depraved and wicked of all the Wise, "
+       "my nemesis the Necromancer abides somewhere in the underworld. "
+       "He is powerful, deceitful and corrupt beyond redemption.")
+       (quest-wise-subinit 'questentry-necromancer)
+       (quest-data-update 'questentry-necromancer 'general-loc 1)
+      )
+
+(define (ench-alch knpc kpc)
+  (say knpc "The Alchemist keeps a lab near Oparine. "
+       "He is greedy and very cunning, so be wary of him.")
+       (quest-wise-subinit 'questentry-alchemist)
+       (quest-data-update 'questentry-alchemist 'oparine 1)
+       )
+
+(define (ench-thie knpc kpc)
+       ;;in case quest generated once in progress
+       (quest-data-assign-once 'questentry-thiefrune)
+  (if (quest-done? (ench-first-quest (gob knpc)))
+      (say knpc "Although a nuisance, he was only a middleman. "
+           "I hope you did not treat him too harshly.")
+      (say knpc "The thief who stole my item must be very clever. The rangers "
+           "lost his trail in Trigrave. Inquire among everyone there if they "
+           "have seen the ^c+mthief^c-.")))
+
+(define (ench-kalc knpc kpc)
+  (say knpc "Kalcifax? She's rather hard to keep track of I'm afraid."))
+
+(define (ench-demo knpc kpc)
+  (say knpc "The Demon Gate is a legendary gate that wizards of old used to cross into other worlds. "
+       "Then, for reasons that vary in the telling, it was lost or sealed or forgotten or destroyed. "
+       "I always thought it a fiction."))
+
+(define (ench-ench knpc kpc)
+  (say knpc "Yes?"))
+
+(define enchanter-conv
+  (ifc basic-conv
+       (method 'default ench-default)
+       (method 'hail ench-hail)
+       (method 'name ench-name)
+       (method 'bye ench-bye)
+       (method 'job ench-job)
+       (method 'join ench-join)
+       
+       (method 'ench ench-ench)
+       (method 'accu ench-accu)
+       (method 'alch ench-alch)
+       (method 'evil ench-good)
+       (method 'gate ench-gate)
+       (method 'good ench-good)
+       (method 'know ench-know)
+       (method 'moon ench-moon)
+       (method 'necr ench-necr)
+       (method 'rune ench-rune)
+       (method 'shri ench-shri)
+       (method 'thie ench-thie)
+       (method 'wand ench-wand)
+       (method 'warr ench-warr)
+       (method 'wise ench-wise)
+       (method 'wiza ench-wiza)
+       (method 'wrog ench-wrog)
+       (method 'wrig ench-wrig)
+       (method 'emgi ench-wrig)
+       (method 'kalc ench-kalc)
+       (method 'demo ench-demo)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-enchanter-first-time tag)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     tag ;;..........tag
+     "Enchanter" ;;.......name
+     sp_human ;;.....species
+     oc_wizard ;;.. .occupation
+     s_old_mage ;;..sprite
+     ;;(mk-composite-sprite (list s_hum_body s_hum_belt s_hum_beard))
+     faction-men ;;..faction
+     0 ;;...........custom strength modifier
+     7 ;;...........custom intelligence modifier
+     0 ;;...........custom dexterity modifier
+     10 ;;............custom base hp modifier
+     2 ;;............custom hp multiplier (per-level)
+     20 ;;............custom base mp modifier
+     5 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     enchanter-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'enchanter-conv ;;...conversation (optional)
+     sch_enchanter ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+     ;;..............container (and contents)
+     (mk-inventory
+      (list
+       (list 10  t_food)
+       (list 100 t_arrow)
+       (list 1   t_bow)
+       (list 1   t_dagger)
+       (list 1   t_sword)
+       (list 1   t_leather_helm)
+       (list 1   t_armor_leather)
+       (list 5   t_torch)
+       (list 5   t_cure_potion)
+       (list 5   t_heal_potion)
+       ))
+     nil ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (enchanter-mk)))
diff --git a/worlds/haxima-1.002/enchanters-tower-mech.scm b/worlds/haxima-1.002/enchanters-tower-mech.scm
new file mode 100644 (file)
index 0000000..6f0a6fb
--- /dev/null
@@ -0,0 +1,283 @@
+;;------------------------------------------------------------
+;; *special* mirror
+
+(define (mag-mirror-active? mir)
+               (car (list-ref (gob mir) 3))
+       )
+
+(define (mag-mirror-active! mir val)
+               (set-car! (list-ref (gob mir) 3) val)
+       )
+
+(define (mag-mirror-have-target mir)
+               (let ((loc (list-ref (gob mir) (if (mag-mirror-active? mir) 1 2))))
+                       (if (null? (portal-place loc))
+                               #f
+                               #t
+                               ))
+       )
+
+(define (mag-mirror-target-loc mir)
+               (portal-coords (list-ref (gob mir) (if (mag-mirror-active? mir) 1 2)))
+       )
+       
+(define (mag-mirror-background mir)
+               (eval (list-ref (gob mir) 0))
+       )
+       
+(define (mag-mirror-handler mir)
+               (list-ref (gob mir) 4)
+       )
+       
+
+(define mag-mirror-ifc
+  (ifc '()
+       (method 'handle 
+               (lambda (kmirror kuser)
+                                       ((eval (mag-mirror-handler kmirror)) kmirror kuser)
+                 ))
+       (method 'step
+               (lambda (kmirror kuser)
+                 ))
+       (method 'remote-sensor
+               (lambda (kmirror kuser) 
+                 (let* ((mirror-loc (kern-obj-get-location kmirror))
+                        (target-loc (mag-mirror-target-loc kmirror))
+                        (character (get-char-at target-loc)))
+                   (if (null? character)
+                       (kern-obj-set-sprite kmirror (mk-composite-sprite (list s_mirror_bg (mag-mirror-background kmirror) s_mirror_fg)))
+                       (kern-obj-set-sprite kmirror (mk-composite-sprite (list s_mirror_bg (kern-obj-get-sprite character) (mag-mirror-background kmirror) s_mirror_fg))))
+                   (kern-map-set-dirty)
+                   )
+                               ))
+          (method 'on
+               (lambda (kmirror kuser)
+                                       (mag-mirror-active! kmirror #t)
+                                       (if (mag-mirror-have-target kmirror)
+                                               (send-signal kuser kmirror 'remote-sensor))
+                 ))
+               (method 'off
+               (lambda (kmirror kuser)
+                                       (mag-mirror-active! kmirror #f)
+                                       (if (mag-mirror-have-target kmirror)
+                                               (send-signal kuser kmirror 'remote-sensor))
+                 ))
+       (method 'init
+               (lambda (kmirror)
+                                       (kern-obj-set-pclass kmirror pclass-wall)
+                 ))
+               (method 'exec
+                 (lambda (kclock)
+                   (kern-sound-play-ambient sound-clock (kern-obj-get-location kclock))
+                   ))  
+               (method 'on-entry
+                 (lambda (kclock)
+                   (kern-sound-play-ambient sound-clock (kern-obj-get-location kclock))
+                   ))  
+       ))
+
+(mk-obj-type 't_mag_mirror "mirror"
+       '()
+       layer-mechanism mag-mirror-ifc)
+       
+(define (mk-mag-mirror background-tag target-loc-a target-loc-i active handler)
+       (let ((kmirror (kern-mk-obj t_mag_mirror 1)))
+               (bind kmirror (list background-tag target-loc-a target-loc-i (list active) handler))
+               (kern-obj-set-sprite kmirror (mk-composite-sprite (list s_mirror_bg (eval background-tag) s_mirror_fg)))
+               kmirror))
+               
+(define doormirhandler 
+                       (lambda (kmirror kuser)
+                               (if (mag-mirror-active? kmirror)
+                                       (let ((target-loc (mag-mirror-target-loc kmirror)))
+                                               (kern-log-msg (kern-obj-get-name kuser) " steps through the mirror!")
+                                               (kern-obj-relocate kuser target-loc nil))
+                                       (let ((target-loc (kern-obj-get-location kmirror))
+                                                       (clone (kern-obj-clone kuser)))
+                                               (println (kern-char-get-arms kuser))
+                                               (map (lambda (ktype)
+                                                       (kern-obj-add-to-inventory clone ktype 1))
+                                                       (kern-char-get-arms kuser))
+                                               (kern-char-arm-self clone)
+                                               (kern-char-set-level clone (kern-char-get-level kuser))
+                                               (kern-being-set-base-faction clone faction-monster)
+                                               (kern-char-set-ai clone 'spell-sword-ai)
+                                               (kern-obj-put-at clone target-loc)
+                                               (kern-log-msg (kern-obj-get-name kuser) "'s reflection steps through the mirror!")
+                                               )
+                               )))
+
+(define testmirhandler 
+                       (lambda (kmirror kuser)
+                               (kern-log-msg (kern-obj-get-name kuser) " spots "
+                                       (if (mag-mirror-active? kmirror)
+                                                       (let* ((target-loc (mag-mirror-target-loc kmirror))
+                                                                       (character (get-char-at target-loc)))
+                                                               (if (null? character)
+                                                                       "nothing"
+                                                                       (kern-obj-get-name character)
+                                                               ))
+                                                       (kern-obj-get-name kuser))
+                                               " in the mirror"
+                                               (if (mag-mirror-active? kmirror) "!" "")
+                                               )
+                               ))
+
+;;---------------------------
+;; send an ifc to multiple targets
+
+(define (send-to-all kuser tags signal)
+  (if (defined? (car tags))
+      (send-signal kuser (eval (car tags)) signal))
+  (if (not (equal? (cadr tags) '()))
+      (send-to-all kuser (cdr tags) signal)
+      ))
+
+(define sig-splitter-ifc
+  (ifc '() (method 'remote-sensor
+                   (lambda (ksensor kuser)
+                       (send-to-all kuser (gob ksensor) 'remote-sensor)
+                     ))
+                       (method 'on
+                   (lambda (ksensor kuser)
+                       (send-to-all kuser (gob ksensor) 'on)
+                     ))
+                       (method 'off
+                   (lambda (ksensor kuser)
+                       (send-to-all kuser (gob ksensor) 'off)
+                     ))
+                       (method 'init tblit-init)
+       ))
+
+(mk-obj-type 't_sig_splitter nil nil layer-mechanism sig-splitter-ifc)
+
+(define (mk-sig-splitter target-tags)
+  (bind (kern-mk-obj t_sig_splitter 1)
+        target-tags))
+               
+;;---------------------
+;; reversible terrain mod
+
+(define bim-secret-ifc
+  (ifc '()  (method 'on
+                   (lambda (ksensor kuser)
+                                               (if (not (equal? (safe-eval (car (caddr (gob ksensor)))) '()))
+                                                       (kern-place-set-terrain
+                                                               (portal-coords (caddr (gob ksensor)))
+                                                               (eval (car (gob ksensor))))
+                                                       )
+                     ))
+                       (method 'off
+                   (lambda (ksensor kuser)
+                                               (if (not (equal? (safe-eval (car (caddr (gob ksensor)))) '()))
+                                                       (kern-place-set-terrain
+                                                               (portal-coords (caddr (gob ksensor)))
+                                                               (eval (cadr (gob ksensor))))
+                                                       )
+                     ))
+                       (method 'init tblit-init)
+       ))
+
+(mk-obj-type 't_bim_secret nil nil layer-mechanism bim-secret-ifc)
+
+(define (mk-bim-secret terrain-on terrain-off target)
+  (bind (kern-mk-obj t_bim_secret 1)
+       (list terrain-on terrain-off target)))
+
+;;-------------------
+;; moving bookshelf -should use bim?
+
+(define moving-shelf-ifc
+  (ifc '()  (method 'search
+                   (lambda (shelf)
+                                          (kern-log-msg "You find a hidden mechanism!")
+                     ))
+                       (method 'handle
+                   (lambda (shelf kuser)
+                       (kern-log-msg "The shelf moves!")
+                                          (let ((data (gob shelf)))
+                                                       (set-car! data (not (car data)))
+                                                       (send-signal kuser (eval (list-ref data 3))
+                                                               (if (car data) 'on 'off))
+                                                       (kern-obj-relocate shelf 
+                                                               (portal-coords (if (car data) (cadr data) (caddr data)))
+                                                               nil))
+                     ))
+                  (method 'init
+                                  (lambda (shelf)
+                                               (kern-obj-set-pclass shelf pclass-wall)
+                                        ))
+               ))
+
+(mk-obj-type 't_moving_shelf "set of shelves"
+       s_bookshelf layer-mechanism moving-shelf-ifc)
+
+(define (mk-moving-shelf loc-open loc-closed trigger)
+  (bind (kern-mk-obj t_moving_shelf 1)
+       (list #f loc-open loc-closed trigger)))
+
+(mk-reusable-item 
+ 't_mans_note "note" s_scroll norm
+ (lambda (kletter kuser)
+   (kern-ui-page-text
+               "Short Note"
+               "Hey Enchanter:"
+               ""
+               "This room is _awfully_ dusty..."
+               "Clean up more often!"
+               "   -- the MAN"
+   )))
+   
+   
+;;--------------------------
+;; magic clock. runs backwards. casts time stop
+
+
+(define mag-clock-ifc
+  (let ((mod
+                       (lambda (input modulus)
+                               (- input (* (floor (/ input modulus)) modulus))
+                       )))
+  (ifc '()
+               (method 'handle 
+                       (lambda (kclock kuser)
+                               (kern-log-msg "The clock hands stop moving!")
+                               (powers-timestop kuser kuser 30)
+                       ))
+               (method 'xamine 
+                       (lambda (kclock kuser)
+                               (let* ((time (kern-get-time))
+                                               (hour (floor (/ (* 12 (- 60 (time-minute time))) 60)))
+                                               (hour (number->string
+                                                       (if (< 1 hour) hour     12)))
+                                               (min (- 6 (mod (time-minute time) 6)))
+                                               (min (if (> min 5)
+                                                               "00"
+                                                               (number->string (* 10 min)))))
+                                       (kern-log-msg "The clock reads " hour ":" min)
+                               )))
+               (method 'step
+                       (lambda (kmirror kuser)
+                               ))
+               (method 'update-gfx
+                       (lambda (kclock)
+                               (let* ((time (kern-get-time))
+                                               (min-hand (clock-get-hand (- 60 (time-minute time))))
+                                               (hour-hand (clock-get-hand (floor (/ (- 65 (time-minute time)) 10)))))
+                                       (kern-obj-set-sprite kclock (mk-composite-sprite (list s_clock_body hour-hand min-hand)))
+                               )))
+               (method 'init
+            (lambda (kmirror)
+                               (kern-obj-set-pclass kmirror pclass-wall)
+            )) 
+       )))
+
+(mk-obj-type 't_mag_clock "clock"
+       (mk-composite-sprite (list s_clock_body s_clock_hand_n s_clock_spin))
+       layer-mechanism mag-clock-ifc)
+
+(define (mk-mag-clock)
+       (let ((kclock (kern-mk-obj t_mag_clock 1)))
+               (kern-obj-add-effect kclock ef_graphics_update nil)
+               (bind kclock nil)
+               kclock))
diff --git a/worlds/haxima-1.002/enchanters-tower-zones.scm b/worlds/haxima-1.002/enchanters-tower-zones.scm
new file mode 100644 (file)
index 0000000..3e23f38
--- /dev/null
@@ -0,0 +1,24 @@
+;;----------------------------------------------------------------------------
+;; Zones for Enchanter's Tower
+;;
+;; A zone is a rectangle formatted as:
+;;      (upper-left-corner-x upper-left-corner-y width height)
+;;----------------------------------------------------------------------------
+(define (mk-zone x y w h) (list 'p_enchanters_tower x y w h))
+(define enchtwr-main-entrance    (mk-zone 31 40 10   8))
+(define enchtwr-dining-room      (mk-zone 28 23  8   5))
+(define enchtwr-dining-room-1    (mk-zone 29 26  1   1))
+(define enchtwr-dining-room-2    (mk-zone 31 26  1   1))
+(define enchtwr-kitchen          (mk-zone 30 18  4   3))
+(define enchtwr-pantry           (mk-zone 31 14  3   2))
+(define enchtwr-fountain         (mk-zone 38 29  6   6))
+(define enchtwr-garden           (mk-zone 46 20  9   9))
+(define enchtwr-bedroom-1        (mk-zone 47 36  2   3))
+(define enchtwr-bedroom-2        (mk-zone 52 36  2   3))
+(define enchtwr-bedroom-3        (mk-zone 52 44  2   3))
+(define enchtwr-bedroom-4        (mk-zone 47 44  2   3))
+(define enchtwr-workshop         (mk-zone 13 38  5   6))
+(define enchtwr-campsite         (mk-zone 20 29  6   6))
+(define enchtwr-guardhouse-1     (mk-zone  3  3  3   3))
+(define enchtwr-guardhouse-2     (mk-zone 59  3  3   3))
+(define enchtwr-guardhouse-3     (mk-zone  3 59  3   3))
diff --git a/worlds/haxima-1.002/enchanters-tower.scm b/worlds/haxima-1.002/enchanters-tower.scm
new file mode 100644 (file)
index 0000000..342058f
--- /dev/null
@@ -0,0 +1,474 @@
+(kern-load "enchanters-tower-mech.scm")
+
+;;----------------------------------------------------------------------------
+;; Map
+;;
+;; Declare the map for the place here.
+;;----------------------------------------------------------------------------
+(kern-mk-map 
+ 'm_enchanters_tower 31 31 pal_expanded
+       (list
+         "tt tt bb te bb |v |v tt %a %% %% %% %% %c .. .. .. %a %% %% %% %% %% %% %% %% %% %% %% %% %% "
+         "bb te .. t% tb tt |v |v tt t5 %% %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. bb .. %a %% "
+         "td t# .. .. .. .. bb |v |v tt %% %% %% .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. %% "
+         "bb .. .. .. .. .. .. ta |v |v %a %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. .. .. bb %% "
+         "|v .. .. .. .. .. .. .. bb |v t5 %% %% %d .. .. .. %b %% %% %% %% %% %% %% %% %5 .. .. .. %% "
+         "|v bb .. .. .. .. .. .. .. |v |v %a %c xx w+ cc w+ xx %e tb tt tt tt tt t5 %a %% bb .. bb %% "
+         "|v |v .. .. .. .. && .. .. ta |v xx xx xx ,, cc ,, xx xx xx |v |v |v tt tt t5 %% .. .. .. %% "
+         "tc bb .. .. bb .. .. .. .. xx w+ xx && xx ,, cc ,, xx ,, xx xx xx |v |v |v tt %% bb .. bb %% "
+         "%5 .. .. |v |v tA .. .. xx xx ,, ,, ,, xx x! cc x! xx ,, 00 x! xx ?? xx |v tt %% .. .. .. %% "
+         "%% bb .. bb |v t5 tA xx xx ,, ,, ,, ,, xx ,, cc ,, xx ,, ,, xx ,, ,, xx |v tt %% bb .. bb %% "
+         "%% .. .. |v |v tt td xx ,, ,, 00 ,, ,, xx ,, cc ,, xx ,, ,, xx xx xx xx |v tc %% .. .. .. %% "
+         "%% bb .. bb |v |v xx xx ,, ,, 00 ,, ,, xx ,, cc ,, xx ,, ,, ,, ,, ,, xx xx %3 %% bb .. bb %% "
+         "%% .. .. %f ta |v xx ,, ,, ,, ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, ,, ,, && xx %a %% .. .. .. %% "
+         "%c bb .. bb %f xx xx xx xx xx xx xx xx xx ,, cc ,, xx xx xx xx xx xx xx xx xx %e bb .. bb %a "
+         ".. .. .. .. .. w+ ,, ,, ,, ,, xx ,, ,, x! ,, cc ,, ,, xx ,, xx ,, ,, ,, ,, w+ .. .. .. .. .. "
+         ".. .. .. .. .. cc cc cc cc ,, xx ,, ,, ,, ,, cc cc ,, xx w+ xx ,, cc cc cc cc .. .. .. .. .. "
+         ".. .. .. .. .. w+ ,, ,, cc ,, xx ,, ,, xx ,, cc ,, ,, xx ,, xx ,, cc ,, ,, w+ .. .. .. .. .. "
+         "%5 bb .. bb %7 xx xx x! cc x! xx xx xx xx ,, cc ,, xx xx xx xx x! cc x! xx xx %7 bb .. bb %3 "
+         "%% %% %% %% %% %5 w+ ,, cc ,, ,, ,, ,, ,, ,, cc ,, ,, ,, ,, ,, ,, cc ,, w+ t7 %a %% %% %% %% "
+         "%% %c .. %a %% %% xx xx cc ,, pp ,, ,, pp ,, cc ,, pp ,, ,, pp ,, cc xx xx tt tt tt tt tt tt "
+         "%% .. .. .. %% %% %5 w+ cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx t3 |v |v |v |v |v tt "
+         "%% %5 .. %3 %% %% %% xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx |v |v bb te bb |v |v "
+         "%% %% %% %% %% %% %% %5 xx xx x! ,, ,, pp ,, cc ,, pp ,, ,, x! xx xx |v |v tt td t& tb tt |v "
+         "%% %c t3 tt tt t5 tA %a %5 xx xx xx ,, ,, ,, cc ,, ,, ,, xx xx xx tb |v |v bb .. .. .. bb |v "
+         "%c t3 tL ~3 ~5 tJ t5 tA %a %% %5 xx w+ xx xx cc xx xx w+ xx %3 %% ~5 ta |v td .. ++ .. tb |v "
+         "tt tL ~3 -- -- ~5 tJ t5 .. %% %% %% %5 xx ,, cc ,, xx %3 %% %% ~b ~~ -d |v bb .. .. .. bb |v "
+         "tt ~3 -- __ __ -- ~5 tt .. %% %% %% %% xx ,, cc ,, xx %a %% %% %% ~c %% |v |v td .. tb |v |v "
+         "tt ~a -- __ __ -- ~c tt .. %% %% %% %% xx w+ cc w+ xx .. bb .. bb %% %c |v |v bb .. bb |v |v "
+         "tt tH ~a -- -- ~c tG tc .. %e .. %a %% .. .. .. .. .. .. .. .. .. == .. tt tc tA .. t3 |v |v "
+         "%5 ta tH ~a ~c tG tc t# %7 .. .. .. %% bb .. .. .. bb .. bb .. bb %% %5 |v bb t7 bb |v |v |v "
+         "%% %5 tt tt tt tt t# %3 %% %5 .. %3 %% %5 .. .. .. %3 %% %% %% %% %% %% |v |v |v |v |v |v |v "
+       )
+)
+
+(kern-mk-map 
+ 'm_enchanters_tower_l2 31 31 pal_expanded
+       (list
+         "tt tt bb te bb |. |. tt %a %% %% %% %% %c .. .. .. %a %% %% %% %% %% %% %% %% %% %% %% %% %% "
+         "bb te .. t% tb tt |. |. tt t5 %% %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. bb .. %a %% "
+         "td t# .. .. .. .. bb |. |. tt %% %% %% .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. %% "
+         "bb .. .. .. .. .. .. ta |. |. %a %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. .. .. bb %% "
+         "|. .. .. .. .. .. .. .. bb |. t5 %% %% %d .. .. .. %b %% %% %% %% %% %% %% %% %5 .. .. .. %% "
+         "|. bb .. .. .. .. .. .. .. |. |. %a %c ee ee ee ee ee %e tb tt tt tt tt t5 %a %% bb .. bb %% "
+         "|. |. .. .. .. .. && .. .. ta |. ee ee ee ee ee ee ee ee ee |. |. |. tt tt t5 %% .. .. .. %% "
+         "tc bb .. .. bb .. .. .. .. ee ee ee ee ee ee ee ee ee ee ee ee ee |. |. |. tt %% bb .. bb %% "
+         "%5 .. .. |. |. tA .. .. ee ee ee ee xx w+ xx xx xx w+ xx ee ee ee ee ee |. tt %% .. .. .. %% "
+         "%% bb .. bb |. t5 tA ee ee ee xx xx xx ,, ,, xx ,, ,, xx xx xx ee ee ee |. tt %% bb .. bb %% "
+         "%% .. .. |. |. tt td ee ee xx xx ,, ,, ,, ,, xx ,, ,, ,, 00 xx xx ee ee |. tc %% .. .. .. %% "
+         "%% bb .. bb |. |. ee ee ee w+ ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, w+ ee ee ee %3 %% bb .. bb %% "
+         "%% .. .. %f ta |. ee ee xx xx ,, 00 ,, ,, ,, xx ,, ,, ,, xx xx xx xx ee ee %a %% .. .. .. %% "
+         "%c bb .. bb %f ee ee ee xx ,, ,, ,, xx xx ,, xx ,, xx xx xx [[ ]] xx ee ee ee %e bb .. bb %a "
+         ".. .. .. .. .. ee ee ee w+ ,, ,, ,, xx ,, ,, ,, ,, ,, xx 00 ,, 00 xx ee ee ee .. .. .. .. .. "
+         ".. .. .. .. .. ee ee ee xx ,, ,, ,, x! ,, cc cc cc ,, x! ,, ,, 00 xx ee ee ee .. .. .. .. .. "
+         ".. .. .. .. .. ee ee ee xx xx xx xx xx ,, ,, ,, ,, ,, xx 00 ,, 00 xx ee ee ee .. .. .. .. .. "
+         "%5 bb .. bb %7 ee ee ee xx ,, ,, xx xx xx x! ,, x! xx xx xx [[ ]] xx ee ee ee %7 bb .. bb %3 "
+         "%% %% %% %% %% %5 ee ee xx xx xx x! ,, ,, ,, ,, ,, ,, ,, x! xx xx xx ee ee t7 %a %% %% %% %% "
+         "%% %c .. %a %% %% ee ee ee w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ee ee ee tt tt tt tt tt tt "
+         "%% .. .. .. %% %% %5 ee ee xx xx [[ ]] ,, ,, ,, ,, ,, [[ ]] xx xx ee ee t3 |. |. |. |. |. tt "
+         "%% %5 .. %3 %% %% %% ee ee ee xx w+ xx [[ @@ @@ @@ ]] xx w+ xx ee ee ee |. |. bb te bb |. |. "
+         "%% %% %% %% %% %% %% %5 ee ee ee ee xx w+ xx xx xx w+ xx ee ee ee ee |. |. tt td t& tb tt |. "
+         "%% %c t3 tt tt t5 tA %a %5 ee ee ee ee ee ee ee ee ee ee ee ee ee tb |. |. bb .. .. .. bb |. "
+         "%c t3 tL ~3 ~5 tJ t5 tA %a %% %5 ee ee ee ee ee ee ee ee ee %3 %% ~5 ta |. td .. ++ .. tb |. "
+         "tt tL ~3 -- -- ~5 tJ t5 .. %% %% %% %5 ee ee ee ee ee %3 %% %% ~b ~~ -d |. bb .. .. .. bb |. "
+         "tt ~3 -- __ __ -- ~5 tt .. %% %% %% %% ee ee ee ee ee %a %% %% %% ~c %% |. |. td .. tb |. |. "
+         "tt ~a -- __ __ -- ~c tt .. %% %% %% %% ee ee ee ee ee .. bb .. bb %% %c |. |. bb .. bb |. |. "
+         "tt tH ~a -- -- ~c tG tc .. %e .. %a %% .. .. .. .. .. .. .. .. .. == .. tt tc tA .. t3 |. |. "
+         "%5 ta tH ~a ~c tG tc t# %7 .. .. .. %% bb .. .. .. bb .. bb .. bb %% %5 |. bb t7 bb |. |. |. "
+         "%% %5 tt tt tt tt t# %3 %% %5 .. %3 %% %5 .. .. .. %3 %% %% %% %% %% %% |. |. |. |. |. |. |. "
+       )
+)
+
+(kern-mk-map 
+ 'm_enchanters_tower_l3 31 31 pal_expanded
+       (list
+         "tt tt bb te bb |. |. tt %a %% %% %% %% %c .. .. .. %a %% %% %% %% %% %% %% %% %% %% %% %% %% "
+         "bb te .. t% tb tt |. |. tt t5 %% %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. bb .. %a %% "
+         "td t# .. .. .. .. bb |. |. tt %% %% %% .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. %% "
+         "bb .. .. .. .. .. .. ta |. |. %a %% %% bb .. .. .. bb .. bb .. bb .. bb .. bb .. .. .. bb %% "
+         "|. .. .. .. .. .. .. .. bb |. t5 %% %% %d .. .. .. %b %% %% %% %% %% %% %% %% %5 .. .. .. %% "
+         "|. bb .. .. .. .. .. .. .. |. |. %a %c ee ee ee ee ee %e tb tt tt tt tt t5 %a %% bb .. bb %% "
+         "|. |. .. .. .. .. && .. .. ta |. ee ee ee ee ee ee ee ee ee |. |. |. tt tt t5 %% .. .. .. %% "
+         "tc bb .. .. bb .. .. .. .. ee ee ee ee ee ee ee ee ee ee ee ee ee |. |. |. tt %% bb .. bb %% "
+         "%5 .. .. |. |. tA .. .. ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee |. tt %% .. .. .. %% "
+         "%% bb .. bb |. t5 tA ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee |. tt %% bb .. bb %% "
+         "%% .. .. |. |. tt td ee ee ee ee ee ee 00 00 00 00 00 ee ee ee ee ee ee |. tc %% .. .. .. %% "
+         "%% bb .. bb |. |. ee ee ee ee ee 00 00 00 ,, ,, ,, 00 00 00 ee ee ee ee ee %3 %% bb .. bb %% "
+         "%% .. .. %f ta |. ee ee ee ee ee 00 ,, ,, ,, xx ,, ,, ,, 00 ee ee ee ee ee %a %% .. .. .. %% "
+         "%c bb .. bb %f ee ee ee ee ee 00 00 ,, x! ,, ,, ,, x! ,, 00 00 ee ee ee ee ee %e bb .. bb %a "
+         ".. .. .. .. .. ee ee ee ee ee 00 ,, ,, ,, ,, cc ,, ,, ,, ,, 00 ee ee ee ee ee .. .. .. .. .. "
+         ".. .. .. .. .. ee ee ee ee ee 00 ,, xx ,, cc cc cc ,, xx ,, 00 ee ee ee ee ee .. .. .. .. .. "
+         ".. .. .. .. .. ee ee ee ee ee 00 ,, ,, ,, ,, cc ,, ,, ,, ,, 00 ee ee ee ee ee .. .. .. .. .. "
+         "%5 bb .. bb %7 ee ee ee ee ee 00 00 ,, x! ,, ,, ,, x! ,, 00 00 ee ee ee ee ee %7 bb .. bb %3 "
+         "%% %% %% %% %% %5 ee ee ee ee ee 00 ,, ,, ,, xx ,, ,, ,, 00 ee ee ee ee ee t7 %a %% %% %% %% "
+         "%% %c .. %a %% %% ee ee ee ee ee 00 00 00 ,, ,, ,, 00 00 00 ee ee ee ee ee tt tt tt tt tt tt "
+         "%% .. .. .. %% %% %5 ee ee ee ee ee ee 00 00 00 00 00 ee ee ee ee ee ee t3 |. |. |. |. |. tt "
+         "%% %5 .. %3 %% %% %% ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee |. |. bb te bb |. |. "
+         "%% %% %% %% %% %% %% %5 ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee |. |. tt td t& tb tt |. "
+         "%% %c t3 tt tt t5 tA %a %5 ee ee ee ee ee ee ee ee ee ee ee ee ee tb |. |. bb .. .. .. bb |. "
+         "%c t3 tL ~3 ~5 tJ t5 tA %a %% %5 ee ee ee ee ee ee ee ee ee %3 %% ~5 ta |. td .. ++ .. tb |. "
+         "tt tL ~3 -- -- ~5 tJ t5 .. %% %% %% %5 ee ee ee ee ee %3 %% %% ~b ~~ -d |. bb .. .. .. bb |. "
+         "tt ~3 -- __ __ -- ~5 tt .. %% %% %% %% ee ee ee ee ee %a %% %% %% ~c %% |. |. td .. tb |. |. "
+         "tt ~a -- __ __ -- ~c tt .. %% %% %% %% ee ee ee ee ee .. bb .. bb %% %c |. |. bb .. bb |. |. "
+         "tt tH ~a -- -- ~c tG tc .. %e .. %a %% .. .. .. .. .. .. .. .. .. == .. tt tc tA .. t3 |. |. "
+         "%5 ta tH ~a ~c tG tc t# %7 .. .. .. %% bb .. .. .. bb .. bb .. bb %% %5 |. bb t7 bb |. |. |. "
+         "%% %5 tt tt tt tt t# %3 %% %5 .. %3 %% %5 .. .. .. %3 %% %% %% %% %% %% |. |. |. |. |. |. |. "
+       )
+)
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;
+;; kern-load the character files here and call their first-time constructors.
+;;----------------------------------------------------------------------------
+(kern-load "zane.scm")
+(mk-zane-first-time 'ch_zane)
+
+;;(kern-load "gate-guard.scm")
+
+(kern-load "enchanter.scm")
+(mk-enchanter-first-time 'ch_enchanter)
+
+;;----------------------------------------------------------------------------
+;; Place
+;;
+;; Call the place constructor here.
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_enchanters_tower ; tag
+ "Enchanters Tower" ; name
+ s_tower             ; sprite
+ m_enchanters_tower ; map
+ #f                 ; wraps
+ #f                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ ;;objects
+ (list  
+
+  ;; characters
+  (list ch_zane 0 0) 
+
+  ;; magically locked doors at all entrances
+  (put (mk-magic-locked-door) 5 15)
+  (put (mk-magic-locked-door) 25 15)
+  (put (mk-magic-locked-door) 15 5)
+  (put (mk-magic-locked-door) 15 27)
+  
+  ;; dbg hack
+  ;; (put (kern-mk-obj t_poison_immunity_potion 1) 14 4)
+  ;; (put (kern-mk-obj t_in_ex_por_scroll 1) 16 4)
+
+  ;; portcullis's & levers for west store room
+  (put (kern-tag 'enchtwr-port-4 (mk-portcullis)) 13 15)
+  (put (mk-lever 'enchtwr-port-4) 21 9)
+
+  ;; treasure in west store room
+  (put (mk-chest 
+        'burn-trap
+        '((10 sulphorous_ash)
+                     (10 ginseng)
+                     (10 garlic)
+                     (10 spider_silk)
+                     (10 blood_moss)
+                     (10 black_pearl)
+                     (10 nightshade)
+                     (10 mandrake)
+                    (1 t_spell_book_white_magick_1)
+                    (1 t_spell_book_white_magick_2)
+                    ))
+       11 14)
+  (put (mk-chest
+        'spike-trap
+        '((10 t_heal_potion)
+                     (10 t_mana_potion)
+                     (5 t_cure_potion)
+                     (5 t_poison_immunity_potion)
+                     (1 t_invisibility_potion)
+                    (1 t_spell_book_force_magick_fields)
+                    ))
+       11 15)
+  (put (mk-chest
+        'lightning-trap
+        '(
+         (100 t_gold_coins)
+         ))
+       11 16)
+
+  (put (mk-bed) 21 11)
+  
+  (put (mk-magic-locked-door) 19 14)
+
+  (put (mk-door) 15  8)
+  (put (mk-door) 15 24)
+  (put (mk-door) 22 17)
+  (put (mk-door)  8 17)
+
+  (put (mk-ladder-up 'p_enchanters_tower_l2 16 15) 
+               16 15)
+
+  (put (mk-door) 13 12)
+  (put (mk-door) 17 12)
+  (put (mk-clock) 7 12)
+  
+  (put (mk-shelf) 18 7)
+  (put (mk-shelf) 19 10)
+  )
+
+ (list 'on-entry-trigger-all 'quest-calltoarms-tower) ; hooks
+ (list  ; edge entrances
+       (list northeast 3 30)
+       (list southwest 30 14)
+ )
+ )
+(mk-place-music p_enchanters_tower 'ml-castle)
+
+(kern-mk-place 
+ 'p_enchanters_tower_l2 ; tag
+ "Enchanters Tower" ; name
+ s_keep             ; sprite
+ m_enchanters_tower_l2 ; map
+ #f                 ; wraps
+ #f                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ ;;objects
+ (list
+       (put (mk-ladder-down 'p_enchanters_tower 16 15) 
+               16 15)
+       (put (mk-ladder-up 'p_enchanters_tower_l3 14 15) 
+               14 15)
+    (put (mk-door) 16 13)
+       (put (mk-door) 14 13)
+       (put (mk-door) 15 17)
+       
+       (put (mk-bed) 18 12)
+       
+       (put (mk-shelf) 14 9)
+       (put (mk-shelf) 14 10)
+       (put (mk-shelf) 14 11)
+       (put (mk-shelf) 11 10)
+       (put (mk-shelf) 12 10)
+       (put (mk-shelf) 12 12)
+       (put (mk-shelf) 9 13)
+       (put (mk-shelf) 11 13)
+       
+       (put (mk-shelf) 10 15)
+       (put (mk-shelf) 11 15)
+
+       (put (mk-shelf) 16 18)
+       (put (mk-shelf) 17 18)
+
+       (put (mk-hidden 't_ylem_an_ex_book 1) 14 9)
+       (put (mk-hidden 't_bet_flam_hur_book 1) 11 10)
+   
+    ;; treasure in east store room
+  (put (kern-mk-obj t_doom_staff               1) 20 13)
+  (put (kern-mk-obj t_xen_corp_scroll          1) 21 13)
+
+  (put (kern-mk-obj t_an_tym_scroll            1) 21 14)
+
+  (put (kern-mk-obj t_vas_rel_por_scroll       1) 20 17)
+  (put (kern-mk-obj t_spell_book_divination    1) 20 17)
+  (put (kern-mk-obj t_in_vas_por_ylem_scroll   1) 21 17)
+  (put (kern-mk-obj t_spell_book_gate_magick   1) 21 17)
+
+  (put (kern-mk-obj t_spell_book_enchantment_wards       1) 21 15)
+  (put (kern-mk-obj t_spell_book_enchantment_curses      1) 21 15)
+  (put (kern-mk-obj t_spell_book_enchantment_miscellanea 1) 21 15)
+
+  (put (kern-mk-obj t_gold_coins             500) 21 16)
+
+  (put (kern-mk-obj t_mans_note                1) 19 16)
+
+  
+    (put (kern-tag 'openlibwall 
+                 (mk-tblitter 'p_
+                              8
+                              0
+                              3
+                              1
+                              'm_hall_section))
+       0
+       0)
+
+    (put (kern-tag 'closelibwall 
+                 (mk-tblitter 'p_
+                              8
+                              0
+                              3
+                              1
+                              'm_hall_section))
+       0
+       0)
+  
+ )
+ (list 'on-entry-trigger-all) ; hooks
+ nil ; edge entrances
+ )
+(mk-place-music p_enchanters_tower_l2 'ml-castle)
+
+;;plain old mirror mirror
+(let* ((kmir (kern-tag 'ench-guest-mirror (mk-mirror 's_mirror_bg_flagstones)))
+         (ksen (mk-char-sensor 'ench-guest-mirror)))
+       (kern-obj-put-at kmir (list p_enchanters_tower_l2 16 9))
+       (kern-obj-put-at ksen (list p_enchanters_tower_l2 16 10)))
+
+;;decorative test mirror
+(let* ((testmirror1 (kern-tag 'ench-test-mirror1 
+                       (mk-mag-mirror 's_mirror_bg_flagstones
+                               (list 'p_enchanters_tower_l2 14 19) 
+                               (list 'p_enchanters_tower_l2 12 19)
+                               #t 'testmirhandler
+                               )))
+         (testmirror2 (kern-tag 'ench-test-mirror2
+                       (mk-mag-mirror 's_mirror_bg_flagstones
+                               (list 'p_enchanters_tower_l2 12 19)
+                               (list 'p_enchanters_tower_l2 14 19)
+                               #t 'testmirhandler
+                               )))
+               (sigsplit (kern-tag 'ench-test-mirrors
+                       (mk-sig-splitter (list 'ench-test-mirror1 'ench-test-mirror2 nil))
+                       )))
+       (kern-obj-put-at testmirror1 (list p_enchanters_tower_l2 12 18))
+       (kern-obj-put-at testmirror2 (list p_enchanters_tower_l2 14 18))
+       (kern-obj-put-at sigsplit (list p_enchanters_tower_l2  0 0))
+       (kern-obj-put-at (mk-char-sensor 'ench-test-mirrors) (list p_enchanters_tower_l2 12 19))
+       (kern-obj-put-at (mk-char-sensor 'ench-test-mirrors) (list p_enchanters_tower_l2 14 19))
+       (kern-obj-put-at (mk-lever-on 'ench-test-mirrors)  (list p_enchanters_tower_l2 13 18))
+       )
+       
+;;working portal mirror
+(let* ((doormirror1 (kern-tag 'ench-door-mirror1 
+                       (mk-mag-mirror 's_mirror_bg_flagstones
+                               (list 'p_enchanters_tower_l2 20 15)
+                               (list 'p_enchanters_tower_l2 9 17) 
+                               #f 'doormirhandler
+                               )))
+         (doormirror2 (kern-tag 'ench-door-mirror2
+                       (mk-mag-mirror 's_mirror_bg_flagstones
+                               (list 'p_enchanters_tower_l2 9 17)
+                               (list 'p_enchanters_tower_l2 20 15)
+                               #f 'doormirhandler
+                               )))
+               (sigsplit (kern-tag 'ench-door-mirrors
+                       (mk-sig-splitter (list 'ench-door-mirror1 'ench-door-mirror2 nil))
+                       )))
+       (kern-obj-put-at doormirror1 (list p_enchanters_tower_l2 10 17))
+       (kern-obj-put-at doormirror2 (list p_enchanters_tower_l2 19 15))
+       (kern-obj-put-at sigsplit (list p_enchanters_tower_l2  0 0))
+       (kern-obj-put-at (mk-char-sensor 'ench-door-mirrors) (list p_enchanters_tower_l2 9 17))
+       (kern-obj-put-at (mk-char-sensor 'ench-door-mirrors) (list p_enchanters_tower_l2 20 15))
+       (kern-obj-put-at (mk-lever 'ench-door-mirrors)  (list p_enchanters_tower 19 16))
+       )
+;;ench bedroom entrance
+(let* ((broomwall (kern-tag 'ench-broom-wall
+                       (mk-bim-secret 't_secret_door 't_wall (list 'p_enchanters_tower 19 13)))))
+       (kern-obj-put-at ench-broom-wall (list p_enchanters_tower 19 13))
+       (kern-obj-put-at (mk-hidden-mech) (list p_enchanters_tower 20 8))
+       (kern-obj-put-at (mk-disg-lvr 'ench-broom-wall 's_wall_torch) (list p_enchanters_tower 20 8))
+       ) 
+;;library wall entrance
+(let* ((libwall (kern-tag 'ench-lib-wall
+                       (mk-bim-secret 't_secret_door 't_wall (list 'p_enchanters_tower_l2 9 16)))))
+       (kern-obj-put-at ench-lib-wall (list p_enchanters_tower_l2 9 16))
+       (kern-obj-put-at (mk-moving-shelf 
+               (list 'p_enchanters_tower_l2 10 15)
+               (list 'p_enchanters_tower_l2 9 15)
+               'ench-lib-wall)
+                       (list p_enchanters_tower_l2 9 15))
+       )       
+       
+;;magic clock
+(kern-obj-put-at (mk-mag-clock) (list p_enchanters_tower_l2 18 18))
+(kern-mk-place 
+ 'p_enchanters_tower_l3 ; tag
+ "Enchanters Tower Roof" ; name
+ s_keep             ; sprite
+ m_enchanters_tower_l3 ; map
+ #f                 ; wraps
+ #f                 ; underground
+ #f                 ; large-scale (wilderness)
+ #f                 ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ ;;objects
+ (list
+       (put (mk-ladder-down 'p_enchanters_tower_l2 14 15) 
+               14 15)
+       ;; this needs a telescope 
+ )
+ (list 'on-entry-trigger-all) ; hooks
+ nil ; edge entrances
+ )
+
+(define (obj-line objfactory place yloc xloc xmax)
+       (kern-obj-put-at (objfactory xloc yloc) (list place xloc yloc))
+       (if (< xloc xmax)
+               (obj-line objfactory place yloc (+ xloc 1) xmax)
+       ))  
+       
+(define (obj-rect objfactory place xmin xmax ymin ymax)
+       (obj-line objfactory place ymin xmin xmax)
+       (if (< ymin ymax)
+               (obj-rect objfactory place xmin xmax (+ ymin 1) ymax)
+       ))
+
+(define (obj-list objfactory place loclist)
+       (kern-obj-put-at (objfactory (caar loclist) (cadar loclist)) (list place (caar loclist) (cadar loclist)))       
+       (if (not (equal? (cadr loclist) '()))
+               (obj-list objfactory place (cdr loclist))
+       ))
+
+(mk-place-music p_enchanters_tower_l3 'ml-castle)
+       
+;;no teleporting out of the tower!
+;; TODO use same mechanism as gryphon peak
+
+(let ((blockers
+               (lambda (xloc yloc) (mk-blocker))))
+       (obj-rect blockers p_enchanters_tower_l2 0 30 0 7)
+       (obj-rect blockers p_enchanters_tower_l2 0 7 8 22)
+       (obj-rect blockers p_enchanters_tower_l2 23 30 8 22)
+       (obj-rect blockers p_enchanters_tower_l2 0 30 23 30)
+       (obj-rect blockers p_enchanters_tower_l2 8 11 8 8)
+       (obj-rect blockers p_enchanters_tower_l2 19 22 8 8)
+       (obj-rect blockers p_enchanters_tower_l2 8 11 22 22)
+       (obj-rect blockers p_enchanters_tower_l2 19 22 22 22)
+       (obj-list blockers p_enchanters_tower_l2 (list 
+               (list 8 9) (list 8 10) (list 8 11) (list 9 9) 
+               (list 22 9) (list 22 10) (list 22 11) (list 21 9) 
+               (list 8 19) (list 8 20) (list 8 21) (list 9 21) 
+               (list 22 19) (list 22 20) (list 22 21) (list 21 21) 
+               nil))
+       (obj-rect blockers p_enchanters_tower_l3 0 30 0 9)
+       (obj-rect blockers p_enchanters_tower_l3 0 9 10 20)
+       (obj-rect blockers p_enchanters_tower_l3 21 30 10 20)
+       (obj-rect blockers p_enchanters_tower_l3 0 30 21 30)
+       (obj-rect blockers p_enchanters_tower_l3 10 12 10 10)
+       (obj-rect blockers p_enchanters_tower_l3 18 20 10 10)
+       (obj-rect blockers p_enchanters_tower_l3 10 12 20 20)
+       (obj-rect blockers p_enchanters_tower_l3 18 20 20 20)
+       (obj-list blockers p_enchanters_tower_l3 (list 
+               (list 10 11) (list 10 12) (list 20 11) (list 20 12) 
+               (list 10 18) (list 10 19) (list 20 18) (list 20 29) 
+               nil))
+       )
+       
+       
+       
\ No newline at end of file
diff --git a/worlds/haxima-1.002/endless-deeps-mech.scm b/worlds/haxima-1.002/endless-deeps-mech.scm
new file mode 100644 (file)
index 0000000..7b12c45
--- /dev/null
@@ -0,0 +1,394 @@
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Deeps template maps
+
+(kern-mk-map 'm_deeptempl_wall 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn r8 r8 rn r8 rn rn r8 r8 rn rn rn rn rn rn "
+               "rn rn rn rn r4 .. .. re .. ra rc {4 {{ r2 rn rn rn rn rn "
+               "rn rn rn r8 rc .. .. .. .. bb .. .. .. .. ra r8 rn rn rn "
+               "rn rn r8 {{ {2 .. .. {8 .. .. .. .. {8 .. {4 {{ r8 rn rn "
+               "rn r4 .. {1 {8 .. rf {{ {2 {8 .. {4 {{ rf .. {1 .. r2 rn "
+               "rn rn rd {4 {{ {6 {{ rb r5 {{ {a .. {1 .. .. .. .. ra rn "
+               "rn rc .. .. {1 .. {5 {{ r2 r5 {{ rf .. .. {8 .. {4 {{ r2 "
+               "r4 .. bb .. .. .. .. {1 ra rn rd {8 .. bb {{ {2 .. r3 rn "
+               "r4 .. .. .. .. rf .. {8 .. r6 {{ {{ {2 .. {1 .. rb rn rn "
+               "rn rd .. .. {4 {{ rf {{ r3 r8 r9 rd .. .. .. .. bb ra rn "
+               "r4 .. .. .. .. {1 .. {9 r6 {{ {6 {{ rf .. .. .. .. .. r2 "
+               "rn r5 {8 .. bb .. {4 {{ re {1 .. {1 .. .. .. .. .. .. r2 "
+               "rn r4 {{ .. .. .. .. rf .. {8 .. .. .. .. bb {8 .. r3 rn "
+               "rn rn r1 .. rf .. .. .. {4 {{ bb .. .. .. {4 {{ r1 rn rn "
+               "rn rn rn r5 {{ {2 .. .. .. {1 .. .. .. .. .. r3 rn rn rn "
+               "rn rn rn rn r4 {{ {2 .. {c {{ {{ {2 bb r2 rn rn rn rn rn "
+               "rn rn rn rn rn r5 .. r7 {{ r3 r5 .. r3 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn r1 rn r1 rn rn r1 rn rn rn rn rn rn rn "
+       )
+)
+(kern-mk-map 'm_deeptempl_passage 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn r4 .. .. .. .. {4 {{ {2 .. r2 rn rn rn rn "
+               "rn rn rn rn rn rc .. .. .. .. .. {1 .. rb rn rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn {{ {2 .. .. .. .. .. .. .. .. .. {4 {{ rn rn rn "
+               "r8 rn r8 {1 .. .. {8 .. .. .. .. .. .. .. .. rb r8 r8 rn "
+               ".. re .. .. .. {4 {{ {2 .. .. .. .. .. .. {8 .. .. {8 ra "
+               ".. {8 .. .. .. .. {1 .. .. {8 .. .. .. {4 {{ {2 {4 {{ {2 "
+               "{4 {{ {2 .. .. .. .. .. {4 {{ {2 .. .. .. {1 .. .. {1 .. "
+               ".. {1 .. .. .. .. .. bb .. {1 .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. {8 .. .. .. .. .. .. .. "
+               ".. .. bb .. .. .. .. .. .. .. {4 {{ {2 .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. {8 .. .. .. {1 .. .. .. .. .. .. .. "
+               "r5 .. .. .. .. .. {4 {{ {2 .. .. .. .. .. .. .. .. r7 .. "
+               "rn r1 r1 .. {8 .. .. {1 .. .. .. .. .. .. .. .. r1 rn r1 "
+               "rn rn rn r5 {{ {2 .. .. .. .. .. .. .. .. .. bb rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. {8 .. .. .. r2 rn rn rn rn rn "
+               "rn rn rn rn rn rd .. .. {4 {{ {a .. .. ra rn rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. {5 {{ {2 .. .. r2 rn rn rn rn "
+       )
+)
+       
+(kern-mk-map 'm_deeptempl_water 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn rc ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ r2 rn rn rn rn "
+               "rn rn rn rn r4 ~b ~8 ~8 ~~ ~~ ~~ ~8 ~~ ~4 r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. ~% ~6 %c .. ~% ~e r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra r8 rn rn rn "
+               "r8 r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. r8 r8 r8 "
+               "~~ ~5 .. .. .. .. ~C ~7 ~A .. .. bb .. .. .. .. .. ~b ~~ "
+               "~~ ~c .. .. .. .. ~3 -- ~d .. .. .. .. .. .. .. .. bb ~~ "
+               "~~ %c bb .. .. .. ~a ~~ {G {2 .. .. .. .. .. .. .. ~3 ~~ "
+               "~4 .. .. .. .. .. %a ~e {1 .. .. .. .. .. .. .. .. ~2 ~~ "
+               "~~ ~A .. .. .. .. .. .. .. .. .. ~7 .. .. .. .. .. ~a ~~ "
+               "~~ ~d .. .. .. .. .. .. .. .. %3 ~~ ~5 ~A .. .. .. ~D ~~ "
+               "~~ %c .. .. .. ~C ~7 ~A .. .. ~3 -- -- ~d .. .. .. ~3 ~~ "
+               "~4 .. .. .. .. ~3 -- ~d .. ~b ~~ -- ~c ~# .. .. .. ~2 ~~ "
+               "~c .. .. .. .. ~a ~c ~# .. .. %a ~e ~# .. .. .. .. ~e r3 "
+               "r1 r1 r1 .. .. .. .. .. .. .. .. .. .. .. bb .. r1 r1 rn "
+               "rn rn rn r1 r5 .. .. .. .. .. .. .. .. .. r3 r1 rn rn rn "
+               "rn rn rn rn r4 .. ~C ~7 ~A .. .. ~C ~3 ~d r2 rn rn rn rn "
+               "rn rn rn rn rn rd ~3 ~~ ~~ ~5 ~E ~3 ~~ rb rn rn rn rn rn "
+               "rn rn rn rn r4 ~3 ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~5 r2 rn rn rn rn "
+       )
+)
+       
+       
+(kern-mk-map 'm_deeptempl_hole 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn rc vv vv vv vv vv vv vv *c r2 rn rn rn rn "
+               "rn rn rn rn r4 *b vv vv *8 *c .i *e .g rb rn rn rn rn rn "
+               "rn rn rn rn r4 .h *e .g .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn .. .. .. {8 .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 rn r8 .. .. *7 {j .. .. .. .. .. {8 .. .. .. rn r8 r8 "
+               "*5 re .. .. .. *a vv *5 .j .. .. {4 {{ {a .. .. re .. *3 "
+               "vv *5 .. .. .. .. .h vv *5 .j .. .. bb {{ {2 .. .. .l vv "
+               "vv *4 .. .. .. .. .. *a vv *5 .j .. .. {1 .. .. *b vv vv "
+               "vv *c .. .. .. .. {4 {h vv vv *5 .j .. .. .. .. .h *a vv "
+               "vv .g .. .. .. {8 .. .. *2 vv vv *d .. .. .. .. .. .m vv "
+               "vv .j .. .. {c {{ {2 .. *a vv vv .g .. .. {8 .. .. *b vv "
+               "vv *d .. {4 {{ rf .. .. rf *a vv {j {2 {4 {{ {2 .. .m vv "
+               "vv .k .. .. {1 .. .. .. .. .h *a *5 .j .. {1 .. .. *3 vv "
+               "vv *d .. .. .. .. .. .. .. .. .h *a *5 .. .. .. .. *e r3 "
+               "r1 r1 r1 .. .. .. .. .. .. .. {4 {h *e .. .. .. r1 r1 rn "
+               "rn rn rn .. .. .. .. .. .. .. .. {1 .. .. .. .. rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. *7 .j .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 *7 .n *3 *5 .n vv *5 .n *7 r2 rn rn rn rn "
+               "rn rn rn rn r4 vv vv vv vv vv vv vv vv vv r2 rn rn rn rn "
+       )
+)
+
+(kern-mk-map 'm_deeptempl_lava 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn r4 !_ !_ !_ !_ !_ !_ !_ ra rn rn rn rn rn "
+               "rn rn rn rn rn rc !! !! !! !! !! !! !_ !! r2 rn rn rn rn "
+               "rn rn rn rn r4 !! !c .. .. .. bb !a !c .. r2 rn rn rn rn "
+               "rn rn rn bb re .. .. .. .. .. .. .. .. .. {4 {{ rn rn rn "
+               "rn r8 r8 .. .. .. .. .. .. .. .. .. .. .. .. {1 r8 rn rn "
+               "rc !! !! .. .. .. rf .. .. .. .. !3 !! !5 .. .. !! ra r8 "
+               "!_ !_ !c .. .. .. .. {8 .. .. .. !! !_ !c .. .. !! !_ !_ "
+               "!_ !! {# .. .. .. {4 {{ {2 .. .. !a !c .. {8 .. !a !! !_ "
+               "!_ !! {1 .. bb .. .. {1 .. .. .. .. .. {4 {{ {2 .. !! !_ "
+               "!_ !! .. .. .. .. .. !7 .. .. .. .. .. .. {1 .. .. !! !_ "
+               "!_ !! .. .. .. .. !3 !! !5 .. .. .. .. .. .. .. .. !! !_ "
+               "!_ !! .. .. .. !3 !_ !! !c .. .. .. bb .. .. .. .. !! !_ "
+               "!_ !! !5 .. .. !a !c .. .. .. .. !3 !5 .. .. .. {8 !! !_ "
+               "!_ r7 !! .. .. .. .. .. .. .. .. !a !c .. .. .. {{ r7 !_ "
+               "r1 rn r1 .. {8 .. .. .. .. .. .. .. .. .. .. rb r1 rn r1 "
+               "rn rn rn r5 {{ {2 .. .. .. .. .. .. .. .. .. bb rn rn rn "
+               "rn rn rn rn r4 .. .. !7 bb .. .. !3 !! !! r2 rn rn rn rn "
+               "rn rn rn rn r4 !! !! !! !! !! !! !! !_ rb rn rn rn rn rn "
+               "rn rn rn rn rn r5 !_ !_ !_ !_ !_ !_ !_ !_ r2 rn rn rn rn "
+       )
+)
+       
+(kern-mk-map 'm_deeptempl_swamp 19 19 pal_expanded
+       (list
+               "rn rn rn rn r4 %a %% %% %% %% %% %% ~f %% r2 rn rn rn rn "
+               "rn rn rn rn r4 {% %a %c {4 {% %% %% %% %c r2 rn rn rn rn "
+               "rn rn rn rn rn r5 .. .. .. {1 %% %% {# {2 r2 rn rn rn rn "
+               "rn rn rn .. re %% .. .. bb .. %% %% %% %% %c r2 rn rn rn "
+               "rn r8 r8 .. %b %% %5 .. %3 %% %% %c {8 .. .. ra r8 r8 rn "
+               "rc {{ {2 .. .. %a %% %% %% %c .. {4 {{ {2 .. .. {{ %7 ra "
+               "%% %5 .. .. bb .. .. %% %% .. .. .. {1 .. .. .. {1 %% %% "
+               "%% ~f %% .. .. .. %3 %% %% %5 .. {8 .. %7 .. .. %% %% ~f "
+               "%% %% %% %% %5 .. %% ~b ~d %% %d {{ %3 %% %% %% %% %% %% "
+               "%% %% .. .. %a %% %% %% %% %c rb rd %% %% %c .. .. .. %% "
+               "%% %% bb .. .. %a %% %% %% .. %3 ~e %% .. .. .. .. {8 %% "
+               "%% %c .. .. .. .. %% .. %a %% %% %% %c .. {8 .. {4 {C %% "
+               "%% .. .. .. .. %3 %% .. .. %a %% %% .. {4 {{ {2 .. %b %% "
+               "%c r7 .. .. .. %% ~f %5 .. .. .. %% .. .. {1 .. .. r7 %a "
+               "r1 rn r1 .. .. %% %% %c .. .. .. %% %5 .. .. r3 r1 rn r1 "
+               "rn rn rn .. r7 %% %% .. .. bb .. %% %% %% %5 r2 rn rn rn "
+               "rn rn rn rn r4 .. {8 .. .. .. %% %% %% {{ r2 rn rn rn rn "
+               "rn rn rn rn rn rd {C %3 %% %% %% %% %% rb rn rn rn rn rn "
+               "rn rn rn rn r4 %3 %% %% %% %% %% ~f %% %5 r2 rn rn rn rn "
+       )
+)
+       
+(kern-mk-map 'm_deeptempl_break 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn r4 bb .. .. r2 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn r8 r8 r4 .. .. bb ra r8 rn rn rn rn rn rn "
+               "rn rn rn rn r4 .. .. re .. .. rf {4 {{ r2 rn rn rn rn rn "
+               "rn rn rn r8 rc .. .. .. .. bb .. .. .. .. ra r8 rn rn rn "
+               "rn rn r8 {{ {2 .. .. {8 .. .. .. .. {8 .. {4 {{ r8 rn rn "
+               "rn r4 .. {1 {8 .. rf {{ {2 {8 .. {4 {{ rf .. {1 .. r2 rn "
+               "rn rn rd {4 {{ {6 {{ rb r5 {{ {a .. {1 .. .. .. .. ra rn "
+               "r8 rc .. .. {1 .. {5 {{ r2 r5 {{ rf .. .. {8 .. {4 {{ ra "
+               "bb .. bb .. .. .. .. {1 ra rn rd {8 .. bb {{ {2 .. {1 bb "
+               ".. .. .. .. .. rf .. {8 .. r6 {{ {{ {2 .. {1 .. rf .. .. "
+               ".. bb .. .. {4 {{ rf {{ r3 r8 r9 rd .. .. .. .. bb .. .. "
+               "r5 .. .. .. .. {1 .. {9 r6 {{ {6 {{ rf .. .. .. .. .. r3 "
+               "rn r5 {8 .. bb .. {4 {{ re {1 .. {1 .. .. .. .. .. .. r2 "
+               "rn r4 {{ .. .. .. .. rf .. {8 .. .. .. .. bb {8 .. r3 rn "
+               "rn rn r1 .. rf .. .. .. {4 {{ bb .. .. .. {4 {{ r1 rn rn "
+               "rn rn rn r5 {{ {2 .. .. .. {1 .. .. .. .. .. r3 rn rn rn "
+               "rn rn rn rn r4 {{ {2 .. .. .. .. .. bb r2 rn rn rn rn rn "
+               "rn rn rn rn rn r5 .. r7 .. .. bb .. r3 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn r1 r4 bb .. .. r3 rn rn rn rn rn rn rn "
+       )
+)
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Deeps random map
+
+
+;probability for edge terrains... out of 83
+(define deep-terrain-edges
+       (list
+               (list 20 'm_deeptempl_wall #f)
+               (list 25 'm_deeptempl_water #f)
+               (list 30 'm_deeptempl_hole #f)
+               (list 35 'm_deeptempl_lava #f)
+               (list 40 'm_deeptempl_swamp #t)         
+               (list 100 'm_deeptempl_passage #t)
+       ))
+
+;probability for area terrains... out of 149
+(define deep-terrain-area
+       (list
+               (list 30 'm_deeptempl_wall)
+               (list 45 'm_deeptempl_water)
+               (list 65 'm_deeptempl_hole)             
+               (list 75 'm_deeptempl_lava)             
+               (list 80 'm_deeptempl_swamp)            
+               (list 150 'm_deeptempl_passage)
+       ))
+
+;map areas replaced by the various blitting ops
+(define deep-room-blitstats
+       (prmap-mk-blitstats 19 19 3 4 3))
+
+
+;parameters to random number generators
+(define (deep-rno) (+ (kern-dice-roll "1d70" 33)))
+(define deep-random-type-ew (prmap-mk-prng-params (deep-rno) (deep-rno) 0 (deep-rno) 83))
+(define deep-random-type-ns (prmap-mk-prng-params (deep-rno) (deep-rno) 0 (deep-rno) 83))
+(define deep-random-type-area (prmap-mk-prng-params (deep-rno) (deep-rno) 0 (deep-rno) 149))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; critter lists
+
+(define deep-monster-types
+       (list 
+               (list 
+                       (list 100 'bat)
+               )
+               (list
+                       (list 100 'rat)
+                       (list 200 'bat)
+               )
+               (list
+                       (list 100 'giant-spider)
+                       (list 150 'queen-spider)
+               )
+               (list
+                       (list 100 'cave-goblin-slinger)
+                       (list 200 'cave-goblin-berserker)
+                       (list 250 'cave-goblin-priest)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'cave-goblin-berserker-m)
+                       (list 300 'troll-m)
+                       (list 350 'troll-geomancer-m)
+               )
+               (list
+                       (list 100 'green-slime)
+                       (list 200 'yellow-slime)
+               )       
+               (list
+                       (list 100 'zorn)
+               )
+               (list
+                       (list 20 'ghast)
+                       (list 200 'demon)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'cave-goblin-berserker-m)
+                       (list 150 'troll-m)
+                       (list 350 'gint-warrior-m)
+                       (list 400 'gint-mage-m)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'headless)
+                       (list 150 'cave-goblin-berserker-m)
+                       (list 200 'troll-m)
+                       (list 250 'gint-warrior-m)
+                       (list 350 'gazer)
+               )
+               (list
+                       (list 25 'cave-goblin-slinger-m)
+                       (list 50 'cave-goblin-berserker-m)
+                       (list 300 'dragon)
+               )
+               (list
+                       (list 20 'ghast)
+                       (list 70 'skeletal-warrior)
+                       (list 120 'skeletal-spear-thrower)
+                       (list 150 'craven-archer)
+                       (list 300 'death-knight)
+                       (list 350 'demon)
+               )
+               (list
+                       (list 100 'skeletal-warrior)
+                       (list 200 'skeletal-spear-thrower)
+                       (list 250 'lich)
+               )
+               (list 
+                       (list 100 'headless)
+                       (list 150 'skeletal-warrior)
+                       (list 200 'skeletal-spear-thrower)
+                       (list 220 'craven-archer)
+                       (list 250 'death-knight)
+                       (list 260 'demon)
+                       (list 330 'warlock)
+               )
+       )
+)
+
+(define deep-group-types
+       (list
+               (list 10 0 100 "1d4+3") ;bats
+               (list 20 1 100 "1d4+3") ;rats
+               (list 30 1 200 "1d6+4") ;bats n rats
+               (list 40 5 100 "1d3+2") ;slime
+               (list 50 2 100 "1d4+3") ;spiders
+               (list 60 3 100 "1d3+1") ;goblins
+               (list 70 2 110 "1d4+3") ;spiders 1q
+               (list 80 13 100 "1d6+4") ;headless
+               (list 90 2 150 "1d6+4") ;spiders +qs
+               (list 100 5 200 "1d6+3") ;slime+
+               (list 110 3 200 "1d6+4") ;goblin war
+               (list 120 7 20 "1d6+1")  ;ghost
+               (list 130 11 120 "1d6+4") ;skels
+               (list 140 4 300 "1d6+3") ;trolls
+               (list 150 6 100 "1d2")   ;zorn
+               (list 160 8 350 "1d6+3") ;gint
+               (list 170 7 22 "1d6+1")  ;ghost + d
+               (list 180 11 300 "2d4+4") ;deathknights
+               (list 190 11 310 "2d4+4") ;deathknights +d
+               (list 200 3 210 "1d6+5") ;goblin war +p
+               (list 210 7 200 "1d3")   ;demons
+               (list 220 3 250 "2d4+4") ;goblin tribe
+               (list 230 4 350 "1d6+5") ;trolls +m
+               (list 240 8 400 "2d4+4") ;gint + m
+               (list 250 10 300 "1d4")  ;dragon
+               (list 260 10 80 "1d6+3") ;dragon + gob  
+               (list 270 9 260 "1d6+3") ;gazer
+               (list 280 13 330 "2d4+4") ;warlock              
+               (list 290 12 205 "2d4+4") ;lich 
+               (list 300 9 320 "2d4+4") ;gazers
+       )
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; handles
+
+(define (deeps-link-factory x y z map dir)
+               (list 'm_deeptempl_break nil)
+               )
+
+(define (deeps-init-cohesion mapdata)
+       (if (list-ref mapdata 10)
+               (begin
+                       ;;(kern-log-msg "begin cohesion check")
+                       (prmap-ensure-cohesion mapdata -5 6 -6 5 0 deeps-link-factory)
+                       ;;(kern-log-msg "end cohesion check")
+                       (mutable-list-set mapdata 10 #f)
+               )))
+               
+(define (deeps-room-handle-deeps kplace kplayer)
+       (let* (
+               (roomdata (get-roomdata kplace))
+               (mapdata (prmap-get-mapdata (eval 'p_deeps_1)))
+               )
+               (prmap-room-freeze-current mapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)
+               (prmap-room-cleanout kplace)
+               (prmap-room-thaw kplace mapdata)                
+               (prmap-room-blit-map kplace roomdata mapdata)
+               (prmap-room-init-contents kplace roomdata)
+       ))
+
+(define (deeps-room-handle-garrison kplace kplayer)
+       (let* (
+               (roomdata (get-roomdata kplace))
+               (mapdata (prmap-get-mapdata (eval 'p_deeps_1)))
+               )
+               (deeps-init-cohesion mapdata)
+               (prmap-room-freeze-current mapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)
+       ))      
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Plot type stuff
+
+(mk-reusable-item 
+ 't_garrison_log "Garrison Log" s_lexicon v-hard
+ (lambda (klexicon kuser)
+   (kern-ui-page-text
+   "Garrison Log"
+   ""
+   (string-append
+       "The log details events at the garrison "
+       "while it was still in operation. Early "
+       "entries detail several attempts to "
+       "clear the surrounding caverns.")
+   ""
+   (string-append
+   "However, the paladins were "
+   "unable to even determine how "
+   "large the dungeon is, and "
+   "eventually settled on a policy "
+   "of containment by fortifying "
+   "this bottleneck position.")
+   )))
+
diff --git a/worlds/haxima-1.002/endless-deeps.scm b/worlds/haxima-1.002/endless-deeps.scm
new file mode 100644 (file)
index 0000000..ecabd77
--- /dev/null
@@ -0,0 +1,477 @@
+;
+; I wanted to make the area down here too big and nasty for the paladins to have wiped out.
+; So I thought Id just make a more or less infinite pseudorandom dungeon.
+; The players dont need to go out there, but they can wander around if they like.
+; However, if they do, it is quite large enough for them to get lost and die in.
+;
+; TODO: occasional 'teleportation' to make "get lost and die" that much easier
+;    this latter should occasionally connect a room to a room with a matching
+;    edge at a much different location to the expected one.
+;
+
+(kern-mk-place 
+       'p_lost_garrison
+       "Deep Fortress"
+       nil          ; sprite
+       (kern-mk-map nil 38 38 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. ra rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. .. r2 rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r3 rn xx xx xx rn rn rn xx xx xx rn rn rn xx xx rn rn rn xx xx rn rn rn "
+               "rn r8 rn xx xx xx w+ xx ,, x! ,, xx w+ xx xx xx xx xx rr x! xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn "
+               "rc .. ra xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               ".. .. .. rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, .. ,, ,, xx ,, ,, ,, xx ,, ,, xx ,, xx ,, ,, xx xx rn rn "
+               ".. .. .. w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, rr xx xx x! ,, x! xx xx xx xx rn rn "
+               ".. .. .. xx ,, ,, .. ,, ,, ,, .. bb ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               ".. .. .. ,, ,, ,, ,, ,, ,, ,, ,, .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx ,, xx ,, ,, xx rn rn rn "
+               ".. .. .. x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, ,, x! ,, ,, ,, xx xx xx xx ,, xx xx xx xx rn rn rn "
+               ".. .. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx xx rn rn "
+               ".. .. .. xx ,, ,, bb ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx xx rn rn "
+               ".. .. .. w+ ,, ,, ,, ,, ,, ,, ,, ,, .. ,, ,, w+ ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx rn rn "
+               ".. .. .. xx ,, ,, ,, ,, ,, .. ,, ,, bb ,, ,, xx ,, ,, ,, ,, ,, .. xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               "r1 r5 .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, .. .. .. xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               "rn rn xx xx xx xx w+ w+ x! w+ x! w+ w+ xx xx xx xx xx xx x! xx xx xx ,, ,, ,, x! ,, [[ @@ @@ @@ ]] ,, x! xx rn rn "
+               "rn rn xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx rn xx xx rn xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               "rn rn rn rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb r2 rn rn rn rn rn xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               "rn rn rn x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! rn rn rn rn rn rn xx ,, ,, ,, xx xx xx xx xx xx xx xx xx xx rn rn "
+               "rn rn xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn rn rn xx ,, ,, ,, xx [[ .M .E .D .I .K ]] xx xx rn rn "
+               "rn rn xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn rn rn rr ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               "rn rn rn xx xx rr xx rr xx xx xx xx ,, ,, ,, xx xx rn rn xx xx xx rr ,, ,, ,, x! ,, ,, ,, ,, ,, ,, ,, x! rn rn rn "
+               "rn rn rn xx ,, ,, ,, [[ @@ @@ ]] xx ,, ,, ,, x! xx xx x! xx xx xx x! ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, bb r2 rn rn "
+               "rn rn rn xx 00 ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx rn rn rn "
+               "rn rn xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx rn rn "
+               "rn rn rn xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx xx rn rn "
+               "rn rn xx xx xx xx xx xx x! xx xx xx xx xx xx ,, ,, xx xx xx xx ,, ,, xx xx xx xx xx xx xx xx xx rr xx xx rn rn rn "
+               "rn rn xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, 00 xx rn rn rn "
+               "rn rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx xx rn rn "
+               "rn rn rn rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, [[ @@ @@ @@ @@ @@ @@ @@ @@ ]] ,, ,, ,, 00 xx xx rn rn "
+               "rn rn rn rr .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx rn rn rn "
+               "rn rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, 00 xx rn rn rn "
+               "rn rn xx rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr ,, [[ @@ @@ @@ @@ @@ @@ @@ @@ ]] ,, ,, ,, && xx xx rn rn "
+               "rn rn xx bb ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, 00 xx xx xx rn "
+               "rn rn xx xx xx xx xx xx xx xx xx rr xx xx xx xx xx xx xx xx xx x! xx xx xx xx xx x! xx xx xx xx xx xx xx xx rn rn "
+               "rn rn rn xx rn xx xx xx rn rn xx xx xx xx rn rn rn xx xx xx xx xx rn xx rn xx rn xx xx rn xx xx rn rn xx rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "            )       
+       )
+
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list (put (mk-monman) 0 0) ; objects
+               (put (mk-ladder-up 'p_deepness 12 9) 11 11)
+               (put (kern-tag 'ednp1 (mk-portcullis)) 8 3)
+               (put (kern-tag 'ednp2 (mk-connected-portcullis 'ednp1)) 10 3)
+               (put (kern-tag 'edwp1 (mk-portcullis)) 3 8)
+               (put (kern-tag 'edwp2 (mk-connected-portcullis 'edwp1)) 3 10)
+               (put (kern-tag 'ede1p1 (mk-portcullis)) 15 8)
+               (put (kern-tag 'ede1p2 (mk-connected-portcullis 'ede1p1)) 15 10)
+               (put (kern-tag 'ede2p1 (mk-portcullis)) 22 8)
+               (put (kern-tag 'ede2p2 (mk-connected-portcullis 'ede2p1)) 22 10)
+               (put (mk-locked-door) 29 4)
+               (put (mk-door) 29 7)
+               (put (mk-door) 31 4)
+               (put (mk-locked-door) 31 7)
+               (put (mk-door) 26 12)
+               (put (mk-door) 26 24)
+               (put (mk-door) 21 26)
+               (put (mk-door) 22 26)
+               (put (mk-door) 15 26)
+               (put (mk-door) 16 26)
+               (put (mk-door) 11 24)
+       
+               (put (mk-lever 'edwp2) 4 17)
+               (put (mk-lever-on 'ednp2) 4 16)
+               (put (mk-lever-on 'ede1p2) 14 16)
+               (put (mk-lever-on 'ede2p2) 25 4)
+       
+               (put (mk-bed) 4 25)
+               (put (mk-bed) 5 28)
+               (put (mk-bed) 8 28)
+               (put (mk-bed) 11 28)
+               (put (mk-bed) 14 28)
+               (put (mk-bed) 17 28)
+               (put (mk-bed) 5 30)
+               (put (mk-bed) 8 30)
+               (put (mk-bed) 11 30)
+               (put (mk-bed) 14 30)
+               (put (mk-bed) 17 30)
+               (put (mk-bed) 5 32)
+               (put (mk-bed) 8 32)
+               (put (mk-bed) 11 32)
+               (put (mk-bed) 14 32)
+               (put (mk-bed) 17 32)
+               (put (mk-bed) 28 21)
+               (put (mk-bed) 32 24)
+               (put (mk-bed) 30 24)
+               (put (mk-bed) 32 22)
+               
+               (put (mk-broken-clock s_clock_hand_sw s_clock_hand_se "The clock reads 8:27") 4 22)
+               (put (kern-mk-obj t_garrison_log 1) 4 23)
+               (put (kern-mk-obj t_food 21) 33 27)
+               (put (kern-mk-obj t_food 1) 22 29)
+               (put (kern-mk-obj t_food 1) 27 32)
+               
+               (put (spawn-pt 'troll-m) 6 17)
+               (put (spawn-pt 'troll-m) 11 19)
+               (put (spawn-pt 'cave-goblin-berserker-m) 29 11)
+               (put (spawn-pt 'cave-goblin-slinger-m) 32 13)
+               (put (spawn-pt 'cave-goblin-berserker-m) 32 23)
+               (put (spawn-pt 'gint-warrior-m) 23 28)
+               (put (spawn-pt 'gint-warrior-m) 28 33)
+               
+               ;;guards possessed or dead- captain + 11 troops
+               (put (mk-corpse2
+                  '(
+                       (1 t_armor_chain)
+                       (1 t_sword_2)
+                       (1 t_scratched_shield)
+                       )) 7 24)
+               
+               
+               (put (mk-npc 'corrupt-halberdier 4) 18 12)
+               (put (mk-npc 'corrupt-halberdier 8) 17 6)
+               (put (mk-npc 'corrupt-halberdier 6) 24 12)
+               (put (mk-npc 'corrupt-crossbowman 5) 8 17)
+               (put (mk-npc 'corrupt-crossbowman 6) 14 5)
+               
+               (put (mk-npc 'corrupt-halberdier 7) 24 5)
+               (put (mk-corpse2
+                  '(
+                       (2 t_heal_potion)
+                       (1 t_crossbow)
+                       (13 t_bolt)
+                       )) 13 6)
+               (put (mk-corpse-with-loot) 11 9)
+               (put (mk-corpse-with-loot) 17 13)
+               (put (mk-corpse-with-loot) 7 29)
+
+               (put (mk-corpse-with-loot) 30 30)
+               
+               
+               ;;additional critters
+               ;;gazers
+               (put (mk-npc 'gazer 9) 25 8)
+               (put (mk-npc 'gazer 8) 22 31)
+               (put (mk-npc 'gazer 7) 7 25)
+               (put (mk-npc 'gazer 6) 32 11)
+               
+               ;;gints
+               (put (mk-npc 'gint-warrior-m 8) 5 6)
+               (put (mk-npc 'gint-warrior-m 7) 12 32)
+               (put (mk-npc 'gint-warrior-m 6) 30 27)
+               
+               ;;trolls
+               (put (mk-npc 'troll-m 7) 7 19)
+               (put (mk-npc 'troll-m 6) 29 17)         
+               (put (mk-npc 'troll-m 5) 10 29)
+               (put (mk-npc 'troll-m 5) 31 21)
+               (put (mk-npc 'troll-m 4) 13 16)
+               
+               ;;goblins
+               (put (mk-npc 'cave-goblin-berserker-m 6) 12 31)
+               (put (mk-npc 'cave-goblin-berserker-m 5) 9 32)
+               (put (mk-npc 'cave-goblin-berserker-m 4) 18 8)
+               (put (mk-npc 'cave-goblin-slinger-m 6) 7 20)
+               (put (mk-npc 'cave-goblin-slinger-m 5) 12 16)
+               (put (mk-npc 'cave-goblin-slinger-m 4) 10 32)
+               (put (mk-npc 'cave-goblin-slinger-m 3) 32 16)
+               
+               ;; Rune
+               (put (mk-buried 't_rune_p 1) 3 33)
+        )
+        (list
+               'on-entry-to-dungeon-room
+               'deeps-room-handle-garrison
+               ) ;; hooks
+               (list ;; edge entrances
+                       (list east 0 9)
+                       (list south 9 0)
+               )
+ )
+
+(mk-place-music p_lost_garrison 'ml-dungeon-adventure)
+
+
+(kern-mk-place 
+       'p_deeps_1
+       "endless deepness"
+        nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'deeps-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+ (kern-mk-place 
+       'p_deeps_2
+       "endless deepness"
+       nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list (put (mk-monman) 0 0) ; objects
+        )
+        (list
+               ;'on-entry-to-dungeon-room
+               'deeps-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+   (kern-mk-place 
+       'p_deeps_3
+       "endless deepness"
+        nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list (put (mk-monman) 0 0) ; objects
+        )
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'deeps-room-handle-deeps
+       ) ;; hooks
+       nil
+ )
+   (kern-mk-place 
+       'p_deeps_4
+       "endless deepness"
+        nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list (put (mk-monman) 0 0) ; objects
+        )
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'deeps-room-handle-deeps
+       ) ;; hooks
+       nil
+ )
+ (kern-mk-place 
+       'p_deeps_5
+       "endless deepness"
+         nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list (put (mk-monman) 0 0) ; objects
+        )
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'deeps-room-handle-deeps
+       ) ;; hooks
+       nil
+ )
+
+(mk-place-music p_deeps_1 'ml-dungeon-adventure)
+(mk-place-music p_deeps_2 'ml-dungeon-adventure)
+(mk-place-music p_deeps_3 'ml-dungeon-adventure)
+(mk-place-music p_deeps_4 'ml-dungeon-adventure)
+(mk-place-music p_deeps_5 'ml-dungeon-adventure)
+
+ (kern-mk-place 
+       'deeps_data
+       "null"
+         nil          ; sprite
+       (kern-mk-map nil 1 1 pal_expanded
+               (list
+                 "rr"
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil ;; objects
+       nil ;; hooks
+       nil
+ )
+
+(prmap-linkrooms-2d 'p_deeps_1 'p_deeps_2 'p_deeps_3 'p_deeps_4 'p_deeps_5)
+(prmap-mk-roomdata 'p_lost_garrison 0 0 0 (list 'p_deeps_1 'p_deeps_2 'p_deeps_5 'p_deeps_3))
+
+(prmap-set-mapdata p_deeps_1 (prmap-mk-mapdata "endless_deeps" deep-random-type-ns deep-random-type-ew deep-random-type-area 'deep-terrain-edges 'deep-terrain-area 'deep-room-blitstats nil))
+
+(let ((deep-hardlinks (prmap-params-hardlinks (prmap-get-mapdata p_deeps_1))))
+       (define (link-rm xloc yloc zloc dir target maptemplate passable )
+               (prmap-room-hardlink-set! xloc yloc zloc deep-hardlinks dir target maptemplate passable nil)
+               )
+               
+;;---------------------------------------------------------
+;; hardlink setup
+;; 
+;;                     x       y       z       dir             target                          template                                passable
+
+(link-rm       0       1       0       south   'p_lost_garrison        'm_deeptempl_passage    #f)
+(link-rm       1       1       0       south   nil                                     'm_deeptempl_wall               #f)
+(link-rm       -1      0       0       east    'p_lost_garrison        'm_deeptempl_passage    #f)
+(link-rm       2       0       0       west    nil                                     'm_deeptempl_wall               #f)
+(link-rm       -1      -1      0       east    nil                                     'm_deeptempl_wall               #f)
+(link-rm       2       -1      0       west    nil                                     'm_deeptempl_wall               #f)
+(link-rm       0       -2      0       north   nil                                     'm_deeptempl_wall               #f)
+(link-rm       1       -2      0       north   nil                             'm_deeptempl_wall               #f)
+)
+
+;;flag for checking if cohesion check still needs to be performed
+(mutable-list-set (prmap-get-mapdata p_deeps_1) 10 #t)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/engineer.scm b/worlds/haxima-1.002/engineer.scm
new file mode 100644 (file)
index 0000000..8cc2c26
--- /dev/null
@@ -0,0 +1,369 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define engineer-start-lvl 8)
+
+(define voidship-parts
+  (list 
+       (list t_power_core 1)
+       (list sulphorous_ash 20)
+       (list t_gem 10)
+  ))
+
+(define voidship-loc (mk-loc 'p_shard 50 3))
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Engineer's Tower Ground Floor"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_engineer
+               (list 0  0  eng-workshop   "working")
+               (list 1  0  eng-bed        "sleeping")
+               (list 10 0  eng-workshop   "working")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (engineer-mk)
+  (list #f 
+        (mk-quest)))
+(define (eng-met? gob) (car gob))
+(define (eng-quest gob) (cadr gob))
+(define (eng-met! gob val) (set-car! gob val))
+
+;; ----------------------------------------------------------------------------
+;; Voidship plans
+;; ----------------------------------------------------------------------------
+(mk-reusable-item 
+ 't_voidship_plans "Voidship Plans" s_lexicon norm
+ (lambda (klexicon kuser)
+   (kern-ui-page-text
+   "Voidship Plans"
+   "Parts List:"
+   " Sulphurous Ash (20)"
+   " Gems (10)"
+   " Power Core (1)"
+   )))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; The Engineer is a Wright of great knowledge, and one of the Wise.
+;; He dwells in an isolated workshop on a nearly inaccessible
+;; void-mesa (or void-island) off the edge of the Shard.
+;;----------------------------------------------------------------------------
+(define (eng-hail knpc kpc)
+  (say knpc "[You meet a thin man with wild, white hair. "
+       "He doesn't seem to notice you at first] Oh, hello."))
+
+(define (eng-name knpc kpc)
+  (say knpc "Rudolph. I'm better known as the Engineer."))
+
+(define (eng-job knpc kpc)
+  (say knpc "Oh, this and that. I like to make things."))
+
+(define (eng-default knpc kpc)
+  (say knpc "I don't know. Ask the Enchanter."))
+
+(define (eng-bye knpc kpc)
+  (say knpc "[He seems to have forgotten about you already]"))
+
+(define (eng-join knpc kpc)
+  (say knpc "Too busy. Try the Warritrix, she likes adventures."))
+
+(define (eng-warr knpc kpc)
+  (say knpc "I understand she's one of the finest warriors to ever live, "
+       "but I know for a fact she's one of the most noble. When she isn't "
+       "off doing something incredibly brave and stupid you can find her "
+       "at Glasdrin.")
+    (quest-wise-subinit 'questentry-warritrix)
+       (quest-data-update 'questentry-warritrix 'general-loc 1)
+       )
+
+(define (eng-make knpc kpc)
+  (say knpc "I work on all kinds of different things. Lately I've been "
+       "interested in devices for traveling: gates, voidships, etc. "
+       "Inventing is an obsession of mine."))
+
+(define (eng-wand knpc kpc)
+  (say knpc "You're a Wanderer? I've always wanted to meet one. "
+       "Did you build your own gate?")
+  (kern-conv-get-reply kpc)
+  (say knpc "I've always wondered how it could be done. "
+       "I have some theories, and I've designed a voidship "
+       "to test some of them, but it isn't finished yet."))
+
+(define (eng-void knpc kpc)
+  (let* ((eng (kobj-gob-data knpc))
+         (quest (eng-quest eng)))
+
+    (define (remove-stuff)
+      (map (lambda (ktype) 
+             (kern-obj-remove-from-inventory kpc (car ktype) (cadr ktype)))
+           voidship-parts))
+
+       ;;FIXME: the grammer here needs work
+       
+    (define (really-has-parts?)
+      (display "really-has-parts?")(newline)
+      (let ((missing (filter 
+                               (lambda (ktype)
+                                       (let ((nrem (- (cadr ktype) (num-in-inventory kpc (car ktype)))))
+                                               (cond 
+                                                       ((> nrem 1)
+                                                               (begin
+                                                                       (say knpc "We still need " nrem " " (kern-type-get-name (car ktype)) "s")
+                                                                       #t))
+                                                       ((> nrem 0)
+                                                               (begin
+                                                                       (say knpc "We still need the " (kern-type-get-name (car ktype)))
+                                                                       #t))
+                                                       (else #f))))
+                                       voidship-parts)))
+               
+        (if (null? missing)
+                       #t
+            #f)))
+
+    (define (build-ship)
+      (say knpc "Yes, it looks like you have everything. "
+           "Well, let's get to work...")
+      (remove-stuff)
+      (kern-log-msg "[After a good deal of effort, cursing, trying, failing...]")
+      (prompt-for-key)
+      (kern-log-msg "[retrying, refailing, pacing up and down, tearing out "
+           "fistfuls of hair...]")
+      (prompt-for-key)
+      (kern-log-msg "[more cursing, arguing, starting over, failing again...]")
+      (prompt-for-key)
+      (kern-log-msg "[retrying, refailing, weeping, gnashing of teeth...]")
+      (prompt-for-key)
+      (kern-log-msg "[...and so on and so forth...]")
+      (prompt-for-key)
+      (kern-log-msg "[...finally...]")
+      (prompt-for-key)
+      (kern-log-msg "[...oh, hell, now what?...]")
+      (prompt-for-key)
+      (kern-log-msg "[...but then...]")
+      (kern-obj-relocate (mk-voidship) (eval-loc voidship-loc) nil)
+      (kern-log-msg "[You both collapse with exhaustion] ")
+      (say knpc
+           "Well. That wasn't so bad. She's all yours now, waiting "
+           "for you outside at the end of the dock. Good luck! ")
+      (kern-log-msg "[He starts to snore]")
+      (kern-obj-add-effect knpc ef_sleep nil)
+      (quest-done! quest #t)
+      (kern-conv-end))
+
+    (define (missing-power-core?)
+      (not (in-inventory? kpc t_power_core)))
+
+    (define (has-plans)
+      (say knpc "Ah, you've found the plans for my voidship! "
+           "Do you have all the parts we need?")
+      (if (kern-conv-get-yes-no? kpc)
+          (if (really-has-parts?)
+              (build-ship))
+          (if (missing-power-core?)
+              (say knpc "Somewhere across the chasm to the south lies a wrecked voidship. "
+                   "If you can find a way to cross the chasm it might have a power core "
+                   "you can salvage.")
+              (say knpc "Well, what are you waiting for? Go get them.")
+              )))
+      
+    (define (no-plans)
+      (say knpc "A great void surrounds the Shard. I've designed a ship "
+           "which should be able to cross the void, but it isn't "
+           "finished yet. I've got the plans around here someplace. "
+           "If you find them let me know.")
+           (quest-data-update 'questentry-whereami 'shard 2)
+           )
+
+    (if (quest-done? quest)
+        (say knpc "It's all finished.")
+        (if (in-inventory? kpc t_voidship_plans)
+            (has-plans)
+            (no-plans)))))
+
+(define (eng-gate knpc kpc)
+  (say knpc "The moongates and Shrine Gate are a mystery. I'd love to figure "
+       "them out. You know about the Demon Gate, right?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "I wish I knew if it really existed or not.")
+      (say knpc "It's a legend. The Demon Gate opened from this world to "
+           "others. Then somebody got paranoid, locked it shut, and "
+           "threw away the key. Pity if it's true.")))
+  
+(define (eng-key knpc kpc)
+  (say knpc "Supposedly the key is a set of Runes that were subsequently "
+       "lost or scattered. Typical fairy-tale nonsense. But there may be "
+       "a kernel of truth to it."))
+
+(define (eng-wise knpc kpc)
+  (say knpc "Anyone with the arrogance to call themselves Wise is probably "
+       "an ass. Take the Stewardess of Glasdrin, for example."))
+
+(define (eng-stew knpc kpc)
+  (say knpc "She longs to be counted among the Wise, and doesn't care how "
+       "much blood she has to spill to do it. You've heard of Absalot, I "
+       "assume?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "A perfect example of abusive power. Sad.")
+      (say knpc "The Stewardess conned the other cities and the Enchanter "
+           "into massacring the citizens of Absalot. "
+           "Supposedly Absalot was a hotbed of Accursed insurgency. If there "
+           "was any evidence of the Accursed being there, they burned it to "
+           "the ground with the rest of the city.")))
+
+(define (eng-accu knpc kpc)
+  (say knpc "Supposedly they're a cult of some sort engaging in evil "
+       "practices. People who make it their business to meddle are very "
+       "upset about them. I don't really give a fig."))
+
+(define (eng-shri knpc kpc)
+  (say knpc "I've studied the records about the Shrine Gate and investigated "
+       "the site, of course. But there's nothing to indicate how it works or "
+       "how to control it. I think the last time it opened was over one "
+       "hundred years ago."))
+
+(define (eng-rune knpc kpc)
+  (say knpc "The legend of the Demon Gate insists that it was locked by a set "
+       "of Runes. Some versions say the Runes were scattered so they could "
+       "not be reassambled to open the Gate, others say they were lost "
+       "through simple incompetence and bad luck. Of course, there's no "
+       "telling if the Runes or even the Gate ever existed!"))
+
+(define (eng-wiza knpc kpc)
+  (say knpc "Wizards as a rule tend to be obsessed with power."))
+
+(define (eng-wrog knpc kpc)
+  (say knpc "Mosts Wrogues are simply pests. They're into everything."))
+
+(define (eng-wrig knpc kpc)
+  (say knpc "Wrights are my kind of people. They like to make things, to "
+       "figure out how things work, and just want the freedom to follow "
+       "their own interests."))
+
+(define (eng-necr knpc kpc)
+  (say knpc "Not a bad sort. I've conferred with him a time or two.")
+  (quest-data-update 'questentry-necromancer 'nonevil 1)
+  )
+
+(define (eng-alch knpc kpc)
+  (say knpc "A tricky bastard but I have to respect him."))
+
+(define (eng-man knpc kpc)
+  (say knpc "A Wrogue, but a helpful one. We get along."))
+
+(define (eng-ench knpc kpc)
+  (say knpc "Bit of a fanatic if you ask me. But it takes all kinds."))
+
+(define eng-merch-msgs
+  (list "Not now."
+        "Let me show you some of my inventions..."
+        nil
+        nil
+        "Always glad to help out a fellow tinkerer."
+        "No problem."
+   ))
+
+(define eng-catalog
+  (list
+   ;; Various tools and devices
+   (list t_picklock       10 "I happen to have some spare picklocks. They're handy for all kinds of things.")  ;; high prices, not his specialty
+   (list t_shovel        100 "I hate to part with my shovel, you never know when it might come in handy.")  ;; high prices, not his specialty
+   (list t_pick          100 "I've actually used this pick. Once. I suppose I can part with it.")  ;; high prices, not his specialty
+   (list t_sextant       200 "This is one of my most successful inventions. With this sextant you don't neet the In Wis spell to find your location on the surface.")
+   (list t_chrono        200 "It's a little PORTABLE CLOCK! Isn't it amazing? [He giggles with glee]")
+   
+   ;; A bit of oil and grease, for a grease-monkey:
+   (list t_grease         20 "I've got plenty of grease. I use it for everything.")
+   (list t_oil            10 "If I could figure out how to harness the explosive power of this oil, I'm sure I could make a useful engine.")  ;; high prices, not his specialty
+
+   ;; Crossbows and bolts, as he likes intricate devices
+   (list t_lt_crossbow    50 "Isn't this little crossbow cute? The little levers and actions are quite clever.")
+   (list t_crossbow      100 "I'm a terrible shot, but I wanted to study crossbows to see if I could figure out how to shoot myself safely across the void.")
+   (list t_hvy_crossbow  300 "I couldn't help making some improvements on the standard crossbow. This one works best if you mount it on something first.")
+   (list t_trpl_crossbow 500 "What if a crossbow could fire more than one bolt at a time? I had to try it out, so I made this.") ;; a mechanism of his devising
+   (list t_bolt            2 "I went through a lot of bolts while testing crossbows modifications, and I have a few crates left over.")
+   ))
+
+(define (eng-trade knpc kpc) (conv-trade knpc kpc "buy" eng-merch-msgs eng-catalog))
+
+(define engineer-conv
+  (ifc nil
+       (method 'default eng-default)
+       (method 'hail eng-hail)
+       (method 'name eng-name)
+       (method 'bye eng-bye)
+       (method 'job eng-job)
+       (method 'join eng-join)
+
+       (method 'trad eng-trade)
+       (method 'buy  eng-trade)
+       (method 'inve eng-trade)
+
+       (method 'make eng-make)
+       (method 'thin eng-make)
+       (method 'wand eng-wand)
+       (method 'void eng-void)
+       (method 'gate eng-gate)
+       (method 'key eng-key)
+       (method 'wise eng-wise)
+       (method 'stew eng-stew)
+       (method 'accu eng-accu)
+       (method 'shri eng-shri)
+       (method 'rune eng-rune)
+       (method 'wiza eng-wiza)
+       (method 'wrog eng-wrog)
+       (method 'wrig eng-wrig)
+       (method 'necr eng-necr)
+       (method 'alch eng-alch)
+       (method 'man eng-man)
+       (method 'ench eng-ench)
+       ))
+
+(define (mk-engineer)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_engineer ;;..........tag
+     "Engineer" ;;.......name
+     sp_human ;;.....species
+     oc_wright ;;.. .occupation
+     s_companion_tinker ;;..sprite
+     faction-men ;;..faction
+     2 ;;...........custom strength modifier
+     10 ;;...........custom intelligence modifier
+     2 ;;...........custom dexterity modifier
+     10 ;;............custom base hp modifier
+     2 ;;............custom hp multiplier (per-level)
+     20 ;;............custom base mp modifier
+     5 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     engineer-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'engineer-conv ;;...conversation (optional)
+     sch_engineer ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+     ;;..............container (and contents)
+     (mk-inventory
+      (list
+       (list 1   t_dagger)
+       (list 1   t_doom_staff)
+       (list 1   t_trpl_crossbow)
+       (list 100 t_bolt)
+       (list 5   t_cure_potion)
+       (list 5   t_heal_potion)
+       ))
+     nil ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (engineer-mk)))
diff --git a/worlds/haxima-1.002/engineers-hut.scm b/worlds/haxima-1.002/engineers-hut.scm
new file mode 100644 (file)
index 0000000..728374a
--- /dev/null
@@ -0,0 +1,82 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_engineers_hut 19 19 pal_expanded
+       (list
+               "** *. *8 *8 *8 *8 *8 *8 *8 ** ** ee ee *. ** *8 ** ** ** "
+               "*c rr rr rr rr ws rr rr rr rr *4 ee ee *2 rr rr rr ** ** "
+               ".. rr rr [[ @@ @@ @@ ]] rr rr *6 ee ee *e rr ,, *b rr *. "
+               "|| rr 00 ,, ,, ,, ,, ,, ,, rr *e /0 /d /d ,, ,, ,, *a ** "
+               "*d rr 00 ,, ,, ,, ,, ,, ,, rr .. /7 .. .. rr ,, ,, rr *a "
+               ".. rr 00 ,, ,, [[ ]] ,, ,, ,, /d /6 .. .. rr ,, bb rr .. "
+               "~~ rr ,, ,, ,, ,, ,, ,, ,, rr .. /7 .. .. rr .. ,, rr .. "
+               "~~ bb ~~ ,, ,, ,, ,, ,, ,, rr .. /7 .. .. rr ,, ,, rr .. "
+               "bb ~~ ~~ ,, ,, ,, [[ @@ ]] rr .. /7 .. .. rr rr rr rr .. "
+               "~~ rr ,, ,, ,, ,, rr rr rr rr .. /7 .. bb .. .. .. tC t3 "
+               ".. rr ,, ,, ,, ,, 00 rr .. .. .. /7 .. .. .. .. .. t3 tt "
+               ".. rr ,, ,, ,, ,, 00 rr .. /0 /d /9 /d /d /d /2 .. ta tt "
+               ".. rr ,, rr && rr rr rr .. /7 .. .. .. .. .. /7 .. t% ta "
+               "bb .. .. rr rr rr ~~ .. .. /7 .. .. .. rr rr ,, rr rr .. "
+               "bb .. .. .. .. .. ~2 bb .. /7 .. .. rr rr ,, ,, ,, rr .. "
+               "bb .. .. .. .. .. ~a ~~ ~9 =| ~9 ~~ rr && ,, ,, ,, rr .. "
+               "bb .. .. .. .. .. .. bb .. /7 .. ~~ rr rr ,, ,, ,, rr .. "
+               "bb .. .. .. .. .. bb .. .. /7 .. ~a ~~ rr rr rr rr rr .. "
+               "t5 bb bb bb bb bb t7 .. .. /7 .. .. ~6 .. .. .. .. .. .. "
+       )
+)
+
+;;----------------------------------------------------------------------------
+;; NPC's
+;;----------------------------------------------------------------------------
+(kern-load "engineer.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_engineers_hut     ; tag
+ "Engineers Hut"      ; name
+ s_hamlet      ; sprite
+ m_engineers_hut      ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+
+  (put (mk-engineer) 9 9)
+
+  (put (mk-npc 'bull 8) 3 15)
+  (put (mk-door) 15 13)
+  (put (mk-bed) 16 15)
+  (put (mk-chest
+        nil
+        '((5 t_food))) 14 16)
+
+  (put (mk-door) 14  3)
+
+  (put (mk-door) 9 5)
+  (put (mk-windowed-door) 2 12)
+  (put (mk-clock) 5 9)
+  (put (mk-broken-clock s_clock_stopped s_clock_stopped "The internals of this clock are spread across the table") 8 7)
+
+  (put (kern-mk-obj t_voidship_plans 1) 16 7)
+  )
+
+ nil ; hooks
+ (list  ;; edge entrances
+  (list east  6 18)
+  (list south 11 0) 
+  (list southwest 11 0) 
+  (list southeast 11 0) 
+  (list northeast 6 18)
+  (list north 9 18)
+  (list west  18 9)
+  )
+ )
+
+(mk-place-music p_engineers_hut 'ml-small-town)
diff --git a/worlds/haxima-1.002/enter_moongate.wav b/worlds/haxima-1.002/enter_moongate.wav
new file mode 100644 (file)
index 0000000..9e061e8
Binary files /dev/null and b/worlds/haxima-1.002/enter_moongate.wav differ
diff --git a/worlds/haxima-1.002/eye-of-brune.scm b/worlds/haxima-1.002/eye-of-brune.scm
new file mode 100644 (file)
index 0000000..21461cf
--- /dev/null
@@ -0,0 +1,33 @@
+;; The Eye of Brune is a special mechanism that shows a map of the entire Shard
+;; when handled successfully.
+
+(define (eye-of-brune-handle keye khandler)
+  (kern-obj-set-sprite keye s_eye_open)
+  (kern-log-msg "*** STENTORIAN VOICE ***")
+  (kern-log-msg "WHAT WOULDST THOU BE?")
+  (let ((answer (kern-conv-get-reply khandler)))
+    (cond ((eq? answer 'vigi)
+           (kern-log-msg "THEN SEE!")
+           (let ((kimage (kern-image-load "map.png")))
+             (kern-map-set-image kimage)
+             (kern-print "Hit a key when done gazing...\n")
+             (ui-waitkey)
+             (kern-map-set-image nil)
+             (kern-image-free kimage)))
+          (else
+           (kern-log-msg "WOE TO THE CARELESS, THE FORGETFUL AND THE IMPIOUS!")
+           (apply-lightning khandler)
+           (kern-char-set-intelligence khandler
+                                       (- (kern-char-get-base-intelligence khandler) 
+                                          1))
+           (kern-log-msg (kern-obj-get-name khandler) " loses intelligence!")
+           )))
+  (kern-obj-set-sprite keye s_eye_closed)
+  )
+
+(define eye-of-brune-ifc
+  (ifc nil
+       (method 'handle eye-of-brune-handle)
+       ))
+
+(mk-obj-type 't_eye_of_brune "Eye of Brune" s_eye_closed layer-mechanism eye-of-brune-ifc)
diff --git a/worlds/haxima-1.002/fields.scm b/worlds/haxima-1.002/fields.scm
new file mode 100644 (file)
index 0000000..3af15fd
--- /dev/null
@@ -0,0 +1,119 @@
+;;----------------------------------------------------------------------------
+;; fields.scm - field types supported by the game
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; kern-mk-field-type <tag> <name> <sprite> <light> <dur> <pmask> <effect>
+;; 
+;; 'effect' is a procedure called whenever an object is positioned over the
+;; field. Its only parameter is the object.
+;;
+;; 'light' is the amount of light radiated by the field.
+;;
+;; 'dur' is the number of turns the field will exist before disappearing.
+;; 
+;; 'pmask' is the objective pmask (the passability it permits to cross it)
+;;
+;; 'effect' is an optional procedure to run on an object which steps on the
+;; field. See effects.scm.
+;;----------------------------------------------------------------------------
+
+(kern-mk-field-type 'F_illum  "glowing mote" s_magic          1024 5  pclass-none  nil mmode-field)
+(kern-mk-field-type 'F_fire   "fire field"   s_field_fire     512  20 pclass-none  'burn       mmode-field)
+(kern-mk-field-type 'F_poison "poison field" s_field_poison   256  20 pclass-none  'apply-poison       mmode-field)
+(kern-mk-field-type 'F_sleep  "sleep field"  s_field_sleep    256  20 pclass-none  'apply-field-sleep  mmode-field)
+(kern-mk-field-type 'F_energy "energy field" s_field_energy   512  20 pclass-repel 'apply-lightning    mmode-field)
+(kern-mk-field-type 'F_acid "acid field" s_field_acid   256  20 pclass-none 'apply-acid        mmode-field)
+(kern-mk-field-type 'web-type "spider web"   s_spider_web     0    20 pclass-none  'ensnare    mmode-field)
+
+(kern-mk-field-type 'F_poison_perm "poison field" s_field_poison 256 -1 pclass-none  'apply-poison     mmode-field)
+(kern-mk-field-type 'F_sleep_perm  "sleep field"  s_field_sleep  256 -1 pclass-none  'apply-field-sleep        mmode-field)
+(kern-mk-field-type 'F_energy_perm "energy field" s_field_energy 512 -1 pclass-repel 'apply-lightning  mmode-field)
+(kern-mk-field-type 'F_fire_perm   "fire field"   s_field_fire   512 -1 pclass-none  'burn     mmode-field)
+(kern-mk-field-type 'F_acid_perm "acid field" s_field_acid 256 -1 pclass-none 'apply-acid      mmode-field)
+(kern-mk-field-type 'F_web_perm    "spider web"   s_spider_web   0   -1 pclass-none  'ensnare  mmode-field)
+(kern-mk-field-type 'F_illum_perm    nil   nil   256   -1 pclass-none  nil     mmode-field)
+
+(define all-field-types
+  (list F_fire F_poison F_sleep F_energy web-type
+        F_fire_perm F_poison_perm F_sleep_perm F_energy_perm F_web_perm))
+
+(define (is-field-type? ktype)
+  (foldr (lambda (x field-type) (or x (eqv? ktype field-type)))
+         #f 
+         all-field-types))
+
+(define (is-field? kobj)
+  (kern-obj-is-field? kobj))
+
+(define (is-fire-field? ktype)
+  (or (eqv? ktype F_fire)
+      (eqv? ktype F_fire_perm)))
+
+(define (is-poison-field? ktype)
+  (or (eqv? ktype F_poison)
+      (eqv? ktype F_poison_perm)))
+
+(define (is-sleep-field? ktype)
+    (or (eqv? ktype F_sleep)
+        (eqv? ktype F_sleep_perm)))
+
+(define (is-energy-field? ktype)
+    (or (eqv? ktype F_energy)
+        (eqv? ktype F_energy_perm)))
+
+(define (is-immune-to-field? kchar kfield)
+  (let ((ktype (kern-obj-get-type kfield)))
+    (cond ((is-fire-field? ktype) (has-fire-immunity? kchar))
+          ((is-poison-field? ktype) (has-poison-immunity? kchar))
+          ((is-sleep-field? ktype) (has-sleep-immunity? kchar))
+          (else #f))))
+                
+(define (apply-field-sleep kobj)
+       (if (> (modulo (random-next) 40) 1)
+       (apply-sleep kobj)
+    ))
+    
+;; smoke is here since it more closely resembles a field than anything else
+;; TODO: smoke should calculate a duration and store that in a gob
+;;   so that denser smoke can be created  
+
+(define smoke-ifc
+  (ifc nil
+       (method 'exec (lambda (ksmoke)
+                       (if (> (kern-dice-roll "1d20") 16)
+                           (kern-obj-remove ksmoke)
+
+                           ;; smoke drifts with the wind in wilderness combat
+                           (let ((curloc (kern-obj-get-location ksmoke)))
+                             (if (kern-place-is-combat-map? (loc-place curloc))
+                                 (let ((loc (loc-offset (kern-obj-get-location ksmoke) 
+                                                        (vector-ref opposite-dir (kern-get-wind)))))
+                                   (if (not (kern-is-valid-location? loc))                            
+                                       (kern-obj-remove ksmoke)
+                                       (begin
+                                         (kern-obj-relocate ksmoke loc nil)
+                                         (kern-los-invalidate)
+                                         ))))))))))
+
+
+(mk-obj-type 't_smoke_cloud "smoke" s_smoke layer-projectile smoke-ifc)
+
+(define (fields-smoke-apply kplace x y power)
+       (define (tryput loc)
+               (if (terrain-ok-for-field? loc)
+                       (let ((kfield (kern-mk-obj t_smoke_cloud 1)))
+                               (kern-obj-set-opacity kfield #t)
+                               (kern-obj-put-at kfield loc)))
+       )
+       (tryput (mk-loc kplace x y))
+       (tryput (mk-loc kplace (- x 1) y))
+       (tryput (mk-loc kplace (+ x 1) y))
+       (tryput (mk-loc kplace x (- y 1)))
+       (tryput (mk-loc kplace x (+ y 1)))
+       (tryput (mk-loc kplace (- x 1) (- y 1)))
+       (tryput (mk-loc kplace (- x 1) (+ y 1)))
+       (tryput (mk-loc kplace (+ x 1) (- y 1)))
+       (tryput (mk-loc kplace (+ x 1) (+ y 1)))
+       (kern-los-invalidate)
+)
diff --git a/worlds/haxima-1.002/fing.scm b/worlds/haxima-1.002/fing.scm
new file mode 100644 (file)
index 0000000..b332d63
--- /dev/null
@@ -0,0 +1,145 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Oparine.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_fing
+               (list 0  0  sea-witch-bay        "idle")
+               (list 6  0  sea-witch-shore      "idle")
+               (list 8  0  sea-witch-bay        "idle")
+               (list 20 0  sea-witch-shore      "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (fing-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Fing is a male Nixie, who is a Prince among his people.
+;; He dwells in Oparine, to be close to his true love, the human woman Lia.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (fing-hail knpc kpc)
+  (say knpc "[You meet a nixie] Hail, Landman."))
+
+(define (fing-default knpc kpc)
+  (say knpc "Perhaps another Landman would know about that."))
+
+(define (fing-name knpc kpc)
+  (say knpc "I am Fing."))
+
+(define (fing-join knpc kpc)
+  (say knpc "I cannot stray far from these shores."))
+
+(define (fing-job knpc kpc)
+  (say knpc "I am a prince among the Seamen of this valley... er, bay."))
+
+(define (fing-bye knpc kpc)
+  (say knpc "Farewell, Landman."))
+
+;; Shores...
+(define (fing-shor knpc kpc)
+  (say knpc "I must stay by the shore so I can be near my love."))
+
+(define (fing-love knpc kpc)
+  (say knpc "Although my beloved cannot leave the land, "
+       "she is a princess among the Sea People. "
+       "She is kind and true, and has not despaired even with her curse."))
+
+(define (fing-sea knpc kpc)
+  (say knpc "There are many kingdoms under the sea, many ruins, and caves, "
+       "sunken ships and great treasures. There are magicians, "
+       "and warriors, and mighty beasts! No offense, but the dry land "
+       "must be very dull in comparison."
+       ))
+
+(define (fing-curs knpc kpc)
+  (say knpc "It is a matter for the Sea People."))
+
+;; Townspeople...
+(define (fing-opar knpc kpc)
+  (say knpc "It's okay for you Landman, I suppose."))
+
+(define (fing-gher knpc kpc)
+  (say knpc "We admired her from below! So quick, so brutal! "
+       "Like a tempest disguised as a woman. Her crew, it seems, came to "
+       "a bad end."))
+
+(define (fing-crew knpc kpc)
+  (say knpc "Ghertie's crew sailed east to an island, went ashore, and never "
+       "returned. Her ship is no more."))
+
+(define (fing-alch knpc kpc)
+  (say knpc "He speaks to my love but I am not jealous. "
+       "He is too old and fat for any love potion to decieve her eyes!"))
+
+(define (fing-osca knpc kpc)
+  (say knpc "I know him not."))
+
+(define (fing-henr knpc kpc)
+  (say knpc "A brave Landman, from what I hear."))
+
+(define (fing-bart knpc kpc)
+  (say knpc "I have not seen many goblins. I think they fear the sea. "
+       "He is an oddity among them."))
+
+
+(define fing-conv
+  (ifc nil
+
+       ;; basics
+       (method 'default fing-default)
+       (method 'hail fing-hail)
+       (method 'bye fing-bye)
+       (method 'job fing-job)
+       (method 'name fing-name)
+       (method 'join fing-join)
+       
+       ;; Shores
+       (method 'shor fing-shor)
+       (method 'love fing-love)
+       (method 'sea fing-sea)
+       (method 'deep fing-sea)
+       (method 'bay  fing-sea)
+       (method 'curs fing-curs)
+
+       ;; town & people
+       (method 'opar fing-opar)
+       (method 'alch fing-alch)
+       (method 'gher fing-gher)
+       (method 'crew fing-crew)
+       (method 'osca fing-osca)
+       (method 'henr fing-henr)
+       (method 'bart fing-bart)
+       (method 'lia  fing-love)
+
+       ))
+
+(define (mk-fing)
+  (bind 
+   (kern-mk-char 'ch_fing           ; tag
+                 "Fing"             ; name
+                 sp_nixie           ; species
+                 oc_warrior         ; occ
+                 s_nixie_civilian    ; sprite
+                 faction-men         ; starting alignment
+                 1 2 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'fing-conv         ; conv
+                 sch_fing           ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 10 t_spear)))                ; container
+                 nil                 ; readied
+                 )
+   (fing-mk)))
diff --git a/worlds/haxima-1.002/fire_sea.scm b/worlds/haxima-1.002/fire_sea.scm
new file mode 100644 (file)
index 0000000..edd673b
--- /dev/null
@@ -0,0 +1,86 @@
+(mk-dungeon-room
+ 'p_fire_sea "Fire Sea"
+       (list
+               "rn r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn rn "
+               "r4 !_ !_ !! {A {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ ra rn rn "
+               "r4 !_ !_ !_ !5 {A {{ {{ {3 {9 {9 {9 {9 {5 {{ {C ~! ra rn "
+               "r4 !! !_ !! !! !5 {{ {3 {c {{ {{ {{ {{ {6 {{ ~! !_ ~! r2 "
+               "r4 {% !e {# {{ !! {{ {6 {{ {C !3 !5 {{ {6 {{ {% ~! {# r2 "
+               "r4 {{ {{ {3 {9 == {9 {c {C !3 !_ !! {{ {6 {{ !7 {{ {{ r2 "
+               "r4 {{ {3 {c {{ !! {{ {{ !_ !_ !_ !_ {{ {a {9 == {9 {1 r2 "
+               "r4 {{ {6 {{ {{ !_ !_ !_ r3 r9 r9 r5 !5 {{ {{ !! {{ {2 r2 "
+               "r4 {{ {6 {{ {{ {% !a !_ r6 .. .. ra r5 !! !! !c {{ {2 r2 "
+               "r4 {{ {a {9 {9 {5 {{ r3 r4 .. .. .. re {{ !! {{ {{ {2 r2 "
+               "r4 {{ {{ {{ {{ {6 {{ ra r4 .. bb .. .. {9 == {9 {9 {8 r2 "
+               "r4 {C !3 !! !! =| !! !_ r6 .. .. .. r7 {{ !! {{ {{ {{ r2 "
+               "r4 !! !_ !c {{ {6 {{ !_ ra r9 r5 .. r2 r5 !_ !! !5 {A r2 "
+               "r4 {% !e {# {{ {6 {{ !! !_ !_ ra r9 r8 rc !_ !_ !_ !! r2 "
+               "rn r5 {{ {{ {{ {6 {{ !a !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ r2 "
+               "rn rn r5 {{ {{ {6 {{ {% !a !! !! !_ !_ !_ !_ !_ !_ !_ r2 "
+               "rn rn r4 bb {{ {a {5 {{ {{ {{ {% !a !! !! !_ !_ !_ !_ r2 "
+               "rn rn rn r5 bb {{ {2 {1 {1 {5 {{ {{ {{ {% !a !_ !_ !_ r2 "
+               "rn rn rn rn r1 r1 r1 r5 .. .. {5 {{ {{ {3 bb !! !! ~! r2 "
+       )
+
+ (put (kern-mk-obj t_rune_w 1) 11 12)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 9 8)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 10 8)
+ (put (kern-mk-obj t_iron_helm_4 1) 10 8)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 9 9)
+ (put (kern-mk-obj t_spell_book_enchantment_miscellanea 1) 9 10)
+ (put (kern-mk-obj t_spell_book_illusion_2 1) 9 11)
+ (put (kern-mk-obj t_gem (kern-dice-roll "5d4+1")) 10 9)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 11 9)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 9 10)
+ (put (kern-mk-obj t_sword_4 1) 9 10)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 11 10)
+ (put (kern-mk-obj t_armor_plate_4 1) 11 11)
+ (put (kern-mk-obj t_gem (kern-dice-roll "5d4+1")) 9 11)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 10 11)
+ (put (kern-mk-obj t_shield_4 1) 10 11)
+ (put (kern-mk-obj t_gem (kern-dice-roll "5d4+1")) 11 11)
+ (put (kern-mk-obj t_gold_coins (kern-dice-roll "5d50+5")) 11 12)
+
+ (put (spawn-pt 'dragon) 11 10)
+ )
+
+(mk-place-music p_fire_sea 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_smoldering_cave "Smoldering Cave"
+       (list
+               "rn rn rn rn rn rn rn r4 .. .. .. r2 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn r8 r8 r4 {8 .. {8 r2 r8 r8 rn rn rn rn rn "
+               "rn rn rn rn rc !_ !_ re {{ {6 {{ re !_ !_ ra rn rn rn rn "
+               "rn rn rn rc !_ !_ !_ !! {{ {6 {{ !! !_ !_ !_ ra rn rn rn "
+               "rn rn r4 !_ !_ !_ !_ !_ !! =| !! !_ !_ !_ !_ !_ r2 rn rn "
+               "rn rn rc !_ !_ !_ !_ !c {{ {6 {{ !a !_ !_ !_ !_ ra rn rn "
+               "rn r4 !_ !_ !_ !_ !c bb {{ {6 {{ bb !a !_ !_ !_ !_ r2 rn "
+               "rn r4 !_ !_ !_ !! bb {# {{ {6 {{ {% bb !! !_ !_ !_ r2 rn "
+               "rn r4 !_ !_ !_ !! {# {{ {3 .. {5 {{ {% !! !_ !_ !_ r2 rn "
+               "rn r4 !_ !_ !_ !! {{ {{ {2 .. {4 {{ {{ !! !_ !_ !_ r2 rn "
+               "rn r4 !_ !_ !_ !! {A {{ {a {8 {c {{ {C !! !_ !_ !_ r2 rn "
+               "rn r4 !_ !_ !_ !! bb {A {{ {{ {{ {C bb !! !_ !_ !_ r2 rn "
+               "rn r4 !_ !_ !_ !_ !5 bb {A {{ {C bb !3 !_ !_ !_ !_ r2 rn "
+               "rn rn r5 !_ !_ !_ !_ !! !! !! !! !! !_ !_ !_ !_ r3 rn rn "
+               "rn rn r4 !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ r2 rn rn "
+               "rn rn rn r5 !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ !_ r3 rn rn rn "
+               "rn rn rn rn r1 r5 !_ !_ !_ !_ !_ !_ !_ r3 r1 rn rn rn rn "
+               "rn rn rn rn rn rn r1 r1 r1 r1 r1 r1 r1 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+       )
+ (put (mk-ladder-up 'p_shard 118 46) 9 9)
+ (put (spawn-pt 'fire-slime) 9 1)
+ (put (spawn-pt 'fire-slime) 7 3)
+ (put (spawn-pt 'fire-slime) 10 4)
+
+ ;; Asbestos spellbook, floating in the lava...
+ (put (kern-mk-obj t_spell_book_force_magick_winds 1) 2 11)
+ )
+
+(mk-dungeon-level 
+ (list p_fire_sea)
+ (list p_smoldering_cave)
+ )
+
+(mk-place-music p_smoldering_cave 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/fireblast.wav b/worlds/haxima-1.002/fireblast.wav
new file mode 100644 (file)
index 0000000..e2a37d1
Binary files /dev/null and b/worlds/haxima-1.002/fireblast.wav differ
diff --git a/worlds/haxima-1.002/florinth.scm b/worlds/haxima-1.002/florinth.scm
new file mode 100644 (file)
index 0000000..bea94a3
--- /dev/null
@@ -0,0 +1,111 @@
+(mk-19x19-town
+ 'p_florinth_wharf "Wharf of Florinth" s_town
+ (list
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  )
+ nil ;; entrances
+ )
+
+(mk-19x19-town
+ 'p_florinth_n_tower "North Watchtower of Florinth" s_town
+ (list
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ) 
+ nil ;; entrances
+ )
+
+(mk-19x19-town
+ 'p_florinth_s_tower "South Watchtower of Florinth" s_town
+ (list
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  )
+ nil ;; entrances
+ )
+
+(mk-19x19-town
+ 'p_florinth_bazaar "Bazaar of Florinth" s_town
+ (list
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+  )
+ nil ;; entrances
+)
+
+(mk-place-music p_florinth_wharf 'ml-small-town)
+
+(mk-dungeon-level
+ (list p_florinth_n_tower nil              )
+ (list p_florinth_wharf   p_florinth_bazaar)
+ (list p_florinth_s_tower nil              )
+ )
\ No newline at end of file
diff --git a/worlds/haxima-1.002/food.png b/worlds/haxima-1.002/food.png
new file mode 100644 (file)
index 0000000..b87adac
Binary files /dev/null and b/worlds/haxima-1.002/food.png differ
diff --git a/worlds/haxima-1.002/food.scm b/worlds/haxima-1.002/food.scm
new file mode 100644 (file)
index 0000000..67f786c
--- /dev/null
@@ -0,0 +1,42 @@
+(kern-mk-sprite-set 'ss_food 32 32 2 2 0 0 "food.png")
+
+(kern-mk-sprite 's_food ss_food 1 0 #f 0)
+(kern-mk-sprite 's_beer ss_food 1 1 #f 0)
+(kern-mk-sprite 's_wine ss_food 1 2 #f 0)
+
+;; caloric values
+(define food-value 1)
+(define alcohol-value 1)
+
+(define food-ifc
+  (ifc '()
+       (method 'get (lambda (kobj getter)
+                      (kern-obj-inc-ref kobj)
+                      (kern-obj-remove kobj)
+                      (kern-obj-add-food getter (* food-value
+                                                   (kern-obj-get-count kobj)))
+                      (kern-obj-dec-ref kobj)))
+       (method 'buy (lambda (kbuyer q)
+                      (kern-obj-add-food kbuyer (* food-value q))
+                      ))
+       ))
+
+(define alcohol-ifc
+  (ifc '()
+       (method 'get (lambda (kobj getter)
+                      (kern-obj-inc-ref kobj)
+                      (kern-obj-remove kobj)
+                      (kern-obj-add-food getter (* alcohol-value
+                                                   (kern-obj-get-count kobj)))
+                      (kern-obj-add-effect getter ef_drunk nil)
+                      (kern-obj-dec-ref kobj)))
+       (method 'buy (lambda (kbuyer q)
+                      (display "buy")(newline)
+                      (kern-obj-add-effect kbuyer ef_drunk nil)
+                      (kern-obj-add-food kbuyer (* alcohol-value q))))
+       ))
+
+
+(mk-obj-type 't_food (list "food" "food") s_food layer-item food-ifc)
+(mk-obj-type 't_beer "beer" s_beer layer-item alcohol-ifc)
+(mk-obj-type 't_wine (list "wine" "wine") s_wine layer-item alcohol-ifc)
diff --git a/worlds/haxima-1.002/forsaken-prison.scm b/worlds/haxima-1.002/forsaken-prison.scm
new file mode 100644 (file)
index 0000000..f88729d
--- /dev/null
@@ -0,0 +1,53 @@
+(mk-dungeon-room
+ 'p_forsaken_prison "Forsaken Prison"
+ (list
+         "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+         "rn rn rn rn xx ,, ,, xx ,, ,, ,, xx ,, ,, xx rn rn rn rn "
+         "rn rn rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+         "rn rn rn rn xx ,, ,, xx ,, ,, ,, xx ,, ,, xx rn rn rn rn "
+         "rn rn rn xx xx xx xx xx ,, ,, ,, xx xx xx xx xx rn rn rn "
+         "rn rn rn xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx rn rn rn "
+         "rn rn rn xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx rn rn rn "
+         "xx xx xx xx xx ,, xx xx ,, ,, ,, xx xx ,, xx xx xx xx xx "
+         "xx ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, xx "
+         "xx xx xx xx xx ,, xx xx ,, ,, ,, xx xx ,, xx xx xx xx xx "
+         "rn xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx rn rn rn "
+         "rn xx ?? ?? ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx rn rn rn "
+         "xx xx ?? xx xx xx xx xx ,, ,, ,, xx xx xx xx xx rn rn rn "
+         "xx ,, ,, ,, xx ,, ,, xx ,, ,, ,, xx ,, ,, xx rn rn rn rn "
+         "xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+         "xx ,, ,, ,, xx ,, ,, xx ,, ,, ,, xx ,, ,, xx rn rn rn rn "
+         "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+  )
+ (put (mk-ladder-up 'p_paladins_hold 8 17) 9 9)
+ (put (mk-ladder-up 'p_mans_hideout 9 3) 2 16)
+ (put (mk-locked-door) 7 2)
+ (put (mk-locked-door) 11 2)
+ (put (mk-locked-door) 13 7)
+ (put (mk-locked-door) 15 9)
+ (put (mk-locked-door) 13 11)
+ (put (mk-locked-door) 11 16)
+ (put (mk-locked-door) 7 16)
+ (put (mk-locked-door) 5 11)
+ (put (mk-locked-door) 3 9)
+ (put (mk-locked-door) 5 7)
+
+ ;; prisoners
+ (put (mk-npc 'bandit 4) 5 2)
+ (put (mk-npc 'cave-goblin-berserker 4) 6 15)
+ (put (mk-npc 'troll 6) 2 9)
+ (put (mk-npc 'warlock 8) 13 16)
+ (put (mk-npc 'corrupt-halberdier 3) 17 9)
+ (put (mk-npc 'skeletal-warrior 5) 13 1)
+
+ ;; alas, expired prisoners
+ (put (mk-corpse-with-loot) 14 5)
+ (put (mk-corpse-with-loot) 12 12)
+ (put (mk-corpse-with-loot) 14 5)
+ (put (mk-corpse-with-loot) 5 6)
+
+ )
+
+(mk-place-music p_forsaken_prison 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/frame.png b/worlds/haxima-1.002/frame.png
new file mode 100644 (file)
index 0000000..06cb298
Binary files /dev/null and b/worlds/haxima-1.002/frame.png differ
diff --git a/worlds/haxima-1.002/game.scm b/worlds/haxima-1.002/game.scm
new file mode 100644 (file)
index 0000000..2f58865
--- /dev/null
@@ -0,0 +1,428 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;; This file loads 58 files
+
+;; Toggle handling for quests
+(define use-quest-pane #t)
+
+;; Slots
+(define slot-nil              0)
+(define slot-amulet           1)
+(define slot-ring             2)
+(define slot-gazer-helm       4)
+(define slot-weapon           8)
+(define slot-shield           8)
+(define slot-weapon-or-shield 8)
+(define slot-armor            16)
+(define slot-boot             32)
+(define slot-helm             64)
+
+;; Speeds  ;; TODO: move most of these into kern-intvars ?
+
+(define speed-human             50)  ;; typical AP/round for humans
+
+(define base-move-ap           50)  ;; this may not bear a neat relationship to speed-human
+(define default-weapon-rap      50)  ;; this may not bear a neat relationship to speed-human
+(define default-armour-apmod    2)  ;; this may not bear a neat relationship to speed-human
+
+(define base-skill-ap                  base-move-ap)  ;; this may not bear a neat relationship to speed-human
+(define base-spell-ap                  base-move-ap)  ;; this may not bear a neat relationship to speed-human
+
+;; AP costs of various actions which the kernal needs to know about:
+(kern-set-kern-intvar "AP_TOTAL:normal_human"    speed-human)
+
+(kern-set-kern-intvar "AP_COST:default"           speed-human)
+(kern-set-kern-intvar "AP_COST:search"            (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:get_item"          (* 0.34 speed-human))
+(kern-set-kern-intvar "AP_COST:drop_item"         (* 0.34 speed-human))
+(kern-set-kern-intvar "AP_COST:open_mechanism"    speed-human)
+(kern-set-kern-intvar "AP_COST:open_container"    speed-human)
+(kern-set-kern-intvar "AP_COST:handle_mechanism"  speed-human)
+(kern-set-kern-intvar "AP_COST:use_item"          speed-human)  ;; may be unused, per comment in cmd.c cmdUse()
+
+;; Normal mixing: 18 + (num_mixed * 12) + (spell_level * 12) AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_base"         (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_per_mix"      (* 2 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_per_level"    (* 2 speed-human))
+;; Attempt at non-existent spell: 3d18+6 AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_num"   3)
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_dice" (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_plus"  speed-human)
+;; Missing or additional ingredients: (2 * spell_level)d18+18 AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_num"    2)  ;; times spell Level
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_dice"  (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_plus"  (* 3 speed-human))
+
+;; These values are used by ctrl.c ctrl_attack_target() 
+;; to adjust weapon AP costs in the event of dual wielding.
+;; The dual weapon rules can thus be tweaked here...
+(kern-set-kern-intvar "AP_MULT12:second_wpn_attack"       6)  ;; AP cost * 6/12 for 2nd weapon attack if dual wpns used
+(kern-set-kern-intvar "AP_MULT12:third_plus_wpn_attack"   6)  ;; AP cost * 6/12 for 3rd+ weapon attacks, if 3+ weapons used
+(kern-set-kern-intvar "AP_THRESHOLD:multi_attack_overage" 0)  ;; attack sequence can continue if AP overage is not > 0
+
+(kern-set-kern-intvar "submerged_def_bonus" 10) ;; defense bonus for submerged critters
+
+;; ship speeds are better handled using mmodes/pclasses-
+;; it should only affect actual movement
+(define speed-ship            speed-human)  
+
+;; Action Point costs for various basic actions:
+;; are these used anywhere?
+;;(define ap-for-1H-melee-attack   9)
+;;(define ap-for-2H-melee-attack  12)
+
+;;(define ap-for-1H-thrown-attack 12)
+;;(define ap-for-2H-thrown-attack 18)
+
+;;(define ap-for-shooting-attack  12)
+
+;;(define ap-for-combat-spell      9)
+;;(define ap-to-use-scroll        12)
+
+
+;; Difficulty Classes. "Normal" means an L5 professional with key attribute at
+;; 16 will succeed 50% of the time. For example, an L5 wrogue with 16 dexterity
+;; will have a thiefly ability of 10. This person should be able to pick a
+;; normal lock 50% of the time (remember, he gets to retry with no penalty
+;; except mana loss and maybe breaking a pick on critical failure).
+;;
+;; 1d10 + 1d20 = 5.5 + 10.5 = 16
+;;
+;; For the most difficult things, an L9 professional wrogue with an unusually
+;; strong key attribute of 30 will have an ability rating of 19, and should
+;; only succeed on two perfect rolls:
+;;
+;; 19 + 20 = 39
+;;
+;; Caveat: for abilities other than wrogues (eg, magic or strength-based
+;; abilities), the relationship between ability level, key attribute and
+;; advancement level is different (in fact, it's different in each case, see
+;; occs.scm).
+(define dc-trivial        3) ;; >98%
+(define dc-easy           6) ;; >90%
+(define dc-nontrivial     10) ;; >75%
+(define dc-normal         15) ;; >50%
+(define dc-challenging    26) ;; 5%
+(define dc-hard           28) ;; <2%
+(define dc-masterful      30) ;; just impossible at L5,DEX=16
+(define dc-supremely-hard 38) ;; perfect roll at high levels
+
+(define dc-escape-ensnare  dc-challenging)
+(define dc-escape-paralyze dc-normal)
+(define dc-avoid-stuck     dc-hard)
+(define dc-escape-stuck    dc-hard)
+(define dc-reach           dc-hard)
+
+;; Pmasks (keep them around until mechs are converted to use passability
+;; classes (see below))
+(define pmask-none   0)
+(define pmask-solid  1)
+(define pmask-land   2)
+(define pmask-water  4)
+(define pmask-shoals 8)
+(define pmask-bridge (+ pmask-land pmask-water pmask-shoals))
+(define pmask-all    (+ pmask-solid pmask-land pmask-water pmask-shoals))
+
+;; Passability Difficulty Levels 
+;;   (Note: 255 is well-known to the kernel to mean
+;;   "impassible" in the case of movement costs)
+(define fast        (* 0.66 base-move-ap))  ;; 0.66 (2/3)
+(define s-fast      (* 0.8 base-move-ap))  ;; 'slightly fast' 0.8
+(define norm        base-move-ap)  ;; 1.0
+(define s-hard      (* 1.5 base-move-ap))  ;; 1.5
+(define hard       (* 2 base-move-ap))  ;; 2.0
+(define v-hard     (* 3 base-move-ap))  ;; 3.0
+
+(define no-drop    100)  ;; special, used for dropability (not related to speed-human)
+(define cant      255)  ;; special
+
+;; Passability classes
+(define pclass-none          0)
+(define pclass-grass         1)
+(define pclass-deep          2)
+(define pclass-shoals        3)
+(define pclass-mountains     4) ;; no ceiling
+(define pclass-wall          5) ;; has a ceiling
+(define pclass-trees         6)
+(define pclass-forest        7)
+(define pclass-hills         8)
+(define pclass-repel         9) ;; energy shield blocks all
+(define pclass-space         10)
+(define pclass-bridge        pclass-grass)
+(define pclass-road          pclass-grass)
+(define pclass-boulder       11) ;; no ceiling, smaller than mountain
+(define pclass-waterboulder  12) ;; worst case of boulder and water
+(define pclass-sludge        13)
+(define pclass-shallows      14)
+(define pclass-bars          15) ;; portcullis
+(define pclass-window        16) ;; separating from bars for shoot-but-not-crawl-through passability
+(define pclass-vmountains    17)
+(define pclass-canfloat      18) ;; avoids drowning
+(define pclass-canfly        19) ;; avoids ground based issues
+
+;; Movement modes
+(define mmodes
+  (list
+   (list 'mmode-walk      "walking"     0)
+   (list 'mmode-hover     "hovering"    1)
+   (list 'mmode-ship      "sailing"     2)
+   (list 'mmode-phase     "phasing"     3)
+   (list 'mmode-fly       "flying"      4)
+   (list 'mmode-skiff     "rowing"      5)
+   (list 'mmode-fish      "swimming"    6)
+   (list 'mmode-crawl     "crawling"    7) ;; spiders, can cross boulders
+   (list 'mmode-voidship  "sailing"     8)
+   (list 'mmode-ranger    "stalking"    9)
+   (list 'mmode-none      "stationary" 10)
+   (list 'mmode-wriggle   "wriggle"    11) ;; rogue special move
+   (list 'mmode-missile   "missile"    12)
+   (list 'mmode-fastfly   "flying"     13)
+   (list 'mmode-fastrun   "running"    14)
+   (list 'mmode-fastcrawl "crawling"   15)
+   (list 'mmode-smallobj  "smallobj"   16) ;; for determining dropability of small objects
+   (list 'mmode-largeobj  "largeobj"   17) ;; for determining dropability of big objects- basically, stuff that wont fit through bars/windows
+   (list 'mmode-field     "field"      18) ;; for determining dropability of fields
+   (list 'mmode-return    "return"     19) ;; return path for magic axe (for now assume it always returns)
+   (list 'mmode-cannon    "cannon"     20) ;; enhanced missile passibility for cannon shells
+   (list 'mmode-large     "striding"   21) ;; big critters
+))
+(map (lambda (mmode) (apply kern-mk-mmode mmode)) mmodes)
+
+(define mmode-jump mmode-fly)
+
+;; Movement cost table (optimized for cut to/paste from spreadsheet!)
+(kern-mk-ptable                                                                                                                                                                                                        
+       ;;      walk    hover   ship    phase   fly     skiff   fish    crawl   vship   rangr   none    wrigl   missl   f_fly   f_run   f_crawl sml_obj lrg_obj fields  return  cannon  striding                
+       (list   0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       )       ;; none
+       (list   norm    norm    cant    norm    norm    cant    cant    norm    cant    norm    cant    norm    0       fast    fast    fast    norm    norm    norm    0       0       norm    )       ;; grass/paving
+       (list   cant    cant    s-fast  cant    norm    v-hard  norm    cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       cant    )       ;; deep
+       (list   cant    s-hard  cant    cant    norm    norm    norm    cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       s-hard  )       ;; shoals
+       (list   cant    cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    95      s-fast  cant    cant    no-drop no-drop cant    0       90      cant    )       ;; mountains
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    cant    100     cant    cant    cant    cant    cant    cant    0       100     cant    )       ;; wall (w/ ceiling)
+       (list   hard    hard    cant    norm    norm    cant    cant    hard    cant    norm    cant    hard    10      fast    norm    norm    norm    norm    norm    0       7       hard    )       ;; trees
+       (list   v-hard  v-hard  cant    norm    norm    cant    cant    v-hard  cant    s-hard  cant    v-hard  30      fast    hard    hard    norm    norm    norm    0       20      v-hard  )       ;; forest
+       (list   v-hard  hard    cant    norm    norm    cant    cant    v-hard  cant    s-hard  cant    v-hard  7       fast    hard    hard    norm    norm    norm    0       5       hard    )       ;; hills/bog
+       (list   cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    100     cant    cant    cant    no-drop no-drop norm    0       100     cant    )       ;; energy fields
+       (list   cant    cant    cant    cant    norm    cant    cant    cant    norm    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       cant    )       ;; space
+       (list   cant    norm    cant    norm    norm    cant    cant    hard    cant    cant    cant    hard    10      fast    cant    norm    norm    norm    norm    0       4       norm    )       ;; boulder
+       (list   cant    hard    cant    cant    norm    cant    cant    hard    cant    cant    cant    hard    10      fast    cant    norm    norm    norm    no-drop 0       4       hard    )       ;; waterboulder
+       (list   cant    norm    hard    cant    norm    v-hard  v-hard  cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       norm    )       ;; sludge
+       (list   s-hard  norm    cant    norm    norm    norm    norm    s-hard  cant    norm    cant    cant    0       fast    norm    norm    cant    cant    no-drop 0       0       norm    )       ;; shallow sludge
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    v-hard  7       cant    cant    cant    norm    no-drop norm    0       7       cant    )       ;; bars (eg portcullis)
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    cant    30      cant    cant    cant    no-drop no-drop no-drop 0       25      cant    )       ;; window
+       (list   cant    cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    30      s-fast  cant    cant    no-drop no-drop no-drop 0       10      cant    )       ;; passlos mountains
+       (list   cant    v-hard  s-fast  cant    norm    cant    norm    cant    cant    cant    cant    cant    norm    norm    cant    cant    cant    cant    norm    norm    norm    v-hard  )       ;; float
+       (list   cant    hard    cant    cant    norm    hard    cant    cant    norm    cant    cant    cant    norm    norm    cant    cant    cant    cant    norm    norm    norm    cant    )       ;; fly
+)                                                                                                                                                                                                      
+;; Note that pclass 'missl' is using the value as a percentage chance 
+;; for a missile to be blocked by obscuring terrain, not as an AP cost
+
+
+;; Factions. The diplomacy table (which defines the relationship between
+;; factions) must be defined in the session file, because it changes over time.
+(define faction-none          0)
+(define faction-player        1)
+(define faction-men           2)
+(define faction-cave-goblin   3)
+(define faction-accursed      4)
+(define faction-monster       5)
+(define faction-troll         6)
+(define faction-spider        7)
+(define faction-outlaw        8)
+(define faction-gint          9)
+(define faction-demon         10)
+(define faction-forest-goblin 11)
+(define faction-green-tower   faction-men)
+(define faction-oparine       faction-men)
+(define faction-trigrave      faction-men)
+(define faction-nixie         faction-monster)
+(define faction-prisoner      12)
+(define faction-glasdrin      13) ;; must be separate from men, or exile by statue will affect player with all towns
+(define faction-num           14)
+
+;; Layers (must match object.h)
+(define layer-none       0)
+(define layer-tfeat      1)
+(define layer-mechanism  2)
+(define layer-portal     3)
+(define layer-vehicle    4)
+(define layer-bed        5)
+(define layer-container  6)
+(define layer-item       7)
+(define layer-field      8)
+(define layer-being      9)
+(define layer-projectile 10)
+(define layer-crosshair  11)
+
+;; Contexts
+(define context-world 1)
+(define context-town  2)
+(define context-any      (+ context-town context-world))
+
+;; Damage/Immunity types (ordinal, not bitmasks)
+(define damage-none   0)
+(define damage-fire   1)
+(define damage-poison 2)
+(define damage-sleep  3)
+
+;; Damage amounts
+(define lava-damage 10)
+
+;; Directions (as returned by kern-ui-get-direction)
+(define northwest 0)
+(define north     1)
+(define northeast 2)
+(define west      3)
+(define here      4)
+(define east      5)
+(define southwest 6)
+(define south     7)
+(define southeast 8)
+(define up        9)
+(define down      10)
+
+;; Scroll directions (for UI keyhandling, must match kernel's StatusScrollDir)
+(define scroll-up       0)
+(define scroll-down     1)
+(define scroll-right    2)
+(define scroll-left     3)
+(define scroll-pageup   4)
+(define scroll-pagedown 5)
+(define scroll-top      6)
+(define scroll-bottom   7)
+
+(define opposite-dir (vector southeast south southwest
+                             east here west
+                             northeast north northwest
+                             down up))
+
+;; Player character bonuses
+(define pc-hp-off  25)
+(define pc-hp-gain 5)
+(define pc-mp-off  1)
+(define pc-mp-gain 1)
+
+;; NPC activities
+(define (isdrunk? knpc)
+  (string=? "drunk" (kern-obj-get-activity knpc)))
+(define (isworking? knpc)
+  (string=? "working" (kern-obj-get-activity knpc)))
+
+;; Prices
+(define base-scroll-cost 20) ;; gold pieces per level of scroll's spell
+(define reagent-price-mult 1) ;; global reagent price multiplier
+
+;; rather than trying to calculate appropriate hp/mp for
+;; characters, stick in a big number and let Character::new
+;; trim it as needed
+(define max-health 999999999)
+
+;; Some of the following are order-dependent
+(load "loc.scm")
+(load "kobj.scm")
+(load "ifc.scm")
+(load "sprite-sets.scm")
+(load "sprites.scm")
+(load "sounds.scm")
+(load "effects.scm")
+(load "terrains.scm")
+(load "palette.scm")
+(load "fields.scm")
+(load "combat-maps.scm")
+
+;; Object types
+(load "objs.scm")
+(load "traps.scm")
+(load "pitfalls.scm")
+(load "landslide.scm")
+(load "containers.scm")
+(load "reagents.scm")
+(load "food.scm")
+(load "arms.scm")
+(load "powers.scm")
+(load "ability.scm")
+(load "cast-ui.scm")
+(load "spells.scm")
+(load "items.scm")
+(load "vehicles.scm")
+(load "beds.scm")
+(load "money.scm")
+(load "skills.scm")
+(load "occs.scm")
+(load "ai.scm")
+(load "species.scm")
+(load "conv.scm") ;; basic conversation
+(load "yellow-slime.scm")
+(load "troll.scm")
+(load "spider.scm")
+(load "npc-types.scm")
+(load "mimic.scm")
+(load "parties.scm")
+(load "jewelry.scm")
+(load "gate-guard.scm")
+
+;; Mechanism-like things
+(load "bim.scm")
+(load "step.scm")
+(load "monster-generator.scm")
+;;(load "wilderness-manager.scm")
+(load "terrain-to-ptype.scm")
+(load "edge-spawn.scm")
+(load "door.scm")
+(load "portcullis.scm")
+(load "hidden.scm")
+(load "lever.scm")
+(load "timer.scm")
+(load "tblit.scm")
+(load "portals.scm")
+(load "moongate.scm")
+(load "bridge.scm")
+(load "drawbridge.scm")
+(load "weather-vane.scm")
+(load "wind-bridge.scm")
+
+;; Astronomy
+(load "moon.scm")
+
+;; Quest system
+(load "tbl.scm")
+(load "ztats-quest-ui.scm")
+(load "quest-sys.scm")
+
+;; Miscellaneous crap
+(mk-obj-type 't_crosshair "crosshair" s_crosshair layer-crosshair nil)
+(kern-set-crosshair t_crosshair)
+(kern-set-frame s_frame_ulc
+                s_frame_urc
+                s_frame_llc
+                s_frame_lrc
+                s_frame_td
+                s_frame_tu
+                s_frame_tl
+                s_frame_tr
+                s_null
+                s_frame_horz
+                s_frame_vert
+                s_frame_endl
+                s_frame_endr)
+(kern-set-ascii ss_u4_charset 32)
+(kern-set-cursor ls_whirlpool)
+(kern-set-damage-sprite s_hit)
+(kern-add-query 'str_based_attack_query proc-stratt)
+(kern-add-query 'dex_based_attack_query proc-dexatt)
+(kern-add-query 'damage_bonus_query proc-stratt)
+(kern-add-query 'defense_bonus_query proc-dexdef)
+(kern-add-hook 'combat_change_hook 'music-on-combat-change)
+(kern-add-hook 'session_start_hook 'music-on-combat-change)
+
+;; Setup the global effect sprites
+(kern-set-quicken-sprite s_quicken)
+(kern-set-time-stop-sprite s_time_stop)
+(kern-set-magic-negated-sprite s_magic_negated)
+(kern-set-reveal-sprite s_reveal)
+(kern-set-xray-vision-sprite s_xray_vision)
+
+(kern-init-random)
+
diff --git a/worlds/haxima-1.002/gamestart-mech.scm b/worlds/haxima-1.002/gamestart-mech.scm
new file mode 100644 (file)
index 0000000..3e22618
--- /dev/null
@@ -0,0 +1,196 @@
+
+  
+(define (get-player-name kbeing)
+      (begin
+        (kern-log-msg "Speak your name, Seeker")
+               (let
+               ((reply (kern-conv-get-string kbeing)))
+            (if (equal? reply "")
+                               nil
+               (begin
+                       (kern-log-msg (string-append "Hail, " reply "!"))
+                       (kern-being-set-name kbeing reply)
+                                       (kern-map-flash 1)
+               )
+            )
+        ) 
+               #f
+               ))
+               
+(define (one-off-message kbeing message messageid)
+       (if (is-player-party-member? kbeing)
+               (begin
+                       (kern-log-msg message)
+                       (map (lambda (trigobj)
+                               (if (equal? (length (gob trigobj)) 3)
+                                       (if (equal? (caddr (gob trigobj)) messageid)
+                                               (kern-obj-remove trigobj)
+                                       ))
+                               )
+                               (kplace-get-objects-of-type (car (kern-obj-get-location kbeing)) t_step_trig))
+                       #f
+                       )))
+               
+(define (gamestart-statue-clean kbeing messageid)
+       (map (lambda (trigobj)
+               (if (equal? (length (gob trigobj)) 3)
+                       (if (equal? (caddr (gob trigobj)) messageid)
+                               (kern-obj-remove trigobj)
+                       ))
+               )
+       (kplace-get-objects-of-type (car (kern-obj-get-location kbeing)) t_step_trig))
+       )
+                               
+(define (gamestart-statue-speak kbeing speaker messageid)
+       (if (is-player-party-member? kbeing)
+               (begin
+                       (kern-log-msg "A statue suddenly speaks to you!")
+                       (kern-conv-begin (eval speaker))
+                       ))
+                       #f
+               )
+
+(define (get-gamestart-data kbeing key)
+       (let ((rdata (get-roomdata (car (kern-obj-get-location kbeing)))))
+               (list-ref rdata key)
+    ))
+    
+(define (gamestart-field-circle ftype loc x y count)
+       (define (sign n)
+               (cond ((> n 0) 1)
+                               ((< n 0) -1)
+                               (#t 0))
+               )
+       (define (is-my-field? kobj) (eqv? ftype (kern-obj-get-type kobj)))
+       (define (gamestart-field-circle-elem xp yp toshow tocheck)
+               (let* ((xf (+ x xp))
+                               (yf (+ y yp))
+                               (show (not (< (* toshow 8) (* tocheck count))))
+                               (fields (filter is-my-field? (kern-get-objects-at (mk-loc loc xf yf))))
+                               )
+                       (cond ((null? fields) nil)
+                               (else
+                                       (kern-obj-remove (car fields))))
+                       (if show
+                               (kern-obj-put-at (kern-mk-obj ftype 1) (mk-loc loc xf yf))
+                               )
+                       (if (> tocheck 1)
+                               (let (
+                                       (ntoshow (if show (- toshow 1) toshow))
+                                       (nxp (sign (- xp yp)))
+                                       (nyp (sign (+ xp yp)))
+                                       )
+                               (gamestart-field-circle-elem nxp nyp ntoshow (- tocheck 1))
+                               ))
+                       ))      
+       (let* ((sa (kern-dice-roll "1d3-2"))
+                       (sb (if (> 1 (kern-dice-roll "1d2")) 1 -1))
+                       (xy (kern-dice-roll "1d2"))
+                       (xp (if (> xy 1) sa sb))
+                       (yp (if (> xy 1) sb sa))
+                       )
+                       (gamestart-field-circle-elem xp yp count 8)
+       )
+)
+       
+(define (gamestart-reset-lamps kbeing)
+               (let ((str (floor (+ (/ (* (- (kern-char-get-strength kbeing) 10) 7) 12) 1)))
+                               (dex (floor (+ (/ (* (- (kern-char-get-dexterity kbeing) 10) 7) 12) 1)))
+                               (int (floor (+ (/ (* (- (kern-char-get-intelligence kbeing) 10) 7) 12) 1)))
+                               (place (eval 'p_char_setup)))
+                       (gamestart-field-circle F_fire_perm place 4 10 str)
+                       (gamestart-field-circle F_acid_perm place 9 8 dex)
+                       (gamestart-field-circle F_energy_perm place 14 10 int)
+               (kern-map-repaint)
+       ))
+       
+(define (gamestart-light-lamps kbeing unused messageid)
+       (if (is-player-party-member? kbeing)
+               (begin
+                               (gamestart-reset-lamps kbeing)
+       (map (lambda (trigobj)
+
+               (if (equal? (length (gob trigobj)) 3)
+                       (if (equal? (caddr (gob trigobj)) messageid)
+                               (kern-obj-remove trigobj)
+                       ))
+               )
+       (kplace-get-objects-of-type (car (kern-obj-get-location kbeing)) t_step_trig))
+       )
+       
+       )
+       #f)
+
+(define (set-gamestart-data kbeing key value)
+       (println (get-roomdata (car (kern-obj-get-location kbeing))))
+       (let* ((rdata (get-roomdata (car (kern-obj-get-location kbeing))))
+                       (curdat (list-tail rdata key)))
+               (set-car! curdat value)
+    ))
+
+(define (initstats kbeing)
+       (let ((rdata (get-roomdata (car (kern-obj-get-location kbeing)))))
+               (kern-char-set-strength     kbeing (/ (- 24    (list-ref rdata 0)  (list-ref rdata 1)) 2))
+               (kern-char-set-dexterity    kbeing (/ (- (+ 12 (list-ref rdata 0)) (list-ref rdata 2)) 2))
+               (kern-char-set-intelligence kbeing (/ (+       (list-ref rdata 1)  (list-ref rdata 2)) 2))
+
+               (kern-log-msg "Strength: "     (number->string (kern-char-get-strength     kbeing)) ", "
+                             "Dexterity: "    (number->string (kern-char-get-dexterity    kbeing)) ", "
+                             "Intelligence: " (number->string (kern-char-get-intelligence kbeing))
+                             )
+
+       ))
+       
+(define (set-stat-info kbeing key value)
+       (set-gamestart-data kbeing key value)
+       (initstats kbeing)
+       (kern-sound-play sound-moongate-enter)
+       (kern-map-flash 1)
+       #f
+       )
+       
+(mk-obj-type 't_start_portal "path forward" s_blackgate_full layer-mechanism step-trig-ifc)    
+
+(define (mk-start-portal proc-tag . args)
+  (bind (kern-mk-obj t_start_portal 1)
+        (trig-mk proc-tag args)))
+
+(define (start-cutscene kplayer startgate)
+       (kern-char-set-sleep ch_wanderer #t)
+       (kern-log-enable #t)
+       (kern-log-msg "A dark gate rises in a quiet clearing...")
+       (moongate-animate black-gate blackgate-stages)
+       (kern-sleep 2000)       
+       (kern-log-enable #f)
+       )
+
+(define (mk-start-cutscene kplayer startgate)
+       (lambda () (start-cutscene kplayer startgate)))
+       
+(define (start-actual-game kplayer)
+    
+  (kern-log-enable #f)
+
+  (kern-obj-set-sprite (eval (get-gamestart-data kplayer 3)) s_grass)
+   (kern-map-repaint)
+       
+  (kern-obj-relocate kplayer (list p_moongate_clearing 11 12) (mk-start-cutscene kplayer (get-gamestart-data kplayer 3)))
+
+  (kern-log-enable #t)
+  (kern-log-msg "Then closes without a trace...")
+  (moongate-animate black-gate (reverse blackgate-stages))
+  (kern-sleep 1000)
+  
+  (kern-log-msg "You lie dreaming for a while, of another life...")
+  (kern-sleep 2000)
+
+  (kern-log-enable #f)
+  (kern-char-set-sleep ch_wanderer #f)
+  (kern-player-set-follow-mode)
+  (kern-log-enable #t)  
+  (kern-log-msg "...then awaken to a strange new world.")
+  (kern-log-msg "To the southwest you see a cave.")
+  (quest-remove (quest-data-get 'questentry-charcreate))
+  (quest-assign (quest-data-get 'questentry-whereami))
+  )
+       
\ No newline at end of file
diff --git a/worlds/haxima-1.002/gamestart-statues.scm b/worlds/haxima-1.002/gamestart-statues.scm
new file mode 100644 (file)
index 0000000..052e125
--- /dev/null
@@ -0,0 +1,234 @@
+(define (gsstatue-unknown knpc kpc)
+  (say knpc "[The statue remains silent]"))
+
+(define (gsstatue-hail knpc kpc)
+  (say knpc "[A statue speaks to you]")
+  (gamestart-statue-clean knpc "statspeak")
+  )
+    
+(define gsstatue-conv
+  (ifc '()
+       ;; fundamentals
+       (method 'default gsstatue-unknown)
+       (method 'hail gsstatue-hail)
+       )
+       )
+
+(define (gsstatue-dostat knpc kpc iname iset iget dname dset dget initial)
+       (define (gs-check-upper value)
+               (if (> value 11)
+                       (begin
+                               (say knpc "I cannot raise your " iname " further")
+                               #t
+                               )
+                       #f))
+       (define (gs-check-lower value)
+               (if (< value 1)
+                       (begin
+                               (say knpc "You must not abuse your " dname " further")
+                               #t
+                               )
+                       #f))
+       (define (gs-initialcheck)
+               (say knpc "Do you wish to convert " dname " into " iname "?")
+               (if (kern-conv-get-yes-no? kpc)
+                       #f #t)
+               )
+       (define (gs-repeatcheck)
+               (say knpc "Continue?")
+               (if (kern-conv-get-yes-no? kpc)
+                       #f #t)
+               )
+       (let ((ival (iget kpc))
+                       (dval (dget kpc))
+                       )
+               (cond ((gs-check-upper ival))
+                       ((gs-check-lower dval))
+                       ((and initial (gs-initialcheck)) (say knpc "As you wish"))
+                       ((and (not initial) (gs-repeatcheck)) (say knpc "As you wish"))
+                       (#t
+                               (iset kpc (+ ival 1))
+                               (dset kpc (- dval 1))
+                               (say knpc "[Your " iname " increases]")
+                               (say knpc "[Your " dname
+                                       (cond ((< dval 3) " withers!]")
+                                               ((< dval 9) " diminishes]")
+                                               (#t " wanes]")
+                                       )
+                               )
+                               (gamestart-reset-lamps kpc)
+                               (gsstatue-dostat knpc kpc iname iset iget dname dset dget #f)
+                       )
+               )       
+       ))
+                      
+;; Statue of intelligence
+
+(define (gs-int-hail knpc kpc)
+  (say knpc "Welcome, Seeker. I give wisdom to those who ask for it.")
+  (gamestart-statue-clean knpc "statspeak")
+  )
+  
+(define (gs-int-job knpc kpc)
+       (say knpc "I represent the force of reason, and can assist you in endeavors of magic or wit.")
+       )
+  
+(define (gs-int-assi knpc kpc)
+       (say knpc "I can raise your intellect, but it will cost you some of your strength or dexterity")
+       )
+
+(define (gs-int-rais knpc kpc)
+       (say knpc "You will need to say which attribute you want to suffer the penalty")
+       )
+               
+;; expand on this as other abilities become available
+(define (gs-int-inte knpc kpc)
+  (say knpc "The wise weave spells of power, and resist malignant magicks, but fools are ensnared and easily deceived. "
+       "Beware, Seeker! Evil beings of vast intelligence lie in wait along your path. "
+       "You will need wisdom to overcome them. Is this your wish?")
+  (if (yes? kpc)
+      (say knpc "To grow wise you must give up strength or dexterity.")
+      (say knpc "He who turns away from wisdom is the delight of daemons.")
+      )
+  )
+       
+(define (gs-int-stre knpc kpc)
+  (say knpc "Take heed, Seeker! Physical strength will not avail you against the strongest of the dark powers.")
+  (gsstatue-dostat knpc kpc "intelligence" kern-char-set-intelligence kern-char-get-base-intelligence 
+                   "strength" kern-char-set-strength kern-char-get-base-strength #t)
+  )
+      
+       
+(define (gs-int-dext knpc kpc)
+  (say knpc "Consider well, Seeker! The straightest arrow will miss the unclean warlock, "
+       "and the doors of the deep are locked with spells that cannot be picked.")
+  (gsstatue-dostat knpc kpc "intelligence" kern-char-set-intelligence kern-char-get-base-intelligence 
+                   "dexterity" kern-char-set-dexterity kern-char-get-base-dexterity #t)
+  )
+
+(define (gs-int-bye knpc kpc)
+  (say knpc "Go now, Seeker. May your wards shield you, your summonings aid you, and your wrath rain fire and lightning on the unholy!")
+  )
+
+(define gs-int-conv
+  (ifc '()
+       ;; fundamentals
+       (method 'default gsstatue-unknown)
+       (method 'bye gs-int-bye)
+       (method 'hail gs-int-hail)
+       (method 'job gs-int-inte)
+       (method 'inte gs-int-inte)
+       (method 'int gs-int-inte)
+       (method 'wis gs-int-inte)
+       (method 'wisd gs-int-inte)
+       (method 'stre gs-int-stre)
+       (method 'str gs-int-stre)
+       (method 'dext gs-int-dext)
+       (method 'dex gs-int-dext)
+       )
+  )
+       
+;; Statue of might
+
+(define (gs-str-hail knpc kpc)
+  (say knpc "Hail, Seeker. I give strength to those who would be mighty.")
+  (gamestart-statue-clean knpc "statspeak")
+  )
+  
+;; expand on this as other abilities become available
+(define (gs-str-stre knpc kpc)
+       (say knpc "Gain strength, and you will split helms, crush bones, and batter the shields of your foes to splinters. "
+             "You can bear the heaviest armour without staggering, and the blows of your enemies will glance off unheeded. "
+             "Strength is not the most important thing to a warrior, it is the only thing! "
+             "Would you be strong?")
+        (if (yes? kpc)
+            (say knpc "What will you sacrifice for strength: intelligence or dexterity?")
+            (say knpc "Only the strong will survive where you must go.")
+            ))
+       
+(define (gs-str-inte knpc kpc)
+  (say knpc "A warrior needs some cunning, but might is paramount!")
+  (gsstatue-dostat knpc kpc "strength" kern-char-set-strength kern-char-get-base-strength 
+                   "intelligence" kern-char-set-intelligence kern-char-get-base-intelligence #t)
+  )
+       
+(define (gs-str-dext knpc kpc)
+  (say knpc "Your friends may be impressed by feats of dexterity, "
+       "but your foes will be persuaded by force of arms!")
+  (gsstatue-dostat knpc kpc "strength" kern-char-set-strength kern-char-get-base-strength 
+                   "dexterity" kern-char-set-dexterity kern-char-get-base-dexterity #t)
+  )
+
+(define (gs-str-bye knpc kpc)
+  (say knpc "Go now and smite the wicked."))
+
+(define gs-str-conv
+  (ifc '()
+       ;; fundamentals
+       (method 'default gsstatue-unknown)
+       (method 'bye gs-str-bye)
+       (method 'hail gs-str-hail)
+       (method 'job gs-str-stre)
+       (method 'stre gs-str-stre)
+       (method 'inte gs-str-inte)
+       (method 'int gs-str-inte)
+       (method 'dext gs-str-dext)
+       (method 'dex gs-str-dext)
+       )
+  )
+       
+;; Statue of agility
+
+(define (gs-dex-hail knpc kpc)
+  (say knpc "Well met, Seeker. Alas, I cannot make you a powerful brute nor an absent-minded mage like my adjacent cohorts, "
+       "but allow me to profer dexterity.")
+  (gamestart-statue-clean knpc "statspeak")
+  )
+  
+(define (gs-dex-dext knpc kpc)
+  (say knpc "Dexterity is the attribute of the subtle adventurer. Why beat down a door when one can pick the lock?\n\n"
+       "Why ruin the eyesite on musty grimoires when treasure is easily found by stealth and craft?\n\n"
+       "Why risk mussing one's tastefully chosen accoutrements in a melee when foes can be shot from afar with aplomb?\n\n"
+       "And indeed, should a momentary lapse in judgment leave one cornered, speed and quick thinking will save the day. "
+       "Do you agree?")
+  (if (yes? kpc)
+      (say knpc "Indeed. Dexterity is well worth the sacrifice of crass strength or boorish intelligence.")
+      (say knpc "Ah. Well. Mind your wallet, friend. Thieves love to prey on the clumsy.")
+      )
+  )
+       
+(define (gs-dex-inte knpc kpc)
+  (say knpc "If you ask me, intelligence is greatly overrated. "
+       "I mean, who cares about raising the dead when one can loot their corpses?")
+       (gsstatue-dostat knpc kpc "dexterity" kern-char-set-dexterity kern-char-get-base-dexterity 
+                        "intelligence" kern-char-set-intelligence kern-char-get-base-intelligence #t)
+       )
+       
+(define (gs-dex-stre knpc kpc)
+  (say knpc "Strength is impressive to the impressionable, "
+       "but hauling all that armour and weaponry around looks like pointless hard work.")
+  (gsstatue-dostat knpc kpc "dexterity" kern-char-set-dexterity kern-char-get-base-dexterity 
+                   "strength" kern-char-set-strength kern-char-get-base-strength #t)
+  )
+
+(define (gs-dex-bye knpc kpc)
+  (say knpc "Farewell, always keep your wits about you, "
+       "never pass up an opportunity to sip from a flagon or kiss a pretty maid, "
+       "and at all costs, Seeker, remember to die well!")
+  )
+
+(define gs-dex-conv
+  (ifc '()
+       ;; fundamentals
+       (method 'default gsstatue-unknown)
+       (method 'bye gs-dex-bye)
+       (method 'hail gs-dex-hail)
+       (method 'job gs-dex-dext)
+       (method 'dex gs-dex-dext)
+       (method 'dext gs-dex-dext)
+       (method 'stre gs-dex-stre)
+       (method 'str gs-dex-stre)
+       (method 'inte gs-dex-inte)
+       (method 'int gs-dex-inte)
+       )
+  )
diff --git a/worlds/haxima-1.002/gamestart.scm b/worlds/haxima-1.002/gamestart.scm
new file mode 100644 (file)
index 0000000..d4cd76c
--- /dev/null
@@ -0,0 +1,120 @@
+(kern-load "gamestart-mech.scm")
+(kern-load "gamestart-statues.scm")
+
+(kern-mk-place 'p_char_setup "the Path"
+  s_shrine ;; sprite
+  (kern-mk-map 'm_char_setup 19 19 pal_expanded
+       (list
+         "xx xx xx xx xx xx x! xx xx xx xx xx x! xx xx xx xx xx xx "
+         "x! @@ @@ .C .H .O .O .S .E @@ @@ @@ .Y .O .U .R @@ @@ x! "
+         "xx @@ @@ @@ @@ @@ @@ .P .A .T .H @@ @@ @@ @@ @@ @@ @@ xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ++ ,, ,, ,, ,, ,, ,, ,, ++ ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, cx cx cx ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, cx cx cx ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, cx cx cx ,, ,, cx cx cx ,, ,, cx cx cx ,, ,, xx "
+         "xx ,, ,, cx cx cx ,, ,, ,, ,, ,, ,, ,, cx cx cx ,, ,, xx "
+         "xx ,, ,, cx cx cx ,, ,, ,, ,, ,, ,, ,, cx cx cx ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+         "x! ,, ,, +s ,, ,, ,, ,, pp cc pp ,, ,, ,, ,, +s ,, ,, x! "
+         "xx ,, ,, ,, ,, ,, ,, pp ,, cc ,, pp ,, ,, ,, ,, ,, ,, xx "
+         "xx xx xx xx xx xx x! xx xx xx xx xx x! xx xx xx xx xx xx "
+       )
+       )
+
+  #f #t #f #f
+  ;; subplaces
+  nil
+  ;; neighbors
+  nil
+  
+ ;; *** contents of the place ***
+  (list
+   (put (mk-step-trig 'get-player-name nil) 9 16)
+   (put (kern-tag 'start-gate (mk-start-portal 'start-actual-game)) 9 4)
+   (put (kern-mk-obj F_illum_perm 1) 3 1)
+   (put (kern-mk-obj F_illum_perm 1) 15 1)
+   (put (kern-mk-obj F_illum_perm 1) 9 1)
+   (put (kern-mk-obj F_illum_perm 1) 10 4)
+   (put (kern-mk-obj F_illum_perm 1) 8 4)
+   )
+
+  nil ;; hooks
+  nil
+
+)
+(define (obj-line objfactory yloc xloc xmax)
+       (kern-obj-put-at (objfactory xloc) (list p_char_setup xloc yloc))
+       (if (< xloc xmax)
+               (obj-line objfactory yloc (+ xloc 1) xmax)
+       ))  
+;; Note: start-gate must be a tag to survive saving/reloading.
+(set-roomdata p_char_setup (list 6 6 6 'start-gate))
+
+(obj-line (lambda (unused)
+       (mk-step-trig 'one-off-message "A portal beckons on the far side of the room" "intromes"))
+       15 8 10)
+       
+(obj-line (lambda (unused)
+       (mk-step-trig 'gamestart-light-lamps nil "lamps"))
+       14 7 11)
+       
+(kern-obj-put-at (mk-step-trig 'gamestart-light-lamps nil "lamps") (list p_char_setup 7 15))
+(kern-obj-put-at (mk-step-trig 'gamestart-light-lamps nil "lamps") (list p_char_setup 11 15))
+(kern-obj-put-at (mk-step-trig 'gamestart-light-lamps nil "lamps") (list p_char_setup 7 16))
+(kern-obj-put-at (mk-step-trig 'gamestart-light-lamps nil "lamps") (list p_char_setup 11 16))
+
+(define (mk-start-statue tag name sprite conv)
+  (let ((kchar (bind 
+                (kern-mk-char 
+                 tag            ; tag
+                 name             ; name
+                 sp_statue         ; species
+                 nil              ; occ
+                 sprite     ; sprite
+                 faction-men      ; starting alignment
+                 0 0 0            ; str/int/dex
+                 999 0              ; hp mod/mult
+                 0 0              ; mp mod/mult
+                 max-health ; hp
+                 0                   ; xp
+                 max-health ; mp
+                 0
+                 9
+                 #f               ; dead
+                 conv         ; conv
+                 nil           ; sched
+                 'ankh-ai              ; special ai
+                 nil              ; container
+                 nil              ; readied
+                 )
+                nil)))
+    (kern-char-set-known kchar #t)
+    ))
+
+(kern-obj-put-at (mk-start-statue 'str_statue "Statue of Might" s_str_statue 'gs-str-conv) (list p_char_setup 4 10))
+(kern-obj-put-at (mk-start-statue 'dex_statue "Statue of Agility" s_dex_statue 'gs-dex-conv) (list p_char_setup 9 8))
+(kern-obj-put-at (mk-start-statue 'int_statue "Statue of Wisdom" s_int_statue 'gs-int-conv) (list p_char_setup 14 10))
+
+(obj-line (lambda (unused)
+       (mk-step-trig 'gamestart-statue-speak 'str_statue "statspeak"))
+       10 1 6)
+(obj-line (lambda (unused)
+       (mk-step-trig 'gamestart-statue-speak 'dex_statue "statspeak"))
+       9 6 12)
+(obj-line (lambda (unused)
+       (mk-step-trig 'gamestart-statue-speak 'int_statue "statspeak"))
+       10 12 17)
+
+       
+;;(gamestart-field-circle F_fire_perm p_char_setup 4 10 4)
+;;(gamestart-field-circle F_acid_perm p_char_setup 9 8 4)
+;;(gamestart-field-circle F_energy_perm p_char_setup 14 10 4)
+
diff --git a/worlds/haxima-1.002/gate-guard.scm b/worlds/haxima-1.002/gate-guard.scm
new file mode 100644 (file)
index 0000000..8be3fcf
--- /dev/null
@@ -0,0 +1,189 @@
+;;----------------------------------------------------------------------------
+;; gate-guard -- wizard guards of the Enchanter's Tower
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (mk-gate-guard-gob gate-tag post passwd)
+  (list 'gate-guard gate-tag 0 post passwd))
+
+(define (gate-guard-gate-tag guard) (cadr guard))
+(define (gate-guard-gate-timer guard) (caddr guard))
+(define (gate-guard-post guard) (cadddr guard))
+(define (gate-guard-passwd guard) (list-ref guard 4))
+(define (gate-guard-set-gate-timer! guard val) (set-car! (cddr guard) val))
+(define (gate-guard-start-timer! guard) (gate-guard-set-gate-timer! guard 10))
+
+(define (char-is-gate-guard? kchar)
+  (let ((gob (kobj-gob-data kchar)))
+    (if (notnull? gob)
+        (eq? (car gob) 'gate-guard)
+        #f)))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+(define (gate-guard-default knpc kpc)
+  (say knpc "[No reply]"))
+
+(define (gate-guard-hail knpc kpc)
+  (say knpc "Halt! What is the password?")
+  (let ((passwd (kern-conv-get-reply kpc)))
+    (if (eq? passwd (gate-guard-passwd (gob knpc)))
+        (let* ((guard (kobj-gob-data knpc))
+               (gate (eval (gate-guard-gate-tag guard))))
+          (signal-kobj gate 'on gate nil)
+          (gate-guard-start-timer! guard)
+          (say knpc "You may pass")
+          (kern-conv-end))
+        (begin
+          (say knpc "That is not correct")
+          (kern-conv-end)
+          ))))
+
+(define gate-guard-conv
+  (ifc nil
+       (method 'default gate-guard-default)
+       (method 'hail gate-guard-hail)
+       ))
+
+;;----------------------------------------------------------------------------
+;; Mage Guard AI
+;;
+;; FIXME: when and if mundane gate guards are added don't hardcode the
+;; gate-guard AI to use this "sub"-AI
+;;----------------------------------------------------------------------------
+(define (need-more-troops? kchar)
+  (> (length (all-visible-hostiles kchar)) 
+     (length (all-visible-allies kchar))))
+
+(define (mguard-cast-spell kchar ktarg)
+  (if (and (need-more-troops? kchar)
+           (> (kern-char-get-mana kchar) 4))
+      (begin
+        (kern-log-msg "The mage guard summons help!")
+        (summon (kern-obj-get-location ktarg) 
+                mk-ranger
+                (kern-being-get-current-faction kchar)
+                (kern-dice-roll "1d3"))
+        (kern-char-dec-mana kchar 4)
+        (kern-obj-dec-ap kchar 4)
+        #t)
+      ;; don't need or can't summon more troops
+      (if (and (is-undead? ktarg)
+               (can-cast? kchar an-xen-corp))
+          (begin
+            (cast0 kchar (lookup-spell an-xen-corp))
+            #t)
+          ;; don't need or can't repel undead
+          #f)))
+
+(define (mguard-ai kchar)
+  (let ((ktarg (ai-select-target kchar)))
+    (if (null? ktarg)
+        (ai-wander kchar)
+        (or (mguard-cast-spell kchar ktarg)
+            (ai-attack-target kchar ktarg)
+            (ai-pathfind-to-target kchar ktarg)))))
+
+;;----------------------------------------------------------------------------
+;; AI
+;;----------------------------------------------------------------------------
+
+(define (guard-is-holding-gate-open? guard)
+  (> (gate-guard-gate-timer guard) 0))
+
+(define (guard-dec-gate-timer! guard)
+  (gate-guard-set-gate-timer! guard (- (gate-guard-gate-timer guard) 1))
+  (if (<= (gate-guard-gate-timer guard) 0)
+      (let ((kgate (eval (gate-guard-gate-tag guard))))
+        (signal-kobj kgate 'off kgate nil)
+        (gate-guard-set-gate-timer! guard 0))))
+
+(define (guard-start-gate-timer! guard)
+  (gate-guard-start-timer! guard))
+
+(define (gate-is-open? kgate)
+  (signal-kobj kgate 'is-on? kgate nil))
+
+(define (hostiles-visible? kguard)
+  (notnull? (all-visible-hostiles kguard)))
+
+(define (guard-close-gate! guard kgate)
+  (signal-kobj kgate 'off kgate nil)
+  (gate-guard-set-gate-timer! guard 0)
+  (kern-log-msg "The guard closes the gate"))
+
+(define (guard-too-far-from-gate? kguard kgate)
+  (> (distance kguard kgate) 1))
+
+(define (guard-return-to-post kguard)
+  (pathfind kguard 
+            (cons (loc-place (kern-obj-get-location kguard))
+                  (gate-guard-post (gob kguard)))))
+
+(define (gate-guard-ai kchar)
+  (or (get-off-bad-tile? kchar)
+      (use-potion? kchar)
+      (let* ((guard (kobj-gob-data kchar))
+             (kgate (eval (gate-guard-gate-tag guard))))
+        (if (any-visible-hostiles? kchar)
+            (if (gate-is-open? kgate)
+                (guard-close-gate! guard kgate)
+                #f)
+            (begin
+              (guard-return-to-post kchar)
+              (if (guard-is-holding-gate-open? guard)
+                  (guard-dec-gate-timer! guard)
+                  (if (gate-is-open? kgate)
+                    (guard-start-gate-timer! guard)
+                    ))
+              #t)))))
+
+;;----------------------------------------------------------------------------
+;; Constructor -- make a guard captain
+;;----------------------------------------------------------------------------
+(define (mk-gate-guard gate-tag post passwd)
+  (println "mk-gate-guard: " gate-tag ", " post)
+  (bind
+   (set-level
+    (kern-char-arm-self
+     (mk-stock-char
+      "a guard captain" ;;......name
+      sp_human ;;.........species
+      oc_warrior ;;........occupation
+      s_companion_paladin ;;........sprite
+      faction-men ;;...faction
+      'gate-guard-ai ;;.......custom ai (optional)    
+      ;;..................container (and contents, used to arm char)
+      (mk-inventory
+       (mk-contents
+        (roll-to-add 100  "3"     t_heal_potion)
+        (roll-to-add 100  "1"     t_sword)
+        (roll-to-add 199  "1"     t_shield)
+        (roll-to-add 100  "1"     t_armor_plate)
+        (roll-to-add 100  "1"     t_iron_helm)
+        (roll-to-add 100  "1d5"   t_gold_coins)
+        ))
+      
+      nil ;;...............readied arms (in addition to container contents)
+      'gate-guard-conv ;;..conversation
+      ))
+    8)
+   (mk-gate-guard-gob gate-tag post passwd)))
+
+(define (put-gate-guard ktrig gate-tag passwd)
+  (println "put-gate-guard: " ktrig "," gate-tag)
+  (kern-obj-put-at (mk-gate-guard gate-tag
+                                  (cdr (kern-obj-get-location ktrig))
+                                  passwd)                   
+                   (kern-obj-get-location ktrig))
+  #f)
+
+;;----------------------------------------------------------------------------
+;; gate-guard generator
+;;----------------------------------------------------------------------------
+(define (mk-gate-guard-gen is-one? mk-one . mk-args)
+  (mk-mongen2 0 1 is-one? mk-one mk-args))
diff --git a/worlds/haxima-1.002/gen.scm b/worlds/haxima-1.002/gen.scm
new file mode 100644 (file)
index 0000000..4b1ee68
--- /dev/null
@@ -0,0 +1,317 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Green Tower.
+;;----------------------------------------------------------------------------
+(define (mk-zone x y w h) (list 'p_green_tower x y w h))
+(kern-mk-sched 'sch_gen
+               (list 0  0  (mk-zone 2  13 1  1)  "sleeping")
+               (list 4  0  (mk-zone 3  12 3  3)  "eating")
+               (list 5  0  gt-woods  "idle")
+               (list 10 0  (mk-zone 26 27 2  12) "idle")
+               (list 12 0  (mk-zone 49 54 1  1)  "eating")
+               (list 13 0  (mk-zone 49 3  7  2)  "idle")
+               (list 14 0  (mk-zone 7  20 5  5)  "idle")
+               (list 18 0  (mk-zone 49 54 1  1)  "eating")
+               (list 19 0  (mk-zone 3  12 3  3)  "idle")
+               (list 0  0  (mk-zone 2  13 1  1)  "sleeping")
+               )
+
+;; ----------------------------------------------------------------------------
+;; Gen's Goblin Lexicon
+;; ----------------------------------------------------------------------------
+(mk-reusable-item 
+ 't_goblin_lexicon "Goblin Lexicon" s_lexicon norm
+ (lambda (klexicon kuser)
+   (kern-ui-page-text
+   "Goblin Lexicon"
+   "I compiled these notes to help others learn the goblin language. "
+   "I hope they are useful."
+   "--Gen"
+   ""
+   "Bo.....My, Myself"
+   "Cho....Mankind"
+   "Da.....Abode, World"
+   "Eh.....'What?'"
+   "Gu.....Spirit, Ancestor"
+   "Ha.....Good, Yes, Skillful"
+   "Hi.....Magic"
+   "Iki....Go, At"
+   "Jo.....Join"
+   "Ka.....Kill, Destroy, End"
+   "Ki.....Health, Life-Force, Power"
+   "Lu.....Change, Metamorphosis, Transformation"
+   "Ma.....Forest, Hidden Ways"
+   "Me.....Duty, Job, Destiny"
+   "Na.....Yours, Yourself"
+   "Nu.....Give Birth, Create, Begin"
+   "No.....Name"
+   "Nin....Stealth"
+   "Ru.....Ancient, Primordal, Deep, Cave"
+   "To.....Individual"
+   "Tu.....No, Bad"
+   "Zu.....Watch, Seek"
+   )))
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (gen-mk will-join? gave-notes?) (list will-join? gave-notes?))
+(define (gen-will-join? gen) (car gen))
+(define (gen-gave-notes? gen) (cadr gen))
+(define (gen-set-will-join! gen val) (set-car! gen val))
+(define (gen-set-gave-notes! gen val) (set-car! (cdr gen) val))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Gen is a Ranger who dwells in Green Tower.
+;; He has much knowledge of Goblin kind, and is a friend of Kama.
+;; Gen is a potential party member.
+;;----------------------------------------------------------------------------
+(define (gen-hail     gen player) (say gen "Hail, Wanderer"))
+(define (gen-bye      gen player) (say gen "Farewell"))
+(define (gen-default  gen player) (say gen "I can't help you with that"))
+(define (gen-name     gen player) (say gen "I am Gen." ))
+(define (gen-woodsman gen player) (say gen "Yes, some call me the Woodsman." ))
+(define (gen-job      gen player) (say gen "Once I was a Ranger, but my duty now is done. I wander 'midst the woods for my own reasons." ))
+(define (gen-reasons  gen player) (say gen "My reasons are my own." ))
+
+(define (gen-captain gen player) 
+  (say gen "Captain Deric commands the Rangers of Green Tower. Have you met him?")
+  (if (kern-conv-get-yes-no? player)
+      (say gen "A decent man, if somewhat ambitious.")
+      (say gen "You can find him in the Tower. His office is on the second floor.")))
+
+(define (gen-ambitious   gen player) (say gen "In peace there's nothing so becomes a man as modest stillness and humility." ))
+(define (gen-culture     gen player) 
+  (say gen "Though a culture their own, truly a culture they have, (unlike the trolls and headless)."
+       "The truths of culture can be seen in Shakespeare, truths which hold across the gulfs between different folk."))
+(define (gen-shakespeare gen player)
+  (say gen "You know of him! Very good! Some interesting conversation at last.")
+  (if (in-player-party? 'ch_kama)
+      (say gen player "[He points at Kama] Another who knows of the Bard! You should hear his telling of Hamlet!")
+      ))
+
+(define (gen-ranger gen player) (say gen "Rangers fought in these woods during the Goblin Wars. Now they maintain a token presence."))
+(define (gen-wars   gen player) (say gen "Yes, I fought as a Ranger in the goblin wars. That was a generation ago, and people forget. "
+                                    "They see the goblins as lesser beings, defeated and worthy of slow extinction."))
+(define (gen-goblin gen player) (say gen "An interesting species. Although they have their own language they have no writing. "
+                                    "They are much like men, but more savage, more primal. "
+                                    "Their warriors are beserkers, their shamans are ecstatic mystics."))
+(define (gen-primal gen player) (say gen "You can tell I admire them? But in the wars I fought them, not understanding what they were. "
+                                    "I have friends among the wild forest goblins, now. The cave goblins, though, they are another story..." ))
+(define (gen-cave   gen player) (say gen "The cave goblins, who are larger and stronger than their forest cousins, prefer to live in the deeps of the world. "
+                                    "Their dark god demands living sacrifices. Beware them if you explore the caves, they burn with hatred for humankind." ))
+
+(define (gen-language kgen player)
+  (let ((gen (kobj-gob-data kgen)))
+    (say kgen "Yes, I can speak a few words of goblin. Would you like to learn?")
+    (if (kern-conv-get-yes-no? player)
+        (if (gen-gave-notes? gen)
+            (say kgen "Study the notes I gave you, and then practice on me.")
+            (begin
+              (say kgen "Here are some notes I have made on their language. You may keep it. Feel free to practice with me.")
+              (kern-obj-add-to-inventory player t_goblin_lexicon 1)
+              (gen-set-gave-notes! gen #t)))
+        (say kgen "Perhaps another time."))))
+
+
+(define (gen-practice gen player) (say gen "If you want to practice speaking goblin, just ask me something in goblin!" ))
+
+(define (gen-join gen player)
+  (if (gen-will-join? (kobj-gob-data gen))
+      (begin
+        (say gen "Yes, I will join you. "
+             "I'll need my equipment from my chest, "
+             "so let's go to my hut in the west part of town. "
+             "Once more unto the breach, dear friends!")
+             (join-player gen))
+      (say gen "No, for the woods call my name.")))
+
+;; SAM: Added a few words from the Lexicon which were not defined as responses.
+;;      These were (Iki, Lu, Nin)
+;;      Also enhanced a few responses such as for (Eh).
+;; Added responses having to do with the concepts of Wanderer, Warrior, Wizard, Rogue, Wright.
+;; A bit of organization/tidying may still be wanted, to make sure there are no loose ends .
+
+(define (gen-da  gen player) (say gen "Ha! Da-Ma-To means forest goblin." ))
+(define (gen-gu  gen player) (say gen "Ha! Da-Gu means world." ))
+(define (gen-ru  gen player) (say gen "Ha! Da-Ru-To means cave goblin." ))
+(define (gen-no  gen player) (say gen "Bo-No-Gen. But the goblins call me Ma-Zu-To." ))
+(define (gen-ki  gen player) (say gen "Bo-Ha-Ki! I am healthy." ))
+(define (gen-jo  gen player) (say gen "Very good! If you befriend a goblin he may join you in your adventures."))
+(define (gen-cho gen player) (say gen "Ha! Cho-To means 'a man'." ))
+(define (gen-nu  gen player) (say gen "Ha! Nu-Ki is the goblin word for 'food'" ))
+(define (gen-ha  gen player) (say gen "Yes, Ha is a general affirmative term." ))
+(define (gen-tu  gen player) (say gen "Right, Tu is a general negative term." ))
+(define (gen-bo  gen player) (say gen "Yes, Bo-Gu means your spirit self, which is your altar ego in the spirit world." ))
+(define (gen-na  gen player) (say gen "Yes, Bo-Na means 'us', or 'tribe'. Bo-Na-Ma refers to forest goblins in general." ))
+(define (gen-to  gen player) (say gen "Right, To is a general suffix meaning person." ))
+(define (gen-ma  gen player) (say gen "Yes, and Ka-Ma-To is their term for lumberjack." ))
+(define (gen-eh  gen player) (say gen "Eh?  Ah yes, Eh-Na-Me means what is your job, or duty." ))
+(define (gen-iki gen player) (say gen "Ha! Bo-Iki-Da means 'I go home'."))
+
+(define (gen-me  gen player) (say gen "Bo-Ma-Zu. I watch the forest, or I seek the hidden ways.  Me-Lu-Ki is to grow, change, learn, explore.  Such is the path of the Wanderer!"))
+(define (gen-ka  gen player) (say gen "Ha! Ka-Ha-To means warrior.  And Me-Ka-Ha is the path of the Warrior!"))
+(define (gen-hi  gen player) (say gen "Ha! Hi-Ma-To is the word for 'shaman'.  And Me-Ha-Zu-Ru is the path of the Wizard!"))
+(define (gen-nin gen player) (say gen "Ha! Nin-Ma-To is a Forest Stalker.  And Me-Ha-Nin-Zu is the path of the Rogue!"))
+(define (gen-lu  gen player) (say gen "Ha! Lu-Da-To is one who makes.  And Me-Ha-Lu-Da is the path of the Wright!"))
+
+(define (gen-zu       gen player) (say gen "Good! And Zu-To means seeker, or Wanderer.  [He looks at you percingly.]  Iki Meluki?"))
+(define (gen-meluki   gen player) (say gen "So, you are a seeker indeed.  I would join you, if you can master Gunodama"))
+(define (gen-gunodama gen player) (say gen "The names given by the ancestor spirits, to those who abide in the forest.  In other words, the language of the Forest Goblins."))
+
+(define (gen-nuki knpc kpc)
+  (say knpc "That's goblinese for 'food'."))
+
+(define (gen-bonaha gen player) 
+  (say gen "Excellent! That is the goblin word for friend. You have come far in mastering their language.")
+  (gen-set-will-join! (kobj-gob-data gen) #t))
+
+(define (gen-shroom gen player) (say gen "She is an old friend. Can you believe she was a war-maiden in the Goblin Wars?"))
+(define (gen-maiden gen player) (say gen "It's true! I can still remember her hand-axe flashing in the moonlight "
+                                   "as she hacked her way through goblin war parties, chanting a battle-ward "
+                                   "with ragged breath! She was a sight to see."))
+
+(define (gen-thie knpc kpc)
+  (say knpc "I've seen no one odd around here, but the goblins who live in "
+       "the north wood recently saw a lone man traveling northeast toward "
+       "Bole.")
+       (quest-data-update 'questentry-thiefrune 'tower 1)
+       (quest-data-update-with 'questentry-thiefrune 'bole 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+
+(define (gen-kama knpc kpc)
+  (if (is-player-party-member? ch_kama)
+      (begin
+        (say knpc "I see Kama has joined you. Bonaha Kama!")
+        (say ch_kama "Unh. Bonaha Mazuto."))
+      (begin
+        (say knpc "Kama is a forest goblin hunter. He was supposed to meet me at the edge of town a few nights back but he never showed up. Have you seen him?")
+        (if (yes? kpc)
+            (begin
+              (say knpc "Is he in trouble?")
+              (if (yes? kpc)
+                  (say knpc "We must help him if we can!")
+                  (say knpc "That is a relief!")))
+            (say knpc "If you do, let me know. I'm a bit worried.")))))
+            
+(define (gen-ruka knpc kpc)
+  (say knpc "Ruka is the goblin's name for Angriss, their god of death. "
+       "The priests of Angriss were agitators during the goblin wars. "
+       "Her cult has all but died out since their defeat. ")
+  (prompt-for-key)
+  (say knpc "Now, she is only a myth to keep children from straying into the woods, "
+       "where more practical dangers still exist."))
+
+(define (gen-clov knpc kpc)
+  (say knpc "King Clovis led the paladins in the Goblin War. "
+       "If my friend Kama would ever show up we could ask him "
+       "if the goblins ever recovered his body.")
+       (quest-data-update-with 'questentry-rune-f 'kama 1 (quest-notify nil))
+       )
+
+(define (gen-band knpc kpc)
+  (say knpc "The goblins report a bandit camp somewhere to the south and west. "
+       "Perhaps Deric knows more."))
+
+(define gen-conv
+  (ifc basic-conv
+       ;;;; Goblin root words:
+       (method 'bo  gen-bo)  ; My, Myself
+       (method 'cho gen-cho) ; Mankind
+       (method 'da  gen-da)  ; Abode, World
+       (method 'eh  gen-eh)  ; What?
+       (method 'gu  gen-gu)  ; Spirit, Ancestor
+       (method 'ha  gen-ha)  ; Good, yes, skillful
+       (method 'hi  gen-hi)  ; Magic
+       (method 'iki gen-iki) ; Go
+       (method 'jo  gen-jo)  ; Join
+       (method 'ka  gen-ka)  ; Kill
+       (method 'ki  gen-ki)  ; Health
+       (method 'lu  gen-lu)  ; Change
+       (method 'me  gen-me)  ; Forest
+       (method 'ma  gen-ma)  ; Duty, Job, Destiny
+       (method 'na  gen-na)  ; Your, yourself
+       (method 'nin gen-nin) ; Stealth
+       (method 'no  gen-no)  ; Name
+       (method 'nu  gen-nu)  ; Give birth, Create, Begin
+       (method 'ru  gen-ru)  ; Ancient, Primordial, Deep, Cave
+       (method 'to  gen-to)  ; Individual
+       (method 'tu  gen-tu)  ; No, Bad
+       (method 'zu  gen-zu)  ; Watch, Seek
+
+       ;;;; Goblin composite words / phrases:
+       (method 'bona gen-bonaha)   ; Friend
+       (method 'kama gen-kama)     ; Kama, the goblin friend of Gen
+       (method 'nuki gen-nuki)     ; Food
+       (method 'ruka gen-ruka)     ; Angriss, the Spider Queen
+       (method 'melu gen-meluki)   ; Seeker, Wanderer
+       (method 'guno gen-gunodama) ; the language of the Forest Goblins
+
+       ;;;; Responses in human speech:
+       ;; Standard responses:
+       (method 'default gen-default)
+       (method 'hail gen-hail)
+       (method 'name gen-name)
+       (method 'job  gen-job)
+       (method 'join gen-join)
+       (method 'bye  gen-bye)
+
+       ;; Having to do with the goblin language:
+       (method 'gobl gen-goblin)
+       (method 'lang gen-language)
+       (method 'prac gen-practice)
+
+       ;; Other responses:
+       (method 'admi gen-primal)
+       (method 'ambi gen-ambitious)
+       (method 'band gen-band)
+       (method 'capt gen-captain)
+       (method 'cave gen-cave)
+       (method 'fore gen-job)
+       (method 'maid gen-maiden)
+       (method 'prim gen-primal)
+       (method 'rang gen-ranger)
+       (method 'reas gen-reasons)
+       (method 'sava gen-primal)
+
+       (method 'cult gen-culture)
+       (method 'shak gen-shakespeare)
+       (method 'bard gen-shakespeare)  ;; synonyn
+       (method 'haml gen-shakespeare)  ;; synonyn
+
+       (method 'shro gen-shroom)
+       (method 'thie gen-thie)
+       (method 'wars gen-wars)
+       (method 'wood gen-woodsman)
+       (method 'clov gen-clov)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-gen tag)
+  (bind 
+   (kern-mk-char tag                 ; tag
+                 "Gen"               ; name
+                 sp_human            ; species
+                 oc_ranger           ; occ
+                 s_old_ranger  ; sprite
+                 faction-men         ; starting alignment
+                 4 2 4                  ; str/int/dex
+                 pc-hp-off  ; hp bonus
+                 pc-hp-gain ; hp per-level bonus
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'gen-conv           ; conv
+                 sch_gen             ; sched
+                 'townsman-ai        ; special ai
+                 (mk-inventory (list (list 1 t_dagger) 
+                                    (list 1 t_playbook_hamlet)
+                                    ))  ; container
+                 (list t_armor_leather)                ; readied
+                 )
+   (gen-mk #f #f)))
diff --git a/worlds/haxima-1.002/generic-mech.scm b/worlds/haxima-1.002/generic-mech.scm
new file mode 100644 (file)
index 0000000..b39cc1f
--- /dev/null
@@ -0,0 +1,3 @@
+(define (mk-mech states start)
+  (lambda (op . args)
+    
diff --git a/worlds/haxima-1.002/ghertie.scm b/worlds/haxima-1.002/ghertie.scm
new file mode 100644 (file)
index 0000000..099d9d6
--- /dev/null
@@ -0,0 +1,203 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Oparine
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_ghertie
+               (list 0  0  cheerful-room-3      "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (ghertie-mk) 
+  (list (mk-quest)))
+
+(define (ghertie-quest gob) (car gob))
+
+
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Ghertie is the vengeful ghost of a murdered female pirate captain.
+;; She haunts an inn room in Oparine.
+;;----------------------------------------------------------------------------
+
+;; Quest...
+(define (ghertie-give-instr knpc kpc)
+  (say knpc "Each member of my crew wears a "
+       "cursed ring, with a skull for a signet. It cannot be "
+       "removed without the finger. Jorn, Gholet and Meaney still "
+       "live. Bring me their rings to fulfil your part of the "
+       "bargain, and I will then fulfill mine.")
+       (quest-data-update-with 'questentry-ghertie 'questinfo 1 (quest-notify nil))
+)
+
+(define (ghertie-update-quest knpc kpc)
+  (let ((nrem (- 3 (num-in-inventory kpc t_skull_ring))))
+    (if (= nrem 0)
+        (begin
+          (say knpc "I am avenged! Now I can rest... the Merciful "
+               "Death lies at [" merciful-death-x ", " merciful-death-y
+               "] by the sextant. But how you will pillage her when "
+               "she lies at the bottom of the sea is your problem! "
+               "[She vanishes with a cruel laugh]")
+                       (quest-data-update-with 'questentry-rune-c 'shiploc 1 (quest-notify nil))
+                       (quest-data-assign-once 'questentry-ghertie)
+                       (quest-data-update-with 'questentry-ghertie 'done 1 (grant-party-xp-fn 20))
+                        (kern-conv-end)
+          (kern-obj-remove knpc)
+          (kern-map-set-dirty))
+        (begin
+          (say knpc "You still have " nrem " rings to collect. "
+               "Have you forgotten my instructions?")
+           (if (kern-conv-get-yes-no? kpc)
+               (begin
+                 (say knpc "If you were one of my crew I would have you "
+                      "flogged for your carelessness!")
+                 (ghertie-give-instr knpc kpc))
+               (say knpc "Then why have you returned empty-handed? "
+                    "If you fail in your oath I will flog your soul with my "
+                    "own hand!"))))))
+
+;; Basics...
+(define (ghertie-hail knpc kpc)
+  (let ((quest (ghertie-quest (kobj-gob-data knpc))))
+               (quest-data-update 'questentry-ghertie 'ghertieloc 1)
+               (quest-data-assign-once 'questentry-ghertie)
+    (display "quest:")(display quest)(newline)
+    (if (quest-accepted? quest)
+        (ghertie-update-quest knpc kpc)        
+        (say knpc "[You meet the ghost of a wild-looking woman] "
+             "You dare disturb me? Be wary, I am in a black mood."))))
+
+(define (ghertie-default knpc kpc)
+  (say knpc "I care not for this line of talk."))
+
+(define (ghertie-name knpc kpc)
+       (quest-data-update 'questentry-ghertie 'ghertieid 1)
+  (say knpc "I am Ghertrude."))
+
+(define (ghertie-join knpc kpc)
+  (say knpc "I am anchored here for eternity."))
+
+(define (ghertie-job knpc kpc)
+  (say knpc "I was a pirate when I was alive. Now I haunt this room."))
+
+(define (ghertie-bye knpc kpc)
+  (if (quest-accepted? (ghertie-quest (kobj-gob-data knpc)))
+      (say knpc "Avenge me without delay!")
+      (say knpc "Trust not your crew!")))
+
+;; Pirate...
+(define (ghertie-pira knpc kpc)
+  (say knpc "I plunderd this coastline for years and amassed a fortune. "
+       "Then, on the eve of my retirement, my crew betrayed me. "
+       "They were like sons to me, the wretches!"))
+
+(define (ghertie-betr knpc kpc)
+  (say knpc "The cowards slew me in my sleep and stole my ship."))
+
+(define (ghertie-ship knpc kpc)
+  (say knpc "The Merciful Death was fast, limber and mean. "
+       "I could not wish for a finer ship. My treasure was nothing, "
+       "my life was doomed, but for stealing my ship I will never "
+       "forgive my crew!"))
+
+(define (ghertie-haun knpc kpc)
+  (say knpc "I am bound to this spot. My first mate knew I would not rest "
+       "in my grave, and with a curse he fixed me here so I could not "
+       "pursue them with my vengeance! Ha! He did not know "
+       "about the curse upon my ship!"))
+
+(define (ghertie-curs knpc kpc)
+  (say knpc "I had a curse put upon my ship. Should it ever be stolen it "
+       "would steer itself to a particular place and sink! I alone know "
+       "of its watery grave..."))
+
+(define (ghertie-grav knpc kpc)
+  (say knpc "Why should I tell you?"))
+
+(define (ghertie-reve knpc kpc)
+  (let ((quest (ghertie-quest (kobj-gob-data knpc))))
+    (if (quest-accepted? quest)
+        (say knpc "Yes, you have sworn to avenge me, "
+             "why are you prattling?")
+        (begin
+          (say knpc "[She fixes you with an icy glare] "
+               "You speak the word dearest to my dead heart. "
+               "Are you offering to avenge me?")
+       (quest-data-update 'questentry-ghertie 'revenge 1)
+          (if (kern-conv-get-yes-no? kpc)
+              (begin
+                (say knpc "Not all of my crew went down with the ship. "
+                     "I have searched among the dead and found some missing. "
+                     "Find and punish the survivors, "
+                     "and I will tell you where my ship lies. "
+                     "Do we have an oath?")
+                (if (kern-conv-get-yes-no? kpc)
+                    (begin
+                      (say knpc "Agreed then, mortal. ")
+                      (quest-accepted! quest #t)
+                      (ghertie-give-instr knpc kpc))
+                    (say knpc "It is wise you do not take such an oath "
+                         "lightly, for I await oath-breakers on this side "
+                         "of the divide.")))
+              (begin
+                (say knpc "Then do not toy with me, fool!")
+                (kern-conv-end)))))))
+
+(define (ghertie-fort knpc kpc)
+  (say knpc "Gold, gems, magical items, weapons armor and runes.")
+       (quest-data-assign-once 'questentry-rune-c)
+       )
+
+(define ghertie-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default ghertie-default)
+       (method 'hail ghertie-hail)
+       (method 'bye ghertie-bye)
+       (method 'job ghertie-job)
+       (method 'name ghertie-name)
+       (method 'join ghertie-join)
+       
+       ;; special
+       (method 'pira ghertie-pira)
+       (method 'betr ghertie-betr)
+       (method 'crew ghertie-betr)
+       (method 'ship ghertie-ship)
+       (method 'haun ghertie-haun)
+       (method 'curs ghertie-curs)
+       (method 'grav ghertie-grav)
+       (method 'fort ghertie-fort)
+       (method 'reve ghertie-reve)
+
+       ))
+
+(define (mk-ghertie)
+  (bind 
+   (kern-mk-char 'ch_ghertie           ; tag
+                 "Ghertie"             ; name
+                 sp_ghast            ; species
+                 oc_warrior                 ; occ
+                 s_ghost               ; sprite
+                 faction-men         ; starting alignment
+                 0 0 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 6  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'ghertie-conv         ; conv
+                 sch_ghertie           ; sched
+                 nil                 ; special ai
+                 nil                 ; container
+                 nil                 ; readied
+                 )
+   (ghertie-mk)))
diff --git a/worlds/haxima-1.002/gholet.scm b/worlds/haxima-1.002/gholet.scm
new file mode 100644 (file)
index 0000000..47f80d5
--- /dev/null
@@ -0,0 +1,187 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define gholet-lvl 4)
+(define gholet-species sp_human)
+(define gholet-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the Prison level under Glasdrin
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (gholet-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Gholet is a former pirate, now imprisoned in the Prison below Glasdrin.
+;; He is one of the surviving crew of the Merciful Death, 
+;; and is sought for vengeance by the ghost Ghertie.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (gholet-hail knpc kpc)
+  (say knpc "'Ello, guv'nah"))
+
+(define (gholet-default knpc kpc)
+  (say knpc "Right you are, guv'nah, that's what I like about you!"))
+
+(define (gholet-name knpc kpc)
+  (say knpc "Gholet's me 'andle, but take no account o' me, guv'nah")
+  (quest-data-update 'questentry-ghertie 'gholet-dungeon 1))
+
+(define (gholet-join knpc kpc)
+  (say knpc "And leave behind 'is 'ere life of luxury? Tosh!"))
+
+(define (gholet-job knpc kpc)
+  (say knpc "Why, I's a cook. Or I was, at any rate, 'fore I took up the new "
+       "vocation you see me at 'ere."))
+
+(define (gholet-bye knpc kpc)
+  (say knpc "Nice chattin' with ya, guv'nah"))
+
+;; Tier 2 replies
+(define (gholet-cook knpc kpc)
+  (say knpc "I was a cook on a famous luxury liner! The Merciful Death, "
+       "ever 'ear of her?")
+  (if (yes? kpc)
+      (say knpc "Oh. Well, I told you she was famous!")
+      (say knpc "Oh, she was quite-well known in her time. "
+           "Don't know what became of 'er.")))
+
+(define (gholet-merc knpc kpc)
+  (say knpc "Oh, yeah, she was captained by a marvelous woman. "
+       "Ghertie was her name."))
+
+(define (gholet-gher knpc kpc)
+  (say knpc "A real peach. Couldn't ask for a nicer boss."))
+
+(define (gholet-voca knpc kpc)
+  (say knpc "Aye, this is the easiest job I ever had."))
+
+(define (gholet-mean knpc kpc)
+  (say knpc "'Aven't seen old Meaney in ages. "
+       "Last I 'eard 'e was running a poor 'ouse."))
+
+(define (gholet-jorn knpc kpc)
+  (say knpc "Oh, now there's a right dangerous man, now guv'nah. "
+       "Best let sleeping dogs lie, as I like to say. "))
+
+(define (gholet-dog knpc kpc)
+  (say knpc "From what I 'ear, that dog lies at the White Stag.")
+  (quest-data-update 'questentry-ghertie 'jorn-loc 1))
+
+;; Quest-related
+(define (gholet-ring knpc kpc)
+
+  (if (not (in-inventory? knpc t_skull_ring_g))
+      (say knpc "Ring? What ring?")
+      (begin
+
+        (define (take-picklocks)
+          (if (< (num-in-inventory kpc t_picklock) 12)
+               (begin
+               (quest-data-update-with 'questentry-ghertie 'gholet-price 1 (quest-notify nil))
+              (say knpc "Mmm. Bit of a problem, guv'nah, "
+                   "you don't have enough picklocks. "
+                   "But I'll keep the ring 'ere on layaway until you do.")
+                  )
+              (begin
+                (say knpc "Right you are, 'ere you go, and there I go, "
+                     "right as rain, right as rain! Enjoy your new ring, "
+                     "guv'nah!")
+                (kern-obj-remove-from-inventory kpc t_picklock 12)
+                (kern-obj-add-to-inventory knpc t_picklock 12)
+                (kern-obj-remove-from-inventory knpc t_skull_ring_g 1)
+               (skullring-g-get nil kpc)
+               )))
+
+        (say knpc "Oh, that old thing? It got to itchin', "
+             "I must be allergic to it. "
+             "So I took it off. 'Ad to take the whole finger, off, actually, "
+             "bit of a mess. Would you like to see it?")
+        (if (yes? kpc)
+            (begin
+              (say knpc "Don't blame you. Not at all. "
+                   "It's quite the curious item! "
+                   "But one good turn deserves another, "
+                   "don't you agree, guv'nah?")
+              (if (yes? kpc)
+                  (begin
+                    (say knpc "Of course you do! Youse a fair man, guv'nah! "
+                         "You know tit-for-tat, scratch each other's back! "
+                         "A dozen picklocks. A dozen picklocks and you can have the ring. "
+                         "Agreed?")
+                    (if (yes? kpc)
+                        (take-picklocks)
+                        (begin
+                       (quest-data-update-with 'questentry-ghertie 'gholet-price 1 (quest-notify nil))
+                          (say knpc "That's my price. "
+                               "Come back when you're ready to pay.")
+                          (kern-conv-end))))
+                  (begin
+                    (say knpc "Piss off, then.")
+                    (kern-conv-end))))
+            (say knpc "Don't screw with me. "
+                 "I know you're 'ere for the ring or you wouldn't "
+                 "'ave asked.")))))
+      
+(define gholet-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default gholet-default)
+       (method 'hail gholet-hail)
+       (method 'bye  gholet-bye)
+       (method 'job  gholet-job)
+       (method 'name gholet-name)
+       (method 'join gholet-join)
+       
+       ;; other responses
+       (method 'cook gholet-cook)
+       (method 'merc gholet-merc)
+       (method 'gher gholet-gher)
+       (method 'voca gholet-voca)
+       (method 'ring gholet-ring)
+
+       (method 'mean gholet-mean)
+       (method 'jorn gholet-jorn)
+       (method 'dog  gholet-dog)
+       ))
+
+(define (mk-gholet)
+  (bind 
+   (kern-char-force-drop
+   (kern-mk-char 
+    'ch_my           ; tag
+    "Gholet"             ; name
+    gholet-species         ; species
+    gholet-occ              ; occ
+    s_brigand     ; sprite
+    faction-men      ; starting alignment
+    1 0 3            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    gholet-lvl
+    #f               ; dead
+    'gholet-conv         ; conv
+    nil              ; sched
+    nil              ; special ai
+    ;;..........container (and contents)
+    (mk-inventory
+              (list
+               (list 1 t_skull_ring_g)
+               ))
+    nil              ; readied
+    )
+   #t)
+  (gholet-mk)))
diff --git a/worlds/haxima-1.002/glasdrin.scm b/worlds/haxima-1.002/glasdrin.scm
new file mode 100644 (file)
index 0000000..cb3d2a8
--- /dev/null
@@ -0,0 +1,161 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_glasdrin 31 31 pal_expanded
+       (list
+               "xx xx xx xx xx .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. xx xx xx xx xx "
+               "xx ,, ,, ,, xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx cc ++ cc xx "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, cc cc cc xx "
+               "xx ,, ,, ,, xx xx xx xx xx xx xx xx xx xx xx x! xx xx xx xx xx xx xx xx xx xx xx cc cc cc xx "
+               "xx xx ,, xx xx xx .A .R .M .S ]] xx ,, ,, ,, ,, ,, ,, ,, xx .M .E .D .I .C .K xx xx ,, xx xx "
+               ".. xx ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, pp ,, ,, ,, pp ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+               ".. xx ,, xx ,, xx @@ @@ @@ @@ @@ xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+               ".. xx ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, pp ,, ,, ,, pp ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+               ".. xx ,, xx xx xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, xx xx ,, xx .. "
+               ".. xx ,, xx xx xx xx xx ,, sA xx xx ,, pp ,, ,, ,, pp ,, xx xx xx ,, sH xx xx xx xx ,, xx .. "
+               ".. xx ,, xx ,, ,, xx .. cc .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx cc .. xx ,, ,, xx ,, xx .. "
+               ".. xx ,, xx ,, ,, ,, cc cc xx xx ,, xx xx ,, ,, ,, xx xx ,, xx xx cc cc ,, ,, ,, xx ,, xx .. "
+               ".. xx ,, xx xx xx xx .. cc xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx cc .. xx xx xx xx ,, xx .. "
+               ".. xx ,, xx ,, ,, xx .. cc xx ,, ,, ,, xx w+ ,, w+ xx ,, ,, ,, xx cc .. xx ,, ,, xx ,, xx .. "
+               ".. xx ,, xx ,, ,, ,, cc cc xx ,, ,, ,, xx cc cc cc xx ,, ,, ,, xx cc cc ,, ,, ,, xx ,, xx .. "
+               ".. xx ,, xx xx xx xx .. cc xx xx xx xx x! cc cc cc x! xx xx xx xx cc .. xx xx xx xx ,, xx .. "
+               ".. xx ,, ,, cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ,, ,, xx .. "
+               ".. xx ,, xx xx xx xx xx xx xx .. .. .. .. cc cc cc t3 tt tt t5 xx xx xx xx xx xx xx ,, xx .. "
+               ".. xx ,, xx .H .O .T .E .L xx .. .. .. .. cc cc cc tt ~3 ~5 tt xx .H .O .L .Y ]] xx ,, xx .. "
+               ".. xx ,, xx ,, ,, ,, ,, ,, ,, .. .. .. .. cc cc cc tt ~a ~c tt xx .G .R .A .I .L xx ,, xx .. "
+               ".. xx ,, xx @@ @@ @@ @@ @@ sI .. .. .. .. cc cc cc ta tt tt tc ws ,, ,, ,, ,, ,, xx ,, xx .. "
+               ".. xx ,, xx ,, ,, ,, ,, ,, ,, cc cc cc cc cc cx cc cc cc cc cc ,, ,, ,, ,, ,, ,, xx ,, xx .. "
+               ".. xx ,, xx x! ,, ,, ,, ,, ws bb .. .. bb cc cc cc bb bb bb bb ws ,, ,, 00 ,, && xx ,, xx .. "
+               ".. xx ,, xx xx ,, xx ,, xx xx .. .. .. .. cc cc cc bb .. .. .. sT ,, ,, 00 ,, ,, xx ,, xx .. "
+               ".. xx ,, xx ,, ,, xx ,, ,, xx .. .. .. .. cc cc cc bb .. tC t7 xx ,, ,, ,, ,, ,, xx ,, xx .. "
+               ".. xx ,, xx ,, ,, xx ,, ,, xx .. .. .. bb cc cc cc bb .. tb tc xx ,, [[ @@ ]] xx xx ,, xx .. "
+               "xx xx ,, xx xx xx xx xx xx xx xx xx xx x! cc w+ cc x! xx xx xx xx ,, ,, ,, ,, xx xx ,, xx xx "
+               "xx ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, w+ cc cc cc w+ ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ cc cc cc w+ ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, w+ cc cc cc w+ ,, ,, ,, xx xx xx xx xx xx ,, ,, ,, xx "
+               "xx xx xx xx xx .. .. .. .. xx xx xx xx xx cc cc cc xx xx xx xx xx .. .. .. .. xx xx xx xx xx "
+       )
+
+)
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "patch.scm")
+(kern-load "angela.scm")
+(kern-load "jess.scm")
+(kern-load "chester.scm")
+(kern-load "steward.scm")
+(kern-load "ini.scm")
+(kern-load "jeffreys.scm")
+(kern-load "statue-of-justice.scm")
+(kern-load "janice.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_glasdrin     ; tag
+ "Glasdrin"      ; name
+ s_keep          ; sprite
+ m_glasdrin      ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list  ;; objects:
+
+  (put (mk-monman) 0 0)
+
+  ;; npcs
+  (put (mk-patch) 0 0)
+  (put (mk-angela) 0 0)
+  (put (mk-jess) 0 0)
+  (put (mk-chester) 0 0)
+  (put (mk-steward) 0 0)
+  (put (mk-ini) 0 0)
+  (put (mk-jeffreys) 0 0)
+  (put (mk-janice) 0 0)
+  (put (mk-bull) 19 24)
+
+  ;; guards
+  (put (guard-pt 'glasdrin-halberdier) 15 25)
+  (put (guard-pt 'glasdrin-halberdier) 14 12)
+  (put (guard-pt 'glasdrin-halberdier) 16 12)
+  (put (guard-pt 'glasdrin-crossbowman) 12 28)
+  (put (guard-pt 'glasdrin-crossbowman) 18 28)
+
+  ;; doors
+  (put (mk-windowed-door) 21 21)
+  (put (mk-locked-door) 24 11)
+  (put (mk-locked-door) 24 14)
+  (put (mk-locked-door)  6 11)
+  (put (mk-locked-door)  6 14)
+  (put (mk-locked-door) 11 11)
+  (put (mk-locked-door) 19 11)
+  (put (mk-windowed-door) 8 9)
+  (put (mk-door) 5 5)
+  (put (mk-door) 5 7)
+  (put (mk-windowed-door) 15 13)
+
+  ;; hospital
+  (put (mk-windowed-door) 22 9)
+  
+
+  ;; wall doors
+  (put (mk-locked-door) 3 16)
+  (put (mk-locked-door) 27 16)
+  (put (mk-locked-door) 2 4)
+  (put (mk-locked-door) 4 2)
+  (put (mk-door) 26 28)
+  (put (mk-door) 28 26)
+
+  ;; inn
+  (put (mk-windowed-door) 9 21)
+  (put (mk-door) 9 19)
+  (put (kern-tag 'glasdrin-inn-room-1-door (mk-locked-door)) 5 23)
+  (put (kern-tag 'glasdrin-inn-room-2-door (mk-locked-door)) 7 23)
+  (put (mk-bed) 4 25)
+  (put (mk-bed) 8 25)
+  (put (mk-clock) 4 21)
+
+  ;; NPC beds
+  (put (mk-bed) 26 10)
+  (put (mk-bed)  4 13)
+  (put (mk-bed) 26 13)
+  (put (mk-bed)  4 10)
+  (put (mk-bed) 11 14)
+  (put (mk-bed) 29 28)
+  (put (mk-bed) 19 14)
+  (put (mk-bed)  1 29)
+
+  ;; ladder down to prison
+  (put (mk-ladder-down 'p_prison 6 4) 2 2)
+
+  ;; Stewardess's chest
+  (put (let* ((kchest (make-invisible (mk-chest nil '((1 t_stewardess_journal))))))
+         (kcontainer-lock-with-key kchest 't_stewardess_chest_key)
+         kchest)
+       10 14)
+
+  ;; Statue of justice
+  (put (kern-mk-obj t_statue_of_justice 1) 15 21)
+  )
+
+
+ ;; on-entry hook
+ (list 'on-entry-to-dungeon-room 
+       'lock-inn-room-doors
+       )
+ (list ;; edge entrances
+       (list northwest 16 30)
+       (list northeast 14 30)
+ )
+)
+
+(mk-place-music p_glasdrin 'ml-large-town)
diff --git a/worlds/haxima-1.002/goblin-kingdoms.scm b/worlds/haxima-1.002/goblin-kingdoms.scm
new file mode 100644 (file)
index 0000000..90a704a
--- /dev/null
@@ -0,0 +1,264 @@
+;;;;
+;;;; goblin-kingdoms.scm -- dungeon rooms for the first level of Kurpolis
+;;;;
+
+;;
+;; load characters
+;;
+(kern-load "douglas.scm")
+
+;;
+;; define dungeon rooms
+;;
+
+(mk-dungeon-room
+ 'p_kurpolis_entrance "Entrance to Kurpolis"
+       (list
+               "rr rr rr rr xx xx x! xx xx && xx xx x! xx xx rn rn rn rn "
+               "rr .. .. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+               "xx xx x! xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+               "xx xx ,, ,, ,, ,, ,, [[ @@ @@ @@ ]] ,, ,, x! rn rn rn rn "
+               "xx xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+               "xx xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn r8 r8 rn "
+               "xx xx ,, xx xx xx xx xx xx x! xx xx xx xx xx rc bb ,, ra "
+               "xx xx ,, xx xx .K .U .R .P .O .L .I .S xx ,, bb bb bb ,, "
+               "xx xx ,, xx x! ,, ,, ,, ,, ,, ,, ,, ,, x! bb bb ,, bb ,, "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, bb ,, ,, ,, "
+               "x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb ,, "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ bb bb bb bb ,, "
+               "xx xx ,, xx x! ,, ,, ,, ,, ,, ,, ,, ,, x! bb bb ,, bb r3 "
+               "xx xx ,, xx xx xx xx xx xx xx xx xx xx xx xx ,, bb r3 rn "
+               "xx xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx r1 r1 rn rn "
+               "xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+               "xx xx x! xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+               "rn rn rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+       )
+ (put (mk-ladder-up 'p_shard 53 18) 9 10)
+ (put (mk-door) 2 8)
+ (put (mk-door) 2 12)
+ (put (mk-door) 4 15)
+ (put (mk-door) 4 3)
+ (put (mk-locked-door) 4 1)
+ (put (mk-windowed-door) 13 10)
+ (put (mk-chest nil '((10 t_food))) 1 1)
+ (put (mk-bed) 5 17)
+ (put (mk-bed) 7 17)
+ (put (mk-bed) 9 17)
+ (put (mk-bed) 11 17)
+ (put (mk-bed) 13 17)
+ (put (mk-clock) 13 5)
+ (put (spawn-pt 'cave-goblin-slinger) 18 7)
+ (put (spawn-pt 'cave-goblin-slinger) 18 11)
+ (put (spawn-pt 'cave-goblin-berserker) 15 9)
+ (put (guard-pt 'crossbowman) 12 9)
+ (put (guard-pt 'crossbowman) 12 11)
+ (put (guard-pt 'halberdier) 10 10)
+ (put (mk-douglas) 9 9)
+ )
+
+(mk-place-music p_kurpolis_entrance 'ml-castle)
+
+(mk-dungeon-room
+ 'p_goblin_crossroads "Goblin Crossroads"
+       (list
+               "rn rn rn rn rn rn r4 {{ {{ ,, ,, {{ ra r8 r8 rn rn rn rn "
+               "rn rn rn rn rn rn rn r5 {{ ,, {# {{ {{ {{ {{ ra r8 rn rn "
+               "rn rn rn rn rn rn rn r4 {{ {{ ,, {5 {{ rf {{ {{ {{ r2 rn "
+               "rn rn rn rn rn rn rn rn r5 {{ ,, bb {5 {{ {{ {{ {{ r2 rn "
+               "rn rn rn rn rn rn rn rn r4 ,, {{ {a {8 {1 {5 {{ {{ ra rn "
+               "rn rn rn rn rn rn rn rn rn r5 {{ {{ {{ {a bb {d {{ {{ r2 "
+               "r8 r8 r8 rn rn rn rn rn rn r4 bb {{ {{ {{ {e {{ {{ {{ ra "
+               "{{ {{ {{ ra r8 rn rn rn rn rn r5 {{ {{ {{ {{ {{ {{ {{ {{ "
+               ",, {{ {{ {a bb ra rn rn rn rn r4 {{ {{ {{ {{ {{ ,, {C ,, "
+               ",, {E ,, {{ {6 {{ ra rn rn rn rc {{ {{ ,, ,, ,, {A ,, ,, "
+               ",, ,, ,, {1 ,, ,, {{ ra r8 rc {{ {{ {{ {% ,, ,, ,, {% ,, "
+               "{{ {{ {{ {a bb .. {5 {{ {{ {{ {{ {{ {7 {{ {{ {{ {{ {{ {{ "
+               "r5 {{ {{ {{ {2 {8 bb {5 {{ {{ {{ {3 bb {d {{ {{ {{ r3 r1 "
+               "rn r5 {{ r3 rd {{ {a .. {5 {{ {{ {2 {c {{ {{ {{ r3 rn rn "
+               "rn rn r1 r4 {{ {{ {{ {a {8 {1 {1 {4 {{ {{ {{ {{ r2 rn rn "
+               "rn rn rn r4 {{ {{ {{ {{ {{ {2 bb {4 {{ {{ rb r1 rn rn rn "
+               "rn rn rn rn r5 {{ {{ {{ {{ ,, .. {c {{ {{ {{ r2 rn rn rn "
+               "rn rn rn rn rn r1 r5 {{ {{ {2 {4 {{ r3 r1 r1 rn rn rn rn "
+               "rn rn rn rn rn rn r4 {{ ,, .. .. r3 rn rn rn rn rn rn rn "
+       )
+ (put (spawn-pt 'cave-goblin-slinger) 14 11)
+ (put (spawn-pt 'cave-goblin-berserker) 15 9)
+ (put (spawn-pt 'cave-goblin-priest) 16 10)
+ (put (spawn-pt 'forest-goblin-hunter) 15 5)
+ (put (spawn-pt 'forest-goblin-hunter) 12 7)
+ (put (spawn-pt 'forest-goblin-shaman) 13 5)
+ (put (spawn-pt 'forest-goblin-stalker) 16 8)
+ )
+
+(mk-place-music p_goblin_crossroads 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_cave_goblin_village "Cave Goblin Village"
+       (list
+               "rn rn rn rn rn rn r8 r8 r8 r8 r8 r8 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rc {{ {{ {{ {{ {{ {{ ra rn r8 r8 r8 rn rn "
+               "rn rn rn rn r4 {{ ,, ,, ,, ,, {A {{ {{ rr {{ {{ {{ ra rn "
+               "rn rn rn rn r4 {{ ,, ,, && ,, ,, bb {{ rr {{ ,, {A {{ r2 "
+               "rn rn rn rn r4 {{ ,, ,, ,, ,, ,, ,, {1 .. {9 ,, ,, {{ r2 "
+               "rn rn rn rn r4 {{ {a {8 ,, ,, {# {{ ,, rr {{ ,, ,, {{ r2 "
+               "r8 r8 r8 r8 rc {{ {{ {{ {6 {{ bb {C ,, rr {{ {{ {{ {{ r2 "
+               "{{ {{ {{ {{ bb {{ bb {{ {2 {5 {C ,, ,, rr r5 {{ {{ r3 rn "
+               "{{ {{ {{ {{ bb {{ {{ {3 ,, ,, ,, ,, {# rr rn r1 r1 rn rn "
+               ",, {A ,, {9 .. {9 {1 ,, .. ,, ,, ,, {{ {{ ra rn rn rn rn "
+               ",, ,, {c {{ bb {{ {a ,, ,, ,, ,, {4 {{ {{ {{ r2 rn rn rn "
+               "{{ {{ {{ {{ bb {{ {{ ,, ,, ,, ,, ,, {1 {5 {{ ra r8 rn rn "
+               "r1 r1 r1 r1 r5 {{ bb {% ,, ,, ,, {# ,, .. ~C ~~ ~~ ra rn "
+               "rn rn rn rn r4 {{ {{ {{ {D ,, {B {{ {{ {a ~3 -- -- ~~ r2 "
+               "rn rn rn rn rn r1 r5 bb bb .. bb bb rr {{ ~a -- -- ~~ r2 "
+               "rn rn rn rn rn rn r4 {{ {{ {6 {{ {{ rr {{ {H ~a ~c {G r2 "
+               "rn rn rn rn rn rn r4 {{ {{ {a {5 {{ rr r5 {{ {{ {{ {{ r2 "
+               "rn rn rn rn rn rn r4 {{ {{ {{ {6 {{ r2 r4 {{ {{ {{ r3 rn "
+               "rn rn rn rn rn rn r4 {{ {{ {3 {4 {{ r2 rn r1 r1 r1 rn rn "
+       )
+ (put (spawn-pt 'cave-goblin-slinger)    5  8)
+ (put (spawn-pt 'cave-goblin-slinger)    8  2)
+ (put (spawn-pt 'cave-goblin-slinger)    9  3)
+ (put (spawn-pt 'cave-goblin-slinger)   10 13)
+ (put (spawn-pt 'cave-goblin-berserker)  6 10)
+ (put (spawn-pt 'cave-goblin-berserker)  8  4)
+ (put (spawn-pt 'cave-goblin-berserker)  7  3)
+ (put (spawn-pt 'cave-goblin-berserker)  8 13)
+ (put (spawn-pt 'cave-goblin-priest)    15  4)
+ (put (spawn-pt 'cave-goblin-priest)     9  9)
+ (put (guard-pt 'cave-goblin-berserker) 14  4)
+ (put (guard-pt 'cave-goblin-priest)    16  4)
+ (put (mk-locked-door-in-rock) 13 4)
+ (put (mk-treasure-chest) 16 4)
+ (put (mk-treasure-chest) 16 5)
+ (put (mk-treasure-chest) 15 3)
+ )
+
+(mk-place-music p_cave_goblin_village 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_trolls_den "Troll's Den"
+       (list
+               "rn r8 r8 r8 rn rn r4 {{ {2 ,, ,, {{ r2 rn rn rn rn rn rn "
+               "r4 {{ {{ {{ ra rn r4 {{ {2 ,, {B {{ r2 rn rn rn rn rn rn "
+               "r4 {{ {{ {{ {{ ra r4 {{ {a .. ,, {A r2 rn rn rn rn rn rn "
+               "r4 {{ {{ {{ {{ {{ ra r5 {{ {2 ,, bb r2 rn rn rn rn rn rn "
+               "rn r5 {{ {{ r7 {{ {{ re {{ ,, {c {{ r2 rn rn rn rn rn rn "
+               "rn r4 {{ rb rn rd {{ {{ {{ {6 {{ {{ r2 r8 r8 rn rn rn rn "
+               "rn rc {{ {{ re {{ {{ r7 {{ {a {5 {{ re {{ {{ ra r8 rn rn "
+               "r4 {{ {{ {{ {6 {{ rb rn rd {{ {2 {1 {8 {5 {{ {{ {{ ra rn "
+               "r4 {{ {{ {b bb {d {{ re {{ {3 .. r7 {{ {a {5 {{ {3 .. r2 "
+               "r4 {{ {{ {{ {e {{ {{ {{ {{ {2 rb rn rd {{ {2 {1 .. .. r2 "
+               "rn r5 {{ {{ {{ {{ r7 {{ {3 {c {{ re {{ {{ {2 .. .. && r2 "
+               "rn rn r5 {{ {{ rb rn rd {4 {{ {{ {{ {3 {1 .. {8 .. .. r2 "
+               "rn rn rc {{ {7 {{ re {{ {2 r3 r5 {1 bb {8 {c {{ {a .. r2 "
+               "rn rc {{ bb .. {5 {{ {3 {8 ra rn r5 {4 {{ {{ {{ {{ r3 rn "
+               "r4 {{ {3 .. .. .. {9 {c {{ {{ r2 rn r1 r5 {{ {{ {{ r2 rn "
+               "r4 {{ {a .. .. bb {{ {{ {{ {{ r2 rn rn rn r1 r1 r1 rn rn "
+               "r4 {{ {{ {a {8 bb {{ {{ r3 r1 rn rn rn rn rn rn rn rn rn "
+               "rn r5 {{ {{ {{ r3 r1 r1 rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn r1 r1 r1 rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+       )
+ (put (mk-ladder-up 'p_old_mine 17 17) 3 15)
+ (put (spawn-pt 'troll) 16 10)
+ (put (spawn-pt 'troll-geomancer) 17 9)
+ (put (spawn-pt 'troll) 17 11)
+ (put (kern-mk-obj t_food 1) 17 8)
+ (put (kern-mk-obj t_beer 1) 16 8)
+ (put (kern-mk-obj t_food 1) 16 12)
+ (put (kern-mk-obj t_beer 1) 15 11)
+ (put (mk-corpse-with-loot) 12 13)
+ (put (mk-corpse-with-loot) 14 14)
+ (put (mk-corpse-with-loot) 14 6)
+ )
+
+(mk-place-music p_trolls_den 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_shamans_grove "Shaman's Grove"
+       (list
+               "rn rn rn rn rn rn rn rn r8 r8 r8 rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rc t7 bb t7 ra rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rc tb tt t| t| td ra rn rn rn rn rn rn "
+               "rn rn rn rn rn r4 t7 bb te t& te bb t7 r2 rn rn rn rn rn "
+               "rn rn rn rn rn r4 tt t5 tB aa tD t3 tt r2 rn rn rn rn rn "
+               "rn rn rn rn rn r4 ta tt td tE tb t| tc r2 rn rn rn rn rn "
+               "rn rn rn rn rn rn r5 te bb t7 bb te r3 rn rn rn rn rn rn "
+               "rn rn rn r8 r8 r8 rn r5 t3 tt t5 r3 rn r8 r8 r8 rn rn rn "
+               "rn rn rc t3 tt t5 ra r4 || |X || r2 rc |# |X |% ra rn rn "
+               "rn rc t3 tc t& ta t5 re |t || || re |# |X || || |% ra rn "
+               "r4 t3 tc t# .. t% te bb |X |X |t || || |X || || || |% r2 "
+               "r4 tt tB .. && .. tD tb || |t || || || |X tt || || || r2 "
+               "r4 ta t5 tA .. tC t7 bb || || || |t |X |t |X |X || |C r2 "
+               "rn r5 ta t5 tE t3 tc r7 |X || || r7 |A |X || || |C r3 rn "
+               "rn rn r5 ta tt tc r3 r4 |X || |X r2 r5 |A |t |C r3 rn rn "
+               "rn rn rn r1 r1 r1 rn r4 || tt || r2 rn r1 r1 r1 rn rn rn "
+               "rn rn rn rn rn rn rn r4 t| tt tt r2 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn r4 ta tt tc r2 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn r4 .. .. .. r2 rn rn rn rn rn rn rn "
+       )
+ (put (mk-ladder-down 'p_dank_cave 9 1) 14 11)
+ (put (spawn-pt 'forest-goblin-shaman) 9 3)
+ (put (spawn-pt 'forest-goblin-hunter) 3 11)
+ (put (spawn-pt 'forest-goblin-hunter) 4 10)
+ (put (spawn-pt 'forest-goblin-stalker) 5 11)
+ (put (mk-chest 'spike-trap
+                '((5 t_food)
+                  (20 t_arrow)
+                  (30 t_gold_coins)
+                  (3 t_heal_potion)
+                  ))
+      2 13)
+ (put (mk-chest 'lightning-trap
+                '((2 mandrake)
+                  (6 sulphorous_ash)
+                  (4 blood_moss)
+                  (5 garlic)
+                  (5 ginseng)
+                  (2 t_mana_potion)
+                  (1 t_xp_potion)
+                  ))
+      10 1)
+ )
+
+(mk-place-music p_shamans_grove 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_watchpoint  "Watchpoint"
+       (list
+               "rn rn rn rn rn rn r4 {{ {C ,, ,, {{ r2 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rc {{ ,, ,, {4 {{ ra rn rn rn rn rn rn "
+               "rn rn rn rn rn r4 bb {{ ,, .. ,, {5 {{ r2 rn rn rn rn rn "
+               "rn rn rn rn rn rc {{ {{ ,, .. ,, bb {{ r2 rn rn rn r8 rn "
+               "rn rn rn rn r4 bb {{ {{ {2 ,, ,, {c {{ ra rn rn rc __ r2 "
+               "rn rn rn rn rc {{ {{ {{ ,, .. ,, {{ {{ {{ ra rc -- __ r2 "
+               "rn rn rn r4 bb {A {{ {C oo ee oo {{ ~~ -- -- -- -- __ r2 "
+               "rn rn r8 rc bb bb ~3 ~9 ~~ ee ee ~9 ~~ _! -- -- r3 r1 rn "
+               "rn rc -- -- -- ~~ ~c {& oo ee ~c {{ ~~ -- rb r1 rn rn rn "
+               "r4 __ _! _! -- -c {G {{ {{ ,, {{ {{ {{ {{ {{ r2 rn rn rn "
+               "r4 __ -- -- -- {G {{ bb ,, ,, ,, bb {{ {{ {{ r2 rn rn rn "
+               "r4 __ r3 r5 {{ {{ x. x. w+ d, w+ x. x. {{ {{ r2 rn rn rn "
+               "rn r1 rn r4 {{ {{ x. .. ,, ,, ,, ,, r6 {d {{ r2 rn rn rn "
+               "rn rn rn rn rd {{ x. ,, ,, ,, ,, ,, x. {{ {{ r2 rn rn rn "
+               "rn rn rn r4 {{ {{ x. ,, ,, ,, ,, ,, x. {{ {{ r2 rn rn rn "
+               "rn rn rn r4 {{ {{ bb ,, ,, ,, ,, .. x. {{ r3 rn rn rn rn "
+               "rn rn rn rn r5 {{ xx ,, ,, ,, .. bb x. r1 rn rn rn rn rn "
+               "rn rn rn rn rn r1 rn xx xx && xx xx xx rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn r1 rn rn rn rn rn rn rn rn rn "
+       )
+ (put (mk-ladder-down 'p_paladins_hold 3 9) 9 14)
+ (put (guard-pt 'halberdier) 8 12)
+ (put (guard-pt 'crossbowman) 10 12)
+ )
+
+(mk-place-music p_watchpoint 'ml-dungeon-town)
+
+;;
+;; assemble the rooms into a dungeon level
+;;
+
+(mk-dungeon-level 
+ (list nil                 p_shamans_grove     nil                  )
+ (list p_kurpolis_entrance p_goblin_crossroads p_cave_goblin_village)
+ (list nil                 p_watchpoint        p_trolls_den         )
+ )
diff --git a/worlds/haxima-1.002/gold_frame.png b/worlds/haxima-1.002/gold_frame.png
new file mode 100644 (file)
index 0000000..d386cdb
Binary files /dev/null and b/worlds/haxima-1.002/gold_frame.png differ
diff --git a/worlds/haxima-1.002/gong.wav b/worlds/haxima-1.002/gong.wav
new file mode 100644 (file)
index 0000000..5ffd0dc
Binary files /dev/null and b/worlds/haxima-1.002/gong.wav differ
diff --git a/worlds/haxima-1.002/green-tower-lower.scm b/worlds/haxima-1.002/green-tower-lower.scm
new file mode 100644 (file)
index 0000000..72e275d
--- /dev/null
@@ -0,0 +1,122 @@
+(kern-mk-map 
+ 'm_green_tower_lower 22 38 pal_expanded
+ (list
+               "rn r8 r8 rn r8 r8 r8 rn r8 r8 rn rn rn rn rn rr rr rr rr rr rn rn "
+               "r4 cc cc rr cc cc cc rr cc cc r2 rn rn rn rr rr .. .. .. rr rr rn "
+               "r4 cc cc cc cc cc cc cc cc cc r2 rn rn rr rr .. .. .. .. .. rr rr "
+               "r4 cc cc rr cc cc cc rr cc cc r2 rn rn rr .. .. .. rr .. .. .. rr "
+               "rn rr rr rr cc cc cc rr rr rr rn rn rn rr rr .. rr rr rr .. rr rr "
+               "r4 cc cc rr cc cc cc rr cc cc r2 rn rn rr .. .. .. rr .. .. .. rr "
+               "r4 cc cc cc cc cc cc cc cc cc r2 rn rn rr rr .. rr rr rr .. rr rr "
+               "r4 cc cc rr cc cc cc rr cc cc r2 rn rn rr .. .. .. rr .. .. .. rr "
+               "rn rr rr rr cc cc cc rr rr rr rn rn rn rr rr .. rr rr rr .. rr rr "
+               "r4 cc cc rr cc cc cc rr cc cc r2 rn rn rr .. .. .. rr .. .. .. rr "
+               "r4 cc cc cc cc cc cc cc cc cc r2 rn rn rr rr .. rr rr rr .. rr rr "
+               "r4 cc cc rr cc cc cc rr cc cc r2 rn rn rr .. .. .. rr .. .. .. rr "
+               "rn rr rr rr cc cc cc rr rr rr rr rr rn rr rr .. rr rr rr .. rr rr "
+               "rn rr rr rr cc cc cc cc cc cc cc rr rr rr .. .. .. rr .. .. .. rr "
+               "rr rr cc cc cc cc cc cc cc cc cc cc rr rr rr .. .. .. .. .. rr rr "
+               "rr cc cc cc rr cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. rr "
+               "rr cc && cc rr rr rr rr xx x! cc x! xx .. rr ,C ,R ,Y ,P ,T rr rr "
+               "xx xx xx xx xx xx xx xx xx cc cc cc xx ?? xx xx xx xx xx xx xx rr "
+               "xx xx ,T ,A ,L ,O ,S xx xx cc cc cc xx cc cc _! x! _! cc cc xx rr "
+               "xx x! cc cc cc cc cc x! xx cc cc cc xx cc cc -- _! -- cc cc xx rr "
+               "xx cc cc cc cc cc cc cc xx cc cc cc cc cc cc -- -- -- cc cc xx rr "
+               "xx cc cc cc aa cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc xx rr "
+               "xx cc cc cc cc cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc xx rr "
+               "xx x! cc cc cc cc cc x! xx cc cc cc xx ,C ,I ,S ,T ,E ,R ,N xx rr "
+               "xx xx xx xx cc xx xx xx x! cc cc cc x! xx xx xx xx xx xx xx xx xx "
+               "xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+               "xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+               "xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+               "xx xx xx xx cc xx xx xx x! cc cc cc x! xx xx xx cc xx xx xx xx xx "
+               "xx cc cc cc cc cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc xx rn "
+               "xx cc cc cc cc cc cc cc xx cc cc cc xx cc cc cc cc cc cc cc ?? rn "
+               "xx xx cc cc cc x! cc cc xx cc cc cc xx cc cc x! cc cc cc xx xx rn "
+               "rn xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx rn rn "
+               "rn xx xx xx cc cc cc cc xx cc cc cc xx cc cc cc cc xx xx xx rn rn "
+               "rn rn rn xx xx xx cc cc xx cc cc cc xx cc cc xx xx xx rn rn rn rn "
+               "rn rn rn rn rn xx xx xx xx cc cc cc xx xx xx xx rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+  ))
+
+(kern-mk-place 
+ 'p_green_tower_lower "Beneath Green Tower" nil 
+ m_green_tower_lower 
+ #f ;; is-wrapping?
+ #t ;; is-underground?
+ #f ;; is-wilderness? 
+ #f  ;; is-tmp-combat-place?
+
+ nil ;; subplaces
+
+ ;; neighbors
+ (list (list p_green_tower up))
+
+ ;; objects
+ (list
+
+  (put (mk-monman) 0 0)
+  (put (mk-ladder-up 'p_green_tower 32 32) 10 26)
+
+  ;; cell doors
+  (put (mk-locked-windowed-door) 3 2)
+  (put (mk-locked-windowed-door) 3 6)
+  (put (mk-locked-windowed-door) 3 10)
+  (put (kern-tag 'kama-jail-door (mk-locked-windowed-door)) 7 2)
+  (put (mk-locked-windowed-door) 7 6)
+  (put (mk-locked-windowed-door) 7 10)
+
+  ;; prisoners
+  (put (mk-kama 'kama-jail-door) 8 2)
+
+  ;; crypt
+  (put (mk-ladder-down 'p_crypt 9 3) 17 1)
+  (put (mk-corpse-with-loot) 14 3)
+  (put (mk-corpse-with-loot) 14 5)
+  (put (mk-corpse-with-loot) 14 11)
+  (put (mk-corpse-with-loot) 14 13)
+  (put (mk-corpse-with-loot) 16 5)
+  (put (mk-corpse-with-loot) 16 9)
+  (put (mk-corpse-with-loot) 16 11)
+  (put (mk-corpse-with-loot) 16 13)
+  (put (mk-corpse-with-loot) 18 5)
+  (put (mk-corpse-with-loot) 18 7)
+  (put (mk-corpse-with-loot) 18 9)
+  (put (mk-corpse-with-loot) 18 13)
+  (put (mk-corpse-with-loot) 20 3)
+  (put (mk-corpse-with-loot) 20 5)
+  (put (mk-corpse-with-loot) 20 9)
+  (put (mk-corpse-with-loot) 20 11)
+
+  (put (kern-tag 'gtl-portcullis-1 (mk-portcullis)) 10 16)
+
+  ;; storage room doors
+  (put (mk-windowed-door) 12 20)
+  (put (mk-windowed-door) 4 24)
+  (put (mk-windowed-door) 4 28)
+  (put (mk-windowed-door) 8 32)  
+  (put (mk-windowed-door) 12 32)
+  (put (mk-windowed-door) 16 28)
+
+  ;; monsters
+  (put (spawn-pt 'rat) 15 2)
+  (put (spawn-pt 'rat) 7 29)
+  (put (spawn-pt 'rat) 2 32)
+  (put (spawn-pt 'giant-spider) 13 29)
+  (put (spawn-pt 'giant-spider) 19 29)
+
+  ;; Jailer
+  (put (mk-edward) 5 10)
+  (put (mk-bed) 1 14)
+
+  )
+
+
+ ;; hooks
+ (list 'on-entry-to-dungeon-room)
+ nil ;; edge entrances
+ )
+
+(mk-place-music p_green_tower_lower 'ml-dungeon-town)
diff --git a/worlds/haxima-1.002/green-tower.scm b/worlds/haxima-1.002/green-tower.scm
new file mode 100644 (file)
index 0000000..789966c
--- /dev/null
@@ -0,0 +1,218 @@
+;;
+;; Copyright-Only Dedication (based on United States law)
+;;
+;; The person or persons who have associated their work with this document (the
+;; "Dedicator") hereby dedicate the entire copyright in the work of authorship
+;; identified below (the "Work") to the public domain.
+;;
+;; Dedicator makes this dedication for the benefit of the public at large and
+;; to the detriment of Dedicator's heirs and successors. Dedicator intends this
+;; dedication to be an overt act of relinquishment in perpetuity of all present
+;; and future rights under copyright law, whether vested or contingent, in the
+;; Work. Dedicator understands that such relinquishment of all rights includes
+;; the relinquishment of all rights to enforce (by lawsuit or otherwise) those
+;; copyrights in the Work.
+;;
+;; Dedicator recognizes that, once placed in the public domain, the Work may be
+;; freely reproduced, distributed, transmitted, used, modified, built upon, or
+;; otherwise exploited by anyone for any purpose, commercial or non-commercial,
+;; and in any way, including by methods that have not yet been invented or
+;; conceived.
+;;
+
+(kern-mk-map 
+ 'm_green_tower 64 64 pal_expanded
+       (list
+               "|| || || || || || || || || || || || || || || || || || || || || || || || || || || || || tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || || || || || || || || || || || || || || "
+               "|| || || || || || || || || || || |C rr rr rr rr rr rr rr || || || || || || || || || || tt td .. /7 .. tb tt || || || || || || || || || || || || || || || || || || || || || || || || || || || || "
+               "|| || rr rr rr rr rr || || || rr rr rr && cc cc cc cc rr || || || || || || || || || || tt bb .. /7 .. bb tt || || || || || || || || || || || || xx xx xx xx xx xx xx xx xx tt tt || || || || || "
+               "|| || rr cc cc cc rr || || || rr cc rr cc cc cc cc cc rr || || || || || || || || || tt tt td .. /7 .. tb tt || || || || || || || || || || || |C xx .. .. .. .. .. .. .. xx tt tt tt || || || || "
+               "|| || rr cc cc cc rr || || || rr cc cc cc cc cc cc cc rr || || || || || || || || || tt tt bb .. /4 /d /d /d /d /d /d /d /d /d /d /d /d /d /1 /d .. .. .. .. .. .. .. .. ws tt tt tt || || || || "
+               "|| || rr cc cc cc rr || || || rr cc rr cc cc cc rr rr rr || || || || || || || || tt tt tt td .. /7 .. bb t3 || || || || || || || || || |% /7 tf sR @@ @@ @@ @@ @@ @@ @@ xx tt tt tt || || || || "
+               "|| || rr rr cc rr rr || || || rr cc rr cc cc cc cc cc rr || || || || || || || || tt tt tt bb .. /7 .. t3 tt || || || || || || || || || || /7 .. .. .. .. .. .. .. .. .. xx tt tt || || || || || "
+               "|| || || |% /7 |B || || || || |D /7 rr rr rr rr rr rr rr || || || || || || || tt tt tt tt td .. /7 .. ta tt || || || || || || || || || || /7 t7 xx .S .H .R .O .O .M .S xx || || || || || || || "
+               "|| || || || /8 /d /d /d /1 /d /d /a |# || || || || || || || || || || || || || tt tt tt tt bb .. /7 .. bb tt || || || || || || || || || tt /7 tt xx xx xx xx xx xx xx xx xx || || || || || || || "
+               "|| || || || || || || |% /7 |# || || || || || || || || || || || || || || || tt tt tt tt tt td .. /7 .. tb tt || || || || || || || || tt tt /7 te xx .. .. .. xx .. .. .. xx || || || || || || || "
+               "|| || |C rr rr rr |A || /7 |A || || || || || || || || || || || || || || || tt tt tt tt tt bb .. /7 .. bb tt || || || || || || || || tt tt /8 /d .. .. .. .. ?? .. .. .. ?? tt tt tt tt tt tt tt "
+               "|| rr rr rr cc rr rr |E /4 /d /d /d /d /d /d /d /d /d /d /2 || || || || tt tt tt tt tt tt td .. /7 .. tb tt || || || || tt tt tt tt tt tt tt t5 xx .. .. tf xx .. .. .. xx || || || || || || || "
+               "|| rr cc cc cc cc rr rr /7 |# || || || || || || || || |% /7 || || || || tt tt tt tt tt tt bb .. /7 .. bb tt || || || || tt t& ta tt tt || || || xx xx ws xx xx xx .. xx xx || || || || || || || "
+               "|| rr cc cc cc cc cc cc /a || || || || || || || || tt || /7 || || || tt tt tt tt tt tt tt td .. /7 .. tb tt || tt tt tt tt tA tD tt || || || || || || || || || || || || || || || || || || || || "
+               "|| rr rr cc cc cc rr rr |# || || || || tt || || tt tt tt /7 || || || tt tt tt tt tt tt tt bb .. /7 .. bb tt || tt || || tt tt tt tt || || || || || || || || || || || || || || || || || || || || "
+               "|| |% rr rr && rr rr |# tt || || || tt tc bb || || tt || /7 || tt tt tt tt tt tt tt tt tt td .. /7 .. tb tt || tt || || || || || || || || || || || || || || || || || || || || || || || || || || "
+               "|| || |% rr rr rr |# tt tt tt || tt tc t& tb || || tt bb /7 bb .. bb te bb te bb te bb te t# .. /7 .. t% te bb te bb ta tc bb te bb te bb ta tt || || || || || || || || || || || || || || || || "
+               "|| || || tt || || || || tt || tt tt tB .. tD tt || tc .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. bb tt || || || || || || || || || || || || || || || "
+               "|| || tt tt tt || || || || || || tt t5 tE t3 || || bb .. /4 /d /d /d /d /d /d /d /d /d /d /d /d /5 /d /d /d /d /d /d /d /d /d /d /d /d /2 .. || tt || || || || || || || || || || || || || || || "
+               "|| || || tt || || || || || tt tt tt tt tt tt || || td .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. ta tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || tt tt tt tt tt tt tt || || || bb .. /7 .. .. .. bb t7 bb t7 bb t7 .. .. .. /7 .. .. .. bb t3 t5 bb t7 bb tf tA .. /7 .. bb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || tt tt tc t& ta tt tt || || || || td .. /7 .. .. t3 tt tt tt tt tt tt bb .. .. /7 .. .. bb t3 tt tt tt tt t5 bb t7 .. /7 .. tb tt || || || || || || || || || || || || || || || "
+               "|| || || || || bb tt tc t# .. t% ta tt tt || || || bb .. /7 .. bb tt || || || || || tc xx w+ xx cc xx w+ xx ta || || || || || tt tc .. /7 .. bb tt || || || || || || || || || || || || || || || "
+               "|| || || || || tt tt tB .. .. .. tD tt tt || || || || .. /7 .. tb tt || || || |C xx w+ xx cc cc cc cc cc xx xx xx |A || || || tt bb .. /7 .. tb tt || || || || || || || || || || || || || || || "
+               "|| || || || || tt tt t5 tA .. tC t3 tt tt || || || bb .. /7 .. bb tt || |C xx xx xx cc cc cc cc cc cc cc cc cc xx xx xx |A || tt td .. /7 .. bb tt || || || || || || || || || || || || || || || "
+               "|| || || || || tt tt tt t5 tE t3 tt tt || || || || || .. /7 .. tb tt || xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx || tt bb .. /7 .. t3 tt || || || || || || || || || || || || || || || "
+               "|| || tt tt tt tt || tt tt tt tt bb || || tt tt || bb .. /7 .. bb tt |C xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx |A tt td .. /7 .. ta tt || || || || || || || || || || || || || || || "
+               "|| || tt || || || || || tt tt tt || || || || || || td .. /7 .. tb tt xx xx cc cc cc xx x! xx xx cc xx xx x! xx cc cc cc xx xx tt bb .. /7 .. bb tt || || || || || || || || || || || || || || tt "
+               "tt tt tt || || || || || || || || || || || || || tt bb .. /7 .. bb te xx cc cc cc xx xx xx |v .. cc .. tb |v xx xx cc cc cc xx ta td .. /7 .. tb tt || || || || || || || || || || || || || || tt "
+               "bb ta tt tt tt tt tt tt tt tt tt tt tt tt tt tt tc .. .. /7 .. tf bb xx cc cc cc x! |v |v |v .. cc .. t% ta |v x! cc cc cc xx bb .. .. /7 .. bb tt || || || || || || || || || || || || || || tt "
+               ".. .. bb te bb te bb te bb te bb te bb te bb bb .. .. .. /7 .. .. .. w+ cc cc cc xx te t# bb .. cc .. bb t% te xx cc cc cc w+ .. .. .. /7 .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. xx cc cc cc xx .. .. .. .. cc .. .. .. .. xx cc cc cc xx .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "/d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /5 /d /d /d cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc /d /d /d /5 /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d /d "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. xx cc cc cc xx .. .. .. .. cc .. .. .. .. xx cc cc cc xx .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. bb t7 bb t7 bb t7 bb t7 bb t7 bb t3 tt t5 bb .. .. /7 .. .. .. w+ cc cc cc xx t7 tA bb .. cc .. bb tC t7 xx cc cc cc w+ .. .. .. /7 .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "bb t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt t5 .. /7 .. .. bb xx cc cc cc x! |v t5 tA .. cc .. tC t3 |v x! cc cc cc xx bb .. .. /7 .. bb tt || || || || || || || || || || || tt tt tt tt "
+               "tt tt || || || || tt tt tt tt tt tt tt tt || || tt tc .. /7 .. .. t7 xx cc cc cc xx xx |v td .. cc .. tb |v xx xx cc cc cc xx t7 .. .. /7 .. tb tt || || || || || || || || || || || || || || tt "
+               "tt tt || || || || tt tt tt tt tt tt tt tt || || tt bb .. /7 .. bb tt xx xx cc cc cc xx x! xx xx cc xx xx x! xx cc cc cc xx xx tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || tt tt tt tt tt tt tt || || tt td .. /7 .. tb tt |% xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx |# tt td .. /7 .. tb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || || tt tt tt tt tt tt || || tt bb .. /7 .. bb tt || xx xx cc cc cc cc cc cc cc cc cc cc cc cc cc xx xx || tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || || || || || || || || || || tt td .. /7 .. tb tt || |% xx xx xx cc cc cc cc cc cc cc cc cc xx xx xx |# || tt td .. /7 .. tb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || || || || || || || || || || tt bb .. /7 .. bb tt || || || |% xx w+ xx cc cc cc cc cc xx xx xx |# || || || tt bb .. /7 .. bb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || || || || || || || || rr rr tt td .. /7 .. tb tt || || || || || t5 xx w+ xx cc xx w+ xx t3 || || || || tt tt td .. /7 .. tb tt || || || || || || || || || || || || || || || "
+               "|| || || || || || || || || || || || || || || || tt bb .. /7 .. bb tt tt tt tt tt tt tc bb .. .. /7 .. .. bb ta tt tt tt tt tt tt bb .. /7 .. bb tt tt tt tt tt tt tt || || || || || || || || || "
+               "|| || || || || || || tt tt tt tt || || || || || tt td .. /7 .. .. te bb te bb te bb .. .. .. .. /7 .. .. .. .. bb te bb te bb te .. .. /7 .. .. te bb te bb te bb tt || || || || || || || || || "
+               "|| || || || || tt rr tt rr rr tt rr rr |A || || tt bb .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. t% tb tt || || || || || || || || || "
+               "|| || || rr rr tt tt tt || || tt t5 rr rr rr || tt td .. /8 /d /d /d /d /d /d /d /d /d /d /d /d /5 /d /d /d /d /d /d /d /d /d /d /d /d /9 /d /d /d /d /d /2 .. bb tt || || || || || || || || || "
+               "|| || || rr |# || || tt tt tt || tt tt |% rr || || bb .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. tb tt || || || || || || || || || "
+               "|| || || || tt tt tt tc t# t% ta || tt tt || rr rr || || t5 bb t7 bb t7 bb t7 bb t7 bb t7 bb .. /7 .. t7 bb t7 bb t7 bb t7 bb t7 bb t7 bb tf bb tb td bb /4 /2 bb ta || || || || || || || || || "
+               "|| rr rr || tt tt |C t# .. bb t% tt tt tt tt |% rr rr || tt tt tt tt tt tt tt tt tt tt tt t5 .. /7 .. tt tt tt tt tt tt tt tt tt tt tt xx xx xx xx ws sT cc cc sI ws xx xx xx xx || || || || || "
+               "|| || || || tt tc t# .. .. .. .. te t& ta tt || |% rr || || || || || || || || || || || || tt .. /7 .. tt || || || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc xx || || || || || "
+               "|| tt tt tt tc t# .. .. .. .. .. .. .. t% ta tt || tt tt || || || || || || || || || || || tt .. /7 .. tt || || || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc xx || || || || || "
+               "|| tt tt tt t# bb .. .. .. .. .. .. .. bb t% tt tF ta tt tt tt tt tt || || || || || || || tt .. /7 .. tt || || || || || || || || || || xx cc cc 00 cc cc cc cc cc cc 00 cc cc xx || || || || || "
+               "|| || || tt tA .. .. .. .. aa .. .. .. .. tC tt || rr || || || || tt || || || || || || || tt .. /7 .. tt || || || || || || || || || |C xx cc cc 00 cc cc && && cc cc 00 cc cc xx |A || || || || "
+               "|| rr || tt tt tt t5 .. .. .. .. .. .. t3 tt || || rr || || || || tt || || || || || || || tt .. /7 .. tt || || || || || || || || xx xx xx cc cc 00 cc cc cc cc cc cc 00 cc cc xx xx xx || || || "
+               "|| rr |A || || tF tt .. .. .. .. .. .. tt tt || rr || || |C rr rr tt rr rr |A || || || tt tt .. /7 .. tt || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx || || || "
+               "|| rr rr || tt tt tt bb .. .. .. bb .. tt tt |C rr || || rr rr tb tt td rr rr || || || tt tt .. /7 .. tt || || || || || || || || xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx || || || "
+               "|| |% rr || tt tt tt tt t5 tA .. .. tC tt || rr rr || || rr tf .! .! .! tf rr || || || tt tt .. /7 .. tt || || || || || || || |C xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx |A || || "
+               "|| || || || || || || || tt tt tt tt tt || tt rr |# || || rr .! .! && .! .! rr || || || tt tt .. /7 .. || || || || || || || || xx xx cc xx xx @@ @@ @@ @@ @@ @@ @@ @@ @@ @@ xx xx cc xx xx || || "
+               "|| || || rr rr |A || || tt tt tt || tt tt || rr || || || rr tf .! .! .! .! rr || || || tt tt .. /7 .. tt || || || || || || || xx cc cc cc xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc xx || || "
+               "|| || || |% rr rr || rr rr rr || rr rr rr rr || || || || rr rr .! .! tb t5 rr || || || tt tt .. /7 .. tt || || || || || || || xx cc cc cc xx .W .H .I .T .E @@ .S .T .A .G xx cc cc cc xx || || "
+               "|| || || || || || || || || || || || || || || || || || || |% rr rr rr rr tt || || || tt tt tt .. /7 .. tt || || || || || || || xx cc cc cc xx xx xx xx xx xx xx xx xx xx xx xx cc cc cc xx || || "
+               "|| || || || || || || || || || || || || || || || || || || || || || || || || || || || tt tt tc .. /7 .. ta tt || || || || || || xx xx xx xx xx |# || || || || || || || || |% xx xx xx xx xx || || "
+               "|| || || || || || || || || || || || || || || || || || || || || || || || || || || || tt tt t# .. /7 .. t% tt tt || || || || || || || || || || || || || || || || || || || || || || || || || || || "
+       )
+)
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "shroom.scm")
+(mk-shroom 'ch_shroom)
+
+(kern-load "gen.scm")
+(mk-gen 'ch_gen)
+
+(kern-load "doris.scm")
+(mk-doris 'ch_doris)
+
+(kern-load "deric.scm")
+(mk-deric 'ch_deric)
+
+(kern-load "jorn.scm")
+(kern-load "abe.scm")
+(kern-load "kama.scm")
+(kern-load "abigail.scm")
+(kern-load "edward.scm") ;; for GTL
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_green_tower "Green Tower" s_towertown_ruin m_green_tower #f #f #f #f 
+ nil ;; subplaces
+ nil ;; neighbors
+
+ ;; objects:
+ (list
+
+  ;; characters:
+  (put ch_shroom  14 1)
+  (put ch_gen     0 0)
+  (put ch_doris   0 0)
+  (put (mk-abigail) 0 0)
+  (put ch_deric   0 0)
+  (put (mk-jorn) 0 0)
+  (put (mk-abe) 0 0)
+  
+  ;; Shroom's Shop
+  (put (mk-locked-door) 48 10)
+  (put (mk-door) 48 6)
+  (put (mk-door) 48 4)
+  (put (mk-magic-locked-door) 54 12)
+  (put (mk-bed) 51 9)
+  (put (mk-chest 'burn-trap
+                 '((50 sulphorous_ash)
+                              (50 garlic)
+                              (50 ginseng)
+                              (50 blood_moss)
+                              (50 black_pearl)
+                              (50 spider_silk)
+                              (50 mandrake)
+                              (50 nightshade)))
+       53 9)
+  (put (mk-chest 'poison-trap
+                 '((10 t_cure_potion)
+                              (10 t_heal_potion)
+                              (10 t_mana_potion)
+                              (10 t_poison_immunity_potion)
+                              (1 t_invisibility_potion)))
+       54 9)
+  (put (mk-chest 'sleep-trap
+                 '((1 t_armor_leather)
+                              (1 t_sword)
+                              (1 t_shield)
+                              (1 t_leather_helm)))
+       55 9)
+
+
+  ;; Gen's Hut
+  (put (mk-door-in-rock) 7 13)
+  (put (mk-bed) 2 13)
+  (put (mk-chest nil 
+                 '((100 t_arrow)
+                              (1 t_bow)))
+       4 11)
+                
+  ;; Deric's Hut
+  (put (mk-door-in-rock) 11 6)
+  (put (mk-door-in-rock) 16 6)
+  (put (mk-bed) 17 4)
+  (put (mk-chest 'burn-trap
+                 '((100 t_bolt)
+                              (1 t_crossbow)
+                              (1 t_shield)
+                              (2 t_cure_potion)
+                              (5 t_heal_potion)))
+       17 6)
+  
+  ;; White Stag Lodge
+  (put (mk-door) 51 49)
+  (put (mk-door) 52 49)
+  (put (mk-door) 57 59)
+  (put (mk-clock) 46 50)
+  (put (kern-tag 'white-stag-door (mk-locked-door)) 44 58)
+  (put (mk-bed) 43 61)
+  (put (mk-bed) 58 61)
+  (put (mk-locked-door) 59 58)
+  
+  ;; Tower 
+  (put (mk-lever 'gtl-portcullis-1) 29 28)
+  (put (mk-ladder-down 'p_green_tower_lower 10 26) 32 32)
+  (put (mk-door) 32 22)
+  (put (mk-door) 41 32)
+  (put (mk-door) 32 42)
+  (put (mk-door) 23 32)
+
+  ;; Guards
+  (put (mk-monman) 0 0)
+  (put (spawn-pt 'ranger) 31 5)
+  (put (spawn-pt 'ranger) 5  31)
+  (put (spawn-pt 'ranger) 56 31)
+  (put (spawn-pt 'ranger) 31 56)
+  
+  )
+ ;; On-entry hook
+ (list 'on-entry-to-dungeon-room 
+       'lock-inn-room-doors
+       )
+ nil   ; edge entrances
+)
+
+(mk-place-music p_green_tower 'ml-large-town)
diff --git a/worlds/haxima-1.002/gregor.scm b/worlds/haxima-1.002/gregor.scm
new file mode 100644 (file)
index 0000000..1e4af4a
--- /dev/null
@@ -0,0 +1,328 @@
+;;----------------------------------------------------------------------------
+;; gregor.scm - read-only data for Gregor the Charcoal Burner
+;;----------------------------------------------------------------------------
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; At the shrine gate (moongate-clearing.scm)
+;; His home is Gregor's Hut (gregors-hut.scm).
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_gregor
+               (list 0  0  gh-gregors-bed   "sleeping")
+               (list 6  0  gh-graveyard     "idle")
+               (list 7  0  mgc-roadbend     "idle")
+               (list 13 0  gh-table-2       "eating")
+               (list 14 0  gh-pasture       "working")
+               (list 17 0  gh-table-2       "eating")
+               (list 18 0  gh-living-room   "idle")
+               (list 20 0  gh-gregors-bed   "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+(define (gregor-mk) (list (mk-quest)))
+(define (gregor-quest gob) (car gob))
+
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Gregor is an elderly charcoal burner, living near the Shrine Gate.
+;; He tends the grounds of the shrine, and takes care of his grandaughter Ilya.
+;; 
+;; Gregor is the first NPC which the player is likely to encounter,
+;; and has a variety of helpful responses for the starting character
+;; and the first-time player.
+;;----------------------------------------------------------------------------
+
+(define (gregor-kill-nate knpc kpc)
+  (say knpc "[He points a trembling finger at Nate] I have something for you.")
+  (aside kpc 'ch_nate "[Mumbling] What does this old fool want?")
+  (prompt-for-key)
+  (say knpc "[He takes out a scroll] It cost me a lot. I can't read it, but she told me what it says when I bought it.")
+  (aside kpc 'ch_nate "Wait... is that a...?")
+  (prompt-for-key)
+  (say knpc "XEN CORP!")
+  (cast-missile-proc knpc ch_nate t_deathball)
+  (aside kpc 'ch_nate "Gack!")
+  (prompt-for-key)
+  (if (equal? kpc ch_nate)
+      (kern-conv-end)
+      (say knpc "[He turns to you] You shouldn't travel with folks like that. People might get the wrong idea about you."))
+  )
+  
+
+(define (gregor-hail knpc kpc)
+  (if (in-player-party? 'ch_nate)
+      (gregor-kill-nate knpc kpc)
+      (if (in-inventory? kpc t_letter_from_enchanter)
+           (say knpc "I see you got your stuff, and that letter from the Enchanter. "
+                "Don't forget to ready your weapons before leaving. "
+                "It's dangerous out there!")
+           (say knpc "[You meet a grizzled old peasant]"
+                " Welcome, Wanderer. I've been watching for you."
+                " There's some things that belong to you, over in yonder cave."
+                " Go in where the chest is, open it, and get the things inside."
+                " It's all for you."))
+      ))
+
+;; Some prompting with initial commands:
+;; 
+;; Hmmm...perhaps it would be desirable to have game-UI promts
+;; spoken out-of-character, so that the NPCs don't break the game fiction...
+(define (gregor-open knpc kpc)
+  (say knpc "Use the 'o' key to ^c+bopen^c- chests."))
+
+(define (gregor-get knpc kpc)
+  (say knpc "Use the 'g' key to ^c+bget^c- stuff that's on the ground."))
+
+(define (gregor-read knpc kpc)
+  (say knpc "Use the 'r' key to ^c+bready^c- weapons or armor. "
+       "You can't use a weapon in combat until it's ready."))
+
+(define (gregor-camp knpc kpc)
+  (say knpc "Use the 'k' key to ^c+bkamp^c-, err...camp, in the wilderness and heal up."))
+
+
+(define (gregor-dang knpc kpc)
+  (say knpc "Very dangerous! If you need healing, a town inn is the safest place. "
+       "You can camp in the wilderness but it's dangerous when you're alone and have no one to keep watch. "
+       "Of course, there are spells and potions for healing, too."))
+
+(define (gregor-dead knpc kpc)
+  (say knpc "Aye, it's a shame. My daughter and her husband both - "
+       "killed by trolls."))
+
+(define (gregor-charcoal knpc kpc)
+  (say knpc "I take charcoal into town and sell it, "
+       "and some folks come by my place to buy it."))
+
+(define (gregor-hut knpc kpc)
+  (say knpc "My hut's in the forest to the South and East. "
+       "Just myself and my granddaughter living there now."))
+
+(define (gregor-ench knpc kpc)
+  (quest-data-assign-once 'questentry-calltoarms)
+  (say knpc "The Enchanter is one of the Wise. "
+       "He told me to look out for a Wanderer like you. "
+       "If I saw one I was to send him his way. You want directions? ")
+  (quest-wise-subinit 'questentry-enchanter)
+  (quest-data-update 'questentry-enchanter 'common 1)
+  (cond ((yes? kpc)
+         (quest-data-update 'questentry-calltoarms 'directions 1)
+         (quest-data-update 'questentry-enchanter 'general-loc 1)
+         (say knpc "He lives in a tower in a swamp, somewhere west over the mountains. "
+             "Take the road south, then follow it west and ask the rangers at the keep.")
+         (else 
+          (say knpc "As you wish. If you should want directions later, ask me of the Enchanter.")
+          ))
+        ))
+
+(define (gregor-cave knpc kpc)
+  (say knpc "There, that little trail that leads off the main path to the South and West. "
+       "Follow it on in. Open the chest. Get the stuff. "
+       "Come back and we'll talk again, if you have more questions."))
+
+(define (gregor-ches knpc kpc)
+  (say knpc "Go ahead and open it and get the stuff inside."))
+
+(define (gregor-stuf knpc kpc)
+  (say knpc "The common folk made offerings of such things, thinking one day a Wanderer might come again."))
+
+(define (gregor-leav knpc kpc)
+  (say knpc "If you want to leave just follow the trail south and step off the map."))
+
+(define (gregor-band knpc kpc)
+  (let ((quest (gregor-quest (kobj-gob-data knpc))))
+    (cond ((quest-accepted? quest)
+           (say knpc "Have you found the bandits?")
+           (cond ((yes? kpc)
+                  (say knpc "The old gods be praised!")
+                  (quest-done! quest #t)
+                  )
+                 (else 
+                  (say knpc "Go to Green Tower and ask around about the bandits.")
+                  )))
+          (else
+           (say knpc "Bandits are in the woods. "
+                "They robbed me in my own hut. "
+                "I tried to fight them, "
+                "and now I walk with a limp and a cane.")
+           (prompt-for-key)
+           (say knpc "I have a granddaughter living with me now. "
+                "She's just a little girl, but sometimes bad men don't care about that. "
+                "I am afraid of what they will do the next time.")
+           (prompt-for-key)
+           (say knpc "I hate to ask, but they say Wanderers used to help folks. Will you help me now?")
+           (cond ((yes? kpc)
+                  (say knpc "Thank you. "
+                       "When you get your equipment, go to Green Tower. "
+                       "Ask there about bandits. "
+                       "Someone may know where to find them.")
+                  (quest-data-assign-once 'questentry-bandits)
+                  (quest-accepted! quest #t)
+                  )
+                 (else
+                  (say knpc "[He turns away sadly]")
+                  (kern-conv-end)
+                  ))))))
+
+(define (gregor-bye knpc kpc)
+  (let ((quest (gregor-quest (kobj-gob-data knpc))))
+    (cond ((quest-accepted? quest)
+           (say knpc "Farewell, and be careful."))
+          (else
+           (say knpc "Wait! Before you go, I have a favor to ask you.")
+           (prompt-for-key)
+           (gregor-band knpc kpc)
+           ))))
+
+(define gregor-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "Can't help you there.")))
+       (method 'hail gregor-hail)
+       (method 'heal (lambda (knpc kpc) (say knpc "[cough] Well enough, my granddaughter helps take care of me.")))
+       (method 'bye gregor-bye)
+       (method 'job (lambda (knpc kpc) (say knpc "I'm a charcoal burner. I also care for this shrine.")))
+       (method 'join (lambda (knpc kpc) (say knpc "Nope. Already got a job.")))
+       (method 'name (lambda (knpc kpc) (say knpc "Gregor's my name.")))
+
+       (method 'open gregor-open)
+       (method 'get  gregor-get)
+
+       (method 'cave gregor-cave)
+       (method 'ches gregor-ches)
+
+       (method 'stuf gregor-stuf)
+       (method 'equi gregor-stuf)  ;; A synonym
+       (method 'gear gregor-stuf)  ;; A synonym
+
+       (method 'read gregor-read)
+       (method 'dang gregor-dang)
+
+       (method 'camp gregor-camp)
+       (method 'kamp gregor-camp) ;; A synonym
+
+       (method 'band gregor-band)
+       (method 'leav gregor-leav)
+
+;; SAM -- This response seems to be shadowed by the gregor-band declaration above?
+       (method 'band (lambda (knpc kpc) (say knpc "A band of rogues been raiding the shrine "
+                                             "when I'm not around. They haven't attacked me, "
+                                             "so they're probably just vagabonds, "
+                                             "afraid of an old man's cudgel.")))
+
+       (method 'char gregor-charcoal)
+       (method 'burn gregor-charcoal)  ;; A synonym
+
+       (method 'daug (lambda (knpc kpc) (say knpc "Aye, she was a near-witch like her mother. "
+                                             "Had the knack, but not enough to be among the Wise.")))
+       (method 'dead gregor-dead)
+       (method 'ench gregor-ench)
+       (method 'folk (lambda (knpc kpc) (say knpc "There's homesteads scattered about in "
+                                             "the woods and the foothills.")))
+       (method 'fore (lambda (knpc kpc) (say knpc "Stay out of the deep woods. "
+                                               "Bandits, spiders and worse live there.")))
+       (method 'gate (lambda (knpc kpc) (say knpc "No one can predict when it will open, "
+                                             "or if anything will come through if it does. "
+                                             "I've heard of other gates in other parts of the land, "
+                                             "and stories tell of others long forgotten now.")))
+       (method 'gran (lambda (knpc kpc) (say knpc "I've a granddaughter name of Ilya.")))
+       (method 'help (lambda (knpc kpc) (say knpc "There's always folks who need help. "
+                                             "These are hard times in a hard land.")))
+       (method 'hill (lambda (knpc kpc) (say knpc "Trolls are always a threat in the foothills, "
+                                             "but more so of late.")))
+       (method 'husb (lambda (knpc kpc) (say knpc "My son-in-law was a simple farmer. "
+                                             "Why the trolls attacked I don't know. "
+                                             "Maybe they were driven out of the hills "
+                                             "by something else.")))
+       (method 'hut gregor-hut)
+       (method 'ilya (lambda (knpc kpc) (say knpc "Yep. She lives at my place now "
+                                             "that her parents are dead.")))
+
+;; SAM: I dont' see any reference to this lake anywhere, commenting this one out for now...
+;;       (method 'lake (lambda (knpc kpc) (say knpc "Exit this shrine and ye'll find yourself in a "
+;;                                             "hidden valley. Head south and you'll see the Gray Lake "
+;;                                             "to the west.")))
+
+       (method 'offe (lambda (knpc kpc) (say knpc "There in the cave you'll find a chest. "
+                                             "Take what's inside. Wanderers enter this world with little, "
+                                             "and in the past some have done great good, "
+                                             "so folks leave stuff in good will for the next one.")
+                                             (quest-data-update 'questentry-whereami 'wanderer 2)
+                                                                                       ))
+       (method 'pare gregor-dead)
+       (method 'plac gregor-hut)
+
+       (method 'shar (lambda (knpc kpc) (say knpc "The Shard?  That's what we call this land, Wanderer.")
+                                       (quest-data-update 'questentry-whereami 'shard 1)
+                               ))
+
+       (method 'shri (lambda (knpc kpc) (say knpc "This shrine is for those who come through the gate. "
+                                             "Wanderers like yourself. "
+                                             "Folks leave simple offerings here to help you on "
+                                             "your journey.")
+                                             (quest-data-update 'questentry-whereami 'wanderer 1)
+                                                                                               ))
+
+       (method 'spid (lambda (knpc kpc) (say knpc "Some of the spiders in the deep parts  "
+                                            "of the woods are monstrous --  "
+                                            " as big as oxen! "
+                                            "Children of Angriss, we call those.")))
+       (method 'angr (lambda (knpc kpc) (say knpc "Just a legend. "
+                                            "Mother of all wood spiders. "
+                                             "Scares the kids, keeps them out o' the woods "
+                                             "where they can get lost.")))
+
+       (method 'town (lambda (knpc kpc) (say knpc "Trigrave is the closest town. "
+                                            "Follow the road South and you can't miss it.")))
+
+       (method 'trol (lambda (knpc kpc) (say knpc "Trolls eat folks. "
+                                            "Even crack the bones and suck the marrow. "
+                                            "Nothing left to bury.")))
+
+       (method 'wand (lambda (knpc kpc) (say knpc "We call those who come through the gate Wanderers. "
+                                             "No one knows where they come from or where they go. "
+                                             "You are the first to come through in a long, long time.")
+                                             (quest-data-update 'questentry-whereami 'wanderer 1)
+                                                                                       ))
+
+       (method 'wise (lambda (knpc kpc) (say knpc "The Wise are both strong and -mostly- good. "
+                                             "They help the land, as they can, "
+                                            "and keep the Accursed at bay.")))
+       (method 'accu (lambda (knpc kpc) 
+                       (say knpc "The Accursed? Rumour has it they trade their souls for power. "
+                            "If not for the Wise they would overrun the Shard.")))     
+
+       (method 'witc (lambda (knpc kpc) (say knpc "Don't know of any witches in these parts any more.")))
+       ))
+
+;;----------------------------------------------------------------------------
+;; Ctor
+(define (mk-gregor)
+  (bind 
+   (kern-mk-char 'ch_gregor ; tag
+                 "Gregor"              ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_old_townsman          ; sprite
+                 faction-men         ; starting alignment
+                 0 10 5              ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 2  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'gregor-conv        ; conv
+                 sch_gregor          ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                                          (list t_axe
+                                                t_armor_leather
+                                                )              ; readied
+                 )
+   (gregor-mk)
+   ))
diff --git a/worlds/haxima-1.002/gregors-hut.scm b/worlds/haxima-1.002/gregors-hut.scm
new file mode 100644 (file)
index 0000000..28ed35e
--- /dev/null
@@ -0,0 +1,100 @@
+(kern-mk-map 
+ 'm_gregors_hut 32 32 pal_expanded
+       (list
+               "|| || || || tt tc .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. .. tC tt tt tt tt "
+               "|| || || || tt tB .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. t3 tt tt tt tt tt tt "
+               "|| || tt tt tt t5 .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. tC tt || || || tt tt tt "
+               "|| tt tt tt tt tt .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. tC t3 tt || || || tt tt tt "
+               "tt tt tt tt tt tt .. .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. tC t3 tt || || tt || || tt t# "
+               "tc t# .. t% tt tt tA .. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. tb tt tt || tt tt tt || tt .. "
+               ".. .. .. .. ta tt tt td .. .. .. .. .. .. .. .. /7 .. .. .. .. .. t% ta tt || || tt || || tt .. "
+               ".. .. .. .. /0 /d /d /d /d /d /d /d /d /d /d /d /9 /d /d /d /d /d /d /2 ta tt || || || tt tc .. "
+               ".. .. .. /0 /a t3 tt t5 tA .. .. .. .. .. .. .. .. .. .. .. .. .. .. /8 /d /d /2 ta tt tt t# .. "
+               ".. .. .. /7 t3 tt tt tt t5 rr rr wr rr rr rr wr rr rr rr rr rr bb bb bb bb bb /8 /d /2 te .. .. "
+               ".. .. .. /7 ta tt tt tt tt rr cc cc cc cc cc cc cc rr cc cc rr .. .. .. .. .. bb .. /7 .. .. .. "
+               ".. .. .. /7 t% ta tt tt tt rr cc cc cc cc cc cc cc rr cc cc rr t7 tA .. .. .. bb .. /7 .. .. .. "
+               ".. .. .. /7 .. t% tt || || rr cc cc [[ @@ ]] cc cc rr cc cc rr tt t5 tA .. .. bb .. /7 .. .. .. "
+               ".. .. .. /7 .. .. ta || |C rr cc cc cc cc cc cc cc rr cc cc rr tt tt t5 tA .. bb .. /7 .. .. .. "
+               ".. .. .. /7 .. .. rr rr rr rr cc cc cc cc cc cc cc cc cc cc rr tt tt || td .. bb .. /7 .. .. .. "
+               ".. .. .. /7 .. .. wr cc cc rr rr cc rr && rr rr rr rr rr rr rr ta tt tc t# .. bb .. /7 .. .. .. "
+               "/d /d /d /6 .. .. rr cc cc cc cc cc cc cc cc cc cc rr .. .. rr .. .. .. .. .. bb .. /4 /d /d /d "
+               ".. .. .. /7 .. .. rr rr rr rr cc cc cc cc cc cc cc rr .. .. rr .. .. .. .. .. bb .. /7 t3 tt tt "
+               ".. .. .. /7 .. .. rr cc cc rr cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. bb t7 /7 tt tt tt "
+               ".. .. .. /7 .. .. wr cc cc cc cc cc cc cc cc cc cc rr .. .. .. .. .. .. .. .. bb te /7 tt tc %3 "
+               ".. .. .. /7 .. .. rr rr rr rr rr wr rr cc rr wr rr rr .. rr rr bb bb bb bb bb /0 /d /a te %3 %% "
+               ".. .. .. /7 .. .. .. .. .. .. .. tb td /7 .. tb tt td /4 /d /d /d /d /d /d /d /a t3 td %3 %% %% "
+               ".. .. .. /7 .. .. .. .. .. .. .. .. .. /7 .. .. .. .. /7 .. .. .. .. .. tC t3 tt tc %3 %% ~3 ~9 "
+               ".. .. .. /8 /d /d /d /d /d /d /d /d /d /9 /d /1 /d /d /a .. .. .. .. tC t3 tt tt %3 ~3 ~9 ~c %% "
+               ".. .. .. .. .. .. .. t3 tt t5 .. .. .. .. .. /7 .. .. t7 tA .. .. tb tt tt tt tc %% ~6 %% %% %% "
+               "tt t5 tA .. .. .. .. tt tt tt tA .. .. .. .. /7 .. .. tt tt t5 tA .. t% te ~3 ~9 ~9 ~c %% %% %% "
+               "|| tt t5 tA .. .. .. ta tt tt t5 .. .. .. .. /7 .. .. ta tt tt tt t5 .. .. ~6 .. tf %a %c t7 .. "
+               "|| || tt t5 tA .. .. t% ta tt tc .. .. .. .. /7 .. .. t% tt tt tt tc ~3 ~~ -4 .. .. .. t3 tt .. "
+               "|| || tt tt t5 tA .. .. .. .. .. .. .. .. .. /8 /2 .. .. tt tt tt ~3 ~8 ~8 ~c t3 t5 .. ta |C .. "
+               "|| || || tt tt t5 tA .. .. .. .. .. .. .. .. .. /7 .. .. tt tt tc ~6 t3 tt tt tt tt tA .. .. .. "
+               "|| || || || || tt t5 tA .. .. .. .. .. .. .. .. /7 .. .. tt tt ~3 ~c tt t# tD tt tt |% .. .. .. "
+               "|| || || || || || tt t5 .. .. .. .. .. .. .. .. /7 .. .. tt tt ~6 t3 tt .. t3 tt || || .. .. .. "
+       )
+ )
+
+(kern-load "ilya.scm")
+
+(bind 
+ (kern-mk-char 'ch_ilya ; tag
+               "Ilya"              ; name
+               sp_human            ; species
+               nil                 ; occ
+               s_child             ; sprite
+               faction-men         ; starting alignment
+               0 10 5              ; str/int/dex
+               0 0                 ; hp mod/mult
+               0 0                 ; mp mod/mult
+               max-health -1 max-health 0 2  ; hp/xp/mp/AP_per_turn/lvl
+               #f                  ; dead
+               'ilya-conv          ; conv
+               sch_ilya           ; sched
+               'townsman-ai                 ; special ai
+               (mk-inventory (list (list 1 t_sword)))                 ; container
+               nil                 ; readied
+               )
+ (ilya-mk #f #f))
+
+;;(kern-terrain-map-blend m_gregors_hut t_shoals tset_water tset_shore)
+
+
+(kern-mk-place 'p_gregors_hut     ; tag
+               "Gregor's Hut"     ; name
+               s_hamlet           ; sprite
+               m_gregors_hut      ; map
+               #f                 ; wraps
+               #f                 ; underground
+               #f                 ; large-scale (wilderness)
+               #f                 ; tmp combat place
+               nil ; subplaces
+               nil ; neighbors
+               ;;objects
+               (list
+                
+                ;; characters
+                (list ch_ilya   15 15)
+
+                ;; mechanisms
+                (list (mk-door-in-rock) 13 20)
+                (list (mk-door-in-rock)  9 19)
+                (list (mk-door-in-rock)  9 16)
+                (list (mk-door-in-rock) 11 15)
+                (list (mk-door-in-rock) 17 14)
+                (list (mk-door-in-rock) 18 20)
+                (list (mk-clock) 10 10)
+                (list (mk-bridge 'east) 25 26)
+                (list (mk-ambient-sound 'sound-river) 25 26)
+                (put (mk-bed) 7 18)
+                (put (mk-bed) 7 16)
+                (put (mk-npc 'chicken 5) 13 23)
+                (put (mk-npc 'chicken 5) 14 24)
+                
+                )
+               nil ; hooks
+               nil ; edge entrances
+               )
+
+(mk-place-music p_gregors_hut 'ml-small-town)
diff --git a/worlds/haxima-1.002/gwen.scm b/worlds/haxima-1.002/gwen.scm
new file mode 100644 (file)
index 0000000..459fec1
--- /dev/null
@@ -0,0 +1,147 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Trigrave"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_gwen
+               (list 0  0  trigrave-gwens-bed        "sleeping")
+               (list 8  0  trigrave-tavern-table-1a  "eating")
+               (list 9  0  trigrave-inn-counter      "working")
+               (list 13 0  trigrave-tavern-table-1d  "eating")
+               (list 14 0  trigrave-inn-counter      "working")
+               (list 20 0  trigrave-tavern-table-1a  "eating")
+               (list 21 0  trigrave-inn-counter      "working")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (gwen-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Gwen is the innkeeper for Trigrave. She is a gracious, mysterious woman.
+;;----------------------------------------------------------------------------
+(define (gwen-trade knpc kpc)
+  (if (not (string=? "working" (kern-obj-get-activity knpc)))
+      (say knpc "Come by my shop when I'm open. "
+           "It's the Gray Dove Inn in the northwest corner of town. "
+           "I open at 9:00AM and close the counter at midnight.")
+      (let ((door (eval 'trigrave-inn-room-1-door)))
+        ;; is the room still open?
+        (if (not (door-locked? (kobj-gob door)))
+            ;; yes - remind player
+            (say knpc "Your room is still open!")
+            ;; no - ask if player needs a room
+            (begin
+              (say knpc "Do you need a room?")
+              (if (kern-conv-get-yes-no? kpc)
+                  ;; yes - player wants a room
+                  (begin
+                    (say knpc 
+                         "It will be " trigrave-inn-room-price " gold, "
+                         "and you may use the room as "
+                         "long as you are in town. Agreed?")
+                    (if (kern-conv-get-yes-no? kpc)
+                        ;; yes - player agrees to the price
+                        (let ((gold (kern-player-get-gold)))
+                          ;; does player have enough gold?
+                          (if (>= gold trigrave-inn-room-price)
+                              ;; yes - player has enough gold
+                              (begin
+                                (kern-player-set-gold 
+                                 (- gold 
+                                    trigrave-inn-room-price))
+                                (say knpc "You're in room 1. Enjoy your stay!")
+                                (send-signal knpc door 'unlock)
+                                (kern-conv-end)
+                                )
+                              ;; no - player does not have enouvh gold)
+                              (say knpc "Sorry, but you need more gold!")))
+                        ;; no - player does not agree to the price
+                        (say knpc 
+                             "You won't find a better deal in the Peninsula!")))
+                  ;; no - player does not want a room
+                  (say knpc "Perhaps another time.")))))))
+
+(define (gwen-thie knpc kpc)
+  (say knpc "Some recent travelers from Green Tower met a man in great haste heading east through the pass. You might try asking around in Green Tower.")
+  (quest-data-update-with 'questentry-thiefrune 'tower 1 (quest-notify (grant-party-xp-fn 10)))
+  )
+
+(define gwen-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) 
+                          (say knpc "I cannot help you with that")))
+       (method 'hail
+               (lambda (knpc kpc)
+                 (kern-print "[You see an enchanting woman dressed in "
+                             "gray. Belted to her waist is a long, thin "
+                             "sword.]")
+                 (say knpc "Welcome, traveler.")))
+       (method 'bye (lambda (knpc kpc) (say knpc "Goodbye.")))
+       (method 'job 
+               (lambda (knpc kpc) 
+                 (say knpc "I'm the innkeeper of Trigrave.")
+                 (gwen-trade knpc kpc)))
+       (method 'name (lambda (knpc kpc) (say knpc "I am Gwen.")))
+       (method 'trad gwen-trade)
+       (method 'join 
+               (lambda (knpc kpc) 
+                 (say knpc "My journeys are over, "
+                      "but thank you for the offer.")))
+       (method 'chan
+               (lambda (knpc kpc)
+                 (say knpc "That rapscallion is usually at the tavern. He "
+                      "stumbles back to his room here late at night, drunk as a sailor.")))
+       (method 'civi 
+               (lambda (knpc kpc) 
+                 (say knpc "There is not much civilization to speak of around here.")))
+       (method 'earl
+               (lambda (knpc kpc)
+                 (say knpc "A sweet but befuddled old man. He keeps the shop "
+                      "south of my Inn.")))
+       (method 'enem 
+               (lambda (knpc kpc) (say knpc "That is not your business.")))
+       (method 'esca 
+               (lambda (knpc kpc)
+                 (say knpc "If one wishes to hide from an enemy or a "
+                      "shameful act there is no place better than this "
+                      "forgotten corner of the Shard.")))
+       (method 'inn  
+               (lambda (knpc kpc)
+                 (say knpc "I enjoy running the Inn because I get to hear "
+                            "news from travelers.")))
+       (method 'jim
+               (lambda (knpc kpc)
+                 (say knpc "Handsome, but rather grim. He owns the "
+                      "blacksmith shop on the east end.")))
+       (method 'news (lambda (knpc kpc)
+                       (say knpc "I've heard the Enchanter is missing something valuable.")))
+       (method 'room gwen-trade)
+       (method 'sham 
+               (lambda (knpc kpc) (say knpc "That is not your business.")))
+       (method 'swor
+               (lambda (knpc kpc) 
+                 (say knpc "It was a gift from a friend.")))
+       (method 'tave
+               (lambda (knpc kpc)
+                 (say knpc "The Lusty Juggs is in the south part of town.")))
+       (method 'thie gwen-thie)
+       (method 'trig 
+               (lambda (knpc kpc) 
+                 (say knpc "This is a small town, far from civilization. "
+                      "Many come here to escape.")))
+
+       ))
diff --git a/worlds/haxima-1.002/hackle.scm b/worlds/haxima-1.002/hackle.scm
new file mode 100644 (file)
index 0000000..9751a16
--- /dev/null
@@ -0,0 +1,231 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; In Bole.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_hackle
+               (list 0  0  bole-hackles-hut "idle")
+               (list 2  0  bole-bed-hackle "sleeping")
+               (list 10 0  bole-hackles-hut "idle")
+               (list 20 0  bole-hackles-yard "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (hackle-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Hackle is a female hedge-witch dwelling in Bole.
+;; Her mind was shattered by some misadventure with Gazer(s),
+;; though she is still capable of serving as a healer.
+;;----------------------------------------------------------------------------
+(define (hackle-trade knpc kpc)
+  (say knpc "She can heal it, or one of its friends. She requires a piece of "
+       "gold for each piece of life! Does it agree?")
+  (define (hackle-heal)
+    (say knpc "Which shall she heal?")
+    (let ((kchar (kern-ui-select-party-member)))
+      (if (null? kchar)
+          (say knpc "How else can she help it?")
+          (let* ((gold (kern-player-get-gold))
+                 (pts (- (kern-char-get-max-hp kchar)
+                         (kern-char-get-hp kchar))))
+            (if (= 0 gold)
+                (say knpc "No gold, no life! It is the law of the world!")
+                (begin
+                  (if (= 0 pts)
+                      (say knpc "It is well! She can do nothing for it!")
+                      (let ((n (min gold pts)))
+                        (say knpc "She heals it!")
+                        (kern-obj-heal kchar n)
+                        (kern-player-set-gold (- gold n))))
+                  (say knpc "Will it heal another?")
+                  (if (kern-conv-get-yes-no? kpc)
+                      (hackle-heal)
+                      (say knpc "Then something else it wants.")
+                      )))))))
+  (if (kern-conv-get-yes-no? kpc)
+      (hackle-heal)
+      (say knpc "Have it its way!")))
+                   
+              
+        
+
+;; basics...
+(define (hackle-default knpc kpc)
+  (say knpc "She cannot help it with that."))
+
+(define (hackle-hail knpc kpc)
+  (if (in-player-party? 'ch_mesmeme)
+      (begin
+        (say knpc "[She shrinks back in horror at the sight of Mesmeme] AHHH! It frightens her!")
+        (aside kpc 'ch_mesmeme "No frighten.")
+        )
+      (say knpc "[You meet a disheveled, middle-aged woman] It comes to her! "
+           "It wants something!")
+  ))
+
+(define (hackle-name knpc kpc)
+  (say knpc "She is Hackle."))
+
+(define (hackle-job knpc kpc)
+  (say knpc "She is mad! But she can heal it!"))
+
+(define (hackle-join knpc kpc)
+  (say knpc "She cannot join it! She must mind her sheep!"))
+
+(define (hackle-bye knpc kpc)
+  (say knpc "She bids it farewell, but knows it will return!"))
+
+
+;; other characters & town...
+(define (hackle-may knpc kpc)
+  (say knpc "It is a hard woman, hard but kind to Hackle!"))
+
+(define (hackle-kath knpc kpc)
+  (say knpc "A woman clothed in red! A fiend clothed in woman!"))
+
+(define (hackle-bill knpc kpc)
+  (say knpc "It is careless. Yes, the wood gods will have it for supper one "
+       "day."))
+
+(define (hackle-thud knpc kpc)
+  (say knpc "[She laughs, a surprising, golden sound] That is no toy! They "
+       "called for a servant, but summoned a demon!"))
+
+(define (hackle-melv knpc kpc)
+  (say knpc "It is a good soul."))
+
+(define (hackle-bole knpc kpc)
+  (say knpc "Not Bole! Hole! The keyhole to the deep! She knows it!"))
+
+;; misc...
+(define (hackle-mesm knpc kpc)
+  (say knpc "It is only a child. Deaf and dumb it is, to its own kind. "
+       "But the pet will make a pet of its master.")
+  (aside kpc 'ch_mesmeme "No pet")
+  )
+
+(define (hackle-shee knpc kpc)
+  (say knpc "The sheep hides in wolf's clothing! How it howls when it "
+       "bleats!"))
+
+(define (hackle-wood knpc kpc)
+  (say knpc "She has seen them sleeping in the old oaks. She wakes them "
+       "not! They do not like us, they do not like anyone! The goblins "
+       "appease them but she does not know the words."))
+
+(define (hackle-mad knpc kpc)
+  (say knpc "The gazers caught her as a girl! She escaped, but her mind did "
+       "not!"))
+
+(define (hackle-gaze knpc kpc)
+  (say knpc "If it meets one, it should kill one without question! They know "
+       "the answer to any question, and in the answer lies bondage!")
+  (aside kpc 'ch_mesmeme "[Blinks nervously]")
+)
+
+;; thief quest...
+(define (hackle-thie knpc kpc)
+  (say knpc "It is a mighty wrogue indeed that robs a mighty wizard!"))
+
+(define (hackle-robs knpc kpc)
+  (say knpc "It robs and runs, down its little mouse-hole!"))
+
+(define (hackle-hole knpc kpc)
+  (say knpc "Does it like riddles?\n"
+       "  An 'o' has a hole!\n"
+       "  And hole has an 'o'!\n"
+       "  And a mouse has both!\n"
+       "  In the middle of the night\n"
+       "  Down it will go!\n"
+       "Does it know what ^c+mreveals^c-?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Then let it ^c+mreveal^c- and understand my riddle!")
+      (begin
+        (say knpc "Wis Quas! The Red Bitch has a scroll, but has not the "
+             "wisdom.")))
+  )
+
+(define (hackle-reve knpc kpc)
+  (say knpc "The Bill-boy knows where the mouse disappeared! "
+       "Let it ^c+mreveal^c- there!"))
+
+(define (hackle-midd knpc kpc)
+  (say knpc "Yes! The middle of the night!"))
+
+(define hackle-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default hackle-default)
+       (method 'hail hackle-hail)
+       (method 'bye  hackle-bye)
+       (method 'job  hackle-job)       
+       (method 'name hackle-name)
+       (method 'join hackle-join)
+
+       (method 'trad hackle-trade)
+       (method 'buy hackle-trade)
+       (method 'sell hackle-trade)
+       (method 'heal hackle-trade)
+
+       (method 'bill hackle-bill)
+       (method 'kath hackle-kath)
+       (method 'red  hackle-kath)
+       (method 'bitc hackle-kath)
+       (method 'may  hackle-may)
+       (method 'melv hackle-melv)
+       (method 'thud hackle-thud)
+       
+       (method 'bole hackle-bole)
+       (method 'gaze hackle-gaze)
+       (method 'god  hackle-wood)
+       (method 'gods hackle-wood)
+       (method 'hole hackle-hole)
+       (method 'mad  hackle-mad)
+       (method 'mesm hackle-mesm)
+       (method 'migh hackle-robs)
+       (method 'mous hackle-hole)
+       (method 'reve hackle-reve)
+       (method 'rob  hackle-robs)
+       (method 'robs hackle-robs)
+       (method 'wrog hackle-robs)
+       (method 'wiza hackle-robs)
+       (method 'shee hackle-shee)
+       (method 'thie hackle-thie)
+       (method 'wood hackle-wood)
+       (method 'midd hackle-midd)
+       (method 'nigh hackle-midd)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-hackle)
+  (bind 
+   (kern-mk-char 'ch_hackle          ; tag
+                 "Hackle"            ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_beggar             ; sprite
+                 faction-men         ; starting alignment
+                 0 0 1            ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 6  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'hackle-conv        ; conv
+                 sch_hackle          ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 nil                 ; readied
+                 )
+   (hackle-mk)))
diff --git a/worlds/haxima-1.002/haximatext.png b/worlds/haxima-1.002/haximatext.png
new file mode 100644 (file)
index 0000000..4cb77a3
Binary files /dev/null and b/worlds/haxima-1.002/haximatext.png differ
diff --git a/worlds/haxima-1.002/henry.scm b/worlds/haxima-1.002/henry.scm
new file mode 100644 (file)
index 0000000..8cf8f0a
--- /dev/null
@@ -0,0 +1,173 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Oparine.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_henry
+               (list 0  0  bilge-water-bed     "sleeping")
+               (list 8  0  bilge-water-counter "working")
+               (list 23 0  bilge-water-bed     "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (henry-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Henry is a one-handed tavern-keeper, doing trade in Oparine.
+;; He was once a mighty mariner.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (henry-hail knpc kpc)
+  (say knpc "[You meet a cheery man with a hook for one hand] "
+       "Welcome, matey!"))
+
+(define (henry-default knpc kpc)
+  (say knpc "Ye be askin' the wrong salt about that!"))
+
+(define (henry-name knpc kpc)
+  (say knpc "I's Henry! Henry the barkeep."))
+
+(define (henry-join knpc kpc)
+  (say knpc "I'd join ye in a 'eartbeat, lad, but oo's goin' to keep the "
+       "tankards full 'round here if I be goin'? 'Twouldn't be right!"))
+
+(define (henry-job knpc kpc)
+  (say knpc "Why I's a minister! I fills the mugs 'ith 'oly sacraments!"))
+
+(define (henry-bye knpc kpc)
+  (say knpc "Keep a weather eye!"))
+
+(define henry-catalog
+  (list
+   (list t_food 5 "My famous clam chowder will warm you to your toes.")
+   (list t_beer 5 "Aye, drink and be merry, fer tomorro' mornin' you'll be wishin' you were dead!")
+   (list t_wine 7 "I keep some o' the fancy-shmancy stuff fer the occasional gen'leman.")
+   ))
+
+(define henry-merch-msgs
+  (list "I'll serve ye when my hangover's gone."
+        "Let the good times roll!"
+        "I've no interest in used food or drink."
+        "Now we're talkin'!"
+        "Don't drink and sail!"
+        "If yer just lookin' for someplace to loiter, there's a dock outside."
+        "I suppose I can make stew from this."
+        "Good. Fine."
+        "Come back when you need a refill!"
+        "If yer just lookin' for someplace to loiter, there's a dock outside."
+        ))
+
+;; Trade...
+(define (henry-buy knpc kpc) (conv-trade knpc kpc "buy" henry-merch-msgs henry-catalog))
+(define (henry-sell knpc kpc) (say knpc "I've no use for solicitors."))
+
+;; Hook...
+(define (henry-hook knpc kpc)
+  (say knpc "Oy, lost me arm, me did, fightin' fearsome monsters of "
+       "the deep."))
+
+(define (henry-mons knpc kpc)
+  (say knpc "The kraken took me arm, snapped it right off 'ith 'is nasty "
+       "beak, 'e did! The kraken won't shoot from afar like the cowardly "
+       "sea serpent. No, 'e likes to munch right through the decks and get "
+       "in snugly!"))
+
+(define (henry-serp knpc kpc)
+  (say knpc "The sea serpent can crush a ship 'ith its coils, "
+       "but it's a craven beast, and prefers to spit fireballs from afar."))
+
+;; Townspeople...
+(define (henry-opar knpc kpc)
+  (say knpc "It's a fair enough place."))
+
+(define (henry-gher knpc kpc)
+  (say knpc "So ye've 'eard the legend o' Ghastly Ghertie! "
+       "If ye don't mind a bit o' unsolicited advice from an old seabird, "
+       "steer clear o' ghosts! 'ungry they is!")
+       (quest-data-assign-once 'questentry-ghertie))
+
+(define (henry-ghos knpc kpc)
+  (say knpc "The sea is full of the dead, and Ghertie did her share o' "
+       "puttin' 'em there. I've seen nights on full moons where they rise "
+       "up an' prowl the waves like cats! Dreadful is the dead, "
+       "an' Henry's in no 'urry to be joinin' 'em!")
+       (quest-data-assign-once 'questentry-ghertie))
+
+(define (henry-alch knpc kpc)
+  (say knpc "Aye, 'e's a queer one."))
+
+(define (henry-bart knpc kpc)
+  (say knpc "[loudly] Bart's the finest shipwright on the Peninsula! "
+       "[leaning in closer and more softly] And the only shipwright, too!"))
+
+(define (henry-seaw knpc kpc)
+  (say knpc "A lovely lass, but strange as a fish on land!"))
+
+(define (henry-osca knpc kpc)
+  (say knpc "A pathetic, misplaced soul, but 'e drinks 'is share."))
+
+(define henry-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default henry-default)
+       (method 'hail henry-hail)
+       (method 'bye  henry-bye)
+       (method 'job  henry-job)
+       (method 'name henry-name)
+       (method 'join henry-join)
+       
+       ;; trade
+       (method 'trad henry-buy)
+       (method 'buy  henry-buy)
+       (method 'sell henry-sell)
+       (method 'sacr henry-buy)
+
+       ;; hand
+       (method 'hook henry-hook)
+       (method 'hand henry-hook)
+       (method 'mons henry-mons)
+       (method 'deep henry-mons)
+       (method 'sea  henry-serp)
+       (method 'serp henry-serp)
+
+       ;; town & people
+       (method 'opar henry-opar)
+       (method 'alch henry-alch)
+       (method 'gher henry-gher)
+       (method 'ghas henry-gher)
+       (method 'bart henry-bart)
+       (method 'witc henry-seaw)
+       (method 'osca henry-osca)
+
+       ))
+
+(define (mk-henry)
+  (bind 
+   (kern-mk-char 'ch_henry           ; tag
+                 "Henry"             ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_townsman          ; sprite
+                 faction-men         ; starting alignment
+                 1 0 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 6  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'henry-conv         ; conv
+                 sch_henry           ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_dagger)))     ; container
+                 nil                 ; readied
+                 )
+   (henry-mk)))
diff --git a/worlds/haxima-1.002/hidden.scm b/worlds/haxima-1.002/hidden.scm
new file mode 100644 (file)
index 0000000..e960053
--- /dev/null
@@ -0,0 +1,31 @@
+;;----------------------------------------------------------------------------
+;; hidden -- wrapper object; when s)earched it creates the revelaed object and
+;; removes itself
+
+(define (hidden-mk objtype-tag quan) (list objtype-tag quan))
+(define (hidden-objtype-tag hidden) (car hidden))
+(define (hidden-quan hidden) (cadr hidden))
+
+(define (hidden-search khidden ksearcher)
+  (println "hidden-search")
+  (let* ((hidden (kobj-gob-data khidden))
+         (kobj (kern-mk-obj (eval (hidden-objtype-tag hidden))
+                            (hidden-quan hidden))))
+    (kern-obj-put-at kobj
+                     (kern-obj-get-location khidden))
+    (kern-log-msg "You find something!")
+    (kern-obj-remove khidden)))
+
+(define hidden-ifc
+  (ifc nil
+       (method 'search hidden-search)))
+
+(mk-obj-type 't_hidden nil nil layer-none hidden-ifc)
+
+(define (mk-hidden objtype-tag quan)
+  (bind (kern-mk-obj t_hidden 1)
+        (hidden-mk objtype-tag quan)))
+
+(define (is-hidden? kobj)
+  (eqv? (kern-obj-get-type kobj)
+        t_hidden))
diff --git a/worlds/haxima-1.002/hirespeople.png b/worlds/haxima-1.002/hirespeople.png
new file mode 100644 (file)
index 0000000..04e3b90
Binary files /dev/null and b/worlds/haxima-1.002/hirespeople.png differ
diff --git a/worlds/haxima-1.002/horse.wav b/worlds/haxima-1.002/horse.wav
new file mode 100644 (file)
index 0000000..f16c31d
Binary files /dev/null and b/worlds/haxima-1.002/horse.wav differ
diff --git a/worlds/haxima-1.002/humanoids.png b/worlds/haxima-1.002/humanoids.png
new file mode 100644 (file)
index 0000000..a28d646
Binary files /dev/null and b/worlds/haxima-1.002/humanoids.png differ
diff --git a/worlds/haxima-1.002/ifc.scm b/worlds/haxima-1.002/ifc.scm
new file mode 100644 (file)
index 0000000..0ad9820
--- /dev/null
@@ -0,0 +1,120 @@
+;; ----------------------------------------------------------------------------
+;; ifc.scm - kernel-to-object interface
+;; ----------------------------------------------------------------------------
+
+;; Define a vtable scheme - a list of (<name> <body>) pairs
+(define (vtable-call vtable method args)
+  ;;(println method ":" args)
+  (let ((proc (assoc method vtable)))
+    (if (eq? #f proc)
+        ;; If we fail to find the desired method then see if there's a default
+        ;; method
+        (let ((proc (assoc 'default vtable)))
+          (if (eq? #f proc)
+              '()
+              (apply (cdr proc) args)))
+        (apply (cdr proc) args))))
+
+;; Each entry in a vtable is a tagged procedure
+(define (method name body) (cons name body))
+
+;; Implement method inheritance by merging the new methods with the parent
+;; class's vtable
+(define (inherit parent methods)
+  (if (null? parent)
+      methods
+      (append methods (parent 'vtable))))
+
+;; ----------------------------------------------------------------------------
+;; The purpose of this list is to prevent the scheme gc from harvesting the
+;; scroll interfaces which are created on-the-fly in mk-scroll. Without this
+;; I'd have to explicitly assign a variable to each ifc, which is needlessly
+;; verbose.
+;;
+;; The scheme interpreter reclaims any cells not referred to by another cell,
+;; recursively. It can't detect cells that are only referred to by kernel data
+;; structures, and will reclaim them. To prevent this, I add all ifcs to this
+;; list. The list is referred to by the scheme top-level environment, and it
+;; refers to all ifcs that are added to it.
+;; ----------------------------------------------------------------------------
+(define ifc-list '())
+
+(define (ifc-protect ifc)
+  (set! ifc-list (cons ifc ifc-list))
+  ifc)
+
+;; Define a dispatch for a list of methods
+(define (ifc parent . methods)
+  (let ((vtable (inherit parent methods)))
+    (ifc-protect 
+     (lambda (op . args)
+       ;;(display op)(newline)
+       (cond ((eq? op 'vtable) vtable)
+             ((eq? op 'can) 
+              (begin
+                (not (eq? #f (assoc (car args) vtable)))))
+             (else (vtable-call vtable op args)))))))
+
+;; Map standard interface calls to a bitmap for fast lookup in the kernel
+(define (ifc-cap ifc)
+  (define (cap ifc calls)
+    (if (null? calls) 0
+        (+ (* 2 (cap ifc (cdr calls)))
+           (if (ifc 'can (car calls)) 1 0))))
+  (if (null? ifc) 0
+      (cap ifc (list 'get 'use 'exec 'open 'handle 'step 'attack 'mix 
+                     'enter 'cast 'bump 'hit-loc 'buy 'search 'sense 'xamine 'describe 'on-attack
+                     'describe))))
+
+;; The gob internal api:
+(define (gob-mk kobj members) (list kobj members))
+(define (gob-kobj gob) (car gob))
+(define (gob-ifc gob) (kobj-ifc (gob-kobj gob)))
+(define (gob-data gob) (if (null? gob) nil (cadr gob)))
+
+;; Bind a kernel object to a gob and initialize it
+(define (bind kobj gob-data)
+  (kern-obj-set-gob kobj (gob-mk kobj gob-data))
+  (let ((ifc (kobj-ifc kobj)))
+    (cond ((null? ifc) '())
+          (else (ifc 'init kobj))))
+  kobj)
+
+(define (bind-astral-body kobj gob-data)
+  (kern-astral-body-set-gob kobj (gob-mk kobj gob-data)))
+
+;; Make a wrapper for kern-mk-obj-type which inserts the ifc cap info
+(define (mk-obj-type tag name sprite layer ifc)
+  (kern-mk-obj-type tag name sprite layer (ifc-cap ifc) ifc mmode-smallobj))
+
+;; Same as mk-obj-type but flag this type as critical for a quest
+(define (mk-quest-obj-type tag name sprite layer ifc)
+  (kern-type-set-quest-item-flag (mk-obj-type tag name sprite layer ifc)
+                                 #t))
+
+;; ----------------------------------------------------------------------------
+;; send-signal - send a signal to an object. ksender is nil or a pointer to a
+;; kernel object, tag is the tag of the target object (eg 'door-1) and sig is
+;; the symbol of the signal to send (eg 'lock). Examples:
+;;   (send-signal nil 'door-1 'lock)
+;;   (send-signal kplayer 'handle-1b 'on)
+;; ----------------------------------------------------------------------------
+(define (send-signal ksender kobj sig)
+  ((kobj-ifc kobj) sig kobj ksender))
+
+;;----------------------------------------------------------------------------
+;; Yet Another Way to Send a Signal. This one works with arbitrary-length
+;; parameters, so it is more generally applicable to a variety of signals than
+;; previous efforts. It automatically repackages the kobj itself as the first
+;; parameter, so make sure the designated signal handlers expect this.
+;;----------------------------------------------------------------------------
+(define (ifccall kobj sig . parms)
+  (apply (kobj-ifc kobj) (cons sig (cons kobj parms))))
+
+;;----------------------------------------------------------------------------
+;; This returns #t iff kobj has an interface and it has a handler for the sig.
+;;----------------------------------------------------------------------------
+(define (handles? kobj sig)
+  (let ((ifc (kobj-ifc kobj)))
+    (and (not (null? ifc))
+         (ifc 'can sig))))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/ilya.scm b/worlds/haxima-1.002/ilya.scm
new file mode 100644 (file)
index 0000000..8450da0
--- /dev/null
@@ -0,0 +1,208 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Gregor's Hut".
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_ilya
+               (list 0  0  gh-ilyas-bed   "sleeping")
+               (list 6  0  gh-stable      "working")
+               (list 7  0  gh-kitchen     "working")
+               (list 12 0  gh-table-1     "eating")
+               (list 13 0  gh-pasture     "working")
+               (list 15 0  gh-all         "idle")
+               (list 17 0  gh-table-1     "eating")
+               (list 18 0  gh-living-room "idle")
+               (list 20 0  gh-ilyas-bed   "sleeping"))
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Ilya's quest is to find her stuffed horse, which she left behind at the
+;; homestead when she fled the trolls that killed her family. The quest flags
+;; are stored in her gob.
+;;----------------------------------------------------------------------------
+(define (ilya-mk gave-quest? finished-quest?) 
+  (list gave-quest? finished-quest?))
+(define (ilya-gave-quest? ilya) (car ilya))
+(define (ilya-quest-done? ilya) (cadr ilya))
+(define (ilya-give-quest ilya) (set-car! ilya #t))
+(define (ilya-finish-quest ilya) (set-car! (cdr ilya) #t))
+
+;;----------------------------------------------------------------------------
+;; Puska
+;;
+;; Puska -- ilya's stuffed horse toy -- is a quest item. Nothing special about
+;; it really but it is unique and needs its own object type. The object itself
+;; is declared in the p_abandoned_cellar constructor. But the type declaration
+;; needs to be in a file that is reloaded, so here is as good a place as any.
+;;----------------------------------------------------------------------------
+(define puska-ifc
+  (ifc '()
+       (method 'get (lambda (kobj getter)
+                      (kern-log-msg "Some child probably misses this toy!")
+                      (kobj-get kobj getter)))))
+
+(mk-obj-type 't_puska "stuffed toy horse" s_toy_horse layer-item puska-ifc)
+
+;;----------------------------------------------------------------------------
+;; Quest
+;;
+;; This is a single response in Ilya's conversation. I've called it our here
+;; separately to make it obvious.
+;;----------------------------------------------------------------------------
+(define (ilya-quest knpc kpc)
+  (let ((ilya (kobj-gob-data knpc)))
+    (display ilya)(newline)
+    (if (ilya-gave-quest? ilya)
+
+        ;; yes - gave quest already
+        (if (ilya-quest-done? ilya)
+            (say knpc "Puska is happy now!")
+            (begin
+              (say knpc "Did you find Puska yet?")
+              (if (kern-conv-get-yes-no? kpc)
+
+                  ;; yes - puska found
+                  (begin 
+                    (say knpc "May I have her please?")
+                    (if (kern-conv-get-yes-no? kpc)
+
+                        ;; yes - ilya may have puska
+                        (if (kern-obj-has? kpc t_puska)
+
+                            ;; yes - player has puska
+                            (begin
+                              (kern-obj-remove-from-inventory kpc t_puska 1)
+                              (say knpc "There, there, puska. "
+                                   "You're safe with me. [She turns to you] Thank you so much! I wish I could pay you. "
+                                   "Wait, take these, Mommy said wizards use them, so I pick them whenever I can.")
+                              (ilya-finish-quest ilya)
+                              (kern-obj-add-to-inventory kpc nightshade 23)
+                              )
+
+                            ;; no - puska not in player inventory
+                            (begin
+                              (say knpc "[Sob] You don't have her!")
+                              (kern-conv-end)))
+
+                        ;; no - ilya can't have puska
+                        (begin
+                          (say knpc "When I grow up I'll be a sorceress! "
+                               "And I'LL BURN YOU TO A CRISP!")
+                          (kern-conv-end))))
+
+                  ;; no - didn't find her yet
+                  (begin
+                    (say knpc "Do you remember where our farm was?")
+                    (if (kern-conv-get-yes-no? kpc)
+                        (say knpc "She must be there somewhere!")
+                        (say knpc "West through the pass, then north against the hills."))))))
+
+        ;; no - didn't give quest yet
+        (begin
+          (say knpc "Puska is my stuffed horse. But I lost her! "
+               "If you find her will you tell me?")
+          (if (kern-conv-get-yes-no? kpc)
+              (begin
+                (say knpc "Our farm was west through the pass, then north against the hills. "
+                     "Watch out for the trolls!")
+                (ilya-give-quest ilya))
+              (begin
+                (say knpc "If you keep her I will find you when I grow up.")
+                (kern-conv-end)))))))
+
+(define (ilya-join knpc kpc)
+  (say knpc "I'm just a little girl, silly!")
+  )
+
+;;----------------------------------------------------------------------------
+;; Animals
+;;
+;; Ilya has an odd relationship with spiders. She'll teach the player a spell
+;; to ward off spiders if he plays along. Spiders will dominate the woods
+;; around the Abandoned Farm (Ilya's old home). In fact, I intend to have them
+;; locked in a battle with the trolls the first time the player enters the
+;; Abandoned Farm. I'm planning on having a "great mother" spider known around
+;; these parts as Angril or Angriss, perhaps she was one of Ilya's pets as a
+;; child - I'm not sure how I want to play that one out yet.
+;;----------------------------------------------------------------------------
+(define (ilya-animals knpc kpc)
+  (say knpc "We have some sheep, and Charm the cat, and some chickens. "
+       "Do you like animals?")
+  (if (kern-conv-get-yes-no? kpc)
+
+      ;; yes - the player likes animals
+      (begin
+        (say knpc "What's your favorite animal?")
+        (let ((fav (kern-conv-get-reply kpc)))
+          (if (eq? fav 'spid)
+
+              ;; yes - the player's favorite animal is spiders
+              (begin
+                (say knpc "Mine too! I know how to make them harmless. "
+                     "Want me to teach you?")
+                (if (kern-conv-get-yes-no? kpc)
+
+                    ;; yes - the player wants to learn the spider ward
+                    (say knpc "It's easy! Mix spider silk and garlic, "
+                         "and chant An Xen Bet.")
+
+                    ;; no - the player does not want to learn the spider ward
+                    (say knpc "Ok, but they sometimes attack people.")))
+                    
+
+              ;; no - the player's favorite animal is NOT spiders
+              (say knpc "Spiders are my favorite!"))))
+
+      ;; no - the player does not like animals
+      (say knpc "Well don't hurt them!")))
+
+(define (ilya-fire knpc kpc)
+  (say knpc "Making fire is easy. Just mix black pearl and sulphos..."
+       "surephous... that ashy stuff you know? "
+       "And say Vas Flam!"))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+(define ilya-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "I don't know.")))
+       (method 'hail (lambda (knpc kpc) (say knpc "Hi.")))
+       (method 'bye (lambda (knpc kpc) (say knpc "Bye-bye.")))
+       (method 'job (lambda (knpc kpc) (say knpc "I help Grandpa with chores.")))
+       (method 'name (lambda (knpc kpc) (say knpc "I'm Ilya.")))
+       (method 'age (lambda (knpc kpc) (say knpc "I'm eight.")))
+       (method 'chor (lambda (knpc kpc) (say knpc "I feed the animals, and keep the fire, and help cook.")))
+       (method 'anim ilya-animals)
+       (method 'gran (lambda (knpc kpc) (say knpc "I live with Grandpa now because Mommy and Daddy died.")))
+       (method 'died (lambda (knpc kpc) (say knpc "Trolls attacked our farm! "
+                                                "Mommy hid me in the cellar, "
+                                                "and I snuck out when the trolls were sleeping. "
+                                                "But I lost my Puska...")))
+       (method 'trol (lambda (knpc kpc) (say knpc "I hate them! When I grow up I want to kill them all.")))
+       (method 'hate (lambda (knpc kpc) (say knpc "I will be a sorceress some day and I will kill anyone I hate! "
+                                              "I won't be afraid of anything ever again!")))
+       (method 'afra (lambda (knpc kpc) (say knpc "I was afraid in the cellar. "
+                                                "I heard Mommy and Daddy crying when the trolls ate them... "
+                                                "[sniffling] I thought they would find me and eat me too...")))
+       (method 'momm (lambda (knpc kpc) (say knpc "I miss my Mommy. She taught me to make fire with my mind. "
+                                               "She burned up one of the trolls when they attacked!")))
+       (method 'dadd (lambda (knpc kpc) (say knpc "I miss daddy. He tried to fight the trolls but "
+                                               "he was just a farmer.")))
+       (method 'pusk ilya-quest)
+       (method 'home (lambda (knpc kpc) (say knpc "Our farm was north and south through the woods.")))
+       (method 'spid (lambda (knpc kpc) (say knpc "There are lots of spiders in the woods around here.")))
+       (method 'wood (lambda (knpc kpc) (say knpc "Grandpa says to stay out of the woods.")))
+       
+       (method 'fire ilya-fire)
+       (method 'vas ilya-fire)
+       (method 'flam ilya-fire)
+       (method 'greg (lambda (knpc kpc) (say knpc "He's my grandpa.")))
+       (method 'join ilya-join)
+       ))
+
diff --git a/worlds/haxima-1.002/ini.scm b/worlds/haxima-1.002/ini.scm
new file mode 100644 (file)
index 0000000..d71ea1c
--- /dev/null
@@ -0,0 +1,244 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Glasdrin.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_ini
+               (list 0  0  gi-bed      "sleeping")
+               (list 5  0  gs-altar    "idle")
+               (list 6  0  gc-train    "working")
+               (list 12 0  ghg-s2      "eating")
+               (list 13 0  gc-hall     "working")
+               (list 18 0  ghg-s2      "eating")
+               (list 19 0  ghg-hall    "idle")
+               (list 21 0  gi-bed      "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (ini-mk) (list 'townsman #f))
+(define (ini-will-join? ini) (cadr ini))
+(define (ini-will-join! ini) (set-car! (cdr ini) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Ini is a dispirited paladin, dwelling in Glasdrin.
+;; He is loyal to the ideals lived by the Warritrix,
+;; and offended by the corruption which produced her
+;; assassination.
+;; Ini is a potential party member.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (ini-hail knpc kpc)
+  (say knpc "[You meet a morose paladin] Hi."))
+
+(define (ini-default knpc kpc)
+  (say knpc "I can't help you with that."))
+
+(define (ini-notyet knpc kpc)
+  (say knpc "I probably shouldn't talk to civilians about that."))
+
+(define (ini-name knpc kpc)
+  (say knpc "I am Inago, but everyone calls me Ini."))
+
+(define (ini-join knpc kpc)
+  (if (is-player-party-member? knpc)
+      (say knpc "I already joined you. Now let's go!")
+      (let ((ini (kobj-gob-data knpc)))
+        (if (ini-will-join? ini)
+            (begin
+              (say knpc "I thank you! Let's not waste any time finding "
+                   "the Warritrix!")
+              (kern-conv-end)
+              (join-player knpc))
+            (say knpc "[Sigh] My duty is with the paladins.")
+            ))))
+        
+(define (ini-lost knpc kpc)
+   (let ((ini (kobj-gob-data knpc)))
+     (if (ini-will-join? ini)
+                       (begin
+                       (say knpc "The entrance to the Lost Halls is a cavern far to the southwest. "
+                               "Find a ship and sail to ["
+           (loc-x lost-halls-loc) ","
+           (loc-y lost-halls-loc) "].")
+                       (quest-data-update-with 'questentry-rune-l 'know-hall 1 (quest-notify nil))
+                       (quest-data-update 'questentry-warritrix 'lost-hall-loc 1)
+                       )
+                       (say knpc "The Lost Halls are very dangerous. I'd advise you to stay clear!"))))
+               
+(define (ini-cave knpc kpc)
+   (let ((ini (kobj-gob-data knpc)))
+     (if (ini-will-join? ini)
+               (begin
+                       (say knpc "The Lost Halls themselves are deep within the caverns.")
+                       (say knpc (if (is-player-party-member? knpc) "We" "You") " will need to look for the great stairs, in the northern part of the caves.")
+                       (say knpc "Beware of the dungeon's inhabitants!")
+                       )
+               (ini-notyet knpc kpc))))
+               
+(define (ini-inha knpc kpc)
+   (let ((ini (kobj-gob-data knpc)))
+     (if (ini-will-join? ini)
+               (begin
+                       (say knpc "Everytime we try to clear the place out, another band of gints or trolls decides to move in.")
+                       (say knpc (if (is-player-party-member? knpc) "We" "You") "'d best be prepared for a long, hard battle.")
+                       )
+               (ini-notyet knpc kpc))))
+
+(define (ini-stair knpc kpc)
+   (let ((ini (kobj-gob-data knpc)))
+     (if (ini-will-join? ini)
+               (begin
+                       (say knpc "I know the stairs are somewhere in the north, but I'm afraid I've never been that far, so I don't know their precise location.")
+                       )
+               (ini-notyet knpc kpc))))
+                       
+(define (ini-job knpc kpc)
+  (say knpc "I'm a paladin. But I don't like it very much."))
+
+(define (ini-bye knpc kpc)
+  (say knpc "So long."))
+
+(define (ini-warr knpc kpc)
+  (cond ((player-stewardess-trial-done?)
+                (say knpc "Justice has been served, and now I can grieve her loss." ))
+       ((player-found-warritrix?)
+                (if (ask? knpc kpc "The Stewardess is powerful, but there is a way to see that justice is done. An ancient way. A dangerous way. Will you hear me?")
+                    (say knpc "There is a statue in the center of Glasdrin. "
+                         "If you strike it with your sword, you will invoke the oldest law of the city, and a trial will be held. "
+                         "But we dare not strike it until we have convincing evidence against the Stewardess, because if our evidence is lacking then judgment will be passed on us instead!")
+                    (say knpc "We can't let the Stewardess get away with this. Someone must call her to account!")))
+       ((quest-data-assigned? 'questentry-wise)
+                (say knpc "[He straightens up a bit] Something is amiss! The Warritrix has "
+                     "been gone too long with no word. The Commander should have sent out "
+                     "search parties by now. Instead he sits idly by, pretending to be "
+                     "distracted by other problems. I sense foul play. Will you search for "
+                     "her?")
+                (if (kern-conv-get-yes-no? kpc)
+                    (begin
+                      (say knpc "I would join you! I know the deeps well, and though my "
+                           "duty is here, I won't obey an order that leaves her to die.")
+                      (ini-will-join! (kobj-gob-data knpc)))
+                    (say knpc "Someone must do something! The realm owes her a great "
+                         "debt.")))
+       (else
+               (say knpc "Are you looking for the Warritrix?")
+               (if (kern-conv-get-yes-no? kpc)
+                       (begin
+                               (say knpc "She can be hard to find. I believe she is out on patrol right now. ")
+                               (say knpc "If you want come back later, I'll keep an eye out and let you know if she's back")
+                       )
+               ))
+       ))
+
+;; Paladin...
+(define (ini-pala knpc kpc)
+  (say knpc "I've been a paladin my whole life. I'm not very good at it; "
+       "I get sick before and after every battle. I'm surprised they "
+       "let me stay in, but I guess they need the warm bodies. "
+       "I would have quit long ago but I don't know what else to do."
+       ))
+
+(define (ini-quit knpc kpc)
+  (say knpc "I've managed to save some pay. I'll retire soon, buy a farm "
+       "near Trigrave, get away from this place. Just think: no more long "
+       "marches, no more sleeping on stony ground in the lightless deep, "
+       "no more waking up to monsters eating your squad for breakfast."
+       ))
+
+;; Townspeople...
+(define (ini-glas knpc kpc)
+  (say knpc "Kind of a dreary place, don't you think?")
+  (kern-conv-get-yes-no? kpc)
+  (say knpc "I've always wanted to visit Green Tower, see the trees."))
+
+(define (ini-ange knpc kpc)
+  (say knpc "A modest lady. I once saw her spit a cave goblin with a dagger."))
+
+(define (ini-spit knpc kpc)
+  (say knpc "She was assigned to my squad on a standard patrol in the "
+       "hills. We'd just barely survived an encounter with gints when some "
+       "cave goblins decided we looked like easy pickings. "
+       "It was dicey there for a while."))
+
+(define (ini-patc knpc kpc)
+  (say knpc "I owe him my life."))
+
+(define (ini-life knpc kpc)
+  (say knpc "I was killed once. We were in the deeps on patrol, dead tired "
+       "after fleeing a party of death knights that killed our medik, "
+       "and we camped right in the middle of a party of sleeping trolls. ")
+  (prompt-for-key)
+  (say knpc
+       "They woke up first. One minute I was fighting for my life, "
+       "and the next I was in the hospital looking up at Doc Patch. "
+       "Nobody else survived from my squad."
+       ))
+
+(define ini-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default ini-default)
+       (method 'hail ini-hail)
+       (method 'bye  ini-bye)
+       (method 'job  ini-job)
+       (method 'name ini-name)
+       (method 'join ini-join)
+
+       (method 'warr ini-warr)
+       (method 'pala ini-pala)
+       (method 'quit ini-quit)
+       (method 'glas ini-glas)
+       (method 'ange ini-ange)
+       (method 'spit ini-spit)
+       (method 'dagg ini-spit)
+       (method 'patc ini-patc)
+       (method 'life ini-life)
+       
+       (method 'lost ini-lost)
+       (method 'hall ini-lost)
+       (method 'cave ini-cave)
+       (method 'entr ini-cave)
+       (method 'stai ini-stair)
+       (method 'nort ini-stair)
+       (method 'deep ini-stair)
+       (method 'grea ini-stair)
+       (method 'inha ini-inha)
+       (method 'bewa ini-inha)
+       (method 'dung ini-inha)
+       
+       ))
+       
+(define (mk-ini)
+  (bind 
+   (kern-mk-char 'ch_ini           ; tag
+                 "Ini"             ; name
+                 sp_human            ; species
+                 oc_warrior          ; occ
+                 s_companion_paladin ; sprite
+                 faction-glasdrin         ; starting alignment
+                 5 0 5               ; str/int/dex
+                  pc-hp-off  ; hp bonus
+                  pc-hp-gain ; hp per-level bonus
+                  0 ; mp off
+                  0 ; mp gain
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'ini-conv         ; conv
+                 sch_ini           ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 (list t_armor_chain
+                       t_chain_coif
+                       t_halberd
+                       ))         ; readied
+   (ini-mk)))
diff --git a/worlds/haxima-1.002/init.scm b/worlds/haxima-1.002/init.scm
new file mode 100644 (file)
index 0000000..5f6effc
--- /dev/null
@@ -0,0 +1,572 @@
+;    Initialization file for TinySCHEME 1.31 onwards
+
+; Per R5RS, up to four deep compositions should be defined
+(define (caar x) (car (car x)))
+(define (cadr x) (car (cdr x)))
+(define (cdar x) (cdr (car x)))
+(define (cddr x) (cdr (cdr x)))
+(define (caaar x) (car (car (car x))))
+(define (caadr x) (car (car (cdr x))))
+(define (cadar x) (car (cdr (car x))))
+(define (caddr x) (car (cdr (cdr x))))
+(define (cdaar x) (cdr (car (car x))))
+(define (cdadr x) (cdr (car (cdr x))))
+(define (cddar x) (cdr (cdr (car x))))
+(define (cdddr x) (cdr (cdr (cdr x))))
+(define (caaaar x) (car (car (car (car x)))))
+(define (caaadr x) (car (car (car (cdr x)))))
+(define (caadar x) (car (car (cdr (car x)))))
+(define (caaddr x) (car (car (cdr (cdr x)))))
+(define (cadaar x) (car (cdr (car (car x)))))
+(define (cadadr x) (car (cdr (car (cdr x)))))
+(define (caddar x) (car (cdr (cdr (car x)))))
+(define (cadddr x) (car (cdr (cdr (cdr x)))))
+(define (cdaaar x) (cdr (car (car (car x)))))
+(define (cdaadr x) (cdr (car (car (cdr x)))))
+(define (cdadar x) (cdr (car (cdr (car x)))))
+(define (cdaddr x) (cdr (car (cdr (cdr x)))))
+(define (cddaar x) (cdr (cdr (car (car x)))))
+(define (cddadr x) (cdr (cdr (car (cdr x)))))
+(define (cdddar x) (cdr (cdr (cdr (car x)))))
+(define (cddddr x) (cdr (cdr (cdr (cdr x)))))
+
+(macro (unless form)
+     `(if (not ,(cadr form)) (begin ,@(cddr form))))
+
+(macro (when form)
+     `(if ,(cadr form) (begin ,@(cddr form))))
+
+; DEFINE-MACRO Contributed by Andy Gaynor
+(macro (define-macro dform)
+  (if (symbol? (cadr dform))
+    `(macro ,@(cdr dform))
+    (let ((form (gensym)))
+      `(macro (,(caadr dform) ,form)
+         (apply (lambda ,(cdadr dform) ,@(cddr dform)) (cdr ,form))))))
+
+; Utilities for math. Notice that inexact->exact is primitive,
+; but exact->inexact is not.
+(define exact? integer?)
+(define (inexact? x) (and (real? x) (not (integer? x))))
+(define (even? n) (= (remainder n 2) 0))
+(define (odd? n) (not (= (remainder n 2) 0)))
+(define (zero? n) (= n 0))
+(define (positive? n) (> n 0))
+(define (negative? n) (< n 0))
+(define complex? number?)
+(define rational? real?)
+(define (abs n) (if (>= n 0) n (- n)))
+(define (exact->inexact n) (* n 1.0))
+(define (<> n1 n2) (not (= n1 n2)))
+(define (max . lst)
+     (foldr (lambda (a b) (if (> a b) a b)) (car lst) (cdr lst)))
+(define (min . lst)
+     (foldr (lambda (a b) (if (< a b) a b)) (car lst) (cdr lst)))
+(define (succ x) (+ x 1))
+(define (pred x) (- x 1))
+(define (gcd a b)
+  (let ((aa (abs a))
+       (bb (abs b)))
+     (if (= bb 0)
+          aa
+          (gcd bb (remainder aa bb)))))
+(define (lcm a b)
+     (if (or (= a 0) (= b 0))
+          0
+          (abs (* (quotient a (gcd a b)) b))))
+
+(define call/cc call-with-current-continuation)
+
+(define (string . charlist)
+     (list->string charlist))
+
+(define (list->string charlist)
+     (let* ((len (length charlist))
+            (newstr (make-string len))
+            (fill-string!
+               (lambda (str i len charlist)
+                    (if (= i len)
+                         str
+                         (begin (string-set! str i (car charlist))
+                         (fill-string! str (+ i 1) len (cdr charlist)))))))
+          (fill-string! newstr 0 len charlist)))
+
+(define (string-fill! s e)
+     (let ((n (string-length s)))
+          (let loop ((i 0))
+               (if (= i n)
+                    s
+                    (begin (string-set! s i e) (loop (succ i)))))))
+
+(define (string->list s)
+     (let loop ((n (pred (string-length s))) (l '()))
+          (if (= n -1)
+               l
+               (loop (pred n) (cons (string-ref s n) l)))))
+
+(define (string-copy str)
+     (string-append str))
+
+(define (string->anyatom str pred)
+     (let* ((a (string->atom str)))
+       (if (pred a) a
+          (error "string->xxx: not a xxx" a))))
+
+(define (string->number str) (string->anyatom str number?))
+
+(define (anyatom->string n pred)
+  (if (pred n)
+      (atom->string n)
+      (error "xxx->string: not a xxx" n)))
+  
+
+(define (number->string n) (anyatom->string n number?))    
+
+(define (char-cmp? cmp a b)
+     (cmp (char->integer a) (char->integer b)))
+(define (char-ci-cmp? cmp a b)
+     (cmp (char->integer (char-downcase a)) (char->integer (char-downcase b))))
+
+(define (char=? a b) (char-cmp? = a b))
+(define (char<? a b) (char-cmp? < a b))
+(define (char>? a b) (char-cmp? > a b))
+(define (char<=? a b) (char-cmp? <= a b))
+(define (char>=? a b) (char-cmp? >= a b))
+
+(define (char-ci=? a b) (char-ci-cmp? = a b))
+(define (char-ci<? a b) (char-ci-cmp? < a b))
+(define (char-ci>? a b) (char-ci-cmp? > a b))
+(define (char-ci<=? a b) (char-ci-cmp? <= a b))
+(define (char-ci>=? a b) (char-ci-cmp? >= a b))
+
+; Note the trick of returning (cmp x y)
+(define (string-cmp? chcmp cmp a b)
+     (let ((na (string-length a)) (nb (string-length b)))
+          (if (<> na nb)
+               (cmp na nb)
+               (let loop ((i 0))
+                    (if (= i na)
+                         (if (= na 0) (cmp 0 0) #t)
+                         (and (chcmp cmp (string-ref a i) (string-ref b i))
+                              (loop (succ i))))))))
+
+(define (string=? a b) (string-cmp? char-cmp? = a b))
+(define (string<? a b) (string-cmp? char-cmp? < a b))
+(define (string>? a b) (string-cmp? char-cmp? > a b))
+(define (string<=? a b) (string-cmp? char-cmp? <= a b))
+(define (string>=? a b) (string-cmp? char-cmp? >= a b))
+
+(define (string-ci=? a b) (string-cmp? char-ci-cmp? = a b))
+(define (string-ci<? a b) (string-cmp? char-ci-cmp? < a b))
+(define (string-ci>? a b) (string-cmp? char-ci-cmp? > a b))
+(define (string-ci<=? a b) (string-cmp? char-ci-cmp? <= a b))
+(define (string-ci>=? a b) (string-cmp? char-ci-cmp? >= a b))
+
+(define (list . x) x)
+
+(define (foldr f x lst)
+     (if (null? lst)
+          x
+          (foldr f (f x (car lst)) (cdr lst))))
+
+(define (unzip1-with-cdr . lists)
+  (unzip1-with-cdr-iterative lists '() '()))
+
+(define (unzip1-with-cdr-iterative lists cars cdrs)
+  (if (null? lists)
+      (cons cars cdrs)
+      (let ((car1 (caar lists))
+           (cdr1 (cdar lists)))
+       (unzip1-with-cdr-iterative 
+        (cdr lists) 
+        (append cars (list car1))
+        (append cdrs (list cdr1))))))
+
+(define (map proc . lists)
+  (if (null? lists)
+      (apply proc)
+      (if (null? (car lists))
+         '()
+         (let* ((unz (apply unzip1-with-cdr lists))
+                (cars (car unz))
+                (cdrs (cdr unz)))
+           (cons (apply proc cars) (apply map (cons proc cdrs)))))))
+
+(define (for-each proc . lists)
+  (if (null? lists)
+      (apply proc)
+      (if (null? (car lists))
+         #t
+         (let* ((unz (apply unzip1-with-cdr lists))
+                (cars (car unz))
+                (cdrs (cdr unz)))
+           (apply proc cars) (apply map (cons proc cdrs))))))
+
+(define (list-tail x k)
+    (if (zero? k)
+        x
+        (list-tail (cdr x) (- k 1))))
+
+(define (list-ref x k)
+    (car (list-tail x k)))
+
+(define (last-pair x)
+    (if (pair? (cdr x))
+        (last-pair (cdr x))
+        x))
+
+(define (head stream) (car stream))
+
+(define (tail stream) (force (cdr stream)))
+
+(define (vector-equal? x y)
+     (and (vector? x) (vector? y) (= (vector-length x) (vector-length y))
+          (let ((n (vector-length x)))
+               (let loop ((i 0))
+                    (if (= i n)
+                         #t
+                         (and (equal? (vector-ref x i) (vector-ref y i))
+                              (loop (succ i))))))))
+
+(define (list->vector x)
+     (apply vector x))
+
+(define (vector-fill! v e)
+     (let ((n (vector-length v)))
+          (let loop ((i 0))
+               (if (= i n)
+                    v
+                    (begin (vector-set! v i e) (loop (succ i)))))))
+
+(define (vector->list v)
+     (let loop ((n (pred (vector-length v))) (l '()))
+          (if (= n -1)
+               l
+               (loop (pred n) (cons (vector-ref v n) l)))))
+
+;; The following quasiquote macro is due to Eric S. Tiedemann.
+;;   Copyright 1988 by Eric S. Tiedemann; all rights reserved.
+;;
+;; Subsequently modified to handle vectors: D. Souflis
+
+(macro
+ quasiquote
+ (lambda (l)
+   (define (mcons f l r)
+     (if (and (pair? r)
+              (eq? (car r) 'quote)
+              (eq? (car (cdr r)) (cdr f))
+              (pair? l)
+              (eq? (car l) 'quote)
+              (eq? (car (cdr l)) (car f)))
+         (if (or (procedure? f) (number? f) (string? f))
+               f
+               (list 'quote f))
+         (if (eqv? l vector)
+               (apply l (eval r))
+               (list 'cons l r)
+               )))
+   (define (mappend f l r)
+     (if (or (null? (cdr f))
+             (and (pair? r)
+                  (eq? (car r) 'quote)
+                  (eq? (car (cdr r)) '())))
+         l
+         (list 'append l r)))
+   (define (foo level form)
+     (cond ((not (pair? form))
+               (if (or (procedure? form) (number? form) (string? form))
+                    form
+                    (list 'quote form))
+               )
+           ((eq? 'quasiquote (car form))
+            (mcons form ''quasiquote (foo (+ level 1) (cdr form))))
+           (#t (if (zero? level)
+                   (cond ((eq? (car form) 'unquote) (car (cdr form)))
+                         ((eq? (car form) 'unquote-splicing)
+                          (error "Unquote-splicing wasn't in a list:"
+                                 form))
+                         ((and (pair? (car form))
+                               (eq? (car (car form)) 'unquote-splicing))
+                          (mappend form (car (cdr (car form)))
+                                   (foo level (cdr form))))
+                         (#t (mcons form (foo level (car form))
+                                         (foo level (cdr form)))))
+                   (cond ((eq? (car form) 'unquote)
+                          (mcons form ''unquote (foo (- level 1)
+                                                     (cdr form))))
+                         ((eq? (car form) 'unquote-splicing)
+                          (mcons form ''unquote-splicing
+                                      (foo (- level 1) (cdr form))))
+                         (#t (mcons form (foo level (car form))
+                                         (foo level (cdr form)))))))))
+   (foo 0 (car (cdr l)))))
+
+
+;;;;; atom? and equal? written by a.k
+
+;;;; atom?
+(define (atom? x)
+  (not (pair? x)))
+
+;;;;    equal?
+(define (equal? x y)
+     (cond
+          ((pair? x)
+               (and (pair? y)
+                    (equal? (car x) (car y))
+                    (equal? (cdr x) (cdr y))))
+          ((vector? x)
+               (and (vector? y) (vector-equal? x y)))
+          ((string? x)
+               (and (string? y) (string=? x y)))
+          (else (eqv? x y))))
+
+;;;; (do ((var init inc) ...) (endtest result ...) body ...)
+;;
+(macro do
+  (lambda (do-macro)
+    (apply (lambda (do vars endtest . body)
+             (let ((do-loop (gensym)))
+               `(letrec ((,do-loop
+                           (lambda ,(map (lambda (x)
+                                           (if (pair? x) (car x) x))
+                                      `,vars)
+                             (if ,(car endtest)
+                               (begin ,@(cdr endtest))
+                               (begin
+                                 ,@body
+                                 (,do-loop
+                                   ,@(map (lambda (x)
+                                            (cond
+                                              ((not (pair? x)) x)
+                                              ((< (length x) 3) (car x))
+                                              (else (car (cdr (cdr x))))))
+                                       `,vars)))))))
+                  (,do-loop
+                    ,@(map (lambda (x)
+                             (if (and (pair? x) (cdr x))
+                               (car (cdr x))
+                               '()))
+                        `,vars)))))
+      do-macro)))
+
+;;;; generic-member
+(define (generic-member cmp obj lst)
+  (cond
+    ((null? lst) #f)
+    ((cmp obj (car lst)) lst)
+    (else (generic-member cmp obj (cdr lst)))))
+
+(define (memq obj lst)
+     (generic-member eq? obj lst))
+(define (memv obj lst)
+     (generic-member eqv? obj lst))
+(define (member obj lst)
+     (generic-member equal? obj lst))
+
+;;;; generic-assoc
+(define (generic-assoc cmp obj alst)
+     (cond
+          ((null? alst) #f)
+          ((cmp obj (caar alst)) (car alst))
+          (else (generic-assoc cmp obj (cdr alst)))))
+
+(define (assq obj alst)
+     (generic-assoc eq? obj alst))
+(define (assv obj alst)
+     (generic-assoc eqv? obj alst))
+(define (assoc obj alst)
+     (generic-assoc equal? obj alst))
+
+(define (acons x y z) (cons (cons x y) z))
+
+;;;; Utility to ease macro creation
+(define (macro-expand form)
+     ((eval (get-closure-code (eval (car form)))) form))
+
+;;;; Handy for imperative programs
+;;;; Used as: (define-with-return (foo x y) .... (return z) ...)
+(macro (define-with-return form)
+     `(define ,(cadr form)
+          (call/cc (lambda (return) ,@(cddr form)))))
+
+;;;; Simple exception handling
+;
+;    Exceptions are caught as follows:
+;
+;         (catch (do-something to-recover and-return meaningful-value)
+;              (if-something goes-wrong)
+;              (with-these calls))
+;
+;    "Catch" establishes a scope spanning multiple call-frames
+;    until another "catch" is encountered.
+;
+;    Exceptions are thrown with:
+;
+;         (throw "message")
+;
+;    If used outside a (catch ...), reverts to (error "message)
+
+(define *handlers* (list))
+
+(define (push-handler proc)
+     (set! *handlers* (cons proc *handlers*)))
+
+(define (pop-handler)
+     (let ((h (car *handlers*)))
+          (set! *handlers* (cdr *handlers*))
+          h))
+
+(define (more-handlers?)
+     (pair? *handlers*))
+
+(define (throw . x)
+     (if (more-handlers?)
+          (apply (pop-handler))
+          (apply error x)))
+
+(macro (catch form)
+     (let ((label (gensym)))
+          `(call/cc (lambda (exit)
+               (push-handler (lambda () (exit ,(cadr form))))
+               (let ((,label (begin ,@(cddr form))))
+                    (pop-handler)
+                    ,label)))))
+
+(define *error-hook* throw)
+
+
+;;;;; Definition of MAKE-ENVIRONMENT, to be used with two-argument EVAL
+
+(macro (make-environment form)
+     `(apply (lambda ()
+               ,@(cdr form)
+               (current-environment))))
+
+(define-macro (eval-polymorphic x . envl)
+  (display envl)
+  (let* ((env (if (null? envl) (current-environment) (eval (car envl))))
+         (xval (eval x env)))
+    (if (closure? xval)
+       (make-closure (get-closure-code xval) env)
+       xval)))
+
+; Redefine this if you install another package infrastructure
+; Also redefine 'package'
+(define *colon-hook* eval)
+
+;;;;; I/O
+
+(define (input-output-port? p)
+     (and (input-port? p) (output-port? p)))
+
+(define (close-port p)
+     (cond 
+          ((input-output-port? p) (close-input-port (close-output-port p)))
+          ((input-port? p) (close-input-port p))
+          ((output-port? p) (close-output-port p))
+          (else (throw "Not a port" p))))
+
+(define (call-with-input-file s p)
+     (let ((inport (open-input-file s)))
+          (if (eq? inport #f)
+               #f
+               (let ((res (p inport)))
+                    (close-input-port inport)
+                    res))))
+
+(define (call-with-output-file s p)
+     (let ((outport (open-output-file s)))
+          (if (eq? outport #f)
+               #f
+               (let ((res (p outport)))
+                    (close-output-port outport)
+                    res))))
+
+(define (with-input-from-file s p)
+     (let ((inport (open-input-file s)))
+          (if (eq? inport #f)
+               #f
+               (let ((prev-inport (current-input-port)))
+                    (set-input-port inport)
+                    (let ((res (p)))
+                         (close-input-port inport)
+                         (set-input-port prev-inport)
+                         res)))))
+
+(define (with-output-to-file s p)
+     (let ((outport (open-output-file s)))
+          (if (eq? outport #f)
+               #f
+               (let ((prev-outport (current-output-port)))
+                    (set-output-port outport)
+                    (let ((res (p)))
+                         (close-output-port outport)
+                         (set-output-port prev-outport)
+                         res)))))
+
+(define (with-input-output-from-to-files si so p)
+     (let ((inport (open-input-file si))
+           (outport (open-input-file so)))
+          (if (not (and inport outport))
+               (begin
+                    (close-input-port inport)
+                    (close-output-port outport)
+                    #f)
+               (let ((prev-inport (current-input-port))
+                     (prev-outport (current-output-port)))
+                    (set-input-port inport)
+                    (set-output-port outport)
+                    (let ((res (p)))
+                         (close-input-port inport)
+                         (close-output-port outport)
+                         (set-input-port prev-inport)
+                         (set-output-port prev-outport)
+                         res)))))
+
+; Random number generator (maximum cycle)
+(define *seed* 1)
+(define (random-next)
+     (let* ((a 16807) (m 2147483647) (q (quotient m a)) (r (modulo m a)))
+          (set! *seed*
+               (-   (* a (- *seed*
+                         (* (quotient *seed* q) q)))
+                    (* (quotient *seed* q) r)))
+          (if (< *seed* 0) (set! *seed* (+ *seed* m)))
+          *seed*))
+;; SRFI-0 
+;; COND-EXPAND
+;; Implemented as a macro
+(define *features* '(srfi-0))
+
+(define-macro (cond-expand . cond-action-list)
+  (cond-expand-runtime cond-action-list))
+
+(define (cond-expand-runtime cond-action-list)
+  (if (null? cond-action-list)
+      #t
+      (if (cond-eval (caar cond-action-list))
+          `(begin ,@(cdar cond-action-list))
+          (cond-expand-runtime (cdr cond-action-list)))))
+
+(define (cond-eval-and cond-list)
+  (foldr (lambda (x y) (and (cond-eval x) (cond-eval y))) #t cond-list))
+
+(define (cond-eval-or cond-list)
+  (foldr (lambda (x y) (or (cond-eval x) (cond-eval y))) #f cond-list))
+
+(define (cond-eval condition)
+  (cond ((symbol? condition)
+        (if (member condition *features*) #t #f))
+       ((eq? condition #t) #t)
+       ((eq? condition #f) #f)
+       (else (case (car condition)
+               ((and) (cond-eval-and (cdr condition)))
+               ((or) (cond-eval-or (cdr condition)))
+               ((not) (if (not (null? (cddr condition)))
+                          (error "cond-expand : 'not' takes 1 argument")
+                          (not (cond-eval (cadr condition)))))
+               (else (error "cond-expand : unknown operator" (car condition)))))))
+
+(gc-verbose #f)
diff --git a/worlds/haxima-1.002/items.scm b/worlds/haxima-1.002/items.scm
new file mode 100644 (file)
index 0000000..9cd8875
--- /dev/null
@@ -0,0 +1,85 @@
+;;----------------------------------------------------------------------------
+;; item.scm - utility procs for creating types that support the 'use' method in
+;; addition to the default 'get' method
+;;----------------------------------------------------------------------------
+
+;; ----------------------------------------------------------------------------
+;; use-item -- use an item and decrement the action points, unless the usage
+;; result is an abort code (currently I think result-no-target is the only such
+;; case). The 'use' proc should return one of the result-* codes.
+;; ----------------------------------------------------------------------------
+(define (use-item ktype kuser use ap)
+  (let ((result (use ktype kuser)))
+    (if (not (abortive-result? result))
+        (kern-obj-dec-ap kuser ap))
+    result))
+
+;; ----------------------------------------------------------------------------
+;; use-and-remove-item -- use an item type and remove it from the user's
+;; inventory.  The 'use' proc should return one of the standard result-* codes.
+;; ----------------------------------------------------------------------------
+(define (use-and-remove-item ktype kuser use ap)
+  (let ((result (use-item ktype kuser use ap)))
+    (if (not (abortive-result? result))
+        (kern-obj-remove-from-inventory kuser ktype 1))
+    result))
+
+;; ----------------------------------------------------------------------------
+;; mk-usable-item -- make a type for an object that can be U)sed by the
+;; player. The use-proc parm should be a procedure which takes the object and
+;; the user as parameters. ap is the action points required to use the item.
+;; ----------------------------------------------------------------------------
+(define (mk-usable-item tag name sprite ap use-proc)
+  (let ((item-ifc (ifc obj-ifc 
+                       (method 'use 
+                               (lambda (ktype kuser) 
+                                 (use-and-remove-item ktype 
+                                                      kuser 
+                                                      use-proc 
+                                                      ap))))))
+    (mk-obj-type tag name sprite layer-item item-ifc)))
+
+;; ----------------------------------------------------------------------------
+;; mk-usable-clingy-item -- extension to mk-usable-item that gives an item
+;; the ability to cause nearby npc's that want the item to get the item
+;; ----------------------------------------------------------------------------
+(define (mk-usable-clingy-item tag name sprite ap use-proc wants-it?)
+  (let ((item-ifc (ifc obj-ifc 
+                       (method 'use 
+                               (lambda (ktype kuser) 
+                                 (use-and-remove-item ktype 
+                                                      kuser 
+                                                      use-proc 
+                                                      ap)))
+                       (method 'exec
+                               (lambda (kitem)
+                                 (if (not (kern-place-is-wilderness? (loc-place (kern-obj-get-location kitem))))
+                                     (let ((kchars (filter (lambda (kchar)
+                                                             (and (wants-it? kchar)
+                                                                  (not (has-ap-debt? kchar))
+                                                                  (not (is-player-party-member? kchar))))
+                                                           (get-beings-in-range kitem 
+                                                                                1))))
+                                       (if (notnull? kchars)
+                                           (kobj-get kitem 
+                                                     (car kchars))))))))))
+    (mk-obj-type tag name sprite layer-item item-ifc)))
+  
+                                              
+
+;; ----------------------------------------------------------------------------
+;; mk-reusable-item -- make a type for an object that can be U)sed by the
+;; player any number of times.
+;; ----------------------------------------------------------------------------
+(define (mk-reusable-item tag name sprite ap use-proc)
+  (let ((item-ifc (ifc obj-ifc 
+                       (method 'use 
+                               (lambda (ktype kuser) 
+                                 (use-item ktype kuser use-proc ap))))))
+    (mk-obj-type tag name sprite layer-item item-ifc)))
+
+(load "potions.scm")
+(load "books.scm")
+(load "tools.scm")
+(load "scrolls.scm")
+(load "keys.scm")
diff --git a/worlds/haxima-1.002/jake.scm b/worlds/haxima-1.002/jake.scm
new file mode 100644 (file)
index 0000000..9994894
--- /dev/null
@@ -0,0 +1,188 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define jake-lvl 2)
+(define jake-species sp_gint)
+(define jake-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Kun.
+;;----------------------------------------------------------------------------
+(define jake-bed )
+(kern-mk-sched 'sch_jake
+               (list 0  0 cantina-counter-zzz "sleeping")
+               (list 9  0 cantina-counter "working")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (jake-mk) (list #t))
+(define (jake-left? gob) (car gob))
+(define (jake-left! gob val) (set-car! gob val))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Jake / Percy is a gint (two-headed giant) 
+;; who lives in the monster village of Kun.
+;; 
+;; Jake is the brutish left head,
+;; who acts as the bouncer for the tavern there.
+;; 
+;; Percy is the refined right head,
+;; who is the barkeep and proprietor of the tavern there.
+;;----------------------------------------------------------------------------
+
+(define (left-head? knpc)
+  (jake-left? (gob knpc)))
+(define (left-head! knpc)
+  (jake-left! (gob knpc) #t)
+  (say knpc "RIGHT HERE!"))
+(define (right-head! knpc)
+  (jake-left! (gob knpc) #f)
+  (say knpc "How may I be of service?"))
+
+;; Basics...
+(define (jake-hail knpc kpc)
+  (kern-log-msg "You meet an enormous figure with two heads. One is rough-looking, the other somewhat... "
+                "well, prissy is probably not too strong a word.")
+  (if (left-head? knpc)
+      (say knpc "HAIL, MANLING!")
+      (say knpc "Well met, little sir.")
+      ))
+
+(define (jake-default knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "HELL, I DON'T KNOW! ASK PERCY!")
+      (say knpc "A conundrum, to be sure.")
+      ))
+
+(define (jake-name knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "I'M JAKE! AND THIS OTHER IS PERCY! [The left head jerks to indicate the right]")
+      (say knpc "I am Percival. And my constant companion here likes to be called 'Jake'.  [The left head nods to the right]")
+      ))
+
+(define (jake-join knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "HAR! HAR! HAR!")
+      (say knpc "Oh, I'm afraid not. A most gracious offer, though, and all that.")
+      ))
+
+(define (jake-job knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "I'M THE BOUNCER, OF COURSE! NOW DRINK SOMETHING OR GET OUT!")
+      (begin
+        (say knpc "I am the proprieter and bartender. Would you care for a drink?")
+        (if (yes? kpc)
+            (jake-trade knpc kpc)
+            (say knpc "Please reconsider, I offer the finest.")
+            ))))
+
+(define (jake-bye knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "BYE!")
+      (say knpc "Farewell, do come again.")
+      ))
+
+(define (jake-jake knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "YEAH? WHADDAYA WANT?")
+      (begin
+        (say knpc "Do you actually WANT to talk to Jake?")
+        (if (yes? kpc)
+            (left-head! knpc)))
+      ))
+
+(define (jake-perc knpc kpc)
+  (if (left-head? knpc)
+      (begin
+        (say knpc "WHA? YOU WANNA TALK TO PERCY NOW?")
+        (if (yes? kpc)
+            (right-head! knpc)
+            ))
+      (say knpc "Yes, that's me. Can I help you?")
+      ))
+
+(define (jake-drin knpc kpc)
+  (if (left-head? knpc)
+      (say knpc "TALK TO PERCY!")
+      (jake-trade knpc kpc)))
+
+
+;; Trade...
+(define jake-merch-msgs
+  (list nil ;; closed
+        "Let me show you a menu." ;; buy
+        nil ;; sell
+        nil ;; trade
+        "I'm delighted I could be of assistance." ;; bought-something
+        "[sniff] Well, I shan't be offended." ;; bought-nothing
+        nil
+        nil
+        nil
+        nil
+   ))
+
+(define jake-catalog
+  (list
+   (list t_food 7 "My roast lamb is to die for! I'm afraid it's quite wasted on the usual riff-raff.")
+   (list t_beer 4 "I import casks of lager all the way from the famous brewers of Gintspar.")
+   (list t_wine 6 "We get some very good wine from a wrogue who specializes in pilfering wine cellars. I hope you don't recognize any of these bottles... Ahem")
+   ))
+
+(define (jake-trade knpc kpc) (conv-trade knpc kpc "buy" jake-merch-msgs jake-catalog))
+
+;; Town & Townspeople
+
+;; Quest-related
+
+(define jake-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default jake-default)
+       (method 'hail jake-hail)
+       (method 'bye  jake-bye)
+       (method 'job  jake-job)
+       (method 'name jake-name)
+       (method 'join jake-join)
+       
+       ;; trade
+       (method 'drin jake-drin)
+       (method 'trad jake-trade)
+       (method 'buy  jake-trade)
+
+       ;; town & people
+       (method 'jake jake-jake)
+       (method 'perc jake-perc)
+       ))
+
+(define (mk-jake)
+  (bind 
+   (kern-mk-char 
+    'ch_jake           ; tag
+    "Jake&Percival"             ; name
+    jake-species         ; species
+    jake-occ              ; occ
+    s_gint     ; sprite
+    faction-men      ; starting alignment
+    0 0 0            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    jake-lvl
+    #f               ; dead
+    'jake-conv         ; conv
+    sch_jake           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   (jake-mk)))
diff --git a/worlds/haxima-1.002/janice.scm b/worlds/haxima-1.002/janice.scm
new file mode 100644 (file)
index 0000000..742d04f
--- /dev/null
@@ -0,0 +1,108 @@
+;;----------------------------------------------------------------------------
+;; Janice
+;;
+;; Initially Commander Jeffries's assistant, she will be elected to replace
+;; him after the trial.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_jan
+               (list 0  0  gjan-bed    "sleeping")
+               (list 6  0  gc-hall     "working")
+               (list 7  0  ghg-s6      "eating")
+               (list 8  0  gc-hall     "working")
+               (list 11 0  ghg-s3      "eating")
+               (list 12 0  gc-hall     "working")
+               (list 17 0  ghg-s3      "eating")
+               (list 18 0  g-fountain  "idle")
+               (list 20 0  gjan-bed    "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (jan-mk) (list 'townsman))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (jan-hail knpc kpc)
+  (say knpc "Hail, traveler.")
+  )
+
+(define (jan-name knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "I am Commander Janice.")
+      (say knpc "I am Janice.")
+      ))
+
+(define (jan-job knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "I command Glasdrin's militia.")
+      (say knpc "I am a strategic adviser to Commander Jeffries.")
+      ))
+
+;; Special
+(define (jan-comm knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "I was elected to replace Jeffries, the former Commander.")
+      (say knpc "Commander Jeffries is a capable leader.")
+      ))
+
+(define (jan-repl knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "It's a shame that his long history of good service to Glasdrin should end in such disgrace.")
+      (say knpc "Why, whatever do you mean?")
+      ))
+
+(define (jan-mili knpc kpc)
+  (say knpc "Glasdrin's militia is currently engaged in Kurpolis and border patrols. "
+       "We are not actively fighting any wars."))
+
+(define (jan-bord knpc kpc)
+  (say knpc "Although we are currently at peace with Trigrave and Green Tower, we must never relax our vigilance.")
+  )
+
+;; Townspeople...
+
+(define jan-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'hail jan-hail)
+       (method 'job  jan-job)
+       (method 'name jan-name)
+
+       (method 'comm jan-comm)
+       (method 'jeff jan-comm)
+       (method 'mili jan-mili)
+       (method 'repl jan-repl)
+       (method 'bord jan-bord)
+       ))
+
+(define (mk-janice)
+  (bind 
+   (kern-mk-char 'ch_janice       ; tag
+                 "Janice"          ; name
+                 sp_human            ; species
+                 oc_warrior          ; occ
+                 s_cloaked_female ; sprite
+                 faction-glasdrin         ; starting alignment
+                 2 1 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 5  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'jan-conv         ; conv
+                 sch_jan           ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 (list t_armor_chain
+                       t_chain_coif
+                       t_sword
+                       ))         ; readied
+   (jan-mk)))
diff --git a/worlds/haxima-1.002/jeffreys.scm b/worlds/haxima-1.002/jeffreys.scm
new file mode 100644 (file)
index 0000000..fde668f
--- /dev/null
@@ -0,0 +1,242 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Glasdrin.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_jeff
+               (list 0  0  gcj-bed      "sleeping")
+               (list 7  0  gs-altar    "idle")
+               (list 8  0  ghg-s6      "eating")
+               (list 9  0  gc-hall     "working")
+               (list 12 0  ghg-s3      "eating")
+               (list 13 0  gc-train    "working")
+               (list 18 0  ghg-s3      "eating")
+               (list 19 0  ghg-hall    "idle")
+               (list 21 0  gcj-bed      "sleeping")
+               )
+
+;; Make another schedule which will be assigned when Jeffreys resigns after the
+;; trial.
+(kern-mk-sched 'sch_jeff_resigned
+               (list 0 0 kun-road "sleeping")
+               (list 9 0 campfire-4 "idle")
+               (list 13 0 cantina-5 "idle")
+               (list 20 0 kun-road "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (jeff-mk) nil)
+               
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Jeffreys is the Commander of the Paladins of Glasdrin.
+;; He lives in Glasdrin, and reports directly to the ruler there,
+;; currently the Stewardess, Victoria.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (jeff-hail knpc kpc)
+  (cond        ((player-stewardess-trial-done?)
+         (say knpc "I want you to know Wanderer, I did not betray the Warritrix. I did not know about the ambush. "
+              "But I knew something was amiss, I should have acted on my suspicions. "
+              "The Commander of Glasdrin must never fail in diligence. "
+              "For that reason, I have resigned my post.")
+         (aside kpc 'ch_ini "Don't pretend innocence, you corrupt old toad. "
+                "Should we ever meet on the field it will be the end of one of us.")
+         (kern-conv-end)
+         )
+        (else
+         (say knpc "[You meet a splendid paladin] Well-met, sir.")
+         )))
+
+(define (jeff-default knpc kpc)
+  (say knpc "I cannot help you with that."))
+
+(define (jeff-name knpc kpc)
+  (say knpc "I am Commander Jeffreys."))
+
+(define (jeff-join knpc kpc)
+  (say knpc "I already have a job."))
+
+(define (jeff-job knpc kpc)
+  (say knpc "I command the paladins of Glasdrin."))
+
+(define (jeff-bye knpc kpc)
+  (say knpc "Fare thee well."))
+
+;; Special
+(define (jeff-comm knpc kpc)
+  (say knpc "I am the highest-ranking official in Glasdrin, "
+       "save the Stewardess. The military arm of Glasdrin reports to me."))
+
+(define (jeff-mili knpc kpc)
+  (say knpc "Glasdrin is unbeatable on land. All citizens of Glasdrin are "
+       "required to serve a tour. Since everyone has received basic training "
+       "they can be called to duty in a crisis."))
+
+(define (jeff-pala knpc kpc)
+  (say knpc "The paladins of Glasdrin are the finest warriors the Shard has "
+       "ever seen. Individually their skills vary, of course, but their "
+       "strength comes from fighting as a unit."))
+
+(define (jeff-skil knpc kpc)
+  (say knpc "Yes, whether they be a raw recruit or the Warritrix herself, "
+       "when fighting with others in a unit the paladins of Glasdrin are "
+       "nigh unbeatable."))
+
+(define (jeff-warr knpc kpc)
+  (cond ((player-found-warritrix?)
+         (if (ask? knpc kpc "[Cough] Yes. Most unfortunate. We all mourn her loss. "
+                   "But to lose her whole squad like that she must have made some error in judgment. "
+                   "Don't you think so?")
+             (say knpc "Yes. It happens to the best of us. Every military leader makes mistakes, "
+                  "and it costs lives. Now I'm afraid I'm very busy. Good day, sir.")
+             (if (ask? knpc kpc "Are you implying that she was led into some kind of trap?")
+                 (say knpc "Ridiculous. I do not have to answer to you. "
+                      "Speak to the Stewardess if you have a complaint. "
+                      "And if you try to make trouble, the guards will expel you from the city. "
+                      "In fact, it might be best if you left now.")
+                 (say knpc "Good. Mistakes happen in war. Sometimes even friends are slain, "
+                      "when they are mistaken for foes. I hope you take care, friend. Good day.")
+                 ))
+         (kern-conv-end)
+         )
+        ((quest-data-assigned? 'questentry-wise)
+         (say knpc "The Warritrix is a living treasure; the most cunning, versatile "
+              "warrior of the age. I've seen her beat men twice her size and "
+              "slay fearsome beasts. At the moment she has been called away on an "
+              "errand.")
+              (quest-data-update 'questentry-warritrix 'assignment 1)
+         )
+        (else
+         (say knpc "The Warritrix is a living treasure; the most cunning, versatile "
+              "warrior of the age. I've seen her beat men twice her size and "
+              "slay fearsome beasts. At the moment she is out on patrol.")
+              (quest-data-update 'questentry-warritrix 'general-loc 1)
+         )
+        ))
+
+(define (jeff-warr-ready subfn)
+       (if (quest-data-assigned? 'questentry-wise)
+               (subfn)
+               (jeff-default knpc kpc)
+               ))
+
+(define (jeff-erra knpc kpc)
+       (jeff-warr-ready (lambda ()
+  (say knpc "[He looks a bit uneasy] Yes, she took a squad to the Lost Halls. "
+       "It's odd that she hasn't reported back yet... "
+       "Normally I would send a search party, "
+       "but at the moment I haven't the troops to spare.")
+      (quest-data-update-with 'questentry-rune-l 'located 1 (quest-notify nil)) 
+      (quest-data-update 'questentry-warritrix 'lost-hall 1)
+       )))
+
+(define (jeff-sear knpc kpc)
+       (jeff-warr-ready (lambda ()
+       (say knpc "[He grows exasperated] I can spare no one to search for the "
+       "Warritrix! Now, if you don't mind, I'm a busy man...")
+  (kern-conv-end)
+  (if (is-player-party-member? ch_ini)
+      (say ch_ini "Something smells rotten in Denmark. "
+           "We've got to find her!"))
+  )))
+
+;; Townspeople...
+(define (jeff-glas knpc kpc)
+  (say knpc "A mighty city, Glasdrin has never fallen to invaders."))
+
+(define (jeff-ange knpc kpc)
+  (say knpc "Angela is a most gracious, hospitable woman."))
+
+(define (jeff-patc knpc kpc)
+  (say knpc "Doc Patch is an experienced medik and head of our hospital."))
+
+(define (jeff-stew knpc kpc)
+  (say knpc "The Stewardess bears the weight of leadership well."))
+
+(define (jeff-ini knpc kpc)
+  (say knpc "Lt. Inago is a natural warrior and a fine officer."))
+
+(define (jeff-jess knpc kpc)
+  (say knpc "Jess is a cheery lass, and a welcome sight at the end of a "
+       "hard day as she pours a glass."))
+
+(define (jeff-ches knpc kpc)
+  (say knpc "We miss his mighty arm in battle, but his weapons and armor "
+       "serve us well, too."))
+
+(define (jeff-lost knpc kpc)
+  (say knpc "The Lost Halls are very dangerous. No place for amateurs. "
+       "I'd advise you to stay away! Now good day, sir!")
+  (kern-conv-end)
+  (if (is-player-party-member? ch_ini)
+       (begin
+      (say ch_ini "Don't worry. I know where to find the Lost Halls. "
+           "We'll need to get a ship and sail to ["
+           (loc-x lost-halls-loc) " "
+           (loc-y lost-halls-loc) "].")
+          (quest-data-update-with 'questentry-rune-l 'know-hall 1 (quest-notify nil))
+          (quest-data-update 'questentry-warritrix 'lost-hall-loc 1)
+          )
+          )
+  )
+
+(define jeff-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default jeff-default)
+       (method 'hail jeff-hail)
+       (method 'bye  jeff-bye)
+       (method 'job  jeff-job)
+       (method 'name jeff-name)
+       (method 'join jeff-join)
+
+       (method 'comm jeff-comm)
+       (method 'jani (lambda (knpc kpc) (say knpc "My assistant Janice is invaluable as a tactician.")))
+       (method 'mili jeff-mili)
+       (method 'pala jeff-pala)
+       (method 'warr jeff-warr)
+       (method 'erra jeff-erra)
+       (method 'glas jeff-glas)
+       (method 'ange jeff-ange)
+       (method 'lost jeff-lost)
+       (method 'patc jeff-patc)
+       (method 'stew jeff-stew)
+       (method 'vict jeff-stew)  ;; A synonym
+       (method 'ini  jeff-ini)
+       (method 'inag jeff-ini)
+       (method 'jess jeff-jess)
+       (method 'ches jeff-ches)
+       ))
+
+(define (mk-jeffreys)
+  (bind 
+   (kern-mk-char 'ch_jeffreys       ; tag
+                 "Jeffreys"          ; name
+                 sp_human            ; species
+                 oc_warrior          ; occ
+                 s_companion_paladin ; sprite
+                 faction-glasdrin         ; starting alignment
+                 2 1 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 5  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'jeff-conv         ; conv
+                 sch_jeff           ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 (list t_armor_chain
+                       t_chain_coif
+                       t_sword
+                       ))         ; readied
+   (jeff-mk)))
diff --git a/worlds/haxima-1.002/jess.scm b/worlds/haxima-1.002/jess.scm
new file mode 100644 (file)
index 0000000..efdc4f4
--- /dev/null
@@ -0,0 +1,171 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Glasdrin.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_jess
+               (list 0  0  gj-bed      "sleeping")
+               (list 7  0  ghg-counter "working")
+               (list 9  0  g-fountain  "idle")
+               (list 10 0  ghg-counter "working")
+               (list 13 0  gc-hall     "idle")
+               (list 14 0  ghg-counter "working")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (jess-mk) (list 'townsman))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Jess is the female proprietress of the Holy Grail tavern in Glasdrin.
+;; Her face is scarred, the result of an encounter with goblins 
+;; when serving as a crossbowman in the Glasdrin militia.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (jess-hail knpc kpc)
+  (if (string=? "working" (kern-obj-get-activity knpc))
+      (say knpc "[You meet an otherwise attractive young woman with a hideous "
+           "scar on one side of her face]. Relax, gentlemen, you've finally "
+           "found the Holy Grail!")
+      (say knpc "[You meet an otherwise attractive young woman with a hideous "
+           "scar on one side of her face]. Nice day, isn't it?")))
+
+(define (jess-default knpc kpc)
+  (say knpc "Hm... I don't know."))
+
+(define (jess-name knpc kpc)
+  (if (working? knpc)
+      (say knpc "I'm Jess, proprieter of this here oasis.")
+      (say knpc "I'm Jess, proprieter of the Holy Grail. "
+           "Come by some time when you're thirsty.")))
+
+(define (jess-join knpc kpc)
+  (say knpc "No thanks, I get enough action throwing out drunks and "
+       "breaking up fights."))
+
+(define (jess-job knpc kpc)
+  (say knpc "I tempt the weak-minded with my wares. Care to see them?")
+  (if (kern-conv-get-yes-no? kpc)
+      (begin
+        (say knpc "[She winks] I thought you would!")
+        (jess-trade knpc kpc))
+      (say knpc "Too bad.")))
+
+(define (jess-bye knpc kpc)
+  (say knpc "So long, come back again!"))
+
+(define jess-catalog
+  (list
+   (list t_food 7  "The paladins love my roast beef.")
+   (list t_beer 12 "Have a grail-ful!")
+   ))
+
+(define jess-merch-msgs
+  (list "Come by the Holy Grail when I'm working. Breakfast is between 7:00AM and 9:00AM, lunch is 10:00AM to 1:00PM and I reopen at 2:00PM until midnight."
+        "Here's a menu!"
+        nil ;; sell
+        nil ;; trade
+        "Enjoy!" ;; sold-something
+        "Well, it beats hard-tack!" ;; sold-nothing
+        nil ;; the rest are nil
+        ))
+
+;; Trade...
+(define (jess-buy knpc kpc) (conv-trade knpc kpc "buy" jess-merch-msgs jess-catalog))
+
+;; Holy Grail
+(define (jess-grai knpc kpc)
+  (say knpc "According to legend, a Wanderer suggested the title. "
+       "It was based on a popular story in his home-world."))
+
+;; Scar
+(define (jess-scar knpc kpc)
+  (say knpc "I got that courtesy of some cave goblins and a guard who "
+       "couldn't stay awake. They ambushed us while we were sleeping, "
+       "I caught the edge of an axe with my cheek, but my helmet took "
+       "the worst of it. Do you like stories of battles?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Everyone in town has at least one. We've all served.")
+      (say knpc "Too bad, because this is the place to hear them.")))
+
+(define (jess-serv knpc kpc)
+  (say knpc "All citizens of Glasdrin must serve a tour of duty. "
+       "I was a crossbowman, my job was to support the heavy armor from "
+       "behind. My outfit served on the eastern marches of the Great Wood."))
+
+(define (jess-wood knpc kpc)
+  (say knpc "The rangers keep things pretty well in hand, but that year "
+       "the cave goblins and trolls were coming out in force."))
+
+;; Townspeople...
+(define (jess-glas knpc kpc)
+  (say knpc "It's a nice enough place, considering its an armed camp."))
+
+(define (jess-ange knpc kpc)
+  (say knpc "A nice lady. Not exactly a fighter, but she does her part."))
+
+(define (jess-patc knpc kpc)
+  (say knpc "Dirty old man! No, I'm just teasing him."))
+
+(define jess-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default jess-default)
+       (method 'hail jess-hail)
+       (method 'bye  jess-bye)
+       (method 'job  jess-job)
+       (method 'name jess-name)
+       (method 'join jess-join)
+       
+       ;; trade
+       (method 'grai jess-grai)
+       (method 'holy jess-grai)
+       (method 'trad jess-buy)
+       (method 'room jess-buy)
+       (method 'buy  jess-buy)
+       (method 'drin jess-buy)
+       (method 'ware jess-buy)
+       (method 'food jess-buy)
+
+       ;; scar
+       (method 'trade jess-buy)
+       (method 'scar  jess-scar)
+       (method 'serv  jess-serv)
+       (method 'wood  jess-wood)
+
+       ;; town & people
+       (method 'glas jess-glas)
+       (method 'ange jess-ange)
+       (method 'patc jess-patc)
+
+       ))
+
+(define (mk-jess)
+  (bind 
+   (kern-mk-char 'ch_jess           ; tag
+                 "Jess"             ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_townswoman        ; sprite
+                 faction-glasdrin         ; starting alignment
+                 0 0 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'jess-conv         ; conv
+                 sch_jess           ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_dagger)))                 ; container
+                 nil                 ; readied
+                 )
+   (jess-mk)))
diff --git a/worlds/haxima-1.002/jewelry.png b/worlds/haxima-1.002/jewelry.png
new file mode 100644 (file)
index 0000000..d0cfedb
Binary files /dev/null and b/worlds/haxima-1.002/jewelry.png differ
diff --git a/worlds/haxima-1.002/jewelry.scm b/worlds/haxima-1.002/jewelry.scm
new file mode 100644 (file)
index 0000000..05cb3b4
--- /dev/null
@@ -0,0 +1,48 @@
+(kern-mk-sprite-set 'ss_jewelry 32 32 2 2 0 0 "jewelry.png")
+
+(kern-mk-sprite 's_skull_ring ss_jewelry 1 0 #f 0)
+
+(mk-quest-obj-type 't_skull_ring "skull ring" s_skull_ring layer-item obj-ifc)
+
+
+(define (skullring-basic-receive kchar questtag)
+       (quest-data-update-with 'questentry-ghertie questtag 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+
+(define (skullring-basic-get kobj kchar questtag)
+       (if (not (null? kobj))
+               (kern-obj-remove kobj)
+       )
+       (skullring-basic-receive kchar questtag)
+       (kobj-get (kern-mk-obj t_skull_ring 1) kchar)
+       )
+
+(define (skullring-m-get kobj kchar)
+       (skullring-basic-get kobj kchar 'ring-meaney)
+       )
+(define skullring-m-ifc
+  (ifc obj-ifc
+       (method 'get skullring-m-get)))
+(mk-quest-obj-type 't_skull_ring_m "skull ring" s_skull_ring layer-item skullring-m-ifc)
+
+(define (skullring-j-get kobj kchar)
+       (skullring-basic-get kobj kchar 'ring-jorn)
+       )
+(define skullring-j-ifc
+  (ifc obj-ifc
+       (method 'get skullring-j-get)))
+(mk-quest-obj-type 't_skull_ring_j "skull ring" s_skull_ring layer-item skullring-j-ifc)
+
+(define (skullring-g-get kobj kchar)
+       (skullring-basic-get kobj kchar 'ring-gholet)
+       )
+(define (skullring-g-receive ktype kchar)
+       (skullring-basic-receive kchar 'ring-gholet)
+       )
+       
+(define skullring-g-ifc
+  (ifc obj-ifc
+       (method 'get skullring-g-get)
+       (method 'receive skullring-g-receive)))
+(mk-quest-obj-type 't_skull_ring_g "skull ring" s_skull_ring layer-item skullring-g-ifc)
+
diff --git a/worlds/haxima-1.002/jim.scm b/worlds/haxima-1.002/jim.scm
new file mode 100644 (file)
index 0000000..c0fb489
--- /dev/null
@@ -0,0 +1,130 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Trigrave"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_jim
+               (list 0  0  trigrave-jims-bed        "sleeping")
+               (list 6  0  trigrave-tavern-table-1a  "eating")
+               (list 7  0  trigrave-forge            "working")
+               (list 12 0  trigrave-tavern-table-1a  "eating")
+               (list 13 0  trigrave-forge            "working")
+               (list 18 0  trigrave-tavern-hall      "idle")
+               (list 22 0  trigrave-jims-bed         "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (jim-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Jim is a merchant, and will trade with the player if he's at work. He's a
+;; tall, wiry blacksmith with a very dry wit. If the town has a leader it would
+;; be him because the other townsfolk respect him and look to him in times of
+;; crises. He isn't interested in being a celebrity, however, and doesn't
+;; exercise any real ambition. He's not interested in adventures and considers
+;; (privately) that adventurers are fools. But he's happy to trade with
+;; them. He drinks hard, and probably had a very wild youth.
+;;----------------------------------------------------------------------------
+(define jim-merch-msgs
+  (list "Come by my shop when I'm open. It's the Iron Works in the northeast corner. I'm open for business from 7:00AM til 6:00PM."
+        "Let me know if you see something that interests you."
+        "I'll buy back some items for salvage."
+        "Let me know if you see something that interests you."
+        "Strike hard, first and for the good, friend."
+        "Maybe some other time."
+        "I can melt down or re-use parts of this."
+        "Fine."
+        "Strike hard, first and for the good, friend."
+        "Fine."
+   ))
+
+(define jim-catalog
+  (list
+   (list t_dagger          40 "This is a good weapon for the non-fighting classes.")
+   (list t_sword           80 "It's not fancy, but note the perfect balance on that sword.")
+   (list t_axe             70 "An axe is necessary if you camp in the wild, but it can be tricky to keep ahold of in a fight.")
+   (list t_mace            75 "The mace is a simple but effective weapon against lightly armoured foes.")
+   
+   (list t_2H_axe         240 "The battle-axe is made for cleaving armour and shields.")
+   (list t_2H_sword       350 "If you are strong enough to wield it, a two-handed sword is an excellent offensive weapon.")
+   
+   (list t_chain_coif     110 "The chain coif will protect your neck from decapitating strokes.")
+   (list t_iron_helm      160 "With an iron helm you can survive a direct hit from a mace.")
+   (list t_armor_chain    300 "Chain armor will turn aside most blades and arrows.")
+   (list t_armor_plate    600 "Although heavy, plate armour will protect you from all but the mightiest blows or armour-piercing tips.")
+   
+   (list t_shield          45 "A shield is vital for close-in combat.")
+   
+   (list t_spiked_helm    150 "The spiked helm is favored by those with a more... direct style.")
+   (list t_spiked_shield  150 "A spiked shield augments the footsoldier's basic thrust-and-push with extra damage.")
+   ))
+
+(define (jim-trade knpc kpc) (conv-trade knpc kpc "trade" jim-merch-msgs jim-catalog))
+
+(define jim-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "I know not.")))
+       (method 'hail (lambda (knpc kpc) (say knpc "Well met.")))
+       (method 'bye (lambda (knpc kpc) (say knpc "Fare well.")))
+       (method 'job 
+               (lambda (knpc kpc) 
+                 (say knpc "I'm the blacksmith of Trigrave. Need something?")
+                            (if (kern-conv-get-yes-no? kpc)
+                                (jim-trade knpc kpc)
+                                (say knpc "Look around all you like."))))
+       (method 'name (lambda (knpc kpc) (say knpc "Folks call me Jim.")))
+       (method 'buy (lambda (knpc kpc) (conv-trade knpc kpc "buy" jim-merch-msgs jim-catalog)))
+       (method 'sell (lambda (knpc kpc) (conv-trade knpc kpc "sell" jim-merch-msgs jim-catalog)))
+       (method 'trad jim-trade)
+       (method 'join (lambda (knpc kpc) 
+                       (say knpc "Here I make my stand, come what may.")))
+
+
+       (method 'chan (lambda (knpc kpc)
+                       (say knpc "Chanticleer the bard frequents the Trigrave "
+                            "tavern. He knows much of the region.")))
+       (method 'char 
+               (lambda (knpc kpc)
+                 (say knpc "The charcoal burner who lives in the woods "
+                      "keeps my forges hot.")))
+       (method 'earl
+               (lambda (knpc kpc)
+                 (say knpc "Earl is the shopkeeper for the general store. "
+                      "He claims he was once a battle-mage.")))
+       (method 'gwen
+               (lambda (knpc kpc)
+                 (say knpc "Gwen is our innkeeper. She is a beautiful but "
+                      "mysterious woman.")))
+       (method 'iron (lambda (knpc kpc)
+                       (say knpc "The hills are loaded with ore, yet so many "
+                            "battles have been fought in this valley that one "
+                            "need not visit them to find scrap.")))
+       (method 'shie
+               (lambda (knpc kpc)
+                 (say knpc "[he gives you a cold look] I have cast away the "
+                      "shield which bears the emblem of Glasdrin. I'll "
+                      "thank you to speak of this no more.")))
+       (method 'thief
+               (lambda (knpc kpc)
+                 (say knpc "I haven't seen anyone odd. But ask Gwen, she speaks to many travelers.")))
+       (method 'trig 
+               (lambda (knpc kpc) 
+                 (say knpc "Trigrave is not much to speak of.")))
+       (method 'wood 
+               (lambda (knpc kpc)
+                 (say knpc "The deep wood is home to beasts and bandits. "
+                      "You'll need short arms and light armour there, "
+                      "for the thicket is a hindrance to heavy arms "
+                      "and ranged weapons.")))
+       
+       ))
diff --git a/worlds/haxima-1.002/joel.scm b/worlds/haxima-1.002/joel.scm
new file mode 100644 (file)
index 0000000..1370094
--- /dev/null
@@ -0,0 +1,133 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define joel-lvl 3)
+(define joel-species sp_human)
+(define joel-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In front of the Gate to Absalot.
+;;----------------------------------------------------------------------------
+(define joel-bed (list 'p_gate_to_absalot 8 9 1 1))
+(define joel-mealplace joel-bed)
+(define joel-workplace (list 'p_gate_to_absalot 7 10 5 5))
+(define joel-leisureplace joel-workplace)
+(kern-mk-sched 'sch_joel
+               (list 0  0 joel-bed          "sleeping")
+               (list 5  0 joel-mealplace    "eating")
+               (list 6  0 joel-workplace    "working")
+               (list 12 0 joel-mealplace    "eating")
+               (list 13 0 joel-workplace    "working")
+               (list 18 0 joel-mealplace    "eating")
+               (list 19 0 joel-leisureplace "idle")
+               (list 21 0 joel-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (joel-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Joel is a simple cowherd, whose stock is grazing in front of
+;; the gates to the destroyed city of Absalot.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (joel-hail knpc kpc)
+  (kern-log-msg "You meet a laconic herder.")
+  (say knpc "Hi")
+  )
+
+(define (joel-default knpc kpc)
+  (say knpc "Don't know, pardner."))
+
+(define (joel-name knpc kpc)
+  (say knpc "Joel."))
+
+(define (joel-join knpc kpc)
+  (say knpc "Nope."))
+
+(define (joel-job knpc kpc)
+  (say knpc "I herd my cows here. Nice and peaceful."))
+
+(define (joel-peac knpc kpc)
+  (say knpc "Yep. This is the old gate to Absalot."))
+
+(define (joel-absa knpc kpc)
+  (say knpc "You're not thinking of going in there, are you?")
+  (if (yes? kpc)
+      (say knpc "Crazy. Theres nasty stuff down there.")
+      (say knpc "Don't blame you.")))
+
+(define (joel-nast knpc kpc)
+  (say knpc "Gazers? Undead? Who knows what else? The place was bad enough before "
+       "the paladins sealed it up and left it to fester."))
+
+(define (joel-fest knpc kpc)
+  (say knpc "Paladins from Glasdrin destroyed Absalot. And when humans get out of the way, "
+       "monsters move in."))
+       
+(define (joel-gaze knpc kpc)
+  (say knpc "Mind-slavers. And whatever they're controlling. "
+       "If you dont watch out you'll wind up their slaves too."))
+          
+(define (joel-unde knpc kpc)
+  (say knpc "Ghosts, skeletons, and I'd rather not know what else."))
+
+(define (joel-bye knpc kpc)
+  (say knpc "So long"))
+
+(define joel-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default joel-default)
+       (method 'hail joel-hail)
+       (method 'bye joel-bye)
+       (method 'job joel-job)
+       (method 'name joel-name)
+       (method 'join joel-join)
+
+       (method 'peac joel-peac)
+       (method 'nice joel-peac)
+       (method 'absa joel-absa)
+       (method 'nast joel-nast)
+       (method 'stuf joel-nast)
+       (method 'mons joel-nast)
+       (method 'fest joel-fest)
+       (method 'pala joel-fest)
+       (method 'unde joel-unde)
+       (method 'gaze joel-gaze)           
+       ))
+
+(define (mk-joel)
+  (bind 
+   (kern-mk-char 
+    'ch_joel           ; tag
+    "Joel"             ; name
+    joel-species         ; species
+    joel-occ              ; occ
+    s_companion_shepherd     ; sprite
+    faction-men      ; starting alignment
+    1 0 1            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    joel-lvl
+    #f               ; dead
+    'joel-conv         ; conv
+    sch_joel           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_staff
+                                                )              ; readied
+    )
+   (joel-mk)))
diff --git a/worlds/haxima-1.002/jones.scm b/worlds/haxima-1.002/jones.scm
new file mode 100644 (file)
index 0000000..9eaab7d
--- /dev/null
@@ -0,0 +1,113 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define jones-lvl 6)
+(define jones-species sp_human)
+(define jones-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the Keep guarding Kurpolis.
+;;----------------------------------------------------------------------------
+(define jones-bed ph-bed1)
+(define jones-mealplace ph-tbl1)
+(define jones-workplace ph-arms)
+(define jones-leisureplace ph-hall)
+(kern-mk-sched 'sch_jones
+               (list 0  0 jones-bed          "sleeping")
+               (list 7  0 jones-mealplace    "eating")
+               (list 8  0 jones-workplace    "working")
+               (list 12 0 jones-mealplace    "eating")
+               (list 13 0 jones-workplace    "working")
+               (list 18 0 jones-mealplace    "eating")
+               (list 19 0 jones-leisureplace "idle")
+               (list 22 0 jones-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (jones-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Jones runs the supply depot for the Glasdrin militia.
+;; He is stationed in the Keep guarding Kurpolis.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (jones-name knpc kpc)
+  (say knpc "Jonesy at yer service."))
+
+(define (jones-job knpc kpc)
+  (say knpc "I run the Supply Depot for the Glasdrin militia. Would you like to buy some supplies?")
+  (if (yes? kpc)
+      (jones-trade knpc kpc)
+      (say knpc "If you ever need any I'll be right here.")))
+
+;; Trade...
+(define jones-merch-msgs
+  (list "Come by the Supply Depot between 9:00AM and 6:00PM."
+        "I keep the basics in stock."
+        nil
+        nil
+        "Are you sure you have enough? You better get some more."
+        "I hope you've got enough, for your sake."
+   ))
+
+(define jones-catalog
+  (list
+   (list t_arrow        1 "Down here you'll go through arrows like a troll goes through grog!")
+   (list t_bolt         1 "You can run out of bolts in the blink of a gazer's eye!")
+   (list t_oil          6 "Yes, stock up on plenty of that flaming oil. It gets worse deeper down.")
+   (list t_torch        6 "You don't want to run out of torches down here!")
+   (list t_heal_potion 23 "Yes, they are spendy, but healing potions are hard to get and critical to have.")
+   (list t_mana_potion 23 "You better buy extra mana potions. Your mages will be working overtime.")
+   (list t_food        10 "There's nothing worse than runnning out of food when you're lost in the lower levels.")
+   ))
+
+(define (jones-trade knpc kpc) (conv-trade knpc kpc "buy" jones-merch-msgs jones-catalog))
+
+;; Quest-related
+
+(define jones-conv
+  (ifc kurpolis-conv
+
+       ;; basics
+       (method 'job jones-job)
+       (method 'name jones-name)
+       
+       ;; trade
+       (method 'trad jones-trade)
+       (method 'buy jones-trade)
+
+       ))
+
+(define (mk-jones)
+  (bind 
+   (kern-mk-char 
+    'ch_jones        ; tag
+    "Jones"             ; name
+    jones-species         ; species
+    jones-occ              ; occ
+    s_townsman     ; sprite
+    faction-men      ; starting alignment
+    2 0 0            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    jones-lvl
+    #f               ; dead
+    'jones-conv         ; conv
+    sch_jones           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_axe
+               t_armor_chain)              ; readied
+    )
+   (jones-mk)))
diff --git a/worlds/haxima-1.002/jorn.scm b/worlds/haxima-1.002/jorn.scm
new file mode 100644 (file)
index 0000000..151c585
--- /dev/null
@@ -0,0 +1,151 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define jorn-lvl 5)
+(define jorn-species sp_human)
+(define jorn-occ oc_wrogue)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Green Tower.
+;;----------------------------------------------------------------------------
+(define jorn-bed gt-jorn-bed)
+(define jorn-mealplace gt-ws-tbl1)
+(define jorn-workplace gt-jorn-hut)
+(define jorn-leisureplace gt-ws-hall)
+(kern-mk-sched 'sch_jorn
+               (list 0  0 jorn-bed          "sleeping")
+               (list 11 0 jorn-mealplace    "eating")
+               (list 12 0 jorn-workplace    "working")
+               (list 18 0 jorn-mealplace    "eating")
+               (list 19 0 jorn-leisureplace "idle")
+               (list 24 0 jorn-workplace    "working")               
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (jorn-mk) nil)
+
+(define (jorn-on-death knpc)
+       (kern-obj-put-at (kern-mk-obj t_skull_ring_j 1) (kern-obj-get-location knpc))
+       )
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Jorn is a bravo and former pirate, currently living in Green Tower.
+;; He was once a member of the crew of the Merciful Death, 
+;; and is sought for vengeance by the ghost Ghertie.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (jorn-hail knpc kpc)
+  (say knpc "[You meet a rough-looking, surly man] What do you want?"))
+
+(define (jorn-default knpc kpc)
+  (say knpc "Go bother someone else."))
+
+(define (jorn-name knpc kpc)
+  (say knpc "I'm Jorn. Heard of me?")
+   (quest-data-update 'questentry-ghertie 'jorn-loc 1)
+  (if (yes? kpc)
+      (say knpc "Good, then you've been warned.")
+      (say knpc "Too bad. Don't make me make an example out of you.")))
+
+(define (jorn-join knpc kpc)
+  (say knpc "[He laughs coarsely]"))
+
+(define (jorn-job knpc kpc)
+  (say knpc "None of your business."))
+
+(define (jorn-bye knpc kpc)
+  (say knpc "[He ignores your departure]"))
+
+
+;; Town & Townspeople
+
+;; Quest-related
+(define (jorn-pira knpc kpc)
+  (say knpc "You're starting to get on my nerves."))
+
+(define (jorn-ring knpc kpc)
+      (quest-data-update 'questentry-ghertie 'jorn-loc 1)
+        (say knpc "[He gives you a cold look] What of it? Do you want it?")
+        (if (no? kpc)
+            (say knpc "Then quit staring at it.")
+            (begin
+              (say knpc "Well, you're going to have to cut it off my finger "
+                   "to get it. What do you think of that? Are you ready to "
+                   "try and cut it off my finger?")
+              (if (no? kpc)
+                  (say knpc "[He sneers] I didn't think so.")
+                  (begin
+                    (say knpc "[With a roar, too fast for you to see, "
+                         "he draws his sword and thrusts at you in the same "
+                         "motion!]")
+                    (kern-being-set-base-faction knpc faction-outlaw)
+                    (kern-conv-end))))))
+
+(define jorn-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default jorn-default)
+       (method 'hail jorn-hail)
+       (method 'bye  jorn-bye)
+       (method 'job  jorn-job)
+       (method 'name jorn-name)
+       (method 'join jorn-join)
+       
+       ;; other responses
+       (method 'pira jorn-pira)
+       (method 'gher jorn-pira)
+       (method 'merc jorn-pira)
+       (method 'ring jorn-ring)
+
+       ))
+
+(define (mk-jorn)
+       (let ((knpc
+               (kern-mk-char 
+                       'ch_jorn           ; tag
+                       "Jorn"             ; name
+                       jorn-species     ; species
+                       jorn-occ         ; occ
+                       s_brigand        ; sprite
+                       faction-men      ; starting alignment
+                       2 0 1            ; str/int/dex
+                       0 0              ; hp mod/mult
+                       0 0              ; mp mod/mult
+                       max-health ; hp
+                       -1                ; xp
+                       max-health ; mp
+                       0
+                       jorn-lvl
+                       #f               ; dead
+                       'jorn-conv       ; conv
+                       sch_jorn           ; sched
+                       'spell-sword-ai  ; special ai
+
+                       ;; container
+                       (mk-inventory (list
+                               (list 1 t_sword_2)
+                               (list 1 t_dagger_4)
+                               (list 1 t_armor_leather_2)
+                               (list 1 t_leather_helm_2)
+                               (list 67 t_gold_coins)
+                               (list 3 t_picklock)
+                               (list 3 t_heal_potion)
+                       ))
+                       nil              ; readied
+               )))
+               (bind knpc  (jorn-mk))
+               (kern-char-force-drop knpc #t)
+               (kern-char-arm-self knpc)
+               (kern-obj-add-effect knpc 
+                       ef_generic_death
+                       'jorn-on-death)
+               knpc
+       ))
diff --git a/worlds/haxima-1.002/kalcifax.scm b/worlds/haxima-1.002/kalcifax.scm
new file mode 100644 (file)
index 0000000..d06fac8
--- /dev/null
@@ -0,0 +1,147 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define kalc-lvl 6)
+(define kalc-species sp_human)
+(define kalc-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; Kalcifax travels (notionally by the moon gates) 
+;; to many places, carrying messages and such.
+;;----------------------------------------------------------------------------
+(define kalc-bed cheerful-bed-2)
+(define kalc-mealplace )
+(define kalc-workplace )
+(define kalc-leisureplace )
+(kern-mk-sched 'sch_kalc
+               (list 0  0 kalc-bed          "sleeping")
+               (list 7  0 bilge-water-seat-5 "eating")
+               (list 8  0 enchtwr-hall       "idle")
+               (list 11 0 g-fountain         "idle")
+               (list 12 0 ghg-s6             "eating")
+               (list 13 0 eng-workshop       "idle")
+               (list 16 0 trigrave-tavern-hall "idle")
+               (list 17 0 trigrave-tavern-table-3b "eating")
+               (list 19 0 gt-ws-hall           "idle")
+               (list 23 0 kalc-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (kalc-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Kalcifax is a female wizard with considerable knowledge of the moon gates.
+;; She travels to many places (notionally by use of the gates),
+;; carrying messages and such.
+;; Kalcifax is a potential party member.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (kalc-hail knpc kpc)
+  (meet "You meet a cute wizard.")
+  (say knpc "Well met, fellow traveler.")
+  )
+
+(define (kalc-name knpc kpc)
+  (say knpc "I'm Kalcifax. And you are...?")
+  (kern-conv-get-reply kpc)
+  (say knpc "It's nice to meet you.")
+  )
+
+(define (kalc-join knpc kpc)
+  (if (is-player-party-member? knpc)
+      (say knpc "I've already joined you!")
+      (begin
+        (say knpc "Ok, this will be fun!")
+        (join-player knpc)
+        (kern-conv-end)
+        )
+  ))
+
+(define (kalc-job knpc kpc)
+  (say knpc "I travel the gates, running errands for people.")
+  )
+
+(define (kalc-bye knpc kpc)
+  (say knpc "I'm sure we'll meet again!")
+  )
+
+(define (kalc-gate knpc kpc)
+  (say knpc "The moongates! Do you know how they work?")
+  (if (yes? kpc)
+      (say knpc "I don't know why more people don't do it.")
+      (say knpc "The phase of Lumis decides where you can enter, "
+           "the phase of Ord decides where you emerge!")))
+
+(define (kalc-lumi knpc kpc)
+  (say knpc "Lumis is the yellow slow-moving moon."))
+
+(define (kalc-ord knpc kpc)
+  (say knpc "Ord is the blue fast-moving moon."))
+
+(define (kalc-engi knpc kpc)
+  (say knpc "I'm one of the only people who ever visits the Engineer! "
+       "You have to use a moongate to get to his place. "
+       "Enter when Ord has waxed almost full."))
+
+(define (kalc-peop knpc kpc)
+  (say knpc "I deliver messages and packages for the Engineer, the Enchanter, city officials. "
+       "Anyone who needs something delivered safely and fast, and is willing to pay!"))
+
+(define (kalc-pay knpc kpc)
+  (say knpc "I do pretty good."))
+
+(define kalc-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'hail kalc-hail)
+       (method 'bye  kalc-bye)
+       (method 'job  kalc-job)
+       (method 'name kalc-name)
+       (method 'join kalc-join)
+       
+       (method 'gate kalc-gate)
+       (method 'lumi kalc-lumi)
+       (method 'ord  kalc-ord)
+       (method 'engi kalc-engi)
+       (method 'peop kalc-peop)
+       (method 'erra kalc-peop)
+       (method 'pay  kalc-pay)
+       ))
+
+(define (mk-kalcifax)
+  (bind 
+   (kern-mk-char 
+    'ch_kalc           ; tag
+    "Kalcifax"             ; name
+    kalc-species         ; species
+    kalc-occ              ; occ
+    s_blue_wizard
+    faction-men      ; starting alignment
+    0 7 0            ; str/int/dex
+    (/ pc-hp-off 2)  ; hp bonus
+    (/ pc-hp-gain 2) ; hp per-level bonus
+    pc-mp-off        ; mp bonus
+    pc-mp-gain       ; mp per-level bonus
+    max-health ; hp
+    -1  ; xp
+    max-health ; mp
+    0
+    kalc-lvl
+    #f               ; dead
+    'kalc-conv         ; conv
+    sch_kalc           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list            ;; readied
+     t_staff
+     )
+    )
+   (kalc-mk)))
diff --git a/worlds/haxima-1.002/kama.scm b/worlds/haxima-1.002/kama.scm
new file mode 100644 (file)
index 0000000..953e5f9
--- /dev/null
@@ -0,0 +1,249 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define kama-lvl 4)
+(define kama-species sp_forest_goblin)
+(define kama-occ oc_wrogue)
+(define kama-exit-x 6)
+(define kama-exit-y 2)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In a prison cell in the dungeons below Green Tower.
+;;----------------------------------------------------------------------------
+(define kama-cell gtl-cell1)
+(kern-mk-sched 'sch_kama
+               (list 0  0 kama-cell        "sleeping")
+               (list 7  0 kama-cell        "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (kama-mk jail-door-tag) (list #f #f jail-door-tag))
+(define (kama-gave-food? gob) (car gob))
+(define (kama-gave-food! gob) (set-car! gob #t))
+(define (kama-joined-once? gob) (cadr gob))
+(define (kama-joined-once! gob) (set-car! (cdr gob) #t))
+(define (kama-get-jail-door-tag gob) (caddr gob))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Kama is a male Forest Goblin ranger, currently imprisoned below Green Tower.
+;; A friend of Gen, Kama was enroute to a meeting, and detained due to 
+;; some misadventure.
+;; Kama is a potential party member, 
+;; if the player can learn a bit of the Goblin language.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (kama-default knpc kpc)
+  (say knpc "[no response]"))
+
+(define (kama-hail knpc kpc)
+  (meet "You meet a calm goblin who regards you with a fearless, calculating gaze.")
+  (if (kama-gave-food? (gob knpc))
+      (say knpc "Bonaha.")
+      (say knpc "Nuki?")
+      ))
+
+(define (kama-bye knpc kpc)
+  (say knpc "[his expression never changes]"))
+
+;; No == Name
+(define (kama-no knpc kpc)
+  (if (kama-gave-food? (gob knpc))
+      (say knpc "[He points to himself] Kama.")
+      (kama-default knpc kpc)))
+
+;; Me == Job
+(define (kama-me knpc kpc)
+  (if (not (kama-gave-food? (gob knpc)))
+      (kama-default knpc kpc)
+      (begin
+        (say knpc "Ninto. [He points to you] Zuto?")
+        (if (yes? kpc)
+            (say knpc "[He nods]")
+            (say knpc "[He chuckles as if he disbelieves you]")))))
+
+;; Jo == Join
+(define (kama-jo knpc kpc)
+  (define (exit-point)
+    (mk-loc (kobj-place knpc)
+            kama-exit-x
+            kama-exit-y))
+  (define (door-still-locked?)
+    (let ((kdoor (eval (kama-get-jail-door-tag (gob knpc)))))
+      (cond ((null? kdoor) (error "Kama's door tag is undefined!") #t)
+            (else
+             (let ((gob (kobj-gob kdoor)))
+               (or (door-locked? gob)
+                   (door-magic-locked? gob)))))))
+  (define (rejoin)
+    (say knpc "Ha! Iki!")
+    (join-player knpc)
+    (kern-conv-end)
+    )
+  (define (join-first-time)    
+    (say knpc "Hajo! Bona ka ruka!")
+         (say knpc "[On the ground, he scratches what looks to be a map of the Great Forest area. Where the southern edge of the forest meets the eastern mountains, he marks an X several times for emphasis.]")
+         (quest-data-update-with 'questentry-rune-f 'angriss 1 (quest-notify nil))
+    (kama-joined-once! (gob knpc))
+    (join-player knpc)
+    ;; Improve the player's relations with forest goblins
+    (kern-dtable-inc faction-player faction-forest-goblin)
+    (kern-dtable-inc faction-player faction-forest-goblin)
+    (kern-conv-end)
+    )
+  (if (is-player-party-member? knpc)
+      (say knpc "[He looks confused] Ha...")
+      (if (kama-joined-once? (gob knpc))
+          (rejoin)
+          (if (not (kama-gave-food? (gob knpc)))
+              (kama-default knpc kpc)
+              (if (door-still-locked?)
+                  (say knpc "[He points to the cell door and shrugs, maybe if you opened it...]")
+                  (join-first-time)
+                  )))))
+
+(define (kama-food knpc kpc)
+  (kern-log-msg "[Do you give him some food?]")
+  (define (no-food)
+    (say knpc "[He grunts and turns away]")
+    (kern-conv-end))
+  (define (yes-food)
+    (kama-gave-food! (gob knpc))
+    (say knpc "[He gobbles it down hungrily and smacks his lips] "
+         "Ha nuki! [He points to you] Bonaha."))
+  (if (yes? kpc)
+      (if (> (get-food-donation knpc kpc) 0)
+          (yes-food)
+          (no-food))
+      (no-food)))
+          
+(define (kama-rune knpc kpc)
+  (if (not (kama-gave-food? (gob knpc)))
+      (kama-default knpc kpc)
+      (if (any-in-inventory? kpc rune-types)
+          (say knpc "[You show him a Rune. He nods uneasily] Ruka.")
+          (say knpc "[He looks confused as you try to describe a Rune]"))))
+
+;; Ruka == Rune
+;; Having a goblin spout out *sextant coordinates* is just daft. Changing to something descriptive
+;; Maybe for the repeat, give a pointed direction based on the parties location on the worldmap? "He points south" or whatever direction is appropriate
+(define (kama-ruka knpc kpc)
+  (if (kama-joined-once? (gob knpc))
+               (begin
+             (say knpc "Iki ruka.")
+         (say knpc "[On the ground, he scratches what looks to be a map of the Great Forest area. Where the southern edge of the forest meets the eastern mountains, he marks an X several times for emphasis.]")
+         (quest-data-update-with 'questentry-rune-f 'angriss 1 (quest-notify nil))
+       )
+      (begin
+        (say knpc "[In the dust on the cell floor he draws a circle with jointed legs. A spider. He then points to you, himself, and then he scuffs out the spider.]")
+        (prompt-for-key)
+        (say knpc "[You get the impression he is proposing an alliance with you against the spider, or whatever it is.]"))))
+
+;; King Clovis (leader of the human forces in the war against the Goblins, one generation ago.
+(define (kama-clov knpc kpc)
+  (if (not (kama-gave-food? (gob knpc)))
+      (kama-default knpc kpc)  
+      (say knpc "[He looks puzzled at first, but then nods] Ruka ka choto.")))
+
+(define (kama-leav knpc kpc)
+  (if (is-player-party-member? knpc)
+      (begin
+        (say knpc "Kama tujo?")
+        (if (yes? kpc)
+            (begin
+              (if (kern-char-leave-player knpc)
+                  (begin
+                    (say knpc "Kama iki")
+                    (kern-conv-end))
+                  (say knpc "Kama tu iki")))
+            (kern-log-msg "[He looks relieved]")))
+      (kern-log-msg "[He looks confused]")))
+
+;; Shakespeare
+(define (kama-zukakiguru knpc kpc)
+  (begin
+    (say knpc "Ha!  Zukakiguru!")
+    (aside kpc 'ch_gen "We share a common interest, you see.")
+    (say knpc "[He looks at your puzzled expression, and tries again, speaking slowly.] Zu-Ka Ki-Gi-Ru, Choguha Zuluma: Nu Hameluto!")
+    (aside kpc 'ch_gen "Imagine my astonishment, when I learned of the true author!")
+    ))
+
+;; Hameluto == Good/yes/skillful, Destiny change individual (Prince Hamlet)
+(define (kama-hameluto knpc kpc)
+  (begin
+  (say knpc "Hameluto?  Ha!  [Kama changes expression, and then again addresses you, with a serious aspect.]")
+  (aside kpc 'ch_gen "You are in for a treat, to hear it in the original! [Gen watches with devoted interest.]")
+
+  (say knpc "Nuboda? Tuboda? Ehgulu!")
+  (aside kpc 'ch_gen "To be, or not to be.  That is the question!")
+
+  (say knpc "Bogu Hahime, Natuda, Kamana, Rulumada?")
+  (aside kpc 'ch_gen "Whether 'tis nobler in the mind, to suffer the slings and arrows of outrageous fortune?")
+
+  (say knpc "Eh, Bomeka Darutu, Ikikacho, Katucho!")
+  (aside kpc 'ch_gen "Or to take arms against a sea of troubles, and by opposing end them?")
+
+  (say knpc "[He seems prepared to go on at some length, do you wish to listen to the entire recital?]")
+  (if (yes? kpc)
+      (say knpc "[You listen in amazement, for quite some time.]")
+      (say knpc "Bona iki?  Ha!  [He ceases, seemingly content to wait for a more opportune moment.]")
+      )
+  (aside kpc 'ch_gen "The essence of the play comes through more clearly in the original, don't you think?")
+  ))
+
+(define kama-conv
+  (ifc nil
+       (method 'default kama-default)
+       (method 'hail kama-hail)
+       (method 'bye  kama-bye)
+       (method 'leav kama-leav)
+
+       (method 'no   kama-no)
+       (method 'me   kama-me)
+       (method 'jo   kama-jo)
+       (method 'food kama-food)
+       (method 'rune kama-rune)
+       (method 'ruka kama-ruka)
+       (method 'clov kama-clov)
+
+       (method 'shak kama-zukakiguru) ;; synonym
+       (method 'bard kama-zukakiguru) ;; synonym
+       (method 'zuka kama-zukakiguru)
+
+       (method 'haml kama-hameluto) ;; synonym
+       (method 'hame kama-hameluto)
+    ))
+
+(define (mk-kama jail-door-tag)
+  (bind 
+    (kern-mk-char 
+     'ch_kama           ; tag
+     "Kama"             ; name
+     kama-species         ; species
+     kama-occ              ; occ
+     s_fgob_civilian  ; sprite
+     faction-men      ; starting alignment
+     2 0 10            ; str/int/dex
+     pc-hp-off  ; hp bonus
+     pc-hp-gain ; hp per-level bonus
+     0 ; mp off
+     0 ; mp gain
+     max-health ; hp
+     -1                   ; xp
+     max-health ; mp
+     0
+     kama-lvl
+     #f               ; dead
+     'kama-conv         ; conv
+     sch_kama           ; sched
+     nil              ; special ai
+     nil              ; container
+     nil              ; readied
+     )
+   (kama-mk jail-door-tag)))
diff --git a/worlds/haxima-1.002/kathryn.scm b/worlds/haxima-1.002/kathryn.scm
new file mode 100644 (file)
index 0000000..51282a2
--- /dev/null
@@ -0,0 +1,251 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define kathryn-start-lvl  6)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Bole.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_kathryn
+               (list 0  0  bole-bed-kathryn "sleeping")
+               (list 9  0  bole-table-1 "eating")
+               (list 10 0  bole-courtyard   "idle")
+               (list 12 0  bole-table-1 "eating")
+               (list 13 0  bole-dining-hall "idle")
+               (list 18 0  bole-table-1 "eating")
+               (list 19 0  bole-dining-hall "idle")
+               (list 23 0  bole-bed-kathryn "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (kathryn-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Kathryn is a female mercenary wizard, currently in Bole on a mission
+;; to retrieve the Rune of Knowledge from the thief (Mouse) contracted to 
+;; purloin it from the Enchanter...and ensure he tells no tales.
+;; She is manipulative and ruthless.
+;; 
+;; Kathryn is a potential party member (and an eventual betrayer).
+;; She is accompanied by the brute Thud, who will join the party if she does.
+;;----------------------------------------------------------------------------
+(define (kathryn-hail knpc kpc)
+  (say knpc "[You meet a lovely woman who regards you with contempt]. Yes?"))
+
+(define (kathryn-default knpc kpc)
+  (say knpc "[She studiously ignores you]"))
+
+(define (kathryn-name knpc kpc)
+  (say knpc "I don't give my name to vagabonds. Say, why don't you go PUMP "
+       "one of the locals for information? I saw some farm animals on the "
+       "way in..."))
+
+(define (kathryn-join knpc kpc)
+  (say knpc "[She chokes with laughter]"))
+
+(define (kathryn-job knpc kpc)
+  (say knpc "[Sneering] I'm a nun. Blowjobs are 500 gold."))
+
+
+(define (kathryn-blowjob knpc kpc)
+  (say knpc "It's called SARCASM. Beat it, creep."))
+
+(define (kathryn-clients knpc kpc)
+  (say knpc "My clients prefer to remain anonymous. All you need to know is "
+       "that you don't want to piss them off."))
+
+(define (kathryn-things knpc kpc)
+  (say knpc "I'm afraid a thug like you wouldn't understand."))
+
+(define (kathryn-thief knpc kpc)
+  (say knpc "[She gives you a cunning look] You know, perhaps we can help "
+       "each other. I came here on behalf of my clients to purchase an item "
+       "in good faith from an anonymous seller."))
+
+(define (kathryn-seller knpc kpc)
+  (say knpc "Imagine my shock when I discovered the item was stolen! "
+       "Of course, I demanded that he hand over the item immediately so I "
+       "could return it to its rightful owner. No sooner did I make my "
+       "intentions clear when he vanished before my eyes!"))
+
+(define (kathryn-vanish knpc kpc)
+  (say knpc "Poof! Gone! The villian must have a ring of invisibility. "
+       "Thud and I have been searching for him everywhere."))
+
+(define (kathryn-search knpc kpc)
+  (define (do-join)
+    (say knpc "Excellent! Let's see if anyone around here knows about a thief.")
+    (if (in-inventory? knpc t_wis_quas_scroll)
+        (begin
+          (say knpc "Oh, this scroll may come in handy. "
+               "You take it, I really don't understand these magical "
+               "thingies very well.")    
+          (kern-obj-remove-from-inventory knpc t_wis_quas_scroll 1)
+          (kern-obj-add-to-inventory kpc t_wis_quas_scroll 1)))
+    (kern-char-join-player knpc)
+    (if (and (defined? 'ch_thud)
+             (is-alive? ch_thud))
+        (begin
+          (say knpc "You won't mind if my cousin Thud joins us. "
+               "He's really such a child, and quite helpless without me.")
+          (kern-char-join-player ch_thud)))
+    (kern-conv-end))
+  (say knpc "It seems we have a common goal. Join us, and when we catch the "
+       "villian we'll all return the item. You can keep any reward. "
+       "Knowing that we have done the right thing will "
+       "be enough for me and Thud. What do you say, tough guy, will you join "
+       "us?")
+  (if (kern-conv-get-yes-no? kpc)
+      (do-join)
+      (begin
+        (say knpc "[She becomes distressed] Oh, please won't you help me! "
+             "My masters are powerful and cruel! If I don't return with the "
+             "item they seek there will be nowhere I can hide in this life "
+             "or the next! Won't you please join me?")
+        (if (kern-conv-get-yes-no? kpc)
+            (do-join)
+            (begin
+              (say knpc "[She leans close with parted lips and lidded eyes] "
+                   "Okay, tough guy, you win. I don't want the silly item. "
+                   "I just find you irresistible. Let me come with you, "
+                   "pretty-please? I can be oh... so... grateful...")
+              (if (kern-conv-get-yes-no? kpc)
+                  (do-join)
+                  (say knpc "[She turns red and shrieks with rage] Fool! "
+                       "You have no idea who you are dealing with! What you "
+                       "seek draws the gaze of the darkest wizards in the "
+                       "land! That thief will know eternal torment when we "
+                       "catch him! And YOU HAD BETTER STAY OUT OF OUR WAY!")
+                  (kern-conv-end)))))))
+
+(define (kathryn-tavern knpc kpc)
+  (say knpc "Nice place. If you're a cockroach."))
+
+(define (kathryn-companion knpc kpc)
+  (say knpc "Thud? He's my... cousin."))
+
+(define (kathryn-cousin knpc kpc)
+  (say knpc "A DISTANT cousin."))
+
+(define (kathryn-bill knpc kpc)
+  (say knpc "The village idiot? He's probably out using his tool in the "
+       "forest. Why don't you go give him a hand?"))
+
+(define (kathryn-hackle knpc kpc)
+  (say knpc "Crazy bitch? Lives across the creek? I'm afraid she can't cure "
+       "ugly. Sorry."))
+
+(define (kathryn-may knpc kpc)
+  (say knpc "The innkeeper? Nosy old crone. Obviously you don't have money, "
+       "but if you did I'd warn you to sleep with it under your pillow."))
+
+(define (kathryn-melvin knpc kpc)
+  (say knpc "The cook? A dirty old man and a drunk."))
+
+(define (kathryn-sorceress knpc kpc)
+  (say knpc "[She covers her mouth in mock fright] Ooh! You guessed my dirty "
+       "little secret! Now beat it or I'll use you as a torch."))
+
+(define (kathryn-scro knpc kpc)
+  (if (is-player-party-member? knpc)
+      (say knpc "But I already gave you the only one I had. "
+           "I don't even know where I got it!")
+      (say knpc "A scroll? [She laughs] Shall I turn out my pockets for you? "
+           "Mind your own business.")))
+
+
+(define kathryn-conv
+  (ifc nil
+       (method 'default kathryn-default)
+       (method 'hail kathryn-hail)
+       (method 'bye  (lambda (knpc kpc) (say knpc "Good riddance.")))
+       (method 'job  kathryn-job)
+       (method 'name kathryn-name)
+       (method 'join kathryn-join)
+
+       (method 'blow kathryn-blowjob)
+       (method 'bill kathryn-bill)
+       (method 'clie kathryn-clients)
+       (method 'comp kathryn-companion)
+       (method 'cous kathryn-cousin)
+       (method 'fait kathryn-seller)
+       (method 'hack kathryn-hackle)
+       (method 'item kathryn-seller)
+       (method 'inn  kathryn-tavern)
+       (method 'may  kathryn-may)
+       (method 'meet kathryn-thief)
+       (method 'melv kathryn-melvin)
+       (method 'nun  kathryn-blowjob)
+       (method 'ring kathryn-search)
+       (method 'sear kathryn-search)
+       (method 'sell kathryn-seller)
+       (method 'sorc kathryn-sorceress)
+       (method 'tave kathryn-tavern)
+       (method 'thud kathryn-companion)
+       (method 'thie kathryn-thief)
+       (method 'vani kathryn-vanish)
+       (method 'vill kathryn-search)
+       (method 'scro kathryn-scro)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-kathryn)
+  (bind 
+   (kern-char-force-drop
+    (kern-char-arm-self
+     (kern-mk-char 
+      'ch_kathryn ;;..tag
+      "Kathryn" ;;....name
+      sp_human ;;.....species
+      oc_wizard ;;....occupation
+      s_wizard ;;.....sprite
+      faction-men ;;..faction
+      0 ;;............custom strength modifier
+      4 ;;............custom intelligence modifier
+      0 ;;............custom dexterity modifier
+      2 ;;............custom base hp modifier
+      1 ;;............custom hp multiplier (per-level)
+      4 ;;............custom base mp modifier
+      2 ;;............custom mp multiplier (per-level)
+      max-health ;; current hit points
+      -1  ;;...........current experience points
+      max-health ;; current magic points
+      0
+      kathryn-start-lvl  ;;..current level
+      #f ;;...........dead?
+      'kathryn-conv ;;conversation (optional)
+      sch_kathryn ;;..schedule (optional)
+      'spell-sword-ai ;;...custom ai (optional)
+      ;;..............container (and contents)
+      (mk-inventory
+       (list
+        (list 1 t_kathryns_letter)
+        (list 100 t_gold_coins)
+        (list 5 sulphorous_ash )
+        (list 5 ginseng )
+        (list 5 garlic )
+        (list 3 spider_silk )
+        (list 3 blood_moss )
+        (list 2 black_pearl )
+        (list 1 nightshade )
+        (list 1 mandrake )
+        (list 1 t_wis_quas_scroll)
+        ))
+      ;;..............readied arms (in addition to the container contents)
+      (list
+       t_staff
+       )
+      nil ;;..........hooks in effect
+      ))
+    #t)
+   (kathryn-mk)))
diff --git a/worlds/haxima-1.002/keep.scm b/worlds/haxima-1.002/keep.scm
new file mode 100644 (file)
index 0000000..bab2869
--- /dev/null
@@ -0,0 +1,272 @@
+(kern-load "anne.scm")
+(kern-load "jones.scm")
+(kern-load "alex.scm")
+
+(mk-dungeon-room
+ 'p_great_hall "Great Hall"
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx x! xx xx xx xx xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, xx xx ,, cc cc cc ,, xx xx ,, ,, ,, ,, xx "
+  "x! ,, ,, ,, ,, xx x! ,, cc cc cc ,, x! xx ,, ,, ,, ,, x! "
+  ",, ,, ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, ,, ,, "
+  "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+  "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+  "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc "
+  ",, ,, ,, ,, ,, ,, ,, ,, cc cc cc ,, ,, ,, ,, ,, ,, ,, ,, "
+  "x! ,, ,, ,, ,, xx x! ,, cc cc cc ,, x! xx ,, ,, ,, ,, x! "
+  "xx ,, ,, ,, ,, xx xx ,, cc cc cc ,, xx xx ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+
+ (put (mk-ladder-down 'p_pools 9 9) 9 6)
+
+  ;; secret wall mech
+  (put (mk-hidden-mech) 13 0)
+  (put (mk-disg-lvr 'gh_wall 's_wall_torch) 13 0)
+  (put (kern-tag 'gh_wall 
+                 (mk-tblitter 'p_great_hall
+                              8
+                              0
+                              3
+                              1
+                              'm_hall_section))
+       0
+       0)
+                                     
+  ;; militia
+  (put (spawn-pt 'halberdier) 8 8)
+  (put (spawn-pt 'halberdier) 8 10)
+  (put (spawn-pt 'crossbowman) 6 8)
+  (put (spawn-pt 'medik) 7 9)
+  (put (spawn-pt 'crossbowman) 6 10)
+
+  ;; death knights
+  (put (spawn-pt 'death-knight) 10 8)
+  (put (spawn-pt 'death-knight) 10 9)
+  (put (spawn-pt 'death-knight) 10 10)
+  (put (spawn-pt 'warlock)      12 9)
+
+  ;; skeletons
+  (put (spawn-pt 'skeletal-warrior) 9 13)
+  (put (spawn-pt 'skeletal-spear-thrower) 10 14)
+  )
+
+(mk-place-music p_great_hall 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_paladins_hold "Paladin's Hold"
+ (list
+  "rn rn xx xx xx rn rn rn rn xx xx xx xx && xx xx xx xx xx "
+  "rn xx xx ,, xx xx rn rn xx x! ,, ,, ,, ,, ,, ,, ,, x! xx "
+  "xx xx ,, ,, ,, xx x! xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, [[ @@ @@ @@ ]] ,, ,, xx "
+  "xx xx ,, ,, ,, xx ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "rn xx xx xx xx xx ,, xx xx x! ,, ,, ,, ,, ,, ,, ,, x! xx "
+  "rn rn xx xx xx xx ,, xx xx xx xx xx xx xx xx xx xx xx xx "
+  "rn rn xx x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, "
+  "rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, "
+  "rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  "rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, "
+  "rn rn xx x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! .. ,, ,, ,, "
+  "xx xx xx xx xx xx xx xx ,, xx xx xx xx xx xx xx xx xx xx "
+  "xx .A .R .M .S xx xx xx ,, xx xx xx xx .M .E .D .I .K xx "
+  "xx ,, ,, ,, ,, x! ,, ,, ,, ,, ,, ,, sH ,, ,, ,, ,, ,, xx "
+  "x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! "
+  "xx ,, ,, ,, ,, sA ,, ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, xx xx xx ,, xx xx xx xx ,, ,, ,, ,, ,, xx "
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+ (put (kern-tag 'php1 (mk-portcullis)) 14 9)
+ (put (mk-clock) 3 1) 
+ (put (mk-door) 5 15)
+ (put (mk-door) 12 15)
+ (put (mk-bed) 13 17)
+ (put (mk-bed) 15 17)
+ (put (mk-bed) 17 17)
+ (put (mk-bed) 17 15)
+ (put (mk-ladder-down 'p_forsaken_prison 9 9) 8 17)
+ (put (mk-ladder-up 'p_watchpoint 9 14) 3 9)
+ (put (mk-anne) 9 9)
+ (put (mk-jones) 9 9)
+ (put (mk-alex) 9 9)
+
+ (put (custom-pt 'put-gate-guard 'php1 'deep) 11 9)
+
+ ;; inner guard
+ (put (guard-pt 'crossbowman) 13 8)
+ (put (guard-pt 'crossbowman) 13 10)
+
+ ;; outer guard
+ (put (guard-pt 'halberdier) 15 10)
+ (put (guard-pt 'halberdier) 15 8)
+
+ ;; foes...
+ (put (spawn-pt 'death-knight) 17 9)
+ (put (spawn-pt 'skeletal-spear-thrower) 18 7)
+ (put (spawn-pt 'skeletal-spear-thrower) 18 11)
+
+ )
+
+(mk-place-music p_paladins_hold 'ml-castle)
+
+(mk-dungeon-room
+ 'p_treasury "Treasury"
+ (list
+  "xx xx xx xx xx rn xx xx xx xx xx xx xx rn xx xx xx xx xx "
+  "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+  "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+  "xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx "
+  "xx xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+  "rn xx xx ,, ,, ,, ,, ,, w+ xx w+ ,, ,, ,, ,, ,, xx xx rn "
+  "xx xx xx ,, ,, ,, ,, ,, w+ xx w+ ,, ,, ,, ,, ,, xx xx xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, w+ xx w+ ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, xx xx xx x! xx x! xx xx xx ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, xx rn rn xx ,, xx rn rn xx ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, xx xx xx x! xx x! xx xx xx ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, xx rn xx ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx xx xx ,, ,, ,, ,, ,, xx rn xx ,, ,, ,, ,, ,, xx xx xx "
+  "rn xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx rn "
+  "xx xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+  "xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx "
+  "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+  "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx "
+  "xx xx xx xx xx rn xx ,, ,, ,, ,, ,, xx rn xx xx xx xx xx "
+  )
+ ;; four corner blitters and levers
+ (put (kern-tag 'tr-ba
+                (mk-tblitter 'p_treasury
+                             2 2
+                             3 3
+                             'm_hall_section)) 2 2)
+ (put (kern-tag 'tr-bb
+                (mk-tblitter 'p_treasury
+                             14 2
+                             3 3
+                             'm_hall_section)) 14 2)
+ (put (kern-tag 'tr-bc
+                (mk-tblitter 'p_treasury
+                             14 14
+                             3 3
+                             'm_hall_section)) 14 14)
+ (put (kern-tag 'tr-bd
+                (mk-tblitter 'p_treasury
+                             2 14
+                             3 3
+                             'm_hall_section)) 2 14)
+ (put (mk-lever 'tr-ba) 11 11)
+ (put (mk-lever 'tr-bb) 7 11)
+ (put (mk-lever 'tr-bc) 7 7)
+ (put (mk-lever 'tr-bd) 11 7)
+      
+ ;; four center blitters and levers
+ (put (kern-tag 'tr-be1
+                (mk-tblitter 'p_treasury
+                             9 5
+                             1 1
+                             'm_hall_section)) 9 5)
+ (put (kern-tag 'tr-be2
+                (mk-tblitter 'p_treasury
+                             9 6
+                             1 1
+                             'm_hall_section)) 9 6)
+ (put (kern-tag 'tr-be3
+                (mk-tblitter 'p_treasury
+                             9 7
+                             1 1
+                             'm_hall_section)) 9 7)
+ (put (kern-tag 'tr-be4
+                (mk-tblitter 'p_treasury
+                             9 8
+                             1 1
+                             'm_hall_section)) 9 8)
+ (put (mk-lever 'tr-be1) 1 1)
+ (put (mk-lever 'tr-be2) 17 1)
+ (put (mk-lever 'tr-be3) 17 17)
+ (put (mk-lever 'tr-be4) 1 17)
+
+ (put (mk-ladder-up 'p_treasury2 9 9) 9 9)
+
+)
+
+;; slimes in NE corner
+(foldr-rect p_treasury 15 1 3 3 
+            (lambda (x loc) (kern-obj-put-at (spawn-pt 'green-slime) loc)) 
+            #f)
+
+;; skeletal warriors in SE corner
+(foldr-rect p_treasury 15 15 3 3 
+            (lambda (x loc) (kern-obj-put-at (spawn-pt 'skeletal-warrior) loc)) 
+            #f)
+
+;; headless in SW corner
+(foldr-rect p_treasury 1 1 3 3 
+            (lambda (x loc) (kern-obj-put-at (spawn-pt 'headless) loc)) 
+            #f)
+
+;; spiders in NW corner
+(foldr-rect p_treasury 1 15 3 3 
+            (lambda (x loc) (kern-obj-put-at (spawn-pt 'giant-spider) loc)) 
+            #f)
+
+(mk-place-music p_treasury 'ml-dungeon-adventure)
+
+
+(mk-dungeon-room
+ 'p_death_knights_hold "Death Knight's Hold"
+ (list
+               "xx xx xx xx xx xx xx xx xx xx xx r8 r8 r8 r8 r8 rn rn rn "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. .. bb bb ra rn rn "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, .. .. .. .. bb ra rn "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, .. .. .. .. .. bb r2 "
+               "xx xx xx xx ,, ,, ,, xx xx xx xx ,, ,, ,, ,, .. .. .. r2 "
+               ",, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, xx xx ,, xx xx xx xx "
+               ",, ,, ,, xx w+ w+ w+ xx ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, w+ ,, ,, ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, xx w+ w+ w+ xx ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+               ",, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, xx xx ,, xx xx xx xx "
+               "xx xx xx xx ,, ,, ,, xx xx xx xx ,, ,, ,, ,, .. .. .. r2 "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, .. .. .. .. .. bb r2 "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, .. .. .. .. bb rb rn "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. .. bb bb .. bb r2 "
+               "xx xx xx xx xx xx xx xx xx xx xx r1 r1 r1 r1 r1 r1 r1 rn "
+                  )
+ (put (mk-locked-door) 10 2)
+ (put (mk-magic-locked-door) 14 5)
+ (put (mk-magic-locked-door) 14 13)
+ (put (mk-locked-door) 10 16)
+ (put (mk-ladder-down 'p_altar_room 17 17) 17 9)
+
+ ;; defenders
+ (put (guard-pt 'craven-archer)  5  5)
+ (put (guard-pt 'craven-archer)  5 13)
+ (put (guard-pt 'craven-archer) 11  9)
+ (put (spawn-pt 'death-knight)  14  2)
+ (put (spawn-pt 'death-knight)  14 16)
+ (put (spawn-pt 'death-knight)   7  9)
+ (put (guard-pt 'death-knight)   9  2)
+ (put (guard-pt 'death-knight)   9 16)
+ (put (guard-pt 'death-knight)  14  6)
+ (put (guard-pt 'death-knight)  14 12)
+ (put (guard-pt 'warlock)       14  9)
+
+)
+
+(mk-place-music p_death_knights_hold 'ml-dungeon-adventure)
+
+(mk-dungeon-level 
+ (list nil              p_treasury   nil)
+ (list p_paladins_hold  p_great_hall p_death_knights_hold)
+ (list nil              nil          nil)
+ )
diff --git a/worlds/haxima-1.002/keep_crypt_mech.scm b/worlds/haxima-1.002/keep_crypt_mech.scm
new file mode 100644 (file)
index 0000000..e2cffdd
--- /dev/null
@@ -0,0 +1,89 @@
+;;----------------------------------------------------------------------------
+;; Special mech for the Keep Crypt
+;;
+;;    When the lever is pulled, this mech engages. Every turn it picks a
+;; random location from its region. If the location does not contain a being
+;; but does contain a corpse it removes the corpse and creates a skeletal
+;; warrior in its place.
+;;----------------------------------------------------------------------------
+
+(define (kcm-mk area)
+  (list #f area))
+(define (kcm-set-on! kcm) (set-car! kcm #t))
+(define (kcm-on? kcm) (car kcm))
+(define (kcm-area kcm) (cadr kcm))
+
+(define (kcm-exec-main kcm kplace)
+
+  (define (pick-loc)
+    (let ((area (kcm-area kcm)))
+      (let ((x (+ (rect-x area)
+                  (modulo (random-next) (rect-w area))))
+            (y (+ (rect-y area)
+                  (modulo (random-next) (rect-h area)))))
+        (mk-loc kplace x y))))
+
+  (define (get-corpse-at loc)
+    ;;(display "get-corpse-at")(newline)
+    (let ((corpses (find-object-types-at loc t_corpse)))
+      (if (null? corpses)
+          nil
+          (car corpses))))
+  
+  (let* ((loc (pick-loc))
+         (corpse (get-corpse-at loc)))
+    
+    ;;(display "loc:")(display loc)(newline)
+    ;;(display "corpse:")(display corpse)(newline)
+    
+    (define (corpse-at? loc)
+      ;;(display "corpse-at?")(newline)
+      (not (null? corpse)))
+    
+    (define (remove-corpse loc)
+      ;;(display "remove-corpse")(newline)
+      (kern-obj-remove corpse))
+    
+    (define (mk-skeleton)
+      (if (> (modulo (random-next) 2) 0)
+          (mk-npc 'skeletal-warrior (kern-dice-roll "1d3+4"))
+          (mk-npc 'skeletal-spear-thrower (kern-dice-roll "1d3+4"))))
+
+    (define (put-skeleton loc)
+      ;;(display "put-skeleton")(newline)
+      (kern-obj-put-at (mk-skeleton) loc))
+    
+    (define (good? loc)
+      ;;(display "good?")(newline)
+      (and (not (being-at? loc))
+           (corpse-at? loc)))
+    
+    (define (change-corpse-to-skeleton loc)
+      ;;(display "change-corpse-to-skeleton")(newline)
+      (kern-log-msg "You have disturbed the dead!")
+      (remove-corpse loc)
+      (put-skeleton loc))
+    
+    (if (good? loc)
+        (change-corpse-to-skeleton loc))))
+
+(define (kcm-exec kself)
+  (let ((kcm (kobj-gob-data kself)))
+    (if (and (kcm-on? kcm)
+             (> (modulo (random-next) 20) 16))
+        (kcm-exec-main kcm
+                       (loc-place (kern-obj-get-location kself))))))
+
+(define (kcm-on kself ksender)
+  (kcm-set-on! (kobj-gob-data kself)))
+        
+(define kcm-ifc
+  (ifc '()
+       (method 'on kcm-on)
+       (method 'exec kcm-exec)))
+
+(mk-obj-type 't_kcm nil nil layer-none kcm-ifc)
+
+(define (mk-kcm area)
+  (bind (kern-mk-obj t_kcm 1)
+        (kcm-mk area)))
diff --git a/worlds/haxima-1.002/kern-init.scm b/worlds/haxima-1.002/kern-init.scm
new file mode 100644 (file)
index 0000000..4381e11
--- /dev/null
@@ -0,0 +1,40 @@
+(kern-cfg-set 
+
+ ;; This is the image file for the UI border. The pieces need to be arranged in
+ ;; a specific order in this image.
+ "frame-image-filename"  "frame.png"
+
+ ;; These are the letters used by the console, etc, in the UI. The character
+ ;; sprites need to be arranged in a specific order in this image.
+ "ascii-image-filename"  "charset.png"
+
+ ;; This is the cursor prompt used by the command window in the UI. It should
+ ;; have four animation frames.
+ "cursor-image-filename" "cursor.png"
+
+ ;; This is the script file run when the user selects the "Start New Game"
+ ;; option from the main menu.
+ "new-game-filename"     "start-new-game.scm"
+
+ ;; This is the script file run when the user selects the "Journey Onward"
+ ;; option from the main menu. It lists the current save files.
+ "save-game-filename"     "saved-games.scm"
+
+ ;; This is the script file run when the user selects the "Tutorial"
+ ;; option from the main menu.
+ "tutorial-filename"     "tutorial.scm"
+
+ ;; This is the script file which runs the demo scene on startup.
+ "demo-filename" "demo.scm"
+
+ ;; These are the filenames of the splash image shown on startup for the
+ ;; various supported screen sizes. The format of the key must be
+ ;; <width>x<height>-splash-image-filename.
+ "1280x960-splash-image-filename" "splash.png"
+ "640x480-splash-image-filename" "640x480_splash.png"
+ "800x480-splash-image-filename" "640x480_splash.png"
+
+;; This is the image for the sprite pieces of the progress bar.
+"progress-bar-image-filename" "progress_bar_image.png"
+
+ )
diff --git a/worlds/haxima-1.002/keys.scm b/worlds/haxima-1.002/keys.scm
new file mode 100644 (file)
index 0000000..a6f41b3
--- /dev/null
@@ -0,0 +1,25 @@
+;; Keys are a bit unusual in that each unique key must be a unique object
+;; type. This is because player inventory consists only of object types, not
+;; instances, and to use a key it must be in player inventory.
+
+(define (mk-key-type tag name sprite)
+  (mk-reusable-item 
+   tag name sprite norm
+   (lambda (ktype kuser)
+     (let ((ktarg (ui-target (kern-obj-get-location kuser)
+                             1 
+                             (mk-ifc-query 'use-key))))
+       (cond ((null? ktarg) 
+              result-no-target)
+             (else
+              (ifccall ktarg 'use-key ktype)
+              result-ok))))))
+
+(define (mk-key type)
+  (kern-mk-obj type 1))
+
+;; List all the key types. This doesn't *need* to be done here, but like any
+;; type, it must be done in a file that is kern-loaded, which means it can't be
+;; done in a place file. So by convention let's list them here.
+(mk-key-type 't_brundegardt_tower_4_key "weathered key" s_picklock)
+(mk-key-type 't_stewardess_chest_key    "shiny key"     s_picklock)
diff --git a/worlds/haxima-1.002/kobj.scm b/worlds/haxima-1.002/kobj.scm
new file mode 100644 (file)
index 0000000..fba6acc
--- /dev/null
@@ -0,0 +1,36 @@
+;; ----------------------------------------------------------------------------
+;; kobj.scm - utilities related to kernel-objects
+;; ----------------------------------------------------------------------------
+(define (kobj-ktype kobj) (kern-obj-get-type kobj))
+(define (kobj-ifc kobj) ( kern-type-get-gifc (kobj-ktype kobj)))
+(define (kobj-gob kobj) (kern-obj-get-gob kobj))
+(define (kobj-gob-data kobj) (gob-data (kobj-gob kobj)))
+
+;; gob -- convenience accessor for getting the interesting part of a gob from
+;; the kernel object
+(define (gob kobj) (gob-data (kobj-gob kobj)))
+
+(define (signal-kobj kobj sig . args)
+  ;;(display "signal-kobj")(newline)
+  (if (not (null? (kobj-ifc kobj)))
+       (apply (kobj-ifc kobj) (cons sig args))
+  ))
+
+(define (kobj-can? kobj signal)
+  (let ((gifc (kobj-ifc kobj)))
+    (cond ((null? gifc) #f)
+          (else (gifc 'can signal)))))
+         
+(define (ktype-can? ktype signal)
+  (let ((gifc (kern-type-get-gifc  ktype)))
+    (cond ((null? gifc) #f)
+          (else (gifc 'can signal)))))
+  
+(define (kobj-place kobj)
+  (loc-place (kern-obj-get-location kobj)))
+
+(define (can-be-dropped? obj loc max_difficulty)
+       (let ((mcost (kern-place-get-movement-cost loc obj)))
+               (and (not (eqv? mcost 0))
+                       (< mcost max_difficulty))))
+                       
\ No newline at end of file
diff --git a/worlds/haxima-1.002/kraken-lakes.scm b/worlds/haxima-1.002/kraken-lakes.scm
new file mode 100644 (file)
index 0000000..b04c2e1
--- /dev/null
@@ -0,0 +1,152 @@
+
+(mk-dungeon-room
+ 'p_hydra_fen "Hydra Fen"
+       (list
+               "rn rn rn rn rn rn r8 r8 r8 r8 r8 r8 r8 rn rn rn rn rn rn "
+               "rn rn rn rn rn rc {{ {{ {{ {{ {{ {{ {{ ra rn rn rn rn rn "
+               "rn rn rn rn rc {{ {{ {{ {{ {{ {{ {{ {{ {{ ra rn rn rn rn "
+               "rn rn rn rc {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ ra rn rn rn "
+               "rn rn rc {{ {{ {{ {{ {C %3 %% %5 {A {{ {{ {{ {{ ra rn rn "
+               "rn rc {{ {{ {{ {C %3 %% %% %% %% %% %5 {A {{ {{ {{ ra rn "
+               "r4 {{ {{ {{ {C %3 %% %% %% %% %% %% %% %5 {A {{ {{ {{ r2 "
+               "r4 {{ {{ {{ %3 %% %% %% %% %% %% %% %% %% %5 {{ {{ {{ r2 "
+               "r4 {{ {{ {{ %% %% %% %% %% %% %% %% %% %% %% {{ {{ {{ r2 "
+               "r4 {{ {{ {{ %% %% %% %% %% %% %% %% %% %% %% {{ {{ {{ r2 "
+               "r4 {{ {{ {{ %% %% %% %% %% %% %% %% %% %% %% {{ {{ {{ r2 "
+               "r4 {{ {{ {{ %% %% %% %% ee ee ee %% %% %% %c {{ {{ {{ r2 "
+               "r4 {{ {{ {{ %a %% %% oo ee ee ee oo %% %% {# {{ {{ {{ r2 "
+               "rn r5 {{ {{ {% %a %% %% ee ee ee %% %% %c {{ {{ {{ r3 rn "
+               "rn rn r5 {{ {{ {% %e oo ee ee ee oo %e {# {{ {{ r3 rn rn "
+               "rn rn rn r5 {{ {{ {{ {{ ee ee ee {{ {{ {{ {{ r3 rn rn rn "
+               "rn rn rn rn r5 {{ {{ {{ {2 .. {4 {{ {{ {{ r3 rn rn rn rn "
+               "rn rn rn rn rn r5 {{ {{ {2 .. {4 {{ {{ r3 rn rn rn rn rn "
+               "rn rn rn rn rn rn r1 r5 .. .. .. r3 r1 rn rn rn rn rn rn "
+       )
+ (put (spawn-pt 'hydra) 9 9)
+ )
+
+(mk-place-music p_hydra_fen 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_pools "Pools"
+ (list
+               "rn rn r4 .. .. .. .. bb dd dd dd .. .. .. .. .. ra rn rn "
+               "rn r8 r8 r5 .. .. .. .. dd dd dd bb .. .. .. .. .. ra rn "
+               "r4 -- -- r2 r5 .. .. bb dd dd dd .. %3 %% %% %5 .. .. r2 "
+               "r4 -- -- ra rc .. .. .. dd dd dd bb %% ~3 ~5 %% %5 .. r2 "
+               "r4 -- -- ~~ %5 .. .. bb dd dd dd ~C ~3 -- -- ~5 %% %5 r2 "
+               "rn r5 ~~ ~c %% .. .. .. dd dd dd bb -2 -- -- -- ~5 %% r2 "
+               "rn r4 %a %% %c .. .. bb dd dd dd %% -- -- -- -- ~4 %% r2 "
+               "rn rc .. .. .. .. .. xx w+ d, bb xx ~~ -- -- -- ~c %% r2 "
+               "r4 .. .. .. .. .. .. rr ,, ,, ,, xx ~~ -- -- ~c %% %c r2 "
+               "r4 .. %3 %% %% %5 .. w+ gg ,, ,, rr ~% ~a ~c %% %c rb rn "
+               "r4 %3 %% ~3 ~5 %% .. gg ,, ,, ,, gg .. %% %% %% .. .. r2 "
+               "r4 %% ~3 -- ~c %% .. rr xx bb gg rr .. %% ~7 %% %5 .. r2 "
+               "r4 %% ~a ~c %% %c .. .. .. .. .. .. %3 ~3 -- ~5 %% .. r2 "
+               "r4 %a %% %% %c .. .. .. .. .. %3 %% ~3 -- -- ~4 %% .. r2 "
+               "rn r5 .. r3 r5 .. .. .. .. .. %% ~3 -- -- -- ~c %% .. r2 "
+               "rn rn r1 rn rc .. .. .. .. .. %% ~a -- -- ~c %% %c .. r2 "
+               "rn rn rn r4 .. .. .. .. .. .. %a %% ~a ~c %% %c .. r3 rn "
+               "rn rn rn rn r5 .. .. r3 r5 .. .. %a %% %% %c .. .. r2 rn "
+               "rn rn rn rn rn r1 r1 rn rn r1 r1 r1 r1 r1 r1 r1 r1 rn rn "
+      )
+ (put (mk-door) 9 7)
+ (put (mk-ladder-up 'p_great_hall 9 6) 9 9)
+ (put (spawn-pt 'yellow-slime) 11  3)
+ (put (spawn-pt 'yellow-slime)  4  6)
+ (put (spawn-pt 'yellow-slime) 10 13)
+ )
+
+(mk-place-music p_pools 'ml-dungeon-adventure)
+(kern-mk-place 
+ 'p_deepness
+ "The Deepness"
+ nil     ; sprite
+ (kern-mk-map 
+  nil 38 38 pal_expanded 
+       (list
+               "rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 rn r8 rn rn rn r8 r8 r8 r8 r8 r8 r8 rc bb .. .. .. bb ra r8 r8 r8 r8 rn "
+               "rn rc _3 _1 _1 _5 {{ {{ {{ {{ {{ {{ {{ {{ re {{ ra r8 rc bb %3 %% %% ~6 %% %% %5 .. .. .. .. .. %3 %% %% %% %5 r2 "
+               "r4 _3 __ __ __ __ =| _1 _1 _5 rb r9 r5 {{ {{ {{ {{ {{ {{ {% %e bb %a ~e %% %% %% bb .. .. .. bb %% %% %% %% %% r2 "
+               "r4 _a _8 _c r7 _e {{ __ __ __ __ _5 ra r9 rd {{ rb r1 r5 {{ {2 == .. bb %e bb %% %5 .. .. .. %3 %% bb %% bb %% r2 "
+               "r4 {{ {{ rb rn rd {{ _2 __ __ __ __ ~~ ~1 ~1 ~1 ~5 ra rc ~7 .. ~6 .. .. .. .. ~7 %c .. .. .. %a %% %% %% %% %% r2 "
+               "r4 {{ {{ {{ re {{ {L __ __ __ __ ~8 ~8 ~8 ~~ ~~ ~~ ~~ ~~ b~ ~9 ~~ ~~ ~d .. .. == .. .. .. .. .. .. .. %e bb %% r2 "
+               "r4 {{ rf {{ {{ {L _3 __ __ _c {G {{ {{ {{ {H -a ~~ ~~ ~~ ~~ %% b~ ~~ bb %7 bb ~6 %5 .. .. .. %3 %5 .. .. %b %% r2 "
+               "r4 {{ {L _3 _1 __ __ __ __ {G {{ r3 r9 r5 {{ {H ~~ ~~ ~~ ~~ ~~ ~~ ~~ %% %% %% ~6 %% %5 .. ~3 ~9 ~9 ~d .. bb %% r2 "
+               "r4 {{ _3 __ __ __ __ __ _4 {{ r3 rc {{ ra r5 {{ ~2 ~~ ~~ ~~ ~~ ~~ ~~ ~9 ~1 ~9 ~c %% %% %% ~6 %% %% .. .. %b %% r2 "
+               "r4 {{ _a __ __ __ __ __ _4 {{ r6 {{ {{ {{ r6 {{ ~2 ~~ -- ~~ ~~ b~ %% %% ~6 %% %% %% %% bb ~~ bb %% .. %7 bb %% ra "
+               "r4 {{ {H _a __ __ __ __ _c {{ r6 {{ {{ {{ r6 {{ ~2 -- __ -- ~~ ~~ ~5 %% ~6 %c bb ~3 ~1 ~9 ~8 ~9 ~9 =| ~9 ~9 ~9 ~~ "
+               "r4 {{ {{ {H _a _8 _8 _c {G {{ ra r5 {{ rb rc {{ ~2 __ __ __ ~~ ~~ ~~ b~ ~~ bb %3 ~~ bb bb %% %% %% .. .. bb %e r3 "
+               "rn r5 {{ {{ {{ {{ {{ {{ bb {{ {{ r6 {{ {{ {{ {L ~~ -- __ -- ~~ ~~ ~~ ~~ -- ~~ ~~ ~~ ~~ ~5 %% %% %% %5 .. .. .. r2 "
+               "rn rn r1 r1 r5 {1 r7 {{ {{ {{ r3 rc b~ ~1 ~1 ~~ ~~ ~~ -- ~~ ~~ ~~ ~~ ~~ __ __ ~~ b~ %% ~~ ~9 b~ ~9 ~d .. bb .. r2 "
+               "rn rn rn rn rc .. ra r1 r1 r1 rc bb ~~ ~~ b~ ~~ ~~ ~8 ~8 ~8 ~8 ~8 ~~ ~~ __ __ ~~ ~~ ~~ %% %% %% %c .. .. .. .. r2 "
+               "rn rn rn r4 {{ {2 .. r2 rn r4 bb ~3 ~~ b~ ~~ ~c {G {{ {{ {{ {{ {{ {H ~a ~~ ~~ ~~ ~~ ~~ ~d bb .. .. .. bb %7 .. r2 "
+               "rn rn r8 rc {{ {2 .. ra rn rc b~ ~~ ~~ ~~ ~c {G {{ rr rr rr rr rr bb bb {H ~a ~~ -- ~~ %c .. .. .. .. %3 %% %5 r2 "
+               "rn rc {{ bb {1 .. .. bb re bb ~~ ~~ ~~ ~~ {G {{ {{ rr .. .. .. rr .. .. bb {H ~~ -- ~4 bb .. .. .. bb %% ~7 %% r2 "
+               "r4 {{ {{ {2 .. .. .. .. ~C ~3 ~~ -- -- ~4 {A {{ rr rr .. .. .. rr .. .. .. bb ~2 -- ~4 %d .. .. .. %b ~b ~~ ~9 r2 "
+               "r4 {{ bb .. .. .. bb ~C ~3 ~~ -- -- -- ~4 bb {{ rr && .. .. .. .. .. .. .. bb ~2 -- ~4 bb .. .. .. bb %% ~e %% r2 "
+               "r4 {{ {2 .. .. .. .. ~b ~~ -- -- __ -- ~4 {# {{ rr rr .. .. .. rr .. .. .. bb ~2 -- ~4 %5 .. .. .. .. %a %% %c r2 "
+               "r4 {{ bb .. .. .. bb ~% ~~ -- __ __ __ ~~ {J {{ {{ rr .. .. .. rr .. .. bb {L ~~ -- ~~ %% bb .. .. .. bb %e .. r2 "
+               "rn r5 {{ {2 .. .. .. .. ~a -- -- __ -- -- ~5 {J {{ rr rr .. rr rr bb bb {L ~3 ~~ -- ~~ ~d .. .. .. .. .. .. .. r2 "
+               "rn rn r5 bb .. .. .. bb {H ~~ -- __ __ -- ~~ b~ {J {{ {{ {6 {{ {{ {{ {L ~3 ~~ -- -- ~~ bb .. bb .. .. .. bb .. r2 "
+               "rn rn r4 {{ {2 .. {4 {{ r7 ~a -- -- __ -- -- ~~ ~~ ~1 ~1 ~1 ~5 {N ~3 ~~ ~~ -- -- -- ~~ b~ rb r5 .. .. .. .. r3 rn "
+               "rn rn r4 bb .. .. .. bb r2 rd ~~ -- __ __ -- -- ~~ -- -- -- ~~ ~~ ~~ -- -- -- ~~ ~~ ~~ ~~ b~ ra r9 r5 .. .. r2 rn "
+               "rn rn rc {{ {2 .. {4 {{ re ~b ~~ -- __ __ __ -- -- __ __ __ -- -- -- -- -- ~~ ~~ b~ ~~ ~~ ~~ ~~ ~5 r6 .. .. ra rn "
+               "rn r4 {{ bb .. .. .. bb {{ {H ~~ -- -- -- __ __ __ __ __ __ __ -- -- ~~ ~~ ~~ b~ bb b~ ~~ ~~ b~ ~~ r6 .. .. .. r2 "
+               "rn rc {{ {2 .. .. {4 {{ {{ {{ ~a ~8 ~8 ~~ -- -- -- __ __ __ -- -- ~~ ~~ b~ r3 r1 r1 r1 xx xx ~~ ~~ xx xx .. .. r2 "
+               "r4 {{ bb .. .. .. bb {A {{ {{ {{ {{ {{ {H ~a ~8 ~~ -- -- -- ~~ ~8 ~c rb r9 r8 xx xx xx xx __ __ __ __ xx ,, xx xx "
+               "r4 {{ {2 .. .. .. .. bb {1 bb {{ {{ {{ {{ {{ {{ {H ~a ~8 ~c {G {{ {{ bb .. bb xx ,, ,, w+ __ __ __ __ w+ ,, ,, xx "
+               "r4 {{ bb .. .. .. .. .. .. .. {1 bb {1 bb {1 bb {1 bb .. bb {1 bb {1 .. .. .. ,, ,, ,, ,, ee ee ee ee ,, ,, ,, xx "
+               "rn r5 {{ {2 {8 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. xx ,, ,, w+ __ __ __ __ w+ ,, ,, xx "
+               "rn r4 {{ bb {{ bb {8 bb .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. {8 bb xx xx xx xx __ __ __ __ xx xx xx xx "
+               "rn rn r1 r1 r5 {{ {{ {2 .. .. .. .. .. .. .. .. {8 .. {8 .. .. .. {8 bb {{ {{ xx xx xx __ __ __ __ __ __ xx xx xx "
+               "rn rn rn rn rc {{ {{ bb .. .. .. bb {8 bb {8 bb {{ bb {{ bb {8 bb {{ {{ {{ r3 xx xx xx __ __ __ __ __ __ xx xx xx "
+               "rn rn r8 rc {{ {{ {{ {2 .. .. .. {4 {{ {{ {{ rb r1 r1 r5 {{ {{ {{ {{ r3 r1 rn xx xx xx xx __ __ __ __ xx xx xx xx "
+               "rn r4 {{ {{ {{ {{ {{ bb .. .. .. bb {{ {{ {{ {{ r2 rn rn r1 r1 r1 r1 rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx "
+       )
+)
+ #f      ; wraps
+ #t      ; underground
+ #f      ; large-scale (wilderness)
+ #f      ; tmp combat place
+ nil     ; subplaces
+ nil     ; neighbors
+ (list ;; objects
+
+  (put (mk-portcullis) 31 28)
+  (put (mk-portcullis) 32 28)
+  (put (mk-door) 26 31)
+  (put (mk-door) 35 29)
+  (put (mk-windowed-door) 34 31)
+  (put (mk-windowed-door) 29 31)
+  (put (mk-ladder-down 'p_lost_garrison 11 11) 12 9)
+
+  ;; monster generators
+  (put (mk-monman) 0 0)
+  (put (guard-pt 'headless) 3 22)
+  (put (guard-pt 'headless) 7 22)
+  (put (guard-pt 'headless) 5 21)
+  (put (guard-pt 'headless) 3 20)
+  (put (spawn-pt 'kraken) 5 9)
+  (put (spawn-pt 'sea-serpent) 18 11)
+  (put (step-pt "A yellow slime oozes up!" (list 'yellow-slime 32 11)) 33 10)
+  (put (step-pt "A yellow slime oozes up!" (list 'yellow-slime 26 3)) 26 5)
+
+  ;; put a special step trigger on the footbridge across the cistern
+  (put (mk-step-trig 'spawn-kraken-lakes-sea-serpent nil) 31 31)
+
+  )
+ (list 'on-entry-to-dungeon-room) ; hooks
+ (list ;; edge entrances
+  (list north 9 37)
+  (list south 29 0)
+  )
+ )
+
+(mk-place-music p_deepness 'ml-dungeon-adventure)
+
+;; tie rooms together
+(kern-place-set-neighbor south p_deepness p_pools)
+(kern-place-set-neighbor north p_deepness p_hydra_fen)
diff --git a/worlds/haxima-1.002/kun.scm b/worlds/haxima-1.002/kun.scm
new file mode 100644 (file)
index 0000000..5e55e0a
--- /dev/null
@@ -0,0 +1,70 @@
+(kern-load "mesmeme.scm")
+(kern-load "jake.scm")
+(kern-load "slywan.scm")
+(kern-load "tooth.scm")
+(kern-load "tetzl.scm")
+
+(kern-mk-place
+ 'p_kun "Kun" s_town
+ (kern-mk-map 
+  nil 19 19 pal_expanded
+       (list
+               "xx xx xx xx xx xx xx xx xx xx xx {{ {2 .. {4 {{ ^^ ^^ ^^ "
+               "xx [[ .C .A .N .T .I .N .A ]] xx {{ {2 .. {4 {{ {{ ^^ ^^ "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx {{ {2 .. {4 {{ {{ {{ ^^ "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ws {{ {2 .. {4 {{ ^^ ^^ ^^ "
+               "xx ,, ,, 00 00 00 00 00 ,, ,, xx {{ {2 .. {4 {{ ^^ ^^ {{ "
+               "xx ,, ,, 00 ,, ,, ,, 00 ,, ,, xx {{ {2 .. {4 {{ {{ {{ {{ "
+               "xx ,, ,, 00 00 00 00 00 ,, ,, xx {{ {2 .. .. {1 {1 {1 {1 "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ws {{ {2 .. .. .. .. .. .. "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx {{ {2 .. .. .. {8 .. {8 "
+               "xx xx ws xx xx ,, sT xx ws xx xx {{ {2 .. .. bb {{ bb {{ "
+               ".. .. .. .. .. .. .. .. .. .. .. {1 .. .. {4 {{ {{ {{ ^^ "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. bb {{ ^^ ^^ "
+               "{8 .. {8 .. .. .. .. {8 .. .. .. .. .. .. {4 {{ ^^ ^^ ^^ "
+               "{{ bb {{ bb .. .. {4 {{ xx xx xx xx sE ,, xx xx xx xx xx "
+               "{{ {{ {{ {{ {2 .. {4 {{ xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+               "^^ {{ {{ bb .. .. {4 {{ xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+               "^^ ^^ {{ {{ {2 .. {4 {{ xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+               "^^ ^^ ^^ {{ {2 .. {4 {{ xx .D .U .T .Y @@ .F .R .E .E xx "
+               "^^ ^^ ^^ {{ {2 .. {4 {{ xx xx xx xx xx xx xx xx xx xx xx "
+       )
+  )
+ #f      ; wraps
+ #f      ; underground
+ #f      ; large-scale (wilderness)
+ #f      ; tmp combat place
+ nil     ; subplaces
+ nil     ; neighbors
+ ;; objects
+ (list
+
+  ;; npcs
+  (put (mk-mesmeme) 0 0)
+  (put (mk-jake) 0 0)
+  (put (mk-slywan) 0 0)
+  (put (mk-tooth) 0 0)
+  (put (mk-tetzl) 0 0)
+
+  (put (mk-windowed-door) 5 9)
+  (put (mk-door) 13 13)
+  )
+ ;; on-entry hooks
+ nil
+
+ ;; edge entrances
+ (list
+  (list north 5 18)
+  (list south 13 0)
+  (list west 18 7)
+  (list east 0 11)
+  (list northwest 18 9)
+  (list southeast 0 10)
+  (list southwest 15 0)
+  (list northeast 3 18)
+  )
+ )
+
+(mk-place-music p_kun 'ml-small-town)
diff --git a/worlds/haxima-1.002/landslide.scm b/worlds/haxima-1.002/landslide.scm
new file mode 100644 (file)
index 0000000..ee33235
--- /dev/null
@@ -0,0 +1,32 @@
+;; landslide -- shake the map, drop some boulders, and damage any non-flying,
+;; non-phasing beings that get hit.
+(define (drop-rock-on kbeing)
+  (cond ((and (not (can-fly? kbeing))
+              (not (can-phase? kbeing)))
+         (kern-log-msg (kern-obj-get-name kbeing)
+                       " hit by falling rock!")
+         (kern-obj-apply-damage kbeing 
+                                "hit"
+                                (kern-dice-roll "1d10")))
+        ))
+
+(define (drop-boulder x loc)
+  (cond ((<= (modulo (random-next) 100) 50)
+         (kern-place-set-terrain loc t_boulder)         
+         (map drop-rock-on (get-beings-at loc))
+         )))
+
+(define (landslide kbeing x y w h)
+  (kern-log-msg "LANDSLIDE!")
+  (shake-map 10)
+  (foldr-rect (loc-place (kern-obj-get-location kbeing))
+             x
+             y
+             w
+             h
+             drop-boulder
+             #f)
+  #t)
+
+(define (mk-landslide x y w h)
+  (mk-step-trig 'landslide x y w h))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/lever.scm b/worlds/haxima-1.002/lever.scm
new file mode 100644 (file)
index 0000000..7a89acb
--- /dev/null
@@ -0,0 +1,59 @@
+;; A lever is a basic binary mechanism.
+
+(define (lever-state on?)
+  (if on?
+      (state-mk 's_R_lever_up #f pclass-none 0)
+      (state-mk 's_R_lever_down #f pclass-none 0)))
+
+(define lever-ifc
+  (ifc bim-ifc
+       (method 'handle bim-toggle)
+       (method 'state lever-state)))
+
+(mk-obj-type 't_lever "lever" '() layer-mechanism lever-ifc)
+
+(define (mk-lever dest-tag)
+  (bind (kern-mk-obj t_lever 1)
+        (bim-mk #f dest-tag nil)))
+               
+(define (mk-lever-on dest-tag)
+  (bind (kern-mk-obj t_lever 1)
+        (bim-mk #t dest-tag nil)))
+
+(define (mk-lever-with-id dest-tag id)
+  (bind (kern-mk-obj t_lever 1)
+         (bim-mk #f dest-tag id)))
+
+
+;;----------------------------------------------------------------------------
+;; Disguised lever
+;;----------------------------------------------------------------------------
+(define (disg-lvr-state on? klvr)
+  (let ((bim (kobj-gob-data klvr)))
+    (state-mk (bim-members bim) #f pclass-none 0)))
+
+(define disg-lvr-ifc
+  (ifc bim-ifc
+       (method 'handle bim-toggle)
+       (method 'state disg-lvr-state)))
+
+(mk-obj-type 't_disg_lvr nil '() layer-mechanism disg-lvr-ifc)
+
+(define (mk-disg-lvr dest-tag sprite-tag)
+  (bind (kern-mk-obj t_disg_lvr 1)
+        (bim-mk #f dest-tag sprite-tag)))
+               
+               
+;;----------------------------------------------------------------------------
+;; Searchable Description of hidden mechanisms
+;;----------------------------------------------------------------------------
+
+(mk-obj-type 't_hidden_mech  ;; tag
+             "hidden mechanism"       ;; name
+             s_blank    ;; sprite
+             layer-tfeat    ;; stacking layer
+             nil    ;; interface
+             )
+
+(define (mk-hidden-mech)
+       (mk-hidden 't_hidden_mech 1))
diff --git a/worlds/haxima-1.002/lia.scm b/worlds/haxima-1.002/lia.scm
new file mode 100644 (file)
index 0000000..8a167e5
--- /dev/null
@@ -0,0 +1,195 @@
+;; Reagent-seller
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Oparine.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_lia
+               (list 0  0  sea-witch-bed        "sleeping")
+               (list 6  0  sea-witch-beach      "idle")
+               (list 8  0  sea-witch-counter    "working")
+               (list 20 0  sea-witch-beach      "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (lia-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Lia is a female wizard and reagent-seller who dwells in Oparine,
+;; so that she may remain in the proximity to her true love,
+;; the Nixie prince Fing.
+;; 
+;; She is said to be under a curse, of obscure nature.
+;; One likely interpretation is that she is only in human form through 
+;; having been transformed, being born a Nixie or some other water-folk.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (lia-hail knpc kpc)
+  (say knpc "[You meet a haunting beauty] Welcome."))
+
+(define (lia-default knpc kpc)
+  (say knpc "I cannot help you with that."))
+
+(define (lia-name knpc kpc)
+  (say knpc "I am Lia."))
+
+(define (lia-join knpc kpc)
+  (say knpc "I cannot leave these shores."))
+
+(define (lia-job knpc kpc)
+  (say knpc "I sell reagents, including the rare black pearl."))
+
+(define (lia-bye knpc kpc)
+  (say knpc "Goodbye, Wanderer."))
+
+;; Trade...
+(define lia-merch-msgs
+  (list "My shop is open from 8:00AM to 8:00PM."
+        "Here are my wares."
+        "I will buy rare ingredients if they are a good value."
+        "Do you wish to buy or do you have something to sell?"
+        "A blessing on your magic."
+        "Very well."
+        "I will be happy to purchase more."
+        "I only offer what is fair."
+        "May the gods of the deep favour you."
+        "As you wish."
+   ))
+
+(define lia-catalog
+  (list
+   (list sulphorous_ash         (*  2 reagent-price-mult) "This ash comes from the bed of dragons in the Fire Sea.")
+   (list garlic                 (*  4 reagent-price-mult) "Garlic is a common enough herb, but useful in spells.")
+   (list ginseng                (*  4 reagent-price-mult) "I grow this ginseng myself alongside mandrake.")
+   (list black_pearl            (*  4 reagent-price-mult) "These come from my own special source. You will find no others like them.")
+   (list blood_moss             (*  6 reagent-price-mult) "It is difficult to get blood moss here.")
+   (list nightshade             (* 11 reagent-price-mult) "The nightshade is rare in these parts.")
+   (list mandrake               (* 11 reagent-price-mult) "I grow mandrake with my ginseng.")
+   
+   (list t_in_an_scroll         (*  3 base-scroll-cost) "When faced with magic stronger than your own, use this to even the score.")
+   (list t_in_mani_corp_scroll  (*  8 base-scroll-cost) "You need not mourn a fallen companion when you carry one of these.")
+   (list t_vas_rel_por_scroll   (*  3 base-scroll-cost) "You can travel great distances or escape dire circumstances with this gate scroll.")
+   (list t_vas_mani_scroll      (*  2 base-scroll-cost) "When sorely wounded this will restore you to health.")
+   (list t_wis_quas_scroll      (*  2 base-scroll-cost) "This scroll will open your eyes to the invisible world.")
+   ))
+
+(define (lia-trade knpc kpc)  (conv-trade knpc kpc "trade" lia-merch-msgs lia-catalog))
+(define (lia-buy knpc kpc)  (conv-trade knpc kpc "buy" lia-merch-msgs lia-catalog))
+(define (lia-sell knpc kpc)  (conv-trade knpc kpc "sell" lia-merch-msgs lia-catalog))
+
+(define (lia-pear knpc kpc)
+  (say knpc "I have my own source for the rare black pearl. "
+       "Would you like to purchase some?")
+  (if (kern-conv-get-yes-no? kpc)
+      (lia-buy knpc kpc)
+      (say knpc "You won't get this quality anywhere else!")))
+
+;; Shores...
+(define (lia-shor knpc kpc)
+  (say knpc "I must stay by the shore so I can be near my love."))
+
+(define (lia-love knpc kpc)
+  (say knpc "My beloved cannot leave the sea, "
+       "he is a prince among the Sea People. "
+       "He is bold and true, and has not left me despite my curse."
+       ))
+
+;; Sea
+(define (lia-sea knpc kpc)
+  (say knpc "How I long to return to my home! "
+       "I miss the courtyards of the deep, "
+       "and watching the ships cross my ceiling, "
+       "and hearing the conversations of Men as only a distant murmur."))
+
+(define (lia-curs knpc kpc)
+  (say knpc "I'd prefer not to speak of it."))
+
+;; Townspeople...
+(define (lia-opar knpc kpc)
+  (say knpc "All cities of Men are too dry for my liking."))
+
+(define (lia-gher knpc kpc)
+  (say knpc "The scavengers of the sea used to follow her ship. "
+       "They were well-fed with her victims."))
+
+(define (lia-alch knpc kpc)
+  (say knpc "He sometimes visits me, and we discuss magic. "
+       "I have few other friends among Men."))
+
+(define (lia-osca knpc kpc)
+  (say knpc "I know little of him, except that he has never been to sea."))
+
+(define (lia-henr knpc kpc)
+  (say knpc "He was a fine sailor once. The great ones of the deep sometimes "
+       "spoke of his courage."))
+
+(define (lia-bart knpc kpc)
+  (say knpc "His ships are well-respected, but all ships are clumsy and "
+       "ponderous in my sight."))
+
+(define lia-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default lia-default)
+       (method 'hail lia-hail)
+       (method 'bye  lia-bye)
+       (method 'job  lia-job)
+       (method 'name lia-name)
+       (method 'join lia-join)
+       
+       ;; Shores
+       (method 'shor lia-shor)
+       (method 'love lia-love)
+       (method 'sea  lia-sea)
+       (method 'deep lia-sea)
+       (method 'curs lia-curs)
+
+       ;; trade
+       (method 'trad lia-trade)
+       (method 'reag lia-buy)
+       (method 'buy  lia-buy)
+       (method 'sell lia-sell)
+       (method 'blac lia-buy)
+       (method 'pear lia-buy)
+
+       ;; town & people
+       (method 'opar lia-opar)
+       (method 'alch lia-alch)
+       (method 'gher lia-gher)
+       (method 'osca lia-osca)
+       (method 'henr lia-henr)
+       (method 'bart lia-bart)
+       (method 'fing lia-love)
+
+       ))
+
+(define (mk-lia)
+  (bind 
+   (kern-mk-char 'ch_lia           ; tag
+                 "Lia"             ; name
+                 sp_human            ; species
+                 oc_wizard           ; occ
+                 s_townswoman        ; sprite
+                 faction-men         ; starting alignment
+                 0 2 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'lia-conv         ; conv
+                 sch_lia           ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_dagger)))    ; container
+                 nil                 ; readied
+                 )
+   (lia-mk)))
diff --git a/worlds/haxima-1.002/lich-tomb.scm b/worlds/haxima-1.002/lich-tomb.scm
new file mode 100644 (file)
index 0000000..e5ec51c
--- /dev/null
@@ -0,0 +1,31 @@
+(mk-dungeon-room
+ 'p_lich_tomb "Lich Tomb"
+       (list
+               "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+               "xx %3 %% %% %5 pp ,, ,, ,, cc ,, ,, ,, pp %3 %% %% %5 xx "
+               "xx %% %% %% %% ,, ,, cc cc cc cc cc ,, ,, %% %% %% %% xx "
+               "xx %% %% %% %% ,, cc cc cc cc cc cc cc ,, %% %% %% %% xx "
+               "xx %% %% %% %% ,, ,, cc cc cc cc cc ,, ,, %% %% %% %% xx "
+               "xx %% %% %% %% pp ,, ,, cc cc cc ,, ,, pp %% %% %% %% xx "
+               "xx %a %% %% %% %% %% ,, cc cc cc ,, %% %% %% %% %% %c xx "
+               "xx .. %a %% %% %% %% pp cc cc cc pp %% %% %% %% %c .. xx "
+               "xx .. .. %a %% %% %% ,, cc cc cc ,, %% %% %% %c .. .. xx "
+               "xx .. .. .. %a %% %c pp cc cc cc pp %a %% %c .. .. .. xx "
+               "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. ,, cc cc cc ,, .. .. .. .. .. .. xx "
+               "xx .. .. .. .. .. .. pp cc cc cc pp .. .. .. .. .. .. xx "
+               "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+       )
+ (put (mk-ladder-up 'p_crypt 9 10) 9 16)
+ (put (kern-mk-obj F_sleep_perm 1) 8 1)
+ (put (kern-mk-obj F_sleep_perm 1) 10 1)
+ (put (mk-lich-king) 9 2)
+
+ )
+
+(mk-place-music p_lich_tomb 'ml-creepy-area)
diff --git a/worlds/haxima-1.002/lightning.wav b/worlds/haxima-1.002/lightning.wav
new file mode 100644 (file)
index 0000000..7f6562f
Binary files /dev/null and b/worlds/haxima-1.002/lightning.wav differ
diff --git a/worlds/haxima-1.002/loc.scm b/worlds/haxima-1.002/loc.scm
new file mode 100644 (file)
index 0000000..18a9ba9
--- /dev/null
@@ -0,0 +1,274 @@
+(define (mk-loc place x y) (list place x y))
+(define (loc-mk place x y) (list place x y))
+
+(define (loc-place loc) (car loc))
+(define (loc-x loc) (cadr loc))
+(define (loc-y loc) (caddr loc))
+
+;; eval-loc -- given a loc where the place is a tag, return one where the place
+;; is bound to the kernel object referred to by the tag
+(define (eval-loc loc)
+  (mk-loc (eval (loc-place loc))
+          (loc-x loc) 
+          (loc-y loc)))
+
+(define (loc-op a b op)
+  (mk-loc (loc-place a)
+          (op (loc-x a) (loc-x b))
+          (op (loc-y a) (loc-y b))))
+(define (loc-sum a b) (loc-op a b +))
+(define (loc-distance a b)
+  (kern-get-distance a b))
+(define (loc-city-block-distance a b)
+  (+ (abs (- (loc-x a) 
+             (loc-x b)))
+     (abs (- (loc-y a)
+             (loc-y b)))))
+
+
+(define (loc-addx loc dx)
+  (mk-loc (loc-place loc) (+ (loc-x loc) dx) (loc-y loc)))
+
+(define (loc-addy loc dy)
+  (mk-loc (loc-place loc) (loc-x loc) (+ (loc-y loc) dy)))
+
+;; loc-opposite-x -- return a list of locs AWAY from the given loc in the given
+;; x direction
+(define (loc-opposite-x loc dx)
+  (if (= 0 dx)
+      nil
+      (list (loc-addx loc dx)
+            (loc-addx (loc-addy loc -1) dx)
+            (loc-addx (loc-addy loc  1) dx))))
+
+;; loc-opposite-y -- return a list of locs AWAY from the given loc in the given
+;; y direction
+(define (loc-opposite-y loc dy)
+  (if (= 0 dy)
+      nil
+      (list (loc-addy loc dy)
+            (loc-addy (loc-addx loc -1) dy)
+            (loc-addy (loc-addx loc  1) dy))))
+
+;; loc-wrap -- wrap location around edges of a wrapping map
+(define (loc-wrap loc)
+  (let ((place (loc-place loc)))
+    (if (not (kern-place-is-wrapping? place))
+        loc
+        (mk-loc place
+                (modulo (loc-x loc) (kern-place-get-width place))
+                (modulo (loc-y loc) (kern-place-get-height place))))))
+
+;; loc-add -- vector sum of locations (auto wraps)
+(define (loc-add . locs)
+  ;;(println "loc-add " locs)
+  (if (null? locs)
+      nil
+      (loc-wrap (mk-loc (loc-place (car locs))
+                        (foldr (lambda (dx loc) (+ dx (loc-x loc))) 0 locs)
+                        (foldr (lambda (dy loc) (+ dy (loc-y loc))) 0 locs)))))
+
+;; loc-diff -- vector difference of two locations; on wrapping maps there are
+;; two solutions, the shortest is returned
+(define (loc-diff a b)
+  (let ((place (loc-place a)))
+    (if (kern-place-is-wrapping? place)
+        (let ((w (kern-place-get-width place)))
+          (mk-loc place 
+                  (mdist (loc-x a) (loc-x b) w)
+                  (mdist (loc-y a) (loc-y b) w)))
+        (mk-loc place
+                (- (loc-x b) (loc-x a))
+                (- (loc-y b) (loc-y a))))))
+
+
+(define (loc-to-cardinal-dir loc)
+  (let ((x (loc-x loc))
+        (y (loc-y loc)))
+    (if (> x 0)
+        ;; eastern half
+        (if (> y 0)
+          ;; southeast quarter
+          (if (> x y)
+              east
+              south)
+          ;; northeast quarter
+          (if (> x (abs y))
+              east
+              north))
+        ;; western half
+        (if (> y 0)
+            ;; southwest quarter
+            (if (> (abs x) y)
+                west
+                south)
+            ;; northwest quarter
+            (if (> (abs x) (abs y))
+                west
+                north)))))
+          
+          
+
+;; ----------------------------------------------------------------------------
+;; loc-grid-distance -- return the distance needed to walk between two points
+;;
+;; REVISIT: this has a form almost identical to the loc-adjacent? proc below
+;;
+;; ----------------------------------------------------------------------------
+(define (loc-grid-distance a b)
+  (let ((place (loc-place a)))
+    (if (kern-place-is-wrapping? place)
+        (let ((w (kern-place-get-width place)))
+          (+ (mdist (loc-x a) (loc-x b) w)
+             (mdist (loc-y a) (loc-y b) w)))
+        (+ (abs (- (loc-x a) (loc-x b)))
+           (abs (- (loc-y a) (loc-y b)))))))
+
+(define (loc-closer? a b c)
+  (< (loc-grid-distance a c)
+     (loc-grid-distance b c)))
+
+;; loc-canonical -- return "canonical" form of vector (ie, one of the four
+;; cardinal directions)
+(define (loc-canonical loc)
+  (define (norm a)
+    (cond ((> a 0) 1)
+          ((< a 0) -1)
+          (else 0)))
+  (mk-loc (loc-place loc)
+          (norm (loc-x loc))
+          (norm (loc-y loc))))
+
+;; loc-sdiv -- scalar division
+(define (loc-sdiv loc s)
+  (mk-loc (loc-place loc)
+          (/ (loc-x loc s))
+          (/ (loc-y loc s))))
+
+;; loc-smul -- scaler multiplication
+(define (loc-smul loc s)
+  ;;(println "loc-smul " loc " " s)
+  (mk-loc (loc-place loc)
+          (* (loc-x loc) s)
+          (* (loc-y loc) s)))
+
+;; loc-norm -- convert loc to normal form (where at least one component has
+;; length 1)
+(define (loc-norm loc)
+  ;;(println "loc-norm " loc)
+  (let ((s (min (abs (loc-x loc)) 
+                     (abs (loc-y loc)))))
+    (if (<= s 1)
+        loc
+        (loc-sdiv loc s))))
+
+(define (loc-zero? loc)
+  (and (= 0 (loc-x loc))
+       (= 0 (loc-y loc))))
+
+(define (loc-equal? a b)
+  (and (eqv? (loc-place a) (loc-place b))
+       (= (loc-x a) (loc-x b))
+       (= (loc-y a) (loc-y b))))
+
+;; convert loc to short directional vector
+(define (loc-to-delta loc)
+  (if (loc-zero? loc)
+      loc
+      (if (> (abs (loc-x loc)) (abs (loc-y loc)))
+          (mk-loc (loc-place loc) (if (> (loc-x loc) 0) 1 -1) 0)
+          (mk-loc (loc-place loc) 0 (if (> (loc-y loc) 0) 1  -1)))))
+
+;; ----------------------------------------------------------------------------
+;; loc-enum-rect -- given a rectangular region of a place return a flat list of
+;; all locations in that rectangle. Useful in conjunction with map.
+;; ----------------------------------------------------------------------------
+(define (loc-enum-rect place x y w h)
+  (define (enum-row x w)
+    (if (= 0 w)
+        nil
+        (cons (mk-loc place x y) 
+              (enum-row (+ x 1) (- w 1)))))
+  (if (= 0 h)
+      nil
+      (append (enum-row x w)
+              (loc-enum-rect place x (+ y 1) w (- h 1)))))
+
+;; Helper procedure. Checks if location b is a neighbor of location a as judged
+;; by is-adjacent?.
+(define (loc-adjacent-generic? a b is-adjacent?)
+  (let ((place (loc-place a)))
+    (if (kern-place-is-wrapping? place)
+        (let ((w (kern-place-get-width place)))
+          (is-adjacent? (mdist (loc-x a) (loc-x b) w)
+                 (mdist (loc-y a) (loc-y b) w)))
+        (is-adjacent? (abs (- (loc-x a) (loc-x b)))
+               (abs (- (loc-y a) (loc-y b)))))))
+
+;; Checks if location b is one of the 4 neighbors of location a
+(define (loc-4-adjacent? a b)
+  (loc-adjacent-generic? a 
+                         b 
+                         (lambda (dx dy)     
+                           (or (and (= 1 dx) (= 0 dy))
+                               (and (= 0 dx) (= 1 dy))))))
+
+;; Checks if location b is one of the 8 neighbors of location a
+(define (loc-8-adjacent? a b)
+  (loc-adjacent-generic? a
+                        b
+                        (lambda (dx dy)
+                          (and (<= 1 dx) (<= 1 dy)))))
+
+(define (mk-lvect dx dy dz) (list dx dy dz))
+(define (lvect-dx lvect) (car lvect))
+(define (lvect-dy lvect) (cadr lvect))
+(define (lvect-dz lvect) (caddr lvect))
+
+;; Convert a direction code to a location vector
+(define (direction-to-lvect dir)
+  (cond ((= dir east)      (mk-lvect  1  0  0))
+        ((= dir west)      (mk-lvect -1  0  0))
+        ((= dir north)     (mk-lvect  0 -1  0))
+        ((= dir south)     (mk-lvect  0  1  0))
+        ((= dir northwest) (mk-lvect -1 -1  0))
+        ((= dir northeast) (mk-lvect  1 -1  0))
+        ((= dir southwest) (mk-lvect -1  1  0))
+        ((= dir southeast) (mk-lvect  1 -1  0))
+        ((= dir up)        (mk-lvect  0  0  1))
+        ((= dir down)      (mk-lvect  0  0 -1))
+        ))  
+
+(define (loc-offset loc dir)
+  ;;(println "    loc-offset:" loc "," dir)
+  (define (get-place place dz)
+    ;;(println "     get-place:" place "," dz)
+    (cond ((= dz 0) place)
+          (else (kern-place-get-neighbor place dir))))
+  (let* ((vec (direction-to-lvect dir))
+         (place (get-place (loc-place loc) (lvect-dz vec))))
+    (cond ((null? place) nil)
+          (else
+           (mk-loc place
+                   (+ (loc-x loc) (lvect-dx vec))
+                   (+ (loc-y loc) (lvect-dy vec)))))))
+                   
+;; cardinal directions to lists
+                   
+; order is N W E S
+(define (cardinal-dir-num dir)
+       (/ (- dir 1) 2))
+
+(define (get-cardinal-ref avector dir)
+       ;;(println "gcrc " avector)
+       (vector-ref avector
+               (cardinal-dir-num dir))
+               )
+
+(define (get-cardinal-lref alist dir)
+       ;;(println "gcrl " alist)
+       (list-ref alist
+               (cardinal-dir-num dir))
+               )
+
+               
\ No newline at end of file
diff --git a/worlds/haxima-1.002/lost-halls-mech.scm b/worlds/haxima-1.002/lost-halls-mech.scm
new file mode 100644 (file)
index 0000000..0982d4c
--- /dev/null
@@ -0,0 +1,716 @@
+(kern-mk-map 'm_losthalls_cpassage 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn r4 {{ {2 .. .. .. {4 {{ {{ ra rn rn rn rn rn rn "
+               "rn rn rn rn rn rc {{ {2 .. {8 .. .. {1 bb {{ r2 rn rn rn rn rn "
+               "rn rn rn rn rn {{ {{ {2 {4 {{ {2 .. .. {4 {{ ra rn rn rn rn rn "
+               "rn rn rn rn r8 {{ {3 .. .. {1 .. .. .. {4 {{ {{ rn rn rn rn rn "
+               "rn rn rn r4 .. {1 .. .. .. .. .. .. .. .. {1 {1 rn rn rn rn rn "
+               "rc {{ {{ {{ {2 .. {8 .. .. .. .. .. {c {{ {2 .. .. ra r8 rn rn "
+               "{{ {{ {{ {3 .. {c {{ {a .. .. .. {4 {{ {{ {2 .. {4 {{ {{ ra r8 "
+               "{1 bb {{ {2 .. {{ r7 {{ {2 .. .. {4 {{ {3 .. .. .. {5 {{ {{ {2 "
+               ".. .. {1 .. .. r9 r4 {{ {2 .. .. .. {1 .. .. .. .. .. {5 {{ {2 "
+               ".. .. .. .. .. {{ re {{ {2 .. .. .. {8 .. .. .. .. .. .. {1 .. "
+               ".. {8 .. .. .. {5 {{ {3 .. .. {8 {c {{ {a .. .. .. .. .. {8 .. "
+               "{4 {{ {2 .. {8 .. {1 .. .. {4 {{ {{ r7 {{ {2 .. .. .. {4 {{ {2 "
+               "{4 {{ {2 {4 {{ .. .. .. .. .. {5 {{ r6 {{ {2 .. .. .. bb {{ {2 "
+               ".. {1 .. {c {{ .. .. bb .. .. {4 {{ ra rd {8 .. .. {c {{ {b .. "
+               ".. .. {c {{ {{ .. .. .. .. .. .. {5 {{ {{ {{ {2 {4 {{ {{ {{ {2 "
+               "r1 r5 {{ {{ {{ .. .. .. .. .. .. .. .. .. .. .. {4 {{ r3 r1 r1 "
+               "rn rn rn rn rn {{ {2 .. bb .. .. .. .. .. {4 {{ r4 {1 r2 rn rn "
+               "rn rn rn rn rn r5 .. {8 {8 .. .. .. .. .. {8 {1 rn r1 rn rn rn "
+               "rn rn rn rn rn r4 {c {{ {{ {2 .. .. .. bb {{ r3 rn rn rn rn rn "
+               "rn rn rn rn rn r4 {{ {{ rf .. .. .. {4 {{ r3 rn rn rn rn rn rn "
+               "rn rn rn rn rn r4 bb {1 .. .. .. .. {4 {{ r2 rn rn rn rn rn rn "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_cwall 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn r4 bb "
+               "rn rn rn rn rn rn rn rn rn rn r8 r8 rn rn rn rn rn rn rn rn r1 "
+               "rn rn rn rn rn rn rn rn r8 rc {{ {a ra rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn r8 rc {4 {{ bb {{ {2 ra r8 r8 r8 r8 r8 rn rn "
+               "rn rn rn rn rn r4 {{ {{ {2 {5 {{ {{ {2 {4 {{ {2 {4 {{ {{ r2 rn "
+               "rn rn rn rn r8 bb {5 {{ {2 .. {1 {1 .. {4 {{ {{ .. {1 {1 r2 rn "
+               "rn rn rn rc .. {4 {{ {a {8 .. .. r7 .. .. {4 {{ .. .. r3 rn rn "
+               "rn rn rc .. .. .. {5 {{ {{ r3 r1 rn r1 r1 rd {1 .. .. r2 rn rn "
+               "rn r4 {8 {8 .. r1 r5 {{ {{ r2 rn rn r8 rc .. .. .. r3 rn rn rn "
+               "rn r4 {{ {{ {2 r8 r8 r1 r1 rn rn r4 .. .. bb .. .. r2 rn rn rn "
+               "rn rn r5 {{ {2 .. .. ra rn rn rn r4 .. .. {8 {8 .. r2 rn rn rn "
+               "rn rn r4 {{ {2 .. bb .. r2 rn r8 rn r5 {4 {{ {{ .. r2 rn rn rn "
+               "rn rn r4 {1 .. .. .. .. r2 rc {{ ra rc .. {5 {{ .. ra rn rn rn "
+               "rn rn rn rd .. .. .. rb rc {{ {{ {{ {2 .. .. {1 .. .. r2 rn rn "
+               "rn rn rc {8 {8 {8 .. .. {8 {9 {1 {1 .. {8 .. r3 .. .. ra rn rn "
+               "rn r4 {4 {{ {{ {{ {2 {4 {{ {{ {2 .. {c {{ r3 rn r5 .. .. r2 rn "
+               "rn r4 {4 {{ r2 r4 .. .. {4 {{ {2 bb {{ {{ r2 rn r4 .. r2 rn rn "
+               "rn rn r1 r1 rn rn r1 r5 .. r7 .. {4 {{ r3 rn rn rn r1 rn rn rn "
+               "rn rn rn rn rn rn rn rn r1 r4 .. r3 r1 rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn r1 rn rn rn rn rn rn rn rn rn r8 "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn r4 {C "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_cpassage2 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn r4 {8 .. .. .. r2 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn r8 rc {{ {2 .. r3 rn r8 rn rn rn rn rn rn "
+               "rn rn rn rn rn r8 rc {{ {{ {3 .. .. r2 rc .. ra rn rn rn rn rn "
+               "rn rn rn rn r8 {4 {{ {{ {{ {2 .. .. re .. .. .. rn rn rn rn rn "
+               "rn rn rn r4 .. .. {1 {1 {1 .. .. .. .. .. bb .. rn rn rn rn rn "
+               "rn rn rn rc .. .. .. .. .. .. .. {8 .. .. .. .. .. .. .. ra rn "
+               "rn r8 r4 {{ {a .. .. .. .. .. {4 {{ {a .. .. .. {8 {8 .. .. r2 "
+               "r4 .. re {{ {{ .. .. .. .. .. {4 {{ {{ {a .. .. {{ {{ {2 r3 rn "
+               "rc .. .. {1 {1 .. .. .. bb .. {4 {{ {7 {{ {2 .. {5 {{ {2 ra r8 "
+               ".. .. .. .. .. bb .. .. .. .. .. {1 .. {1 .. .. .. bb .. .. .. "
+               ".. .. .. .. .. rd .. .. .. .. .. .. {8 {8 .. .. .. .. .. .. .. "
+               "r5 .. .. r7 .. .. .. {8 .. .. .. r7 {{ {{ {2 .. .. {8 {8 {8 .. "
+               "rn r1 r1 r4 {8 .. {4 {{ {2 .. rb rc {{ {3 .. .. {4 {{ {{ {{ r3 "
+               "rn rn rn rc {{ {8 .. {1 .. .. {4 {{ {3 .. .. .. {4 {{ {{ r3 rn "
+               "rn rn r4 {{ {{ {{ {a .. .. .. .. {1 .. .. bb .. .. {1 r3 rn rn "
+               "rn rn rn r5 {{ {{ {{ {2 .. .. .. .. .. .. .. .. .. r3 rn rn rn "
+               "rn rn rn rn rn .. .. .. .. {8 .. .. .. .. .. .. .. r2 rn rn rn "
+               "rn rn rn rn rn r1 r5 .. r7 {{ {2 .. .. r7 .. r3 r1 rn rn rn rn "
+               "rn rn rn rn rn rn rn r1 r4 {{ {2 .. .. r2 r1 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn r5 .. .. .. ra rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn r4 .. .. .. .. r2 rn rn rn rn rn rn "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_croom 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn r4 .. .. .. .. .. .. r2 rn rn rn rn rn r4 bb "
+               "rn rn rn rn rn rn r4 .. .. .. .. .. .. r2 rn rn rn rn rn rn r1 "
+               "rn rn rn rn rn xx xx bb w+ xx d, xx w+ xx xx rn rn rn rn rn rn "
+               "rn rn rn rn rn rc .. .. .. .. .. .. .. .. ra r8 rn rn rn rn rn "
+               "rn rn rn rn rn .. .. .. .. .. .. .. .. {4 {{ {{ rn rn rn rn rn "
+               "rn rn r4 {{ {{ .. .. .. bb .. .. .. .. .. .. .. {{ ra rn rn rn "
+               "rn r8 xx {5 {{ .. .. .. .. .. .. .. .. .. .. .. {1 .. xx r8 r8 "
+               "rc .. xx .. {1 .. .. bb xx xx w+ xx xx xx .. .. .. .. xx .. .. "
+               ".. .. w+ .. .. .. .. xx ,, ,, ,, ,, ,, rr .. .. .. .. w+ .. .. "
+               ".. .. xx .. .. .. .. xx ,, ,, .. ,, ,, xx .. .. .. .. rr .. .. "
+               ".. .. d, .. .. .. .. w+ ,, ,, ,, ,, ,, w+ .. bb .. .. d, .. .. "
+               ".. .. rr .. .. .. .. xx ,, ,, .. bb .. xx .. .. .. .. xx .. .. "
+               ".. .. w+ .. .. .. .. rr .. ,, ,, .. ,, xx .. .. .. .. w+ .. .. "
+               ".. r3 xx .. {8 .. .. rr xx d, xx w+ xx rr .. .. {8 .. xx .. .. "
+               "r1 r4 bb {4 {{ .. .. .. .. .. ,, .. .. .. .. .. {{ {a xx r1 r1 "
+               "rn rn r1 r5 {1 .. .. .. ,, .. .. .. .. .. .. .. {{ {{ xx rn rn "
+               "rn rn rn rn rn {{ {a .. .. .. .. .. .. .. .. .. {{ r2 rn rn rn "
+               "rn rn rn rn rn {{ {{ {2 .. .. .. .. .. .. .. r3 r1 rn rn rn rn "
+               "rn rn rn rn rn r1 xx xx w+ xx d, xx w+ rr xx xx rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rc .. .. .. .. .. .. r2 rn rn rn rn rn r8 "
+               "rn rn rn rn rn rn r4 .. .. .. .. .. .. .. r2 rn rn rn rn r4 {C "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_cruin 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn r4 .. bb .. .. .. .. r2 rn rn rn rn rn r4 bb "
+               "rn rn rn rn rn rn r4 .. {8 .. .. .. .. r2 rn rn rn rn rn rn r1 "
+               "rn rn rn rn rn xx xx bb {{ xx .. rr w+ xx xx rn rn rn rn rn rn "
+               "rn rn rn rn rn rc .. .. {1 .. .. bb .. .. ra r8 rn rn rn rn rn "
+               "rn rn rn rn rn .. .. .. .. .. .. .. .. {4 {{ {{ rn rn rn rn rn "
+               "rn rn rr {{ {{ .. .. .. bb .. .. .. .. .. .. .. {{ ra rn rn rn "
+               "rn r8 xx {5 {{ .. .. .. .. .. .. .. .. .. bb .. {1 .. xx r8 r8 "
+               "rc .. xx .. {1 .. .. rr xx .. w+ bb .. rr .. .. .. .. xx .. .. "
+               ".. .. rr bb .. .. .. xx .. ,, ,, .. .. rr .. .. .. .. {8 bb .. "
+               ".. bb {{ {2 .. .. .. bb ,, .. .. .. ,, xx .. .. .. {4 {{ {2 .. "
+               ".. .. {9 .. .. bb .. w+ .. ,, ,, ,, ,, d, .. bb .. .. d, .. .. "
+               ".. {4 {C bb .. .. .. .. ,, .. .. bb .. xx .. ,, .. bb .. .. .. "
+               ".. bb w+ .. .. .. .. rr .. ,, .. .. ,, .. .. .. .. .. w+ bb .. "
+               ".. r3 xx .. {8 .. .. xx rr .. rr .. xx rr bb .. {8 .. xx .. .. "
+               "r1 r4 bb {4 {{ .. .. .. .. bb .. .. .. .. .. .. {{ {a xx r1 r1 "
+               "rn rn rr r5 {1 .. .. .. .. .. .. .. .. .. .. .. {{ {{ xx rn rn "
+               "rn rn rn rn rn {{ {a .. .. .. .. .. bb .. .. .. {{ r2 rn rn rn "
+               "rn rn rn rn rn {{ {{ {2 {8 bb .. .. .. .. .. r3 r1 rn rn rn rn "
+               "rn rn rn rn rn rr xx xx {{ xx .. .. bb rr xx xx rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rc {1 .. .. .. .. .. r2 rn rn rn rn rn r8 "
+               "rn rn rn rn rn rn r4 .. .. bb .. .. .. bb r2 rn rn rn rn r4 {C "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_cblock 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn r4 bb "
+               "rn rn rn rn rn rn rn rn r8 rn rn rn rn rn rn rn rn rn rn rn r1 "
+               "rn rn rn rn rn xx xx xx bb xx xx r8 xx xx xx rn rn rn rn rn rn "
+               "rn rn rn rn rn rc .. .. .. .. .. .. .. .. ra r8 rn rn rn rn rn "
+               "rn rn rn rn rn .. .. .. .. .. .. .. .. {4 {{ {{ rn rn rn rn rn "
+               "rn rn rr {{ {{ xx xx ,, ,, xx xx xx w+ w+ xx xx {{ ra rr rn rn "
+               "rn rn xx {5 {{ rr ,, ,, .. ,, xx @@ @@ bb @@ xx {1 .. xx rn rn "
+               "rn rn xx .. {1 ws ,, .. ,, ,, xx ,, ,, ,, ,, rr .. .. bb r2 rn "
+               "rn rn xx bb .. bb ,, ,, ,, ,, ,, ,, ,, .. ,, w+ .. .. xx rn rn "
+               "rn r4 bb .. .. rr ,, ,, ,, ,, xx ,, ,, ,, ,, rr .. .. xx rn rn "
+               "rn rn rr .. .. ws .. .. ,, ,, xx xx bb w+ xx xx .. .. xx rn rn "
+               "rn rn xx bb .. xx ,, ,, ,, ,, xx ,, ,, ,, ,, xx .. .. rr rn rn "
+               "rn rn xx .. .. ,, ,, bb ,, ,, ,, ,, ,, .. ,, ,, .. .. rr rn rn "
+               "rn rn rr .. {8 ,, ,, ,, .. ,, ,, ,, ,, ,, ,, ,, {8 .. xx rn rn "
+               "rn rn xx {4 {{ xx ,, .. ,, ,, xx ,, .. ,, ,, xx {{ {a xx rn rn "
+               "rn rn rn r5 {1 rr rr ,, ,, xx xx xx rr ws xx xx {{ {{ xx rn rn "
+               "rn rn rn rn rn {{ {a .. .. .. .. .. .. .. .. {4 {{ r2 rn rn rn "
+               "rn rn rn rn rn {{ {{ {2 .. .. .. .. .. .. .. r3 r1 rn rn rn rn "
+               "rn rn rn rn rn rr xx xx rr rr xx rr xx xx xx xx rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn r8 "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn r4 {C "
+       )
+       )
+
+(kern-mk-map 'm_losthalls_special 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn rn "
+               "rn rn r4 .. .. .. .. .. .. .. .. .. .. .. .. {8 .. .. r2 rn rn "
+               "rn rn rn rn rn .. .. .. bb .. .. .. .. .. {4 {{ rn rn rn rn rn "
+               "rn rn rn rn rn rd .! {8 {8 .. .! .. .. .! {8 {1 rn rn rn rn rn "
+               "rn rn rn rn rn {{ {e {{ {{ {2 .. .. .. bb {{ {2 rn rn rn rn rn "
+               "rn rn rn rn rn {5 {{ {{ rf .! .. .! {4 {{ {{ r3 rn rn rn rn rn "
+               "rn rn rn rn rn .! bb .! .! .! .! .! .! {A {{ r2 rn rn rn rn rn "
+       )
+       )
+
+
+(kern-mk-map 'm_losthalls_stairu 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. ,, .. ,, .. .. .. ,, .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. ,, .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. ,, ,, ,, ,, .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. ,, .. .. .. ,, ,, ,, ,, .. .. xx rn rn rn "
+               "rn rn rn xx .. .. xx ,, ,, ,, ,, ,, ,, ,, xx .. .. xx rn rn rn "
+               "rn rn rn xx .. xx xx xx cc cc cc cc cc xx xx xx .. xx rn rn rn "
+               "rn rn rn xx .. xx xx xx ,, ,, ,, ,, ,, xx xx xx .. xx rn rn rn "
+               "rn rn rn xx .. .. xx xx cc cc cc cc cc xx xx .. .. xx rn rn rn "
+               "rn rn rn xx .. .. xx xx xx ,, ,, ,, xx xx xx .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. xx xx cc cc cc xx xx .. .. .. xx rn rn rn "
+               "rn rn rn xx xx .. .. xx xx ,, ,, ,, xx xx .. .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx xx cc cc cc xx xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx ,, ,, ,, xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx d, d, d, xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn rn "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_rhall 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn xx .. ,, .. .. .. xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx .. .. .. ,, .. xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx .. .. ,, ,, .. rr rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx rr xx bb .. .. .. .. xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. bb .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. @@ @@ @@ @@ .. .. .. @@ @@ @@ @@ .. xx rn rn rn "
+               "xx rr xx xx .. .. .. .. .. .. ,, .. .. .. .. .. .. xx rr xx xx "
+               ".. bb .. .. .. @@ @@ @@ @@ .. .. .. @@ @@ @@ @@ .. .. .. .. .. "
+               ".. .. .. ,, .. .. ,, .. .. .. .. .. .. .. .. .. .. .. .. ,, .. "
+               ",, .. ,, ,, .. .. .. .. bb .. .. .. .. .. ,, .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. ,, .. .. .. bb .. .. ,, .. ,, "
+               ",, .. .. .. .. @@ @@ @@ @@ .. ,, .. @@ @@ @@ @@ .. .. .. .. .. "
+               "xx xx rr xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx xx rr xx "
+               "rn rn rn xx .. @@ bb @@ @@ .. .. .. @@ @@ @@ @@ .. xx rn rn rn "
+               "rn rn rn rr .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx .. .. .. .. .. xx xx rr xx rn rn rn rn "
+               "rn rn rn rn rn rn r4 bb .. .. ,, .. ,, xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx .. .. ,, bb .. rr rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx .. ,, .. .. .. xx rn rn rn rn rn rn rn "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_rwall 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn r8 rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx rr bb rr xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. pp .. .. .. .. bb pp .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn rr .. pp bb pp .. .. .. .. .. pp .. pp .. rr rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. rr rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. bb .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. bb .. pp .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn rr .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. pp .. pp .. .. .. .. .. pp .. pp .. bb r2 rn rn "
+               "rn rn rn xx .. .. bb .. .. .. .. .. .. .. .. bb .. xx rn rn rn "
+               "rn rn rn rr .. .. .. pp .. .. .. .. .. pp .. .. .. xx rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx rr xx xx bb xx rr rr xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn r1 rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_rrooms 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn xx .. .. ,, xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx xx d, xx xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rr .. .. .. xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx .. ,, .. xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. xx xx .. .. .. rr xx .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. .. xx xx d, xx xx ,, .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. ,, .. ws .. .. .. ws ,, ,, .. .. xx rn rn rn "
+               "rn rn rn xx xx .. ,, .. xx .. ,, .. xx .. .. ,, xx xx rn rn rn "
+               "xx xx xx rr xx xx d, xx xx .. .. .. xx xx d, xx rr xx rr xx xx "
+               ".. xx .. .. .. xx .. .. .. .. .. .. .. .. .. xx .. .. .. xx ,, "
+               ".. d, ,, .. .. d, .. ,, .. ,, .. ,, .. .. ,, d, .. ,, .. d, .. "
+               ",, xx .. .. .. xx .. .. .. .. ,, .. .. .. .. xx .. .. .. xx .. "
+               "xx xx xx xx xx xx d, rr xx .. .. .. xx xx d, xx xx xx xx xx xx "
+               "rn rn rn rr xx .. ,, .. xx .. .. ,, xx .. .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. ,, ,, ws .. ,, .. ws .. ,, ,, .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. xx xx d, xx xx .. ,, .. .. xx rn rn rn "
+               "rn rn rn xx xx .. .. xx rr .. .. .. xx xx .. .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx xx ,, .. .. xx xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx .. ,, .. rr rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx xx d, xx xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx .. .. .. xx rn rn rn rn rn rn rn rn "
+       )
+       )
+
+(kern-mk-map 'm_losthalls_rwall 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn r8 rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx rr bb rr xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. pp .. .. .. .. bb pp .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn rr .. pp bb pp .. .. .. .. .. pp .. pp .. rr rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. rr rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. bb .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. bb .. pp .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn rr .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. pp .. pp .. .. .. .. .. pp .. pp .. bb r2 rn rn "
+               "rn rn rn xx .. .. bb .. .. .. .. .. .. .. .. bb .. xx rn rn rn "
+               "rn rn rn rr .. .. .. pp .. .. .. .. .. pp .. .. .. xx rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx rr xx xx bb xx rr rr xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn r1 rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+       )
+       )
+       
+(kern-mk-map 'm_losthalls_rrockfall 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn xx r8 rn rn r8 rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb ra rc bb ra xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rr rd bb .. .. bb xx rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx .. .. ,, bb .. rr xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. bb .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn rr .. .. bb {8 .. .. .. bb .. bb .. .. .. xx rn rn rn "
+               "rn rn rn xx .. {4 {{ {{ {2 .. .. .. .. .. bb {8 .. xx rn rn rn "
+               "rn xx xx xx .. .. {1 bb .. bb .. r3 r5 .. {4 {{ {2 xx rr xx rn "
+               "r4 bb .. bb .. bb {4 {{ {2 bb r3 r8 r4 bb .. {1 .. .. bb ra rn "
+               "rn r5 bb .. .. .. bb {1 rf .. r6 bb re .. .. bb .. .. bb .. r2 "
+               "rn rn rd .. .. .. bb r7 bb bb re bb .. bb {8 .. .. .. bb r3 rn "
+               "rn r4 bb .. .. .. .. ra rd .. bb r7 .. {4 {{ {2 .. bb .. ra rn "
+               "rn rn r5 .. .. bb .. bb .. rf bb re .. bb bb bb .. .. .. bb r2 "
+               "rn xx xx xx .. bb .. .. .. .. .. .. .. bb rf bb .. xx xx xx rn "
+               "rn rn rn xx .. .. bb .. .. bb .. .. bb .. bb rf .. rr rn rn rn "
+               "rn rn rn xx .. {4 {{ {2 bb .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx xx .. {1 .. bb .. .. .. bb .. bb .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx bb .. .. .. bb xx xx rr xx rn rn rn rn "
+               "rn rn rn rn rn rn rn xx .. .. bb .. r3 rr rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb r3 r5 bb r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx r1 rn rn r1 rn xx rn rn rn rn rn rn rn "
+       ))
+
+
+
+;probability for edge terrains... out of 83
+(define losthalls-terrain-edges
+       (list
+               (list 20 'm_losthalls_cwall #f)
+               (list 30 'm_losthalls_cblock #f)
+               (list 50 'm_losthalls_cpassage #t)
+               (list 60 'm_losthalls_cpassage2 #t)
+               (list 75 'm_losthalls_cruin #t)
+               (list 90 'm_losthalls_croom #t)
+               (list 999 'm_test2templ_room #t 'test2-room-n 'test2-room-w 'test2-room-e 'test2-room-s)
+       ))
+
+;probability for area terrains... out of 149
+(define losthalls-terrain-area
+       (list
+               (list 30 'm_losthalls_cwall)
+               (list 40 'm_losthalls_cblock)
+               (list 65 'm_losthalls_cpassage)
+               (list 95 'm_losthalls_cpassage2)
+               (list 115 'm_losthalls_cruin)
+               (list 990 'm_losthalls_croom)
+       ))
+       
+(define losthalls-passable-edges
+       (list
+               (list 60 'm_losthalls_cpassage)
+               (list 90 'm_losthalls_cpassage2)
+               (list 110 'm_losthalls_croom)
+               (list 999 'm_test2templ_room 'test2-room-n 'test2-room-w 'test2-room-e 'test2-room-s)
+       ))
+       
+;probability for edge terrains... out of 83
+(define losthalls-ruin-edges
+       (list
+               (list 20 'm_losthalls_rwall #f)
+               (list 30 'm_losthalls_rrockfall #f)
+               (list 50 'm_losthalls_rhall #t)
+               (list 60 'm_losthalls_rhall #t)
+               (list 75 'm_losthalls_rrooms #t)
+               (list 90 'm_losthalls_rhall #t)
+               (list 999 'm_test2templ_room #t 'test2-room-n 'test2-room-w 'test2-room-e 'test2-room-s)
+       ))
+
+;probability for area terrains... out of 149
+(define losthalls-ruin-area
+       (list
+               (list 30 'm_losthalls_rwall)
+               (list 40 'm_losthalls_rwall)
+               (list 65 'm_losthalls_rrooms)
+               (list 95 'm_losthalls_rrockfall)
+               (list 115 'm_losthalls_rhall)
+               (list 990 'm_losthalls_rhall)
+       ))
+
+;map areas replaced by the various blitting ops
+(define losthalls-room-blitstats
+       (prmap-mk-blitstats 21 21 5 4 5))
+       
+(define losthalls-ruin-blitstats
+       (prmap-mk-blitstats 21 21 4 4 4))
+       
+;parameters to random number generators
+(define losthalls-random-type-ew (prmap-mk-prng-params (deep-rno) (deep-rno) (deep-rno) (deep-rno) 83))
+(define losthalls-random-type-ns (prmap-mk-prng-params (deep-rno) (deep-rno) (deep-rno) (deep-rno) 83))
+(define losthalls-random-type-area (prmap-mk-prng-params (deep-rno) (deep-rno) (deep-rno) (deep-rno) 149))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; critters
+
+;; critter types, list of lists of (value, critter tag)
+(define losthalls-monster-types
+       (list 
+               (list 
+                       (list 100 'bat)
+               )
+               (list
+                       (list 100 'rat)
+                       (list 200 'bat)
+               )
+               (list
+                       (list 100 'giant-spider)
+                       (list 150 'queen-spider)
+               )
+               (list
+                       (list 100 'cave-goblin-slinger)
+                       (list 200 'cave-goblin-berserker)
+                       (list 250 'cave-goblin-priest)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'cave-goblin-berserker-m)
+                       (list 300 'troll-m)
+                       (list 350 'troll-geomancer-m)
+               )
+               (list
+                       (list 100 'green-slime)
+                       (list 200 'yellow-slime)
+               )       
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'cave-goblin-berserker-m)
+                       (list 150 'troll-m)
+                       (list 350 'gint-warrior-m)
+                       (list 400 'gint-mage-m)
+               )
+       )
+)
+
+;; group types list of lists of
+;; (randomnumber offset, type index, total value, number)
+(define losthalls-group-types
+       (list
+               (list 10 0 100 "1d4+3") ;bats
+               (list 20 1 100 "1d4+3") ;rats
+               (list 30 1 200 "1d6+4") ;bats n rats
+               (list 40 5 100 "1d3+2") ;slime
+               (list 50 2 100 "1d4+3") ;spiders
+               (list 60 3 100 "1d3+1") ;goblins
+               (list 70 2 110 "1d4+3") ;spiders 1q
+               (list 90 2 150 "1d6+4") ;spiders +qs
+               (list 100 5 200 "1d6+3") ;slime+
+               (list 110 3 200 "1d6+4") ;goblin war
+               (list 140 4 300 "1d6+3") ;trolls
+               (list 160 6 350 "1d6+3") ;gint
+               (list 200 3 210 "1d6+5") ;goblin war +p
+               (list 220 3 250 "2d4+4") ;goblin tribe
+               (list 230 4 350 "1d6+5") ;trolls +m
+               (list 240 6 400 "2d4+4") ;gint + m
+       )
+)
+
+; creates new objects for a room
+;    uses lost halls critter types, and difficulty increases a bit northwards and a lot downwards
+(define (losthalls-room-init-contents kplace roomdata)
+       (let* (
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (rzloc (prmap-roomdata-z roomdata))
+                       (distance (+ (* rzloc 20) ryloc))
+               )
+               (if (and (null? (kern-place-get-beings kplace))
+                               (< (kern-dice-roll "1d100") 
+                                       (min 75 (+ 25 (* 2 distance)))))
+                       (begin 
+                       (map (lambda (monster)
+                               (begin 
+                                       (prmap-room-addmonster kplace monster)))
+                               (prmap-mk-monster-group losthalls-group-types losthalls-monster-types 
+                                       (string-append "1d" (number->string (min 300 (ceiling (* 25 distance)))))
+                                       (+ 250 (* 25 distance) (kern-dice-roll "1d200"))
+                                       )))
+               )
+       ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Time memory - move to prmap?
+
+(define (losthalls-timekeeper-mkobj time)
+  (list 'losthalls time))
+(define (losthalls-timekeeper-get tk) (cadr tk))
+(define (losthalls-timekeeper-set! tk val) (set-car! (cdr mm) val))
+
+(mk-obj-type 't_losthalls_timekeeper nil nil layer-none nil)
+
+(define (losthalls-timekeeper-mk)
+  (bind (kern-obj-set-visible (kern-mk-obj t_losthalls_timekeeper 1) #f)
+        (losthalls-timekeeper-mkobj (map - game-start-time
+                        (time-mk 0 0 0 1 1 1)))))
+
+
+(define (losthalls-room-store-time kplace roomdata)
+       (let* (
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (rzloc (prmap-roomdata-z roomdata))
+                       (distance (+ (* rzloc 20) ryloc))
+               )
+               (if (and (null? (kern-place-get-beings kplace))
+                               (< (kern-dice-roll "1d100") 
+                                       (min 75 (+ 25 (* 2 distance)))))
+                       (begin 
+                       (map (lambda (monster)
+                               (begin 
+                                       (prmap-room-addmonster kplace monster)))
+                               (prmap-mk-monster-group losthalls-group-types losthalls-monster-types 
+                                       (string-append "1d" (number->string (min 300 (ceiling (* 25 distance)))))
+                                       (+ 250 (* 25 distance) (kern-dice-roll "1d200"))
+                                       )))
+               )
+       ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; timer object
+
+;; one hour wait
+(define (losthalls-respawn-time? oldtime)
+  (let ((curtime (kern-get-time)))
+    (or (> (time-year curtime) (time-year oldtime))
+        (> (time-month curtime) (time-month oldtime))
+        (> (time-week curtime) (time-week oldtime))
+        (> (time-day curtime) (time-day oldtime))
+        (and (= (time-day curtime) (time-day oldtime))
+             (> (time-hour curtime) (time-hour oldtime))))))
+
+(define (losthalls-timer-time timer) (cadr (gob timer)))
+(define (losthalls-timer-set! timer val) (set-car! (cdr (gob timer)) val))
+
+(mk-obj-type 't_losthalls_timer nil nil layer-none nil)
+
+(define (losthalls-mk-timer)
+  (bind (kern-obj-set-visible (kern-mk-obj t_losthalls_timer 1) #f)
+        (list 'timer (time-mk -1 0 0 0 0 0))))
+      
+(define (losthalls-timer-check kplace)
+       (let ((timerlist (kplace-get-objects-of-type kplace t_losthalls_timer)))
+               (if (equal? (length timerlist) 0)
+                       (let ((newtimer (losthalls-mk-timer)))
+                               (kern-obj-put-at newtimer (list kplace 0 0))
+                               (losthalls-timer-set! newtimer (kern-get-time))
+                               #t
+                               )
+                       (let* ((timer (car timerlist))
+                                       (respawn (losthalls-respawn-time? (losthalls-timer-time timer))))
+                               (losthalls-timer-set! timer (kern-get-time))
+                               respawn
+                               ))
+               ))
+          
+(define (losthalls-do-prmap-content kplace roomdata)
+       (if (losthalls-timer-check kplace)
+               (losthalls-room-init-contents kplace roomdata)))
+       
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; handles
+  
+(define (losthalls-link-factory x y z map dir)
+               (list 'm_losthalls_cpassage2 nil)
+               )  
+
+(define (losthalls-link-factory-ruin x y z map dir)
+               (list 'm_losthalls_rhall nil)
+               )  
+  
+(define (losthalls-init-cohesion mapdata ruindata)
+       (if (list-ref mapdata 10)
+               (begin
+                       ;;(kern-log-msg "begin cohesion check")
+                       (prmap-ensure-cohesion mapdata -3 3 1 7 0 losthalls-link-factory)
+                       (prmap-ensure-cohesion ruindata 0 5 0 5 1 losthalls-link-factory-ruin)
+                       ;;(kern-log-msg "end cohesion check")
+                       (mutable-list-set mapdata 10 #f)
+               )))
+  
+(define (losthalls-room-custom-hardlinks rxloc ryloc rzloc hardlinks)
+       (vector-merge
+               (prmap-room-hardlinkentry-get rxloc ryloc rzloc hardlinks)
+               (vector
+                       (if (> ryloc 7) (list nil 'm_losthalls_cwall) nil)
+                       (if (< rxloc -3) (list nil 'm_losthalls_cwall) nil)
+                       (if (> rxloc 3) (list nil 'm_losthalls_cwall) nil)
+                       (if (< ryloc 1) (list nil 'm_losthalls_cwall) nil)
+               )
+       ))
+       
+(define (losthalls-ruin-custom-hardlinks rxloc ryloc rzloc hardlinks)
+       (vector-merge
+               (prmap-room-hardlinkentry-get rxloc ryloc rzloc hardlinks)
+               (vector
+                       (if (> ryloc 4) (list nil 'm_losthalls_rwall) nil)
+                       (if (< rxloc 1) (list nil 'm_losthalls_rwall) nil)
+                       (if (> rxloc 4) (list nil 'm_losthalls_rwall) nil)
+                       (if (< ryloc 1) (list nil 'm_losthalls_rwall) nil)
+               )
+       ))
+
+(define (losthalls-room-handle-deeps kplace kplayer)
+       (let* (
+                       (roomdata (get-roomdata kplace))
+                       (smapdata (prmap-get-mapdata (eval 'p_lost_halls_r1)))
+                       (mapdata 
+                               (if (zero? (prmap-roomdata-z roomdata))
+                                       smapdata
+                                       (prmap-get-mapdata (eval 'p_lost_halls_r2)))
+                       )
+               )
+               (prmap-room-freeze-current smapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)
+               (prmap-room-cleanout kplace)
+               (prmap-room-thaw kplace smapdata)               
+               (prmap-room-blit-map kplace roomdata mapdata)
+               (losthalls-do-prmap-content kplace roomdata)
+       ))
+       
+(define (losthalls-room-handle-staird kplace kplayer)
+       (let* (
+                       (roomdata (get-roomdata kplace))
+                       (mapdata (prmap-get-mapdata (eval 'p_lost_halls_r1)))
+               )
+               (prmap-room-freeze-current mapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)         
+               (prmap-room-blit-map-edges kplace roomdata mapdata)
+               ;;(losthalls-room-init-contents kplace roomdata)
+       ))
+       
+(define (losthalls-room-handle-stairu kplace kplayer)
+       (let* (
+                       (roomdata (get-roomdata kplace))
+                       (smapdata (prmap-get-mapdata (eval 'p_lost_halls_r1)))
+                       (mapdata (prmap-get-mapdata (eval 'p_lost_halls_r2)))
+               )
+               (prmap-room-freeze-current smapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)         
+               (prmap-room-blit-map-edges kplace roomdata mapdata)
+               (kern-place-set-neighbor south kplace nil)
+               ;;(losthalls-room-init-contents kplace roomdata)
+       ))
+       
+(define (losthalls-room-handle-croom kplace kplayer)
+       (let* (
+                       (roomdata (get-roomdata kplace))
+                       (mapdata (prmap-get-mapdata (eval 'p_lost_halls_r1)))
+               )
+               (prmap-room-freeze-current mapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)         
+               (prmap-room-blit-map-edges kplace roomdata mapdata)
+               ;;(losthalls-room-init-contents kplace roomdata)
+       ))
+       
+(define (losthalls-room-handle-rroom kplace kplayer)
+       (let* (
+                       (roomdata (get-roomdata kplace))
+                       (smapdata (prmap-get-mapdata (eval 'p_lost_halls_r1)))
+                       (mapdata (prmap-get-mapdata (eval 'p_lost_halls_r2)))
+               )
+               (prmap-room-freeze-current smapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)         
+               (prmap-room-blit-map-edges kplace roomdata mapdata)
+               ;;(losthalls-room-init-contents kplace roomdata)
+       ))
+
+(define (losthalls-room-handle-start kplace kplayer)
+       (let* (
+               (roomdata (get-roomdata (eval 'p_lost_halls_r1)))
+               (mapdata (prmap-get-mapdata (eval 'p_lost_halls_r1)))
+               (ruindata (prmap-get-mapdata (eval 'p_lost_halls_r2)))
+               )
+               (losthalls-init-cohesion mapdata ruindata)
+               (prmap-room-freeze-current mapdata)
+               (prmap-roomdata-setxyz roomdata 0 0 0)
+               (kern-place-set-neighbor north kplace (eval 'p_lost_halls_r1))
+       ))      
+       
+(define (losthalls-handle-rshrine kplace kplayer)
+       (if (and (quest-data-assigned? 'questentry-wise)
+                       (null? (quest-data-getvalue 'questentry-warritrix 'reached)))
+               (begin
+                       (kern-obj-put-at (mk-corpse2
+                              '(
+                               (1 t_rune_l_init)
+                               (1 t_armor_chain_4)
+                               (1 t_chain_coif_4)
+                               (1 t_sword_4)
+                               (1 t_shield_4)
+                               (1 t_warritrix_orders)
+                               )) (list p_lost_halls_rshrine 10 10))
+                       (drop-random-corpses p_lost_halls_rshrine 5)
+                       (quest-data-update 'questentry-warritrix 'reached 1)
+               )
+       )
+       )
+       
diff --git a/worlds/haxima-1.002/lost-halls.scm b/worlds/haxima-1.002/lost-halls.scm
new file mode 100644 (file)
index 0000000..a406e77
--- /dev/null
@@ -0,0 +1,745 @@
+;;----------------------------------------------------------------------------
+;; Troll Cave
+;;
+;; Big underground complex; created by some civilized race, now a ruin
+;; inhabited by trolls and other monsters.
+;;----------------------------------------------------------------------------
+
+(kern-load "warritrix.scm")
+(kern-mk-place 
+       'p_lost_halls_entrance
+       "Gate to the Lost Halls"
+       s_dungeon          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn r4 {8 .. bb .. {8 .. .. .. .. .. .. {8 r2 rn rn rn rn "
+               "rn rn rn r4 {{ bb .. {c {{ {2 .. .. .. bb {c {{ r2 rn rn rn rn "
+               "rn rn rn r4 {{ {2 {4 {{ {{ bb .. .. .. {4 {{ rb r8 rn rn rn rn "
+               "rn rn rn rn r5 .. .. {5 {{ {2 .. .. .. {4 {{ {{ {2 r2 rn rn rn "
+               "rn rn rn rn rn rd .. .. {1 .. .. .. .. r7 {{ {{ {a r2 rn rn rn "
+               "rn rn rn rn r4 .. .. bb .. .. .. .. .. ra rd {{ {{ r2 rn rn rn "
+               "rn rn rn rn r8 rd {8 .. .. .. .. .. {4 {{ {{ {7 {{ r2 rn rn rn "
+               "rn rn rn rc {{ {6 {{ {a .. .. .. .. .. {1 bb .. rb rn rn rn rn "
+               "rn rn r4 {{ {3 {4 {{ {{ {2 .. .. .. .. .. .. {4 {{ r2 rn rn rn "
+               "rn rn r4 {1 xx xx xx {{ {2 .. .. .. .. xx xx xx {{ r2 rn rn rn "
+               "rn xx xx xx xx xx xx {1 .. .. .. .. .. xx xx xx xx xx xx rn rn "
+               "^^ ^^ ^^ {{ xx xx xx .. .. .. .. .. .. xx xx xx {{ ^^ ^^ ^^ rn "
+               "^^ ^^ ^^ {{ {a {8 .. .. .. .. .. .. .. .. {4 {{ {{ ^^ ^^ ^^ rn "
+               "^^ {{ {{ {{ {{ {{ {2 .. .. .. .. .. tf {8 bb {{ {{ ^^ ^^ ^^ ^^ "
+               "{{ {{ {C bb {{ {{ {2 .. .. .. .. {4 {{ {{ {{ {{ {{ {{ {{ ^^ ^^ "
+               "{1 t3 t5 .. {9 {9 .. tf .. .. .. .. {1 {5 {{ bb {{ ^^ ^^ ^^ ^^ "
+               "{8 ta tt bb {{ {{ {2 .. .. .. .. .. .. .. {5 {{ {{ {{ ^^ ^^ ^^ "
+               "{{ t% te {# {{ {3 .. .. .. .. .. .. {8 {8 .. {1 tf {{ ^^ ^^ ^^ "
+               "{{ {{ {e {{ {3 {8 .. bb .. .. .. {4 {{ {{ {a {8 {4 {{ {{ {{ {{ "
+               "{{ {{ {{ {C t7 {A {2 .. .. .. .. .. {5 {{ {{ {{ {2 tf {{ {7 {{ "
+               "{A {{ {3 tb tt td .. .. .. .. .. .. {4 {{ {{ {3 .. .. {1 {4 {C "
+
+       )       
+       )
+
+        #f              ; wraps
+        #f              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list ; objects
+               (put (mk-monman) 0 0)
+               (put (spawn-pt 'cave-goblin-slinger-m) 8 7)
+               (put (spawn-pt 'cave-goblin-berserker-m) 9 13)
+               (put (spawn-pt 'cave-goblin-slinger-m) 12 8)
+               (put (spawn-pt 'cave-goblin-berserker-m) 13 14)
+               (put (spawn-pt 'troll-m) 10 10)
+        )
+        (list
+               'losthalls-room-handle-start
+               'on-entry-to-dungeon-room
+               ) ;; hooks
+               (list ;; edge entrances
+               )
+ )
+(kern-mk-place 
+       'p_lost_halls_r1
+       "The Lost halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+               (list
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               'losthalls-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_r2
+       "The Lost halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+               (list
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               'losthalls-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_r3
+       "The Lost halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+               (list
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               'losthalls-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_r4
+       "The Lost halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+               (list
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               'losthalls-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_r5
+       "The Lost halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+               (list
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  ",, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+  "rn rn rn rn ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               'losthalls-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_staird
+       "The Great Stair"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn r8 rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn xx xx xx bb xx xx r8 xx xx xx rn rn rn rn rn rn "
+               "rn rn rn rn r8 rc .. .. .. .. .. .. .. .. ra r8 r8 rn rn rn rn "
+               "rn rn rn r4 .. .. .. .. .. .. .. .. .. .. .. .. .. r2 rn rn rn "
+               "rn rn r4 {{ {2 .. .. .. .. r2 rn rn r4 .. .. .. .. ra rn rn rn "
+               "rn rn xx {1 .. .. .. r3 r1 rn rn rn rn r5 .. .. .. .. xx rn rn "
+               "rn rn xx .. .. .. r3 rn xx d, d, d, xx rn r5 .. .. .. bb r2 rn "
+               "rn rn xx bb .. .. r2 rn xx ,, ,, ,, xx rn rc .. .. .. xx rn rn "
+               "rn r4 bb .. .. .. ra rn xx cc cc cc xx r4 .. .. .. .. xx rn rn "
+               "rn rn r5 .. .. .. .. r2 xx ,, ,, ,, xx r4 .. .. .. .. xx rn rn "
+               "rn rn xx bb .. .. .. r2 xx cc cc cc xx xx .. .. .. .. r2 rn rn "
+               "rn rn xx .. .. .. .. xx xx ,, ,, ,, xx xx .. .. .. .. r2 rn rn "
+               "rn rn r4 .. .. .. xx xx xx cc cc cc xx xx xx .. .. .. xx rn rn "
+               "rn rn xx .. .. .. xx xx xx ,, ,, ,, xx xx xx .. .. {8 xx rn rn "
+               "rn rn rn r5 .. .. .. .. .. .. .. .. .. .. .. .. {4 {{ xx rn rn "
+               "rn rn rn r4 .. {8 {8 .. .. .. .. .. .. .. .. .. .. r2 rn rn rn "
+               "rn rn rn rn r1 {{ {{ {2 .. .. .. .. .. .. .. r3 r1 rn rn rn rn "
+               "rn rn rn rn rn r1 xx xx r1 r1 xx r1 xx xx xx xx rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+       )
+
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       (list
+               (put (mk-monman) 0 0)
+        (put (mk-bump-door 'p_lost_halls_stairu 10 18) 9 7)
+        (put (mk-bump-door 'p_lost_halls_stairu 10 18) 10 7)
+        (put (mk-bump-door 'p_lost_halls_stairu 10 18) 11 7)
+        (put (mk-step-trig 'one-off-message "A huge stairway leads down into the darkness" "losthalls_staird") 9 15)
+        (put (mk-step-trig 'one-off-message "A huge stairway leads down into the darkness" "losthalls_staird") 10 15)
+        (put (mk-step-trig 'one-off-message "A huge stairway leads down into the darkness" "losthalls_staird") 11 15)
+         (put (spawn-pt 'giant-spider) 4 11)
+         (put (spawn-pt 'giant-spider) 5 10)
+         (put (spawn-pt 'giant-spider) 6 12)
+       (put (spawn-pt 'gint-warrior) 15 11)
+       (put (spawn-pt 'gint-warrior) 15 11)
+       (put (spawn-pt 'gint-mage) 14 10)
+       ); objects
+       
+        
+        (list
+               'on-entry-to-dungeon-room
+               'losthalls-room-handle-staird
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_stairu
+       "The Great Stair"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. ,, .. ,, .. .. .. ,, .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. ,, .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. ,, ,, ,, ,, .. .. .. .. .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. ,, .. .. .. ,, ,, ,, ,, .. .. xx rn rn rn "
+               "rn rn rn xx .. .. xx ,, ,, ,, ,, ,, ,, ,, xx .. .. xx rn rn rn "
+               "rn rn rn xx .. xx xx xx cc cc cc cc cc xx xx xx .. xx rn rn rn "
+               "rn rn rn xx .. xx xx xx ,, ,, ,, ,, ,, xx xx xx .. xx rn rn rn "
+               "rn rn rn xx .. .. xx xx cc cc cc cc cc xx xx .. .. xx rn rn rn "
+               "rn rn rn xx .. .. xx xx xx ,, ,, ,, xx xx xx .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. xx xx cc cc cc xx xx .. .. .. xx rn rn rn "
+               "rn rn rn xx xx .. .. xx xx ,, ,, ,, xx xx .. .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx xx cc cc cc xx xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx ,, ,, ,, xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx d, d, d, xx rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx xx xx xx xx rn rn rn rn rn rn rn rn "
+       )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       (list
+               (put (mk-monman) 0 0)
+        (put (mk-bump-door 'p_lost_halls_staird 10 8) 9 19)
+        (put (mk-bump-door 'p_lost_halls_staird 10 8) 10 19)
+        (put (mk-bump-door 'p_lost_halls_staird 10 8) 11 19)
+               (put (spawn-pt 'cave-goblin-slinger-m) 11 8)
+               (put (spawn-pt 'cave-goblin-berserker-m) 8 12)
+               (put (spawn-pt 'troll-m) 9 10)
+               (put (spawn-pt 'gint-warrior-m) 12 9)
+
+       ); objects
+       
+        
+        (list
+               'on-entry-to-dungeon-room
+               'losthalls-room-handle-stairu
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_graves
+       "The Graveyard"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn xx r8 rn rn r8 rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb ra rc bb ra xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx rd bb .. .. bb xx rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx .. .. .. .. .. xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. .. .. xx xx rn rn rn "
+               "rn rn rn xx .. .. .. .. .. .. .. .. .. .. .. {8 .. xx rn rn rn "
+               "rn rn rn xx .. .. .. @@ ,R @@ ,I @@ ,P bb {4 {{ {2 xx rn rn rn "
+               "rn xx xx xx .. .. .. .. .. .. .. .. .. .. .. {1 .. xx xx xx rn "
+               "r4 bb .. bb .. .. 00 .. 00 .. 00 .. 00 .. 00 .. .. .. bb ra rn "
+               "rn r5 bb .. .. {4 {{ {6 {{ {6 {{ {e {{ {6 {{ {2 .. .. bb .. r2 "
+               "rn rn rd .. .. {4 {{ {6 bb {6 {{ {{ {{ {6 {{ {2 .. .. bb r3 rn "
+               "rn r4 bb .. .. .. {1 .. {1 .. {1 {1 {1 .. {1 .. .. bb .. ra rn "
+               "rn rn r5 .. .. .. 00 .. 00 .. 00 .. bb .. 00 .. .. .. .. bb r2 "
+               "rn xx xx xx .. {4 {{ {6 {{ {6 {{ {6 {{ {6 {{ {2 .. xx xx xx rn "
+               "rn rn rn xx .. {c {{ {6 {{ {6 {{ {6 {{ {6 {{ {2 .. xx rn rn rn "
+               "rn rn rn xx {4 {{ {3 .. {1 .. {1 .. {1 .. {1 .. .. xx rn rn rn "
+               "rn rn rn xx xx {{ {2 .. .. .. .. .. bb .. bb .. xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx bb .. .. .. bb xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn xx .. .. bb .. r3 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb r3 r5 bb r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx r1 rn rn r1 rn xx rn rn rn rn rn rn rn "
+       )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       (list
+               (put (mk-monman) 0 0)
+               (put (spawn-pt 'lich) 11 9)
+               (put (spawn-pt 'ghast) 7 11)
+               (put (spawn-pt 'ghast) 13 9)
+               (put (spawn-pt 'skeletal-warrior) 7 7)
+               (put (spawn-pt 'skeletal-warrior) 10 15)
+               (put (spawn-pt 'skeletal-spear-thrower) 15 8)
+               (put (spawn-pt 'skeletal-spear-thrower) 9 13)
+       ); objects
+       
+        
+        (list
+               'on-entry-to-dungeon-room
+               'losthalls-room-handle-croom
+       ) ;; hooks
+       nil
+)
+
+(drop-random-corpses p_lost_halls_graves 5)
+
+(kern-mk-place 
+       'p_lost_halls_rshrine
+       "The Broken Sactuary"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx @@ @@ @@ @@ ,, ++ ,, @@ @@ @@ @@ xx xx rn rn rn "
+               "rn rn rn xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb xx rn rn rn "
+               "rn rn rn xx ,, ~~ ~~ ~~ ,, ,, ,, ,, ,, ~~ ~~ ~~ ,, xx rn rn rn "
+               "rn xx xx xx ,, b~ _! ~~ ,, ,, aa ,, ,, ~~ _! ~~ ,, xx xx xx rn "
+               "r4 bb .. bb ,, ~~ ~~ ~~ ,, ,, ,, ,, ,, ~~ ~~ ~~ ,, ,, bb ra rn "
+               "rn r5 bb ,, ,, ,, ,, ,, ,, ,, ,, .. ,, bb ,, ,, ,, ,, bb .. r2 "
+               "rn rn rd ,, ,, ,, .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb r3 rn "
+               "rn r4 bb ,, ,, ,, ,, ,, ,, bb .. ,, ,, ,, ,, .. ,, bb ,, ra rn "
+               "rn rn r5 ,, ,, ,, ,, ,, ,, ,, ,, ,, .. ,, ,, ,, ,, ,, ,, bb r2 "
+               "rn xx xx xx ,, ,, .. ,, ,, .. ,, ,, ,, ,, ,, ,, ,, xx xx xx rn "
+               "rn rn rn xx ,, .. .. ,, ,, ,, ,, ,, ,, ,, ,, bb ,, xx rn rn rn "
+               "rn rn rn xx ,, ,, ,, ,, .. ,, ,, .. ,, ,, ,, ,, ,, xx rn rn rn "
+               "rn rn rn xx xx ,, bb ,, ,, ,, ,, .. ,, ,, ,, ,, xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx bb ,, ,, ,, bb xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn xx ,, ,, bb ,, r3 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb r3 r5 bb r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx r1 rn rn r1 rn xx rn rn rn rn rn rn rn "
+       )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       (list
+               (put (mk-monman) 0 0)
+               (put (spawn-pt 'yellow-slime) 8 9)
+               (put (spawn-pt 'yellow-slime) 13 11)
+       ); objects
+       
+        
+        (list
+               'on-entry-to-dungeon-room
+               'losthalls-room-handle-rroom
+               'losthalls-handle-rshrine
+       ) ;; hooks
+       nil
+)
+
+(kern-mk-place 
+       'p_lost_halls_fountains
+       "The Lost Halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx ,, .. .. .. .. .. .. %f .. .. ,, xx xx rn rn rn "
+               "rn rn rn xx ,, .. ,, .. .. .. .. .. .. ,, ,, .. .. xx rn rn rn "
+               "rn rn rn xx .. .. ~2 ~~ ~1 ,, ,, .. _s _s _s .. bb xx rn rn rn "
+               "rn xx xx xx .. .. ~2 __ ~~ .. .. .. _s _s _s .. .. xx xx xx rn "
+               "r4 bb .. xx .. .. ~a ~8 ~c .. .. .. _s _s _s %% %d xx bb ra rn "
+               "rn r5 bb xx .. %f .. .. .. .. %7 .. .. %% %% %c .. xx bb .. r2 "
+               "rn rn r9 xx .. .. .. .. .. bb %% %% ,, .. %e .. .. xx bb r3 rn "
+               "rn r4 bb xx .. .. .. %% ,, %% %c .. .. .. .. .. %7 xx ,, ra rn "
+               "rn rn r1 xx ,, .. _s _s _s %% .. .. _s _s _s .. %e xx ,, bb r2 "
+               "rn xx xx xx .. .. _s _s bb .. .. %% _s _s _s %% .. xx xx xx rn "
+               "rn rn rn xx .. %% _s _s _s .. %b %% _s _s _s %% %5 xx rn rn rn "
+               "rn rn rn xx ,, %% %% %% .. ,, .. .. %% %% .. %% %c xx rn rn rn "
+               "rn rn rn xx xx .. .. .. .. .. .. .. .. .. %b %c xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn xx xx xx xx ,, r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb r2 r4 bb r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx r1 rn rn r1 rn xx rn rn rn rn rn rn rn "
+       )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       (list
+               (put (mk-monman) 0 0)
+               (put (spawn-pt 'yellow-slime) 12 8)
+               (put (spawn-pt 'yellow-slime) 12 12)
+               (put (spawn-pt 'green-slime) 9 13)
+               (put (spawn-pt 'green-slime) 7 8)
+       ); objects
+       
+        
+        (list
+               'on-entry-to-dungeon-room
+               'losthalls-room-handle-rroom
+       ) ;; hooks
+       nil
+)
+
+(drop-random-corpses p_lost_halls_fountains 3)
+
+(kern-mk-place 
+       'p_lost_halls_storage
+       "The Lost Halls"
+        nil          ; sprite
+       (kern-mk-map nil 21 21 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn xx xx .. 00 .. ,, 00 xx bb .. .. .. 00 xx xx rn rn rn "
+               "rn rn rn xx .. .. .. ,, .. .. rr .. 00 .. ,, .. .. xx rn rn rn "
+               "rn rn rn xx .. .. .. .. 00 .. xx ,, 00 .. .. .. ,, xx rn rn rn "
+               "rn xx xx xx xx d, xx rr xx xx xx xx xx rr xx d, xx xx xx xx rn "
+               "r4 bb .. xx xx .. xx ,S ,T ,O ,R ,A ,G ,E xx .. xx xx bb ra rn "
+               "rn r5 bb xx .. .. .. .. .. .. .. .. .. .. .. .. .. xx bb .. r2 "
+               "rn rn r9 xx ,, .. .. .. .. ,, .. bb .. .. ,, .. ,, xx bb r3 rn "
+               "rn r4 bb xx .. bb .. ,, .. .. .. .. .. .. .. .. .. xx ,, ra rn "
+               "rn rn r1 xx xx rr d, xx xx xx d, xx xx xx d, rr xx xx ,, bb r2 "
+               "rn xx xx xx xx 00 .. .. rr .. .. .. bb .. .. .. xx xx xx xx rn "
+               "rn rn rn xx .. .. .. .. xx .. .. .. xx .. ,, ,, .. xx rn rn rn "
+               "rn rn rn xx 00 .. ,, .. xx .. ,, .. rr .. .. ,, .. xx rn rn rn "
+               "rn rn rn xx xx .. .. xx xx .. .. .. xx r5 .. 00 xx xx rn rn rn "
+               "rn rn rn rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn "
+               "rn rn rn rn rn rn rn xx xx xx xx ,, r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx bb r2 r4 bb r2 xx rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn xx r1 rn rn r1 rn xx rn rn rn rn rn rn rn "
+       )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       (list
+               (put (mk-monman) 0 0)
+               (put (spawn-pt 'rat) 7 4)
+               (put (spawn-pt 'rat) 7 5)
+               (put (spawn-pt 'rat) 7 6)
+               (put (spawn-pt 'rat) 6 5)
+               (put (spawn-pt 'rat) 13 4)
+               (put (spawn-pt 'rat) 13 5)
+               (put (spawn-pt 'rat) 13 5)
+               (put (spawn-pt 'rat) 14 5)
+               (put (spawn-pt 'rat) 5 15)
+               (put (spawn-pt 'rat) 6 15)
+               (put (spawn-pt 'rat) 7 15)
+               (put (spawn-pt 'rat) 6 14)
+               (put (spawn-pt 'rat) 14 15)
+               (put (spawn-pt 'rat) 15 15)
+               (put (spawn-pt 'rat) 16 15)
+               (put (spawn-pt 'rat) 15 14)
+       ); objects
+       
+        
+        (list
+               'on-entry-to-dungeon-room
+               'losthalls-room-handle-rroom
+       ) ;; hooks
+       nil
+)
+
+
+(mk-place-music p_lost_halls_entrance 'ml-outdoor-adventure)
+(mk-place-music p_lost_halls_r1 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_r2 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_r3 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_r4 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_r5 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_staird 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_stairu 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_graves 'ml-creepy-area)
+(mk-place-music p_lost_halls_rshrine 'ml-creepy-area)
+(mk-place-music p_lost_halls_fountains 'ml-dungeon-adventure)
+(mk-place-music p_lost_halls_storage 'ml-dungeon-adventure)
+
+
+(drop-random-corpses p_lost_halls_storage 2)
+
+;; map linkage
+(prmap-linkrooms-2d 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4 'p_lost_halls_r5)
+
+;; 2 mapdata objects to allow different terrain types in different areas
+(prmap-set-mapdata p_lost_halls_r1 (prmap-mk-mapdata "losthalls" losthalls-random-type-ns losthalls-random-type-ew losthalls-random-type-area 'losthalls-terrain-edges 'losthalls-terrain-area 'losthalls-room-blitstats 'losthalls-room-custom-hardlinks))
+(prmap-set-mapdata p_lost_halls_r2 (prmap-mk-mapdata "losthalls" losthalls-random-type-ns losthalls-random-type-ew losthalls-random-type-area 'losthalls-ruin-edges 'losthalls-ruin-area 'losthalls-ruin-blitstats 'losthalls-ruin-custom-hardlinks))
+
+;; random locations must not clash
+(define (lost-halls-grave-x stair-x stair-y)
+       (if (zero? 
+               (cond
+                       ((> stair-y 6) (kern-dice-roll "1d2-1"))
+                       ((< stair-x -1) 1)
+                       ((> stair-x 1) 0)
+                       (#t (kern-dice-roll "1d2-1"))
+               ))
+               (kern-dice-roll "1d2-4")
+               (kern-dice-roll "1d2+1")
+       ))
+
+(let* ((losthalls-hardlinks (prmap-params-hardlinks (prmap-get-mapdata p_lost_halls_r1)))
+               (stairdown-x (kern-dice-roll "1d5-3"))
+               (stairdown-y (kern-dice-roll "1d2+5"))
+               (grave-x (lost-halls-grave-x stairdown-x stairdown-y))
+               (grave-y (kern-dice-roll "1d5"))
+               )
+       (define (link-rm xloc yloc zloc dir target maptemplate passable . hooks)
+               (prmap-room-hardlink-set! xloc yloc zloc losthalls-hardlinks dir target maptemplate passable hooks)
+               )
+       
+;;---------------------------------------------------------
+;; hardlink setup
+;; 
+;;                     x       y       z       dir             target                          template                        passable        hooks
+
+(link-rm       0       0       0       north   nil                                     'm_losthalls_cpassage   #t)
+(link-rm       0       1       0       south   nil                                     'm_losthalls_cpassage   #t)
+(link-rm       0       0       0       south   'p_lost_halls_entrance          'm_losthalls_special    #t)
+
+;; stair down in random loc
+(prmap-mk-roomdata 'p_lost_halls_staird stairdown-x stairdown-y 0 (list 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4))
+
+(link-rm       stairdown-x     (- stairdown-y 1)       0       north   'p_lost_halls_staird    'm_losthalls_cpassage #t)
+(link-rm       stairdown-x     stairdown-y     0       south   nil             'm_losthalls_cpassage   #t)
+(link-rm       stairdown-x     (+ stairdown-y 1)       0       south   'p_lost_halls_staird    nil                                     #t)
+(link-rm       (- stairdown-x 1)       stairdown-y     0       east    'p_lost_halls_staird    nil                                     #t)
+(link-rm       (+ stairdown-x 1)       stairdown-y     0       west    'p_lost_halls_staird    nil                             #t)
+
+(println "stair at " stairdown-x " " stairdown-y)
+
+;; cemetary in random loc
+(prmap-mk-roomdata 'p_lost_halls_graves grave-x grave-y 0 (list 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4))
+
+(link-rm       grave-x (- grave-y 1)   0       north   'p_lost_halls_graves    'm_losthalls_cruin #t)
+(link-rm       grave-x grave-y                 0       south   nil                                             'm_losthalls_cruin      #t)
+(link-rm       grave-x (+ grave-y 1)   0       south   'p_lost_halls_graves    nil                                     #t)
+(link-rm       (- grave-x 1)   grave-y 0       east    'p_lost_halls_graves    nil                                     #t)
+(link-rm       (+ grave-x 1)   grave-y 0       west    'p_lost_halls_graves    nil                             #t)
+
+)
+
+(let ((losthalls-hardlinks (prmap-params-hardlinks (prmap-get-mapdata p_lost_halls_r2)))
+               (stairup-x (kern-dice-roll "1d3+1")))
+       (define (link-rm xloc yloc zloc dir target maptemplate passable . hooks)
+               (prmap-room-hardlink-set! xloc yloc zloc losthalls-hardlinks dir target maptemplate passable hooks)
+               )
+
+;; stair up in random loc
+(prmap-mk-roomdata 'p_lost_halls_stairu stairup-x 0 1 (list 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4))
+(link-rm       stairup-x       0       1       south   nil             'm_losthalls_stairu     #f)
+(link-rm       stairup-x       1       1       south   'p_lost_halls_stairu    nil             #t)
+(link-rm       (- stairup-x 1) 0       1       east    'p_lost_halls_stairu    nil                                     #t)
+(link-rm       (+ stairup-x 1) 0       1       west    'p_lost_halls_stairu    nil                             #t)
+
+;; warritrix' resting place
+(prmap-mk-roomdata 'p_lost_halls_rshrine 3 5 1 (list 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4))
+(link-rm       3       5       1       north   nil             'm_losthalls_rwall      #f)
+(link-rm       3       5       1       south   nil             'm_losthalls_rrooms     #t)
+(link-rm       3       4       1       north   'p_lost_halls_rshrine   'm_losthalls_rrooms             #t)
+(link-rm       2       5       1       east    'p_lost_halls_rshrine   nil                                     #t)
+(link-rm       4       5       1       west    'p_lost_halls_rshrine   nil                             #t)
+
+;; fountains
+(prmap-mk-roomdata 'p_lost_halls_fountains 5 3 1 (list 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4))
+(link-rm       5       3       1       west    nil             'm_losthalls_rhall      #t)
+(link-rm       5       4       1       south   'p_lost_halls_fountains nil             #t)
+(link-rm       4       3       1       east    'p_lost_halls_fountains 'm_losthalls_rhall      #t)
+(link-rm       5       2       1       north   'p_lost_halls_fountains nil                             #t)
+
+;; storage
+(prmap-mk-roomdata 'p_lost_halls_storage 2 4 1 (list 'p_lost_halls_r1 'p_lost_halls_r2 'p_lost_halls_r3 'p_lost_halls_r4))
+(link-rm       2       4       1       north   nil                                             'm_losthalls_rwall      #f)
+(link-rm       3       4       1       west    'p_lost_halls_storage   nil     #t)
+(link-rm       2       5       1       south   'p_lost_halls_storage   'm_losthalls_rwall              #t)
+(link-rm       1       4       1       east    'p_lost_halls_storage   nil                                     #t)
+(link-rm       2       3       1       north   'p_lost_halls_storage   nil                             #t)
+)
+
+;;flag for checking if cohesion check still needs to be performed
+(mutable-list-set (prmap-get-mapdata p_lost_halls_r1) 10 #t)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/luximene.scm b/worlds/haxima-1.002/luximene.scm
new file mode 100644 (file)
index 0000000..ece6e7a
--- /dev/null
@@ -0,0 +1,215 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define lux-lvl 7)
+(define lux-species sp_ghast)
+(define lux-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; No schedule (found in Green Tower Tombs)
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (lux-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Luximene is a lich (or later, a shade conjured up from his skull),
+;; sitting in rulership over the small realm of his treasury in 
+;; ruined Kurpolis.  In life, he was a great king who conquered and united 
+;; the Shard, and was ultimately overthrown by a coalition of those who 
+;; became known as the Wise.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (lux-hail knpc kpc)
+  (say knpc "[You meet a shade who burns with malice] What do you want, "
+       "mortal?"))
+
+(define (lux-default knpc kpc)
+  (say knpc "Do not waste my time."))
+
+(define (lux-name knpc kpc)
+  (say knpc "I am Luximene the Great, Lord of the Middle Realm."))
+
+(define (lux-rune knpc kpc)
+  (say knpc "[He suddenly looks disturbed] That is a key, one of eight, "
+       "made by the Wise to lock the Demon Gate."))
+
+(define (lux-gate knpc kpc)
+  (say knpc "Each key was given to a Keeper, each Keeper was forbidden to meet with any other, "
+       "and to pass their legacy on to an heir. Art thou a Keeper?")
+  (if (yes? kpc)
+      (begin
+        (say knpc "Then why dost thou ask me of this Rune? Did thy master not explain?")
+        (if (yes? kpc)
+            (say knpc "[He chuckles malignantly] Thou thinkest me a fool, "
+                 "and art a fool for thinking so. The Rune will be thy undoing, "
+                 "and the undoing of thine Age!")
+            (say knpc "Cursed is the Age wherein Men forget their vows.")))
+      (begin
+        (say knpc "Art thou a Thief?")
+        (if (yes? kpc)
+            (say knpc "Doomed is the Age where even thieves know not the value of what they steal.")
+            (say knpc "Then thou hast acquired the Rune by chance, "
+                 "and the end of thine Age is nigh.")))))
+
+(define (lux-age knpc kpc)
+  (say knpc "When the Demon Gate was sealed, the Age of Wizards ended. "
+       "It was I who conquered and united the Shard, and The Age of Luximene began. "
+       "After me each ruler was worse than the one before, and my empire fell into ruin, "
+       "and the present age, the Lost Age, began. Do you wish to know a great secret?")
+  (if (yes? kpc)
+      (say knpc "Then I will tell you, for you are the Last Keeper.")
+      (say knpc "\n[The room fills with his terrible laughter]\n"
+          "But it is thine to know,\n"
+           "Last of the Keepers!"))
+  (say knpc "The Lost Age will end when the Demon Gate is opened."))
+
+(define (lux-keep knpc kpc)
+  (say knpc "Thou art the Last Keeper. You have a Rune, and know its meaning. "
+       "Now all the Runes are thine to Keep. Doest thou have them all?")
+  (if (yes? kpc)
+      (say knpc "Be thou certain, Keeper. The Gate will not open without them all.")
+      (say knpc "Find them. One honorable man will save an Age from disgrace, "
+           "though perhaps not himself.")))
+
+(define (lux-wise knpc kpc)
+  (say knpc "The Wise?  [He laughs]\n"
+       "Rebels against the ruler of an Age!\n"
+       "\n"
+       "The Warrior Argus,\n"
+       "  who defeated my armies\n"
+       "  and led their expedition\n"
+       "The Wizard Xileph,\n"
+       "  who counseled rebellion\n"
+       "  and countered my sorceries\n"
+       "The Wrogue Narthax,\n"
+       "  whose thefts made bold mine enemies\n"
+       "  and found my secret passages\n"
+       "The Wright Weilend,\n"
+       "  who outfitted the quest\n"
+       "  against my stronghold\n"
+       "\n"
+       "Yet in my defeat, was wrought their DOOM!"
+       "\n")
+  (say knpc "\n[He gazes at you in expectation]\n"
+       "What?  Know ye not these names?")
+  (if (yes? kpc)
+      (say knpc "Then marvel, at my legend!")
+      (begin
+       (say knpc
+            "\n[His cold eyes glint in anger]\n"
+            "Ah, rather you refer to those called Wise of this Age.\n"
+            "I know nothing of such trifling matters.\n"
+            "Begone, mortal!")
+       (kern-conv-end)
+       ))
+  )
+
+(define (lux-accu knpc kpc)
+  (say knpc "Accursed?\n"
+       "In each Age there are those who seek power, "
+       "who will not be swayed from that search by warning or scruples.\n"
+       "\n"
+       "Some will be destroyed by this search, "
+       "while others land in thrall to those few who gain true power.\n"
+       "\n"
+       "Such must be, the worms of which you speak.")
+  )
+
+
+(define lux-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default lux-default)
+       (method 'hail lux-hail)
+       (method 'name lux-name)
+
+       (method 'rune lux-rune)
+       (method 'key  lux-rune) ;; A synonym
+
+       (method 'demo lux-gate) ;; A synonym
+       (method 'gate lux-gate)
+
+       (method 'wise lux-wise)
+       (method 'accu lux-accu)
+
+       (method 'age  lux-age)
+       (method 'keep lux-keep)
+
+       ))
+
+(define (mk-luximene)
+  (bind 
+   (kern-mk-char 
+    'ch_lux           ; tag
+    "Luximene"             ; name
+    lux-species         ; species
+    lux-occ              ; occ
+    s_ghost     ; sprite
+    faction-men      ; starting alignment
+    0 0 0            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    lux-lvl
+    #f               ; dead
+    'lux-conv         ; conv
+    nil           ; sched
+    nil              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   (lux-mk)))
+
+(define (mk-lich-king)
+  (let ((kchar 
+         (bind 
+          (kern-char-force-drop
+           (kern-mk-char 
+            'ch_lich_king           ; tag
+            "Lich King" ; name
+            sp_lich         ; species
+            oc_wizard              ; occ
+            s_lich     ; sprite
+            faction-monster      ; starting alignment
+            10 10 10            ; str/int/dex
+            10 1              ; hp mod/mult
+            0  0              ; mp mod/mult
+            max-health ; hp
+            -1                   ; xp
+            max-health ; mp
+            0
+            8
+            #f               ; dead
+            nil              ; conv
+            nil             ; sched
+            'lich-ai        ; special ai
+            (mk-inventory
+             (list (list 1 t_morning_star)
+                   (list 1 t_armor_chain_4)
+                   (list 1 t_chain_coif_4)
+                   (list 100 t_gold_coins)
+                   (list 3 t_mana_potion)
+                   (list 3 t_heal_potion)
+                   (list 1 t_lich_skull)
+                   (list 1 t_lichs_blood)
+                   ))
+            nil              ; readied
+            )
+           #t)
+          (lux-mk))))
+    (map (lambda (eff) (kern-obj-add-effect kchar eff nil))
+         undead-effects)
+    kchar))
+
diff --git a/worlds/haxima-1.002/main-menu.scm b/worlds/haxima-1.002/main-menu.scm
new file mode 100644 (file)
index 0000000..56359ad
--- /dev/null
@@ -0,0 +1,39 @@
+(kern-mk-sprite-set 'ss_u4_shapes        32 32   16 16   0 0   "shapes.png")
+(kern-mk-sprite-set 'ss_frame            16 16    4  4   0 0   "frame.png")
+(kern-mk-sprite-set 'ss_u4_charset       8  16    8 16   0 0   "charset.png")
+
+(kern-mk-sprite 's_null           ss_u4_shapes 1 126 #f 0 )
+(kern-mk-sprite 'ls_whirlpool     ss_u4_charset 4 28 #f 0 )
+
+(kern-mk-sprite 's_frame_ulc   ss_frame 1  0 #f 0 )
+(kern-mk-sprite 's_frame_td    ss_frame 1  1 #f 0 )
+(kern-mk-sprite 's_frame_urc   ss_frame 1  2 #f 0 )
+(kern-mk-sprite 's_frame_endu  ss_frame 1  3 #f 0 )  ; top of vertical bar, currently unused
+(kern-mk-sprite 's_frame_tr    ss_frame 1  4 #f 0 )
+(kern-mk-sprite 's_frame_plus  ss_frame 1  5 #f 0 )  ; center crosspiece, currently unused
+(kern-mk-sprite 's_frame_tl    ss_frame 1  6 #f 0 )
+(kern-mk-sprite 's_frame_vert  ss_frame 1  7 #f 0 )
+(kern-mk-sprite 's_frame_llc   ss_frame 1  8 #f 0 )
+(kern-mk-sprite 's_frame_tu    ss_frame 1  9 #f 0 )
+(kern-mk-sprite 's_frame_lrc   ss_frame 1 10 #f 0 )
+(kern-mk-sprite 's_frame_endb  ss_frame 1 11 #f 0 )  ; bottom of vertical bar, currently unused
+(kern-mk-sprite 's_frame_endl  ss_frame 1 12 #f 0 )
+(kern-mk-sprite 's_frame_horz  ss_frame 1 13 #f 0 )
+(kern-mk-sprite 's_frame_endr  ss_frame 1 14 #f 0 )
+(kern-mk-sprite 's_frame_dot   ss_frame 1 15 #f 0 )  ; disconnected disk, currently unused
+
+(kern-set-frame s_frame_ulc
+                s_frame_urc
+                s_frame_llc
+                s_frame_lrc
+                s_frame_td
+                s_frame_tu
+                s_frame_tl
+                s_frame_tr
+                s_null
+                s_frame_horz
+                s_frame_vert
+                s_frame_endl
+                s_frame_endr)
+(kern-set-ascii ss_u4_charset 32)
+(kern-set-cursor ls_whirlpool)
diff --git a/worlds/haxima-1.002/mans-hideout.scm b/worlds/haxima-1.002/mans-hideout.scm
new file mode 100644 (file)
index 0000000..72cc1c3
--- /dev/null
@@ -0,0 +1,140 @@
+;; ----------------------------------------------------------------------------
+;; Map
+;; ----------------------------------------------------------------------------
+  (kern-mk-map
+    'm_mans_hideout 19 19 pal_expanded
+       (list
+               "xx xx xx x! xx xx xx rn rn rn rn rn xx xx xx xx xx xx xx "
+               "xx pp cc cc cc pp xx xx xx rn rn rn xx .T .O .O .L .S xx "
+               "xx cc ,, ,, ,, cc ,, ,, xx xx xx xx xx ,, ,, ,, ,, ,, xx "
+               "x! cc ,, ,, ,, cc x! ,, ?? ,, ?? ?? ?? ,, ,, ,, ,, ,, xx "
+               "xx cc ,, ,, ,, cc xx xx xx x! ?? xx xx ,, ,, ,, ,, ,, xx "
+               "xx pp cc cc cc pp xx xx ,, ,, ,, xx xx xx x! ,, x! xx xx "
+               "xx xx xx ,, xx xx x! cc ,, ,, ,, cc x! xx xx ,, xx rn rn "
+               "rn rn xx ,, xx xx cc pp cc ,, cc pp cc xx xx ,, xx rn rn "
+               "rn rn xx ,, xx ,, ,, cc ,, ,, ,, cc ,, ,, xx ,, xx rn rn "
+               "rn rn x! ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, x! rn r8 "
+               "rn rn xx ,, xx ,, ,, cc ,, ,, ,, cc ,, ,, xx ,, xx ~~ ~~ "
+               "rn rn xx ,, xx xx cc pp cc ,, cc pp cc xx xx ,, xx ~~ r3 "
+               "rn xx x! ,, x! xx x! cc ,, ,, ,, cc x! xx ~~ ,, ~~ ~c r2 "
+               "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ~~ ee ~~ r3 rn "
+               "xx ,, ,, ,, ,, ,, r2 rn r9 r9 r9 rn r4 ~~ ~~ ~8 ~c r2 rn "
+               "x! ,, ,, 00 ,, ,, r2 rc .. .. .. ra r4 ~2 r3 r9 r9 rn rn "
+               "xx ,, ,, ,, ,, ,, r6 .. .. .. .. .. re ~4 r6 ,, ,, r2 rn "
+               "xx xx xx && xx xx r4 .. .. .. .. ~3 ~~ ~c r6 ,, ,, r2 rn "
+               "rn rn xx xx xx rn rn r5 .. .. .. ~~ r3 r1 rn r1 r1 rn rn "
+       )
+  )
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "the-man.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_mans_hideout ; tag
+ "The MAN's Hideout"   ; name
+ s_dungeon      ; sprite
+ m_mans_hideout  ; map
+ #f               ; wraps
+ #t                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ nil ;; neighbors 
+ ;; objects
+ (list
+
+  (put (mk-the-man) 9 9)
+
+  ;; kitchen
+  (put (mk-chest
+        nil
+        '(
+         (10 t_food))) 5 16)
+
+  ;; bedroom
+  (put (mk-bed) 3 3)
+  (put (mk-chest
+        'bomb-trap
+        '(
+         (100 t_gold_coins))) 7 3)
+
+  ;; closet
+  (put (mk-door) 6 2)
+
+  ;; secret wall mech
+  (put (mk-disg-lvr 'mh-b1 's_wall_rock) 7 18)
+  (put (mk-hidden-mech) 7 18)
+  (put (kern-tag 'mh-b1
+                 (mk-tblitter 'p_mans_hideout 
+                              8 14
+                              3 1
+                              'm_hall_section))
+       0
+       0)
+  
+  ;; tool room
+  (put (mk-magic-locked-door) 15 5)
+  ;; tools...
+  (put (mk-chest
+        'bomb-trap
+        '(
+                        (10 t_gem)
+                        (10 t_torch)
+                        (10 t_picklock)
+                        (1  t_spell_book_illusion_1)
+         )) 13 2)
+  ;; arms...
+  (put (mk-chest
+        'bomb-trap
+        '(
+                        (1 t_sling_4)
+                        (1 t_dagger_4)
+                        (1 t_leather_helm_4)
+                        (1 t_armor_leather_4)
+         )) 13 3)
+  ;; potions 1...
+  (put (mk-chest
+        'bomb-trap
+        '(
+                        (10 t_cure_potion)
+                        (10 t_poison_immunity_potion)
+                        (10 t_invisibility_potion)
+                        (1  t_spell_book_force_magick_mechanismus)
+         )) 13 4)
+  ;; potions 2...
+  (put (mk-chest
+        'bomb-trap
+        '(
+                        (10 t_heal_potion)
+                        (10 t_mana_potion)
+         )) 17 2)
+  ;; scrolls 1...
+  (put (mk-chest
+        'bomb-trap
+        '(
+                        (10 t_in_ex_por_scroll)
+                        (10 t_wis_quas_scroll)
+                        (10 t_vas_mani_scroll)
+         )) 17 3)
+  ;; scrolls 2...
+  (put (mk-chest
+        'bomb-trap
+        '(
+                        (10 t_an_tym_scroll)
+                        (10 t_sanct_lor_scroll)
+                        (10 t_in_quas_xen_scroll)
+                        (10 t_an_xen_ex_scroll)
+         )) 17 4)
+
+  (put (mk-ladder-down 'p_forsaken_prison 2 16) 9 3)
+  )
+ nil ; hooks
+ nil ; edge entrances
+ )
+
+(mk-place-music p_mans_hideout 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/map.png b/worlds/haxima-1.002/map.png
new file mode 100644 (file)
index 0000000..bf1018c
Binary files /dev/null and b/worlds/haxima-1.002/map.png differ
diff --git a/worlds/haxima-1.002/may.scm b/worlds/haxima-1.002/may.scm
new file mode 100644 (file)
index 0000000..d868b77
--- /dev/null
@@ -0,0 +1,212 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define may-start-lvl  6)
+(define inn-room-price 30)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Bole.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_may
+               (list 0  0  bole-bed-may "sleeping")
+               (list 6  0  bole-dining-hall "working")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (may-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; May is a female innkeeper, who lives in Bole.
+;; Melvin is her (seventh) husband.
+;;----------------------------------------------------------------------------
+(define (may-trade knpc kpc)
+  (say knpc "Talk to my husband Melvin in the kitchen."))
+
+(define (may-hail knpc kpc)
+  (say knpc "[You meet a stout older woman who looks at you keenly] "
+       "I know you are trouble, but I welcome thee."))
+
+(define (may-job knpc kpc)
+  (say knpc "I run the tavern with my husband here in the Bole"))
+
+(define (may-husband knpc kpc)
+  (say knpc "My husband Melvin is a worthless drunk and a coward "
+       "but he is a good enough cook. I have outlived six other husbands. "
+       "I married him because I needed help running the inn, that is all."))
+
+(define (may-other-husbands knpc kpc)
+  (say knpc "My other husbands were all fools! A few, indeed, I loved. "
+       "But they were fools and each met his own foolish death. "
+       "I see that you are a fool, too, and will meet your own foolish "
+       "death some day."))
+
+(define (may-tavern knpc kpc)
+  (say knpc "Melvin is the cook and I serve the guests. "
+       "Perhaps you would care to buy a drink or some supper, "
+       "or a room where you may rest."))
+
+(define (may-guests knpc kpc)
+  (say knpc "[She gives you a canny look] Aye, even now we have a strange "
+       "woman and her... companion. But perhaps you were looking for "
+       "someone else, eh?")
+  (if (kern-conv-get-yes-no? kpc)
+      (begin
+        (say knpc "Yes, I thought so. And perhaps this other person had "
+             "something of interest to you?")
+        (if (kern-conv-get-yes-no? kpc)
+            (begin
+              (say knpc "How odd, because that item was also of interest to "
+                   "our current guests. Not that it is any of my business, "
+                   "but one suspects that the woman and he whom you seek "
+                   "arranged to meet here. Perhaps to make an... "
+                   "exchange."))
+            (say knpc "Well, there was another man here briefly. But he "
+                 "left shortly before you arrived.")))
+      (say knpc "Perhaps you are just out admiring the countryside then.")))
+
+(define (may-woman knpc kpc)
+  (say knpc "Yes, we don't often get such beautiful people in these parts. "
+       "Poor Bill is quite smitten. And my fool of a husband ogles here "
+       "whenever he gets a chance. [She leans in close and whispers] But "
+       "if she isn't a sorceress, or one in training, then I'm a goose!"))
+
+(define (may-companion knpc kpc)
+  (say knpc "This woman travels with a great brute. I suspect he has ogre "
+       "blood in his veins. Obviously he is her protector, though what bind "
+       "she has over him I know not."))
+
+(define (may-bill knpc kpc)
+  (say knpc "Aye, Bill is a local boy. Not too bright, but he makes an "
+       "honest living as a woodcutter. He eats here, and sometimes talks "
+       "to the guests."))
+
+(define (may-hackle knpc kpc)
+  (say knpc "Hackle is a crazy but harmless old hedge-witch who lives across "
+       "the stream. She has a knack for the healing arts but hasn't the wits "
+       "for much else."))
+
+(define (may-room knpc kpc)
+  (if (not (string=? "working" (kern-obj-get-activity knpc)))
+      (say knpc "The Inn is closed. Come back in the morning at 0600.")
+      (let ((door (eval 'bole-inn-room-door)))
+        ;; is the room still open?
+        (if (not (door-locked? (kobj-gob door)))
+            ;; yes - remind player
+            (say knpc "Your room is still open.")
+            ;; no - ask if player needs a room
+            (begin
+              (say knpc "Would ye like a room?")
+              (if (kern-conv-get-yes-no? kpc)
+                  ;; yes - player wants a room
+                  (begin
+                    (say knpc 
+                         "It will be " inn-room-price " gold, "
+                         "and you may use the room as "
+                         "long as you are in town. Agreed?")
+                    (if (kern-conv-get-yes-no? kpc)
+                        ;; yes - player agrees to the price
+                        (let ((gold (kern-player-get-gold)))
+                          ;; does player have enough gold?
+                          (if (>= gold inn-room-price)
+                              ;; yes - player has enough gold
+                              (begin
+                                (kern-player-set-gold 
+                                 (- gold 
+                                    inn-room-price))
+                                (say knpc "Good. Your room is down the hall "
+                                     "on the left.")
+                                (send-signal knpc door 'unlock)
+                                (kern-conv-end)
+                                )
+                              ;; no - player does not have enouvh gold)
+                              (say knpc "Ye have not the gold!")))
+                        ;; no - player does not agree to the price
+                        (say knpc 
+                             "Sleep on the ground then. Mind the wolves.")))
+                  ;; no - player does not want a room
+                  (say knpc "Even one such as you must sometimes rest!")))))))
+  
+(define (may-thief knpc kpc)
+  (say knpc "Ah... thou playest the thief-catcher. I suspected something of "
+       "the kind. We HAVE had some odd guests here lately."))
+
+(define (may-trouble knpc kpc)
+  (say knpc "Ye have the hard, pitiless visage like the men of the Old Era. "
+       "But I sense that thou art not unjust."))
+
+(define may-conv
+  (ifc nil
+       (method 'default (lambda (knpc kpc) (say knpc "I can't help thee.")))
+       (method 'hail may-hail)
+       (method 'bye  (lambda (knpc kpc) (say knpc "Begone then for now.")))
+       (method 'job  may-job)
+       (method 'name (lambda (knpc kpc) (say knpc "I am called May.")))
+       (method 'join (lambda (knpc kpc)
+                       (say knpc "Don't flatter me with your foolishness.")))
+
+       (method 'buy   may-trade)
+       (method 'food  may-trade)
+       (method 'drin  may-trade)
+       (method 'supp  may-trade)
+       (method 'trade may-trade)
+
+       (method 'bill  may-bill)
+       (method 'comp  may-companion)
+       (method 'gues  may-guests)
+       (method 'hack  may-hackle)
+       (method 'husb  may-husband)
+       (method 'inn   may-tavern)
+       (method 'melv  may-husband)
+       (method 'other may-other-husbands)
+       (method 'run   may-tavern)
+       (method 'room  may-room)
+       (method 'six   may-other-husbands)
+       (method 'tave  may-tavern)
+       (method 'thie  may-thief)
+       (method 'trou  may-trouble)
+       (method 'woma  may-woman)
+
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-may)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_may ;;......tag
+     "May" ;;.......name
+     sp_human ;;.....species
+     nil ;;..........occupation
+     s_townswoman ;;...sprite
+     faction-men ;;..faction
+     0 ;;............custom strength modifier
+     1 ;;............custom intelligence modifier
+     0 ;;............custom dexterity modifier
+     0 ;;............custom base hp modifier
+     0 ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     may-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'may-conv ;;...conversation (optional)
+     sch_may ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+     nil ;;..........container (and contents)
+     (list t_dagger) ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (may-mk)))
diff --git a/worlds/haxima-1.002/meaney.scm b/worlds/haxima-1.002/meaney.scm
new file mode 100644 (file)
index 0000000..1aa4deb
--- /dev/null
@@ -0,0 +1,278 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define meaney-lvl 6)
+(define meaney-species sp_human)
+(define meaney-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the Poorhouse, near Oparine.
+;;----------------------------------------------------------------------------
+(define meaney-bed poorh-bed1)
+(define meaney-mealplace poorh-sup1)
+(define meaney-workplace poorh-hall)
+(define meaney-leisureplace poorh-dining)
+(kern-mk-sched 'sch_meaney
+               (list 0  0 meaney-bed          "sleeping")
+               (list 5  0 meaney-mealplace    "eating")
+               (list 6  0 meaney-workplace    "working")
+               (list 12 0 meaney-mealplace    "eating")
+               (list 13 0 meaney-workplace    "working")
+               (list 18 0 meaney-mealplace    "eating")
+               (list 19 0 meaney-leisureplace "idle")
+               (list 21 0 meaney-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (meaney-mk) (list 0 #t))
+(define (meaney-get-donated meaney) (car meaney))
+(define (meaney-donated? meaney) (> (meaney-get-donated meaney) 
+                                    0))
+(define (meaney-donate! meaney q) (set-car! meaney (+ (car meaney) q)))
+(define (meaney-has-ring meaney) (cadr meaney))
+(define (meaney-remove-ring meaney) (set-car! (cdr meaney) #f))
+
+(define (meaney-on-death knpc)
+       (if  (meaney-has-ring (kobj-gob-data knpc))
+               (kern-obj-put-at (kern-mk-obj t_skull_ring_m 1) (kern-obj-get-location knpc))
+       ))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Meaney is a monk of the Order of the Crossroad, 
+;; living in the Poorhouse near Oparine.
+;; He was once a pirate, in the crew of the Merciful Death,
+;; and is sought for vengeance by the ghost captain Ghertie.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (meaney-hail knpc kpc)
+  (say knpc "I greet thee, traveler."))
+
+(define (meaney-default knpc kpc)
+  (say knpc "I cannot help thee with that."))
+
+(define (meaney-name knpc kpc)
+  (say knpc "I am brother Meaney.")
+  (quest-data-update 'questentry-ghertie 'meaney-loc 1))
+
+(define (meaney-join knpc kpc)
+  (say knpc "My duty is to the poor and afflicted."))
+
+(define (meaney-job knpc kpc)
+  (say knpc "I run the poor house, "
+       "where we care for the sick and destitute."))
+
+(define (meaney-bye knpc kpc)
+  (say knpc "Farewell."))
+
+;; Second-tier responses
+(define (meaney-get-donation knpc kpc)
+  (define (rejected)
+    (cond ((> (kern-player-get-gold) 0)
+           (say knpc "I see. Perhaps another time. [He turns away sadly]")
+           (kern-conv-end))
+          (else
+           (say knpc "Perhaps you also are in great need."))))
+  (let ((meaney (kobj-gob-data knpc)))
+    (if (not (meaney-donated? meaney))
+        (begin
+          (say knpc "Wilt thou donate some gold to help the poor?")
+          (if (kern-conv-get-yes-no? kpc)
+              (let ((q (get-gold-donation knpc kpc)))
+                (if (> q 0)
+                    (begin
+                      (say knpc "Bless you, stranger! "
+                           "Your kindness will be remembered.")
+                      (meaney-donate! meaney q))
+                    (rejected)))
+              (rejected))))))
+
+(define (meaney-poor knpc kpc)
+  (say knpc "At the poor house we aid widows and orphans mostly. "
+       "Art thou in great need?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Then we gladly share what little food we have with thee.")
+      (meaney-get-donation knpc kpc)))
+
+(define (meaney-sick knpc kpc)
+  (say knpc "We heal any who come here in need. Do you need healing?")
+  (if (kern-conv-get-yes-no? kpc)
+      (meaney-trade knpc kpc)
+      (meaney-get-donation knpc kpc)))
+
+(define (meaney-brot knpc kpc)
+  (say knpc "I am a monk of the Order of the Crossroad. "
+       "My order was founded by the Wanderer Davis over seven centuries ago "
+       "to minister to the poor."))
+
+;; Trade...
+(define (meaney-trade knpc kpc)
+  (if (trade-services knpc kpc
+                      (list
+                       (svc-mk "Heal" 0 heal-service)
+                       (svc-mk "Cure" 0 cure-service)
+                       ))
+      (begin
+        (say knpc "How else can I aid you?")
+        (meaney-trade knpc kpc))
+      (begin
+        (say knpc "Will there be anything else?")
+        (if (kern-conv-get-yes-no? kpc)
+            (meaney-trade knpc kpc)
+            (meaney-get-donation knpc kpc)))))
+
+;; Town & Townspeople
+
+;; Quest-related
+(define (meaney-pira knpc kpc)
+       (quest-data-update 'questentry-ghertie 'meaney-loc 1)
+       (say knpc "Yes, I was once a pirate, long ago. "
+               "I sailed with Ma Ghertie on the Merciful Death. "
+               "Now I spend my life in penance to the poor."))
+
+(define (meaney-gher knpc kpc)
+  (say knpc "Ma Ghertie treated us crew like family. "
+       "She was a ruthless brigand and thoroughly wicked. "
+       "No doubt she deserved to die, "
+       "but not at the hands of her own Bully Boys."))
+
+(define (meaney-pena knpc kpc)
+  (say knpc "I am guilty of many heinous crimes, "
+       "and all the bloodletting was for naught. "
+       "I betrayed my captain, and was betrayed in turn."))
+
+(define (meaney-betr knpc kpc)
+  (say knpc "The whole crew conspired to murder our captain and divide the loot. "
+       "We were certain she was going to murder us all first if we did not. "
+       "The first mate, the cook and I did the deed while she lay drunk, "
+       "but when we returned to the dock the ship had sailed without us."))
+
+(define (meaney-firs knpc kpc)
+  (say knpc "The first mate was an evil wretch named Jorn. "
+       "I heard he is a bandit now, somewhere in the great forest to the east. "
+       "You might ask around Green Tower.")
+       (quest-data-update 'questentry-ghertie 'jorn-forest 1))
+
+(define (meaney-cook knpc kpc)
+  (say knpc "Gholet is no doubt either dead or rotting in prison somewhere. "
+       "The last time I saw him he stopped here for the night. "
+       "When I awoke the next morning I found the lock on our donation box broken. "
+       "The box was even more empty than usual.")
+       (quest-data-update 'questentry-ghertie 'gholet-prison 1)
+       )
+
+(define (meaney-ring knpc kpc)
+  (if (not (meaney-has-ring (kobj-gob-data knpc)))
+      (say knpc "I hope I never see that cursed thing again.")
+      (begin
+        (say knpc "Yes, I wear the ring of Ma Ghertie's Bully Boys, "
+             "the crew of the Merciful Death. Yes, I am a murdering pirate. ")
+        (prompt-for-key)
+        (say knpc "Legend says the Wanderer Luto traveled the countryside, "
+              "dispensing justice at the point of his sword. Have you come to "
+              "slay me for my crimes?")
+        (if (yes? kpc)
+            (begin
+              (say knpc "Then be done with it, I am ready. [He stands with head bowed].")
+              (kern-conv-end))
+            (begin
+              (say knpc "You are merciful. "
+                    "But it is time I parted ways with this ring, "
+                    "which means I must part ways with this finger. "
+                    "I have not the courage to cut it off, "
+                    "will you do it?")
+              (if (yes? kpc)
+                  (begin
+                    (say knpc "[With a quick motion you grab his hand and hack off the "
+                          "finger] Ah! There, it is off, and I am free from its curse. "
+                          "I thank you, Wanderer. Know that if you ever need aid "
+                          "or healing, I will do what I can for you.")
+                       (skullring-m-get nil kpc)
+                       (meaney-remove-ring (kobj-gob-data knpc))
+                    )
+                  (say knpc "I wish I could be rid of the wretched thing!")))))))
+
+(define meaney-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default meaney-default)
+       (method 'hail meaney-hail)
+       (method 'bye  meaney-bye)
+       (method 'job  meaney-job)
+       (method 'name meaney-name)
+       (method 'join meaney-join)
+       
+       ;; trade
+       (method 'trad meaney-trade)
+       (method 'buy  meaney-trade)
+       (method 'sell meaney-trade)
+
+       ;; town & people
+
+       ;; other responses
+       (method 'poor meaney-poor)
+       (method 'dest meaney-poor)
+       (method 'sick meaney-sick)
+       (method 'heal meaney-sick)
+       (method 'affl meaney-sick)
+       (method 'brot meaney-brot)
+       (method 'hous meaney-job)
+
+       ;; pirate quest replies
+       (method 'pira meaney-pira)
+       (method 'gher meaney-gher)
+       (method 'ma   meaney-gher)
+       (method 'capt meaney-gher)
+       (method 'pena meaney-pena)
+       (method 'betr meaney-betr)
+       (method 'firs meaney-firs)
+       (method 'cook meaney-cook)
+       (method 'ring meaney-ring)
+       (method 'skul meaney-ring)
+       (method 'ghol meaney-cook)
+       (method 'jorn meaney-firs)
+       ))
+
+(define (mk-meaney)
+       (let ((knpc
+    (kern-mk-char 
+     'ch_meaney           ; tag
+     "Meaney"             ; name
+     meaney-species         ; species
+     meaney-occ              ; occ
+     s_companion_shepherd  ; sprite
+     faction-men      ; starting alignment
+     1 2 1            ; str/int/dex
+     0 0              ; hp mod/mult
+     0 0              ; mp mod/mult
+     max-health ; hp
+     -1                   ; xp
+     max-health ; mp
+     0
+     meaney-lvl
+     #f               ; dead
+     'meaney-conv         ; conv
+     sch_meaney           ; sched
+     'townsman-ai              ; special ai
+
+     ;;..........container (and contents)
+     (mk-inventory
+      (list
+       (list 1 t_dagger)
+       ))
+     nil              ; readied
+     )))
+ (kern-char-force-drop knpc #t)
+  (bind knpc (meaney-mk))
+  (kern-obj-add-effect knpc 
+           ef_generic_death
+           'meaney-on-death)
+         knpc) )
+  
\ No newline at end of file
diff --git a/worlds/haxima-1.002/melvin.scm b/worlds/haxima-1.002/melvin.scm
new file mode 100644 (file)
index 0000000..d5a7f73
--- /dev/null
@@ -0,0 +1,181 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; In Bole.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_melvin
+               (list 0  0  bole-bed-melvin      "sleeping")
+               (list 7  0  bole-kitchen "working")
+               (list 21 0  bole-bedroom-may      "idle")
+               (list 22 0  bole-bed-melvin "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (melvin-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Melvin is the cook at the Inn in Bole.
+;; He is the (seventh) husband to May.
+;;----------------------------------------------------------------------------
+(define melv-merch-msgs
+  (list "Come by the tavern when I'm open. I open at 7:00AM and close at midnight."
+        "Try the daily special." ;; buy
+        nil ;; sell
+        nil ;; trade
+        "Not bad, eh?" ;; sold-something
+        "Now don't be shy." ;; sold-nothing
+        nil ;; bought-something
+        nil ;; bought-nothing
+        nil ;; traded-something
+        nil ;; traded-nothing
+   ))
+
+(define melv-catalog
+  (list
+   (list t_beer  4 "Beer; it's what's for breakfast!")
+   (list t_food  3 "Folks say I make the best jalapeno quiche in the Shard!")
+   ))
+
+(define (melvin-buy knpc kpc) (conv-trade knpc kpc "buy" melv-merch-msgs melv-catalog))
+
+;; basics...
+(define (melvin-default knpc kpc)
+  (say knpc "Ask May about that, I don't know."))
+
+(define (melvin-hail knpc kpc)
+  (say knpc "[You meet a hungover chef] Hello, partner."))
+
+(define (melvin-name knpc kpc)
+  (say knpc "I'm Melvin, the cook."))
+
+(define (melvin-job knpc kpc)
+  (say knpc "I run the Bole Inn & Tavern with my wife, May. I cook, she "
+       "serves."))
+
+(define (melvin-join knpc kpc)
+  (say knpc "I wouldn't be much good to you, partner. Better leave me here "
+       "to my kitchen where at least I can cook you some grub."))
+
+(define (melvin-bye knpc kpc)
+  (say knpc "Farewell, partner. Come back any time you're hungry."))
+
+;; other characters & town...
+(define (melvin-may knpc kpc)
+  (say knpc "My wife May is an ornery woman, but sharp as a tack."))
+
+(define (melvin-kath knpc kpc)
+  (say knpc "That red lady is a wicked beauty! But I'm neither drunk nor "
+       "fool enough to mingle with wizards business. Take my advice, stay "
+       "far away from her and that thing she travels with!"))
+
+(define (melvin-bill knpc kpc)
+  (say knpc "He's missing a screw or two, but he's a good lad."))
+
+(define (melvin-thud knpc kpc)
+  (say knpc "That's no man traveling with the red lady, but I've never seen a "
+       "troll that could talk so well. I'm not sure what it is, but magic had "
+       "a hand in making it."))
+
+(define (melvin-bole knpc kpc)
+  (say knpc "It's a nice enough place."))
+
+(define (melvin-hack knpc kpc)
+  (say knpc "Hackle lives in the northwest corner of town across the bridge. "
+       "She's a crazy old hedge-witch but harmless."))
+
+
+;; thief quest...
+(define (melvin-thie knpc kpc)
+  (say knpc "There was a strange rogue who came in here not long ago, "
+       "looking like he had demons hounding his trail. He left shortly after "
+       "the red lady arrived. Spoke with Hackle before he left, I think. "
+       "Most odd."))
+
+;; misc...
+(define (melvin-wiza knpc kpc)
+  (say knpc "There's foul business afoot! There's something going on between "
+       "that red sorceress and that mysterious rogue, I know it."))
+
+(define (melvin-inn knpc kpc)
+  (say knpc "If you need a room for the night or something cold to wash the "
+       "dust from your throat, talk to May. But if you're hungry just say so "
+       "and I'll fix you right up!"))
+
+(define (melvin-hung knpc kpc)
+  (say knpc "Are you hungry?")
+  (if (kern-conv-get-yes-no? kpc)
+      (melvin-buy knpc kpc)
+      (say knpc "Well if you get hungry just say so!")))
+
+(define melvin-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default melvin-default)
+       (method 'hail melvin-hail)
+       (method 'bye  melvin-bye)
+       (method 'job  melvin-job)       
+       (method 'name melvin-name)
+       (method 'join melvin-join)
+
+       (method 'buy  melvin-buy)
+       (method 'food melvin-buy)
+       (method 'drin melvin-buy)
+       (method 'supp melvin-buy)
+       (method 'trad melvin-buy)
+
+       (method 'food melvin-buy)
+       (method 'trad melvin-buy)
+       (method 'buy  melvin-buy)
+
+       (method 'bill melvin-bill)
+       (method 'cook melvin-inn)
+       (method 'inn  melvin-inn)
+       (method 'kath melvin-kath)
+       (method 'red  melvin-kath)
+       (method 'lady melvin-kath)
+       (method 'sorc melvin-kath)
+       (method 'may  melvin-may)
+       (method 'hack melvin-hack)
+       (method 'hung melvin-hung)
+       (method 'tave melvin-inn)
+       (method 'thud melvin-thud)
+       (method 'thin melvin-thud)
+       (method 'pet  melvin-thud)
+
+       (method 'thie melvin-thie)
+       (method 'rogu melvin-thie)
+       (method 'char melvin-thie)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-melvin)
+  (bind 
+   (kern-mk-char 'ch_melvin          ; tag
+                 "Melvin"            ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_townsman          ; sprite
+                 faction-men         ; starting alignment
+                 2 0 1             ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'melvin-conv        ; conv
+                 sch_melvin          ; sched
+                 'townsman-ai         ; special ai
+                 nil                                   ; container
+                 (list t_dagger)   ; readied
+                 )
+   (melvin-mk)))
diff --git a/worlds/haxima-1.002/merciful-death.scm b/worlds/haxima-1.002/merciful-death.scm
new file mode 100644 (file)
index 0000000..d199802
--- /dev/null
@@ -0,0 +1,138 @@
+(kern-mk-map
+ 'm_merciful_death 19 19 pal_expanded
+       (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. ~C ~3 ~1 ~1 ~1 ~5 ~A .. .. .. ~C ~3 ~1 ~1 ~1 ~5 ~A .. "
+               "~~ ~~ ~~ bb -- -- ~~ ~~ ~1 ee ~1 ~~ ~~ -- -- -- ~~ ~5 ~A "
+               "-- -- -- ~~ -- -- -- -- -- ee -- -- -- -- -- bb -- ~~ ~~ "
+               "-- #e #a #a #a #a #a #a #a ee #a #a #f -- -- ~~ -- -- -- "
+               "-- #b ee ee ee ee ee ee ee ee ee ee #F #a #a #f -- -- -- "
+               "-- #b ee ee ee ee ee ee ee ee ee ee ee ee ee #F #f -- -- "
+               "-- #b ee ee ee ee ee ee ee ee ee ee ee ee ee ee #F #f -- "
+               "-- #b ee ee oo ee ee ee ee oo ee ee ee WW ee ee ee #c -- "
+               "-- #b ee ee ee ee ee ee ee ee ee ee ee ee ee ee #H #h -- "
+               "-- #b ee ee ee ee ee ee ee ee ee ee ee ee ~~ ~~ ~~ ~~ -- "
+               "-- #b ee ~~ ~~ ~~ ee ee ~~ ~~ ee ee #H #d #d ~~ ~~ ~~ -- "
+               "-- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ bb -- "
+               "-- ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ bb ~~ ~~ ~~ ~~ -- -- bb ~~ -- "
+               "-- -- bb -- -- -- -- -- -- ~~ -- -- -- -- -- -- ~~ -- -- "
+               "-- -- ~~ -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+               "-- -- -- -- __ __ __ __ -- -- -- -- __ __ __ -- -- -- -- "
+               "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- "
+       )
+  )
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Special Objects
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_merciful_death ; tag
+ "Wreck of the Merciful Death (abovedecks)"   ; name
+ s_ship              ; sprite
+ m_merciful_death  ; map
+ #f               ; wraps
+ #f                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ ;; neighbors
+ (list
+  )
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+  (put (mk-ladder-down 'p_merciful_death_l2 6 9) 6 9)
+  (put (spawn-pt 'skeletal-warrior) 7 9)
+  (put (spawn-pt 'skeletal-spear-thrower) 10 9)
+  )
+
+ (list 'on-entry-to-dungeon-room) ; hooks
+ nil ; edge entrances
+ )
+
+(mk-place-music p_merciful_death 'ml-dungeon-adventure)
+
+;; ----------------------------------------------------------------------------
+;; Map
+;; ----------------------------------------------------------------------------
+  (kern-mk-map
+    'm_merciful_death_l2 19 19 pal_expanded
+    (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr -- -- -- -- -- rr rr rr rr rr -- -- -- -- -- rr rr "
+      "-- -- -- bb -- -- -- -- -- -- -- -- -- -- -- -- -- -- rr "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- bb -- -- -- "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- #I #r #r #r #r #r #r #r #r #J -- -- -- -- -- -- -- "
+      "-- -- #s ee ee ee ee ee ee ee ee #K #r #r #J -- -- -- -- "
+      "-- -- #s ee ee ee ee ee ee ee ee ee ee ee #K #J -- -- -- "
+      "-- -- #s ee ee ee ee ee ee ee ee ee ee ee ee #s -- -- -- "
+      "-- -- #s ee ee ee ee ee ee ee ee ee ee ee #I #L -- -- -- "
+      "-- -- #s ee ee ee ee ee ee ee ee #I #r #r #L -- -- -- -- "
+      "-- -- #K #r #r #r #r #r #r #r #r #L -- -- -- -- -- -- -- "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- bb -- "
+      "-- -- -- -- -- -- -- -- -- bb -- -- -- -- -- -- bb -- -- "
+      "-- -- bb -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "
+      "-- -- -- -- __ __ __ __ -- -- -- -- __ __ __ -- -- -- -- "
+      "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- "
+    )
+  )
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Special Objects
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_merciful_death_l2 ; tag
+ "Wreck of the Merciful Death (belowdecks)"   ; name
+ nil              ; sprite
+ m_merciful_death_l2  ; map
+ #f               ; wraps
+ #t                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ ;; neighbors
+ (list
+  )
+ ;; objects
+ (list
+  (put (mk-monman) 0 0)
+  (put (mk-ladder-up 'p_merciful_death 6 9) 6 9)
+  (put (mk-chest
+        'poison-trap
+        '((1   t_rune_c)
+                     (342 t_gold_coins)
+                     (4   t_gem)
+                     (1 t_sextant)
+                     ))
+       14 9)
+  (put (spawn-pt 'skeletal-warrior) 7 9)
+  (put (spawn-pt 'skeletal-spear-thrower) 10 9)
+  )
+
+ (list 'on-entry-to-dungeon-room) ; hooks
+ nil ; edge entrances
+ )
+
+(mk-place-music p_merciful_death 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/mesmeme.scm b/worlds/haxima-1.002/mesmeme.scm
new file mode 100644 (file)
index 0000000..ba32f02
--- /dev/null
@@ -0,0 +1,130 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define mesmeme-lvl 2)
+(define mesmeme-species sp_gazer)
+(define mesmeme-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_mesmeme
+               (list 0  0 campfire-1 "sleeping")
+               (list 9  0 cantina-6 "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (mesmeme-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (mesmeme-hail knpc kpc)
+  (kern-log-msg "You meet a battered gazer.")
+  (say knpc "I see you.")
+  )
+
+(define (mesmeme-default knpc kpc)
+  (say knpc "No knowing. No asking. Alone.")
+  )
+
+(define (mesmeme-name knpc kpc)
+  (say knpc "I Mesmeme.")
+  )
+
+(define (mesmeme-leav knpc kpc)
+  (if (is-player-party-member? knpc)
+      (begin
+               (say knpc "Be alone?")
+        (if (yes? kpc)
+            (begin
+              (if (kern-char-leave-player knpc)
+                  (begin
+                    (say knpc "Here waiting. Until void.")
+                    (kern-conv-end))
+                  (say knpc "Not now!")))
+            (say knpc "Not alone!")))
+      (begin
+               (say knpc "Until void.")
+           (kern-conv-end)))
+  )
+
+(define (mesmeme-join knpc kpc)
+  (say knpc "Yes! I alone.")
+  (join-player knpc)
+  (kern-conv-end)
+  )
+
+(define (mesmeme-job knpc kpc)
+  (say knpc "No job. No kindred. Alone.")
+  )
+
+(define (mesmeme-bye knpc kpc)
+  (say knpc "Until void.")
+  )
+
+(define (mesmeme-alon knpc kpc)
+  (say knpc "I crippled. No... think voice? Mind voice? No talk kindred. Alone.")
+  )
+
+(define (mesmeme-kind knpc kpc)
+  (say knpc "Kindred. Gazers. Swarm.")
+  )
+
+(define (mesmeme-crip knpc kpc)
+  (say knpc "Gint slave, mine. Too strong. Broke free, hurt!")
+  )
+
+(define (mesmeme-slav knpc kpc)
+  (say knpc "Tools. Hands. One body too few!")
+  )
+
+(define mesmeme-conv
+  (ifc nil
+
+       ;; basics
+       (method 'default mesmeme-default)
+       (method 'hail mesmeme-hail)
+       (method 'bye mesmeme-bye)
+       (method 'job mesmeme-job)
+       (method 'name mesmeme-name)
+       (method 'join mesmeme-join)
+       (method 'leav mesmeme-leav)
+       
+       (method 'alon mesmeme-alon)
+       (method 'kind mesmeme-kind)
+       (method 'crip mesmeme-crip)
+       (method 'slav mesmeme-slav)
+       ))
+
+(define (mk-mesmeme)
+  (bind 
+   (kern-mk-char 
+    'ch_mesmeme           ; tag
+    "Mesmeme"             ; name
+    mesmeme-species         ; species
+    mesmeme-occ              ; occ
+    s_gazer     ; sprite
+    faction-men      ; starting alignment
+    0 0 0            ; str/int/dex
+    (/ pc-hp-off 2)  ; hp bonus
+    (/ pc-hp-gain 2) ; hp per-level bonus
+    0 ; mp off
+    1 ; mp gain
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    mesmeme-lvl
+    #f               ; dead
+    'mesmeme-conv         ; conv
+    sch_mesmeme           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   (mesmeme-mk)))
diff --git a/worlds/haxima-1.002/miggs.scm b/worlds/haxima-1.002/miggs.scm
new file mode 100644 (file)
index 0000000..3a78a5b
--- /dev/null
@@ -0,0 +1,95 @@
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Trigrave"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_miggs
+               (list 0  0  trigrave-miggs-bed      "sleeping")
+               (list 7  0  trigrave-tavern-kitchen "working")
+               (list 23 0  trigrave-miggs-bed      "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (miggs-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Miggs is the tavern-keeper.
+;;----------------------------------------------------------------------------
+(define miggs-merch-msgs
+  (list "Come by the tavern when I'm open. I open at 7:00AM and close at midnight."
+        "[She silently points to a menu]"
+        nil
+        nil
+        "Thank you."
+        "Ok."
+        ))
+
+(define miggs-catalog
+  (list
+   (list t_food 5 "[She ladles some delicious-smelling stew]")
+   (list t_beer 3 "[She points to a cask labeled Fenmire's Finest]")
+  ))
+
+(define (miggs-trade knpc kpc) (conv-trade knpc kpc "buy" miggs-merch-msgs miggs-catalog))
+
+(define (miggs-hail knpc kpc)
+  (kern-print "[You meet a large woman with a pretty face. She shyly avoids "
+              "your gaze]\n"))
+
+(define (miggs-job knpc kpc)
+  (say knpc "I run the the Lusty Jugs."))
+
+(define (miggs-lust knpc kpc)
+  (say knpc "It's a tavern. Want something?")
+  (if (kern-conv-get-yes-no? kpc)
+      (miggs-trade knpc kpc)
+      (say knpc "Ok")))
+
+(define miggs-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "[She shrugs]")))
+       (method 'hail miggs-hail)
+       (method 'bye (lambda (knpc kpc) (say knpc "[She smiles slightly]")))
+       (method 'job miggs-job)       
+       (method 'name (lambda (knpc kpc) (say knpc "Miggs")))
+
+       (method 'trad miggs-trade)
+       (method 'buy miggs-trade)
+       (method 'food miggs-trade)
+       (method 'lust miggs-lust)
+       (method 'jugs miggs-lust)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-miggs tag)
+  (bind 
+   (kern-mk-char tag                 ; tag
+                 "Miggs"            ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_fat_townswoman    ; sprite
+                 faction-men         ; starting alignment
+                 2 0 0             ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'miggs-conv        ; conv
+                 sch_miggs          ; sched
+                 'townsman-ai                 ; special ai
+                  nil                ; container
+                 (list t_dagger)                 ; readied
+                 )
+   (miggs-mk)))
diff --git a/worlds/haxima-1.002/mimic.scm b/worlds/haxima-1.002/mimic.scm
new file mode 100644 (file)
index 0000000..6e311bd
--- /dev/null
@@ -0,0 +1,27 @@
+;; mimic.scm -- define a mechanism which looks like a chest, but when opened it
+;; spawns a hostile mimic npc
+
+;; Spawn a mimic npc where the mimic mechanism is and remove the mechanism.
+(define (mimic-open kobj kchar)
+  (kern-obj-put-at (mk-npc 'mimic (calc-level))
+                   (kern-obj-get-location kobj))
+  (kern-obj-remove kobj)
+  )
+
+;; The trap detection handlers are nops
+(define (mimic-get-traps kobj) nil)
+(define (mimic-rm-traps kobj) nil)
+
+;; Emulate the container-ifc, including the trap detection signal handlers,
+;; otherwise An Sanct will give the mimic away.
+(define mimic-ifc
+  (ifc '()
+       (method 'open mimic-open)
+       (method 'get-traps mimic-get-traps)
+       (method 'rm-traps mimic-rm-traps)
+       ))
+
+(mk-obj-type 't_mimic "chest" s_chest layer-mechanism mimic-ifc)
+
+(define (mk-mimic)
+  (kern-mk-obj t_mimic 1))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/minimal-game.scm b/worlds/haxima-1.002/minimal-game.scm
new file mode 100644 (file)
index 0000000..181e263
--- /dev/null
@@ -0,0 +1,725 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;; This file loads 58 files
+
+
+;; Slots
+(define slot-nil              0)
+(define slot-amulet           1)
+(define slot-ring             2)
+(define slot-gazer-helm       4)
+(define slot-weapon           8)
+(define slot-shield           8)
+(define slot-weapon-or-shield 8)
+(define slot-armor            16)
+(define slot-boot             32)
+(define slot-helm             64)
+
+;; Speeds  ;; TODO: move most of these into kern-intvars ?
+
+(define speed-human             50)  ;; typical AP/round for humans
+
+(define base-move-ap           50)  ;; this may not bear a neat relationship to speed-human
+(define default-weapon-rap      50)  ;; this may not bear a neat relationship to speed-human
+(define default-armour-apmod    2)  ;; this may not bear a neat relationship to speed-human
+
+(define base-skill-ap                  base-move-ap)  ;; this may not bear a neat relationship to speed-human
+(define base-spell-ap                  base-move-ap)  ;; this may not bear a neat relationship to speed-human
+
+;; AP costs of various actions which the kernal needs to know about:
+(kern-set-kern-intvar "AP_TOTAL:normal_human"    speed-human)
+
+(kern-set-kern-intvar "AP_COST:default"           speed-human)
+(kern-set-kern-intvar "AP_COST:search"            (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:get_item"          (* 0.34 speed-human))
+(kern-set-kern-intvar "AP_COST:drop_item"         (* 0.34 speed-human))
+(kern-set-kern-intvar "AP_COST:open_mechanism"    speed-human)
+(kern-set-kern-intvar "AP_COST:open_container"    speed-human)
+(kern-set-kern-intvar "AP_COST:handle_mechanism"  speed-human)
+(kern-set-kern-intvar "AP_COST:use_item"          speed-human)  ;; may be unused, per comment in cmd.c cmdUse()
+
+;; Normal mixing: 18 + (num_mixed * 12) + (spell_level * 12) AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_base"         (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_per_mix"      (* 2 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_per_level"    (* 2 speed-human))
+;; Attempt at non-existent spell: 3d18+6 AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_num"   3)
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_dice" (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_nospell_plus"  speed-human)
+;; Missing or additional ingredients: (2 * spell_level)d18+18 AP
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_num"    2)  ;; times spell Level
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_dice"  (* 3 speed-human))
+(kern-set-kern-intvar "AP_COST:mix_reagents_badmix_plus"  (* 3 speed-human))
+
+;; These values are used by ctrl.c ctrl_attack_target() 
+;; to adjust weapon AP costs in the event of dual wielding.
+;; The dual weapon rules can thus be tweaked here...
+(kern-set-kern-intvar "AP_MULT12:second_wpn_attack"       6)  ;; AP cost * 6/12 for 2nd weapon attack if dual wpns used
+(kern-set-kern-intvar "AP_MULT12:third_plus_wpn_attack"   6)  ;; AP cost * 6/12 for 3rd+ weapon attacks, if 3+ weapons used
+(kern-set-kern-intvar "AP_THRESHOLD:multi_attack_overage" 0)  ;; attack sequence can continue if AP overage is not > 0
+
+(kern-set-kern-intvar "submerged_def_bonus" 10) ;; defense bonus for submerged critters
+
+;; ship speeds are better handled using mmodes/pclasses-
+;; it should only affect actual movement
+(define speed-ship            speed-human)  
+
+;; Action Point costs for various basic actions:
+;; are these used anywhere?
+;;(define ap-for-1H-melee-attack   9)
+;;(define ap-for-2H-melee-attack  12)
+
+;;(define ap-for-1H-thrown-attack 12)
+;;(define ap-for-2H-thrown-attack 18)
+
+;;(define ap-for-shooting-attack  12)
+
+;;(define ap-for-combat-spell      9)
+;;(define ap-to-use-scroll        12)
+
+
+;; Difficulty Classes
+(define dc-escape-ensnare  26)
+(define dc-escape-paralyze 16)
+
+;; Pmasks (keep them around until mechs are converted to use passability
+;; classes (see below))
+(define pmask-none   0)
+(define pmask-solid  1)
+(define pmask-land   2)
+(define pmask-water  4)
+(define pmask-shoals 8)
+(define pmask-bridge (+ pmask-land pmask-water pmask-shoals))
+(define pmask-all    (+ pmask-solid pmask-land pmask-water pmask-shoals))
+
+;; Passability Difficulty Levels 
+;;   (Note: 255 is well-known to the kernel to mean
+;;   "impassible" in the case of movement costs)
+(define fast        (* 0.66 base-move-ap))  ;; 0.66 (2/3)
+(define s-fast      (* 0.8 base-move-ap))  ;; 'slightly fast' 0.8
+(define norm        base-move-ap)  ;; 1.0
+(define s-hard      (* 1.5 base-move-ap))  ;; 1.5
+(define hard       (* 2 base-move-ap))  ;; 2.0
+(define v-hard     (* 3 base-move-ap))  ;; 3.0
+
+(define no-drop    100)  ;; special, used for dropability (not related to speed-human)
+(define cant      255)  ;; special
+
+;(define norm       50)  ;; 1.0
+;(define s-hard     75)  ;; 1.5
+;(define hard      100)  ;; 2.0
+;(define v-hard    150)  ;; 3.0
+;(define fast       30)  ;; 0.6
+;(define s-fast     40)  ;; 0.4
+;(define no-drop   100)  ;; 2.0
+;(define cant      255)  ;; 
+
+
+;; Passability classes
+(define pclass-none          0)
+(define pclass-grass         1)
+(define pclass-deep          2)
+(define pclass-shoals        3)
+(define pclass-mountains     4) ;; no ceiling
+(define pclass-wall          5) ;; has a ceiling
+(define pclass-trees         6)
+(define pclass-forest        7)
+(define pclass-hills         8)
+(define pclass-repel         9) ;; energy shield blocks all
+(define pclass-space         10)
+(define pclass-bridge        pclass-grass)
+(define pclass-road          pclass-grass)
+(define pclass-boulder       11) ;; no ceiling, smaller than mountain
+(define pclass-waterboulder  12) ;; worst case of boulder and water
+(define pclass-sludge        13)
+(define pclass-shallows      14)
+(define pclass-bars          15) ;; portcullis
+(define pclass-window        16) ;; separating from bars for shoot-but-not-crawl-through passability
+(define pclass-vmountains    17)
+(define pclass-canfloat      18) ;; avoids drowning
+(define pclass-canfly        19) ;; avoids ground based issues
+
+;; Movement modes
+(define mmodes
+  (list
+   (list 'mmode-walk      "walking"     0)
+   (list 'mmode-hover     "hovering"    1)
+   (list 'mmode-ship      "sailing"     2)
+   (list 'mmode-phase     "phasing"     3)
+   (list 'mmode-fly       "flying"      4)
+   (list 'mmode-skiff     "rowing"      5)
+   (list 'mmode-fish      "swimming"    6)
+   (list 'mmode-crawl     "crawling"    7) ;; spiders, can cross boulders
+   (list 'mmode-voidship  "sailing"     8)
+   (list 'mmode-ranger    "stalking"    9)
+   (list 'mmode-none      "stationary" 10)
+   (list 'mmode-wriggle   "wriggle"    11) ;; rogue special move
+   (list 'mmode-missile   "missile"    12)
+   (list 'mmode-fastfly   "flying"     13)
+   (list 'mmode-fastrun   "running"    14)
+   (list 'mmode-fastcrawl "crawling"   15)
+   (list 'mmode-smallobj  "smallobj"   16) ;; for determining dropability of small objects
+   (list 'mmode-largeobj  "largeobj"   17) ;; for determining dropability of big objects- basically, stuff that wont fit through bars/windows
+   (list 'mmode-field     "field"      18) ;; for determining dropability of fields
+   (list 'mmode-return    "return"     19) ;; return path for magic axe (for now assume it always returns)
+   (list 'mmode-cannon    "cannon"     20) ;; enhanced missile passibility for cannon shells
+   (list 'mmode-large     "striding"   21) ;; big critters
+))
+(map (lambda (mmode) (apply kern-mk-mmode mmode)) mmodes)
+
+(define mmode-jump mmode-fly)
+
+;; Movement cost table (optimized for cut to/paste from spreadsheet!)
+(kern-mk-ptable                                                                                                                                                                                                        
+       ;;      walk    hover   ship    phase   fly     skiff   fish    crawl   vship   rangr   none    wrigl   missl   f_fly   f_run   f_crawl sml_obj lrg_obj fields  return  cannon  striding                
+       (list   0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       0       )       ;; none
+       (list   norm    norm    cant    norm    norm    cant    cant    norm    cant    norm    cant    norm    0       fast    fast    fast    norm    norm    norm    0       0       norm    )       ;; grass/paving
+       (list   cant    cant    s-fast  cant    norm    v-hard  norm    cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       cant    )       ;; deep
+       (list   cant    s-hard  cant    cant    norm    norm    norm    cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       s-hard  )       ;; shoals
+       (list   cant    cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    95      s-fast  cant    cant    no-drop no-drop cant    0       90      cant    )       ;; mountains
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    cant    100     cant    cant    cant    cant    cant    cant    0       100     cant    )       ;; wall (w/ ceiling)
+       (list   hard    hard    cant    norm    norm    cant    cant    hard    cant    norm    cant    hard    10      fast    norm    norm    norm    norm    norm    0       7       hard    )       ;; trees
+       (list   v-hard  v-hard  cant    norm    norm    cant    cant    v-hard  cant    s-hard  cant    v-hard  30      fast    hard    hard    norm    norm    norm    0       20      v-hard  )       ;; forest
+       (list   v-hard  hard    cant    norm    norm    cant    cant    v-hard  cant    s-hard  cant    v-hard  7       fast    hard    hard    norm    norm    norm    0       5       hard    )       ;; hills/bog
+       (list   cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    cant    100     cant    cant    cant    no-drop no-drop norm    0       100     cant    )       ;; energy fields
+       (list   cant    cant    cant    cant    norm    cant    cant    cant    norm    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       cant    )       ;; space
+       (list   cant    norm    cant    norm    norm    cant    cant    hard    cant    cant    cant    hard    10      fast    cant    norm    norm    norm    norm    0       4       norm    )       ;; boulder
+       (list   cant    hard    cant    cant    norm    cant    cant    hard    cant    cant    cant    hard    10      fast    cant    norm    norm    norm    no-drop 0       4       hard    )       ;; waterboulder
+       (list   cant    norm    hard    cant    norm    v-hard  v-hard  cant    cant    cant    cant    cant    0       fast    cant    cant    cant    cant    no-drop 0       0       norm    )       ;; sludge
+       (list   s-hard  norm    cant    norm    norm    norm    norm    s-hard  cant    norm    cant    cant    0       fast    norm    norm    cant    cant    no-drop 0       0       norm    )       ;; shallow sludge
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    v-hard  7       cant    cant    cant    norm    no-drop norm    0       7       cant    )       ;; bars (eg portcullis)
+       (list   cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    cant    30      cant    cant    cant    no-drop no-drop no-drop 0       25      cant    )       ;; window
+       (list   cant    cant    cant    cant    s-hard  cant    cant    cant    cant    cant    cant    cant    30      s-fast  cant    cant    no-drop no-drop no-drop 0       10      cant    )       ;; passlos mountains
+       (list   cant    v-hard  s-fast  cant    norm    cant    norm    cant    cant    cant    cant    cant    norm    norm    cant    cant    cant    cant    norm    norm    norm    v-hard  )       ;; float
+       (list   cant    hard    cant    cant    norm    hard    cant    cant    norm    cant    cant    cant    norm    norm    cant    cant    cant    cant    norm    norm    norm    cant    )       ;; fly
+)                                                                                                                                                                                                      
+;; Note that pclass 'missl' is using the value as a percentage chance 
+;; for a missile to be blocked by obscuring terrain, not as an AP cost
+
+
+;; Factions. The diplomacy table (which defines the relationship between
+;; factions) must be defined in the session file, because it changes over time.
+(define faction-none          0)
+(define faction-player        1)
+(define faction-men           2)
+(define faction-cave-goblin   3)
+(define faction-accursed      4)
+(define faction-monster       5)
+(define faction-troll         6)
+(define faction-spider        7)
+(define faction-outlaw        8)
+(define faction-gint          9)
+(define faction-demon         10)
+(define faction-forest-goblin 11)
+(define faction-green-tower   faction-men)
+(define faction-oparine       faction-men)
+(define faction-trigrave      faction-men)
+(define faction-nixie         faction-monster)
+(define faction-prisoner      12)
+(define faction-glasdrin      13)
+(define faction-num           14)
+
+;; Layers (must match object.h)
+(define layer-none       0)
+(define layer-tfeat      1)
+(define layer-mechanism  2)
+(define layer-portal     3)
+(define layer-vehicle    4)
+(define layer-bed        5)
+(define layer-container  6)
+(define layer-item       7)
+(define layer-field      8)
+(define layer-being      9)
+(define layer-projectile 10)
+(define layer-crosshair  11)
+
+;; Contexts
+(define context-world 1)
+(define context-town  2)
+(define context-any      (+ context-town context-world))
+
+;; Damage/Immunity types (ordinal, not bitmasks)
+(define damage-none   0)
+(define damage-fire   1)
+(define damage-poison 2)
+(define damage-sleep  3)
+
+;; Damage amounts
+(define lava-damage 10)
+
+;; Directions (as returned by kern-ui-get-direction)
+(define northwest 0)
+(define north     1)
+(define northeast 2)
+(define west      3)
+(define here      4)
+(define east      5)
+(define southwest 6)
+(define south     7)
+(define southeast 8)
+(define up        9)
+(define down      10)
+
+;; Scroll directions (for UI keyhandling, must match kernel's StatusScrollDir)
+(define scroll-up       0)
+(define scroll-down     1)
+(define scroll-right    2)
+(define scroll-left     3)
+(define scroll-pageup   4)
+(define scroll-pagedown 5)
+(define scroll-top      6)
+(define scroll-bottom   7)
+
+(define opposite-dir (vector southeast south southwest
+                             east here west
+                             northeast north northwest
+                             down up))
+
+;; Player character bonuses
+(define pc-hp-off  25)
+(define pc-hp-gain 5)
+(define pc-mp-off  1)
+(define pc-mp-gain 1)
+
+;; NPC activities
+(define (isdrunk? knpc)
+  (string=? "drunk" (kern-obj-get-activity knpc)))
+(define (isworking? knpc)
+  (string=? "working" (kern-obj-get-activity knpc)))
+
+;; Prices
+(define base-scroll-cost 20) ;; gold pieces per level of scroll's spell
+(define reagent-price-mult 1) ;; global reagent price multiplier
+
+;; rather than trying to calculate appropriate hp/mp for
+;; characters, stick in a big number and let Character::new
+;; trim it as needed
+(define max-health 999999999)
+
+;; Some of the following are order-dependent
+(load "loc.scm")
+(load "kobj.scm")
+(load "ifc.scm")
+
+;; sprite sets
+;;
+;; 'ss_sprite_set_name tile_pix_w tile_pix_h tiles_h tiles_w x_offset y_offset "path/filename"
+;;
+;;                  'ss_sprite_set_name 
+;;                  |                    tile_pixels_wide tile_pixels_high
+;;                  |                    |       sheet_tiles_high sheet_tiles_wide
+;;                  |                    |       |       sheet_pixels_x_offset sheet_pixels_y_offset
+;;                  |                    |       |       |     "path/filename"
+;;                  |                    |       |       |     |
+;;                  v                    v       v       v     v
+;;----------------------------------------------------------------------------
+(kern-mk-sprite-set 'ss_u4_shapes        32 32   16 16   0 0  "shapes.png")
+(kern-mk-sprite-set 'ss_u4_charset       8  16    8 16   0 0  "charset.png")
+(kern-mk-sprite-set 'ss_frame            16 16    4  4   0 0  "frame.png")
+; (kern-mk-sprite-set 'ss_rune             32 32    4  8   0 0  "rune.png")
+(kern-mk-sprite-set 'ss_addon            32 32   16  8   0 0  "addons.png")
+(kern-mk-sprite-set 'ss_moons            16 16    4  8   0 0  "moons.png")
+; (kern-mk-sprite-set 'ss_signs            32 32    1  8   0 0  "signs.png")
+; (kern-mk-sprite-set 'ss_runestones       32 32    4  8   0 0  "runestones.png")
+; (kern-mk-sprite-set 'ss_newmonst         32 32   16  8   0 0  "newmonst.png") 
+; (kern-mk-sprite-set 'ss_newfolks         32 32   16  8   0 0  "newfolks.png")
+; (kern-mk-sprite-set 'ss_buildings        32 32    1  2   0 0  "tower.png")
+; (kern-mk-sprite-set 'ss_overlays         32 32   13  8   0 0  "newterrain.png")
+; (kern-mk-sprite-set 'ss_effects          8  16    3  16  0 0  "effects.png")
+; (kern-mk-sprite-set 'ss_bigobjects       40 40    8  8   0 0  "bigobjects.png")
+; (kern-mk-sprite-set 'ss_humanoids        32 32   16  8   0 0  "humanoids.png")
+; (kern-mk-sprite-set 'ss_people           32 32   16  8   0 0  "hirespeople.png")
+; (kern-mk-sprite-set 'ss_monsters         32 32   16  8   0 0  "monsters.png")
+; (kern-mk-sprite-set 'ss_ship             32 32    8  8   0 0  "ship.png")
+; (kern-mk-sprite-set 'ss_sfx              32 32    8  8   0 0  "sfx.png")
+; (kern-mk-sprite-set 'ss_creatures        32 32   16  8   0 0  "creatures.png")
+; (kern-mk-sprite-set 'ss_tools            32 32    8  8   0 0  "tools.png")
+
+;; New paper-doll sprite sets
+; (kern-mk-sprite-set 'ss_bodies     32 32 4 4 0 0 "bodies.png")
+; (kern-mk-sprite-set 'ss_adornments 32 32 4 4 0 0 "adornments.png")
+; (kern-mk-sprite-set 'ss_clothes    32 32 5 4 0 0 "clothes.png")
+
+
+;; sprites
+(kern-mk-sprite 's_sun                      ss_moons 1 24 #f 0 )
+(kern-mk-sprite 's_grass         ss_u4_shapes 1  4 #f 0 )
+(kern-mk-sprite 's_wanderer         ss_u4_shapes 4 224 #f 0 )
+(kern-mk-sprite 's_crosshair            ss_addon 1  0 #f   0 )
+; (kern-mk-sprite 's_bog           ss_u4_shapes 1  3 #f 0 )
+; (kern-mk-sprite 's_town          ss_u4_shapes 1 10 #f 0 )
+(kern-mk-sprite 's_keep          ss_u4_shapes 1 11 #f 0 )
+; (kern-mk-sprite 's_hamlet        ss_u4_shapes 1 12 #f 0 )
+; (kern-mk-sprite 's_leftwing      ss_u4_shapes 1 13 #f 0 )
+; (kern-mk-sprite 's_castle        ss_u4_shapes 1 14 #f 0 )
+; (kern-mk-sprite 's_rightwing     ss_u4_shapes 1 15 #f 0 )
+; (kern-mk-sprite 's_cobblestone   ss_u4_shapes 1 22 #f 0 )
+; (kern-mk-sprite 's_ew_bridge     ss_u4_shapes 1 23 #f 0 )
+; (kern-mk-sprite 's_ballon        ss_u4_shapes 1 24 #f 0 )
+; (kern-mk-sprite 's_bridge_top    ss_u4_shapes 1 25 #f 0 )
+; (kern-mk-sprite 's_bridge_bottom ss_u4_shapes 1 26 #f 0 )
+; (kern-mk-sprite 's_ladder_up     ss_u4_shapes 1 27 #f 0 )
+; (kern-mk-sprite 's_ladder_down   ss_u4_shapes 1 28 #f 0 )
+; (kern-mk-sprite 's_ruin          ss_u4_shapes 1 29 #f 0 )
+; (kern-mk-sprite 's_shrine        ss_u4_shapes 1 30 #f 0 )
+; (kern-mk-sprite 's_pillar      ss_u4_shapes 1 48 #f 0 )
+; (kern-mk-sprite 's_wall_b      ss_u4_shapes 1 49 #f 0 )
+; (kern-mk-sprite 's_wall_a      ss_u4_shapes 1 50 #f 0 )
+; (kern-mk-sprite 's_wall_c      ss_u4_shapes 1 51 #f 0 )
+; (kern-mk-sprite 's_wall_d      ss_u4_shapes 1 52 #f 0 )
+; (kern-mk-sprite 's_mast        ss_u4_shapes 1 53 #f 0 )
+; (kern-mk-sprite 's_ships_wheel ss_u4_shapes 1 54 #f 0 )
+; (kern-mk-sprite 's_boulder     ss_u4_shapes 1 55 #f 0 )
+(kern-mk-sprite 's_asleep      ss_u4_shapes 1 56 #f 0 )
+; (kern-mk-sprite 's_wall_rock   ss_u4_shapes 1 57 #f 0 )
+; (kern-mk-sprite 's_door_locked ss_u4_shapes 1 58 #f 0 )
+; (kern-mk-sprite 's_door        ss_u4_shapes 1 59 #f 0 )
+; (kern-mk-sprite 's_chest       ss_u4_shapes 1 60 #f 0 )
+; (kern-mk-sprite 's_ankh        ss_u4_shapes 1 61 #f 0 )
+; (kern-mk-sprite 's_flagstone   ss_u4_shapes 1 62 #f 0 )
+; (kern-mk-sprite 's_deck        ss_u4_shapes 1 63 #f 0 )
+
+; (kern-mk-sprite 's_moongate_quarter        ss_u4_shapes 1 64 #f 0 )
+; (kern-mk-sprite 's_moongate_half           ss_u4_shapes 1 65 #f 0 )
+; (kern-mk-sprite 's_moongate_three_quarters ss_u4_shapes 1 66 #f 0 )
+; (kern-mk-sprite 's_moongate_full           ss_u4_shapes 1 67 #f 0 )
+
+; (kern-mk-sprite 's_field_poison ss_u4_shapes 1 68 #t 0 )
+; (kern-mk-sprite 's_field_energy ss_u4_shapes 1 69 #t 0 )
+; (kern-mk-sprite 's_field_fire   ss_u4_shapes 1 70 #t 0 )
+; (kern-mk-sprite 's_field_sleep  ss_u4_shapes 1 71 #t 0 )
+; (kern-mk-sprite 's_wall         ss_u4_shapes 1 72 #f 0 )
+; (kern-mk-sprite 's_secret_door  ss_u4_shapes 1 73 #f 0 )
+; (kern-mk-sprite 's_altar_obj        ss_u4_shapes 1 74 #f 0 )
+; (kern-mk-sprite 's_lava         ss_u4_shapes 1 76 #t 0 )
+; (kern-mk-sprite 's_projectile   ss_u4_shapes 1 77 #f 0 )
+; (kern-mk-sprite 's_magic        ss_u4_shapes 1 78 #f 0 )
+(kern-mk-sprite 's_hit          ss_u4_shapes 1 79 #f 0 )
+; (kern-mk-sprite 's_guard        ss_u4_shapes 2 80 #f 0 )
+; (kern-mk-sprite 's_townsman     ss_u4_shapes 2 82 #f 0 )
+; (kern-mk-sprite 's_bard         ss_u4_shapes 2 84 #f 0 )
+; (kern-mk-sprite 's_jester       ss_u4_shapes 2 86 #f 0 )
+; (kern-mk-sprite 's_beggar       ss_u4_shapes 2 88 #f 0 )
+; (kern-mk-sprite 's_child        ss_u4_shapes 2 90 #f 0 )
+; (kern-mk-sprite 's_bull         ss_u4_shapes 2 92 #f 0 )
+; (kern-mk-sprite 's_lord         ss_u4_shapes 2 94 #f 0 )
+
+; (kern-mk-sprite 's_A ss_u4_shapes 1  96 #f 0 )
+; (kern-mk-sprite 's_B ss_u4_shapes 1  97 #f 0 )
+; (kern-mk-sprite 's_C ss_u4_shapes 1  98 #f 0 )
+; (kern-mk-sprite 's_D ss_u4_shapes 1  99 #f 0 )
+; (kern-mk-sprite 's_E ss_u4_shapes 1 100 #f 0 )
+; (kern-mk-sprite 's_F ss_u4_shapes 1 101 #f 0 )
+; (kern-mk-sprite 's_G ss_u4_shapes 1 102 #f 0 )
+; (kern-mk-sprite 's_H ss_u4_shapes 1 103 #f 0 )
+; (kern-mk-sprite 's_I ss_u4_shapes 1 104 #f 0 )
+; (kern-mk-sprite 's_J ss_u4_shapes 1 105 #f 0 )
+; (kern-mk-sprite 's_K ss_u4_shapes 1 106 #f 0 )
+; (kern-mk-sprite 's_L ss_u4_shapes 1 107 #f 0 )
+; (kern-mk-sprite 's_M ss_u4_shapes 1 108 #f 0 )
+; (kern-mk-sprite 's_N ss_u4_shapes 1 109 #f 0 )
+; (kern-mk-sprite 's_O ss_u4_shapes 1 110 #f 0 )
+; (kern-mk-sprite 's_P ss_u4_shapes 1 111 #f 0 )
+; (kern-mk-sprite 's_Q ss_u4_shapes 1 112 #f 0 )
+; (kern-mk-sprite 's_R ss_u4_shapes 1 113 #f 0 )
+; (kern-mk-sprite 's_S ss_u4_shapes 1 114 #f 0 )
+; (kern-mk-sprite 's_T ss_u4_shapes 1 115 #f 0 )
+; (kern-mk-sprite 's_U ss_u4_shapes 1 116 #f 0 )
+; (kern-mk-sprite 's_V ss_u4_shapes 1 117 #f 0 )
+; (kern-mk-sprite 's_W ss_u4_shapes 1 118 #f 0 )
+; (kern-mk-sprite 's_X ss_u4_shapes 1 119 #f 0 )
+; (kern-mk-sprite 's_Y ss_u4_shapes 1 120 #f 0 )
+; (kern-mk-sprite 's_Z ss_u4_shapes 1 121 #f 0 )
+
+; (kern-mk-sprite 's_counter_2x1_c ss_u4_shapes 1 122 #f 0 )
+; (kern-mk-sprite 's_counter_2x1_e ss_u4_shapes 1 123 #f 0 )
+; (kern-mk-sprite 's_counter_2x1_w ss_u4_shapes 1 124 #f 0 )
+; (kern-mk-sprite 's_counter_1x1   ss_u4_shapes 1 125 #f 0 )
+
+; (kern-mk-sprite 's_blank          ss_u4_shapes 1 126 #f 0 )
+(kern-mk-sprite 's_null           ss_u4_shapes 1 126 #f 0 )
+; (kern-mk-sprite 's_wall_stone     ss_u4_shapes 1 127 #f 0 )
+
+; (kern-mk-sprite 's_pirate_left    ss_u4_shapes 1 128 #f 0 )
+; (kern-mk-sprite 's_pirate_front   ss_u4_shapes 1 129 #f 0 )
+; (kern-mk-sprite 's_pirate_right   ss_u4_shapes 1 130 #f 0 )
+; (kern-mk-sprite 's_pirate_back    ss_u4_shapes 1 131 #f 0 )
+
+; (kern-mk-sprite 's_nixie          ss_u4_shapes 2 132 #f 0 )
+; (kern-mk-sprite 's_kraken         ss_u4_shapes 2 134 #f 0 )
+; (kern-mk-sprite 's_sea_serpent    ss_u4_shapes 2 136 #f 0 )
+; (kern-mk-sprite 's_sea_horse      ss_u4_shapes 2 138 #f 0 )
+; (kern-mk-sprite 's_whirlpool      ss_u4_shapes 2 140 #f 0 )
+; (kern-mk-sprite 's_tornado        ss_u4_shapes 2 142 #f 0 )
+
+; (kern-mk-sprite 's_rat            ss_u4_shapes 4 144 #f 0 )
+; (kern-mk-sprite 's_bat            ss_u4_shapes 4 148 #f 0 )
+; (kern-mk-sprite 's_spider         ss_u4_shapes 4 152 #f 0 )
+; (kern-mk-sprite 's_ghost          ss_u4_shapes 4 156 #f 0 )
+; (kern-mk-sprite 's_slime          ss_u4_shapes 4 160 #f 0 )
+; (kern-mk-sprite 's_slime_asleep   ss_u4_shapes 1 160 #f 0 )
+; (kern-mk-sprite 's_troll          ss_u4_shapes 4 164 #f 0 )
+; (kern-mk-sprite 's_gremlin        ss_u4_shapes 4 168 #f 0 )
+; (kern-mk-sprite 's_mimic          ss_u4_shapes 4 172 #f 0 )
+; (kern-mk-sprite 's_reaper         ss_u4_shapes 4 176 #f 0 )
+; (kern-mk-sprite 's_insects        ss_u4_shapes 4 180 #f 0 )
+; (kern-mk-sprite 's_gazer          ss_u4_shapes 4 184 #f 0 )
+; (kern-mk-sprite 's_deathknight         ss_u4_shapes 4 188 #f 0 )
+; (kern-mk-sprite 's_orc            ss_u4_shapes 4 192 #f 0 )
+; (kern-mk-sprite 's_skeleton       ss_u4_shapes 4 196 #f 0 )
+; (kern-mk-sprite 's_brigand        ss_u4_shapes 4 200 #f 0 )
+; (kern-mk-sprite 's_snake          ss_u4_shapes 4 204 #f 0 )
+; (kern-mk-sprite 's_ettin          ss_u4_shapes 4 208 #f 0 )
+; (kern-mk-sprite 's_headless       ss_u4_shapes 4 212 #f 0 )
+; (kern-mk-sprite 's_cyclops        ss_u4_shapes 4 216 #f 0 )
+; (kern-mk-sprite 's_wisp           ss_u4_shapes 4 220 #f 0 )
+; (kern-mk-sprite 's_lich           ss_u4_shapes 4 228 #f 0 )
+; (kern-mk-sprite 's_drake          ss_u4_shapes 4 232 #f 0 )
+; (kern-mk-sprite 's_zorn           ss_u4_shapes 4 236 #f 0 )
+; (kern-mk-sprite 's_demon          ss_u4_shapes 4 240 #f 0 )
+; (kern-mk-sprite 's_hydra          ss_u4_shapes 4 244 #f 0 )
+; (kern-mk-sprite 's_dragon         ss_u4_shapes 4 248 #f 0 )
+; (kern-mk-sprite 's_balron         ss_u4_shapes 4 252 #f 0 )
+
+(kern-mk-sprite 's_frame_ulc   ss_frame 1  0 #f 0 )
+(kern-mk-sprite 's_frame_td    ss_frame 1  1 #f 0 )
+(kern-mk-sprite 's_frame_urc   ss_frame 1  2 #f 0 )
+(kern-mk-sprite 's_frame_endu  ss_frame 1  3 #f 0 )  ; top of vertical bar, currently unused
+(kern-mk-sprite 's_frame_tr    ss_frame 1  4 #f 0 )
+(kern-mk-sprite 's_frame_plus  ss_frame 1  5 #f 0 )  ; center crosspiece, currently unused
+(kern-mk-sprite 's_frame_tl    ss_frame 1  6 #f 0 )
+(kern-mk-sprite 's_frame_vert  ss_frame 1  7 #f 0 )
+(kern-mk-sprite 's_frame_llc   ss_frame 1  8 #f 0 )
+(kern-mk-sprite 's_frame_tu    ss_frame 1  9 #f 0 )
+(kern-mk-sprite 's_frame_lrc   ss_frame 1 10 #f 0 )
+(kern-mk-sprite 's_frame_endb  ss_frame 1 11 #f 0 )  ; bottom of vertical bar, currently unused
+(kern-mk-sprite 's_frame_endl  ss_frame 1 12 #f 0 )
+(kern-mk-sprite 's_frame_horz  ss_frame 1 13 #f 0 )
+(kern-mk-sprite 's_frame_endr  ss_frame 1 14 #f 0 )
+(kern-mk-sprite 's_frame_dot   ss_frame 1 15 #f 0 )  ; disconnected disk, currently unused
+
+; (kern-mk-sprite 'ls_ankh          ss_u4_charset 1  0 #f 0 )
+; (kern-mk-sprite 'ls_shield        ss_u4_charset 1  1 #f 0 )
+; (kern-mk-sprite 'ls_holey_wall    ss_u4_charset 1  2 #f 0 )
+; (kern-mk-sprite 'ls_wall          ss_u4_charset 1  3 #f 0 )
+; (kern-mk-sprite 'ls_updown_arrow  ss_u4_charset 1  4 #f 0 )
+; (kern-mk-sprite 'ls_down_arrow    ss_u4_charset 1  5 #f 0 )
+; (kern-mk-sprite 'ls_up_arrow      ss_u4_charset 1  6 #f 0 )
+; (kern-mk-sprite 'ls_holey_ankh    ss_u4_charset 1  7 #f 0 )
+; (kern-mk-sprite 'ls_white_ball    ss_u4_charset 1  8 #f 0 )
+; (kern-mk-sprite 'ls_copyright     ss_u4_charset 1  9 #f 0 )
+; (kern-mk-sprite 'ls_trademark     ss_u4_charset 1 10 #f 0 )
+; (kern-mk-sprite 'ls_male          ss_u4_charset 1 11 #f 0 )
+; (kern-mk-sprite 'ls_female        ss_u4_charset 1 12 #f 0 )
+; (kern-mk-sprite 'ls_hbar          ss_u4_charset 1 13 #f 0 )
+; (kern-mk-sprite 'ls_vbar          ss_u4_charset 1 13 #f 0 )
+; (kern-mk-sprite 'ls_square        ss_u4_charset 1 14 #f 0 )
+; (kern-mk-sprite 'ls_blue_ball     ss_u4_charset 1 15 #f 0 )
+; (kern-mk-sprite 'ls_hbar_right    ss_u4_charset 1 16 #f 0 )
+; (kern-mk-sprite 'ls_hbar_left     ss_u4_charset 1 17 #f 0 )
+; (kern-mk-sprite 'ls_vbar_top      ss_u4_charset 1 16 #f 0 )
+; (kern-mk-sprite 'ls_vbar_bottom   ss_u4_charset 1 17 #f 0 )
+; (kern-mk-sprite 'ls_blank_one     ss_u4_charset 1 18 #f 0 )
+; (kern-mk-sprite 'ls_dot_dot_dot   ss_u4_charset 1 19 #f 0 )
+(kern-mk-sprite 'ls_whirlpool     ss_u4_charset 4 28 #f 0 )
+; (kern-mk-sprite 'ls_blank_three   ss_u4_charset 1 32 #f 0 )
+
+
+;; sounds
+(load "sounds.scm")
+
+;(load "effects.scm")
+
+;; terrain
+(define opq 12) ;; opaque
+(define hvy 5)  ;; heavy
+(define dns 3)  ;; dense
+(define lgt 2)  ;; light (density)
+(define trn 0)  ;; transparent
+(kern-mk-terrain 't_grass "grass" pclass-grass s_grass trn 0 nil)
+
+;; palette
+(kern-mk-palette 'pal_expanded
+  (list
+    (list  ".."   t_grass)              ;; "grass"
+  )
+) ;; palette pal_expanded
+
+
+
+
+;(load "fields.scm")
+;;(load "combat-maps.scm")
+
+;; Object types
+(load "objs.scm")
+;(load "traps.scm")
+;(load "pitfalls.scm")
+;(load "landslide.scm")
+;(load "containers.scm")
+;(load "reagents.scm")
+;(load "food.scm")
+
+;; arms
+(define (weap-ap mult)
+       (floor (* mult default-weapon-rap)))
+       
+(define (armour-ap mult)
+       (floor (* mult default-armour-apmod)))
+
+(define obj-ifc-cap (ifc-cap obj-ifc))    
+
+(define (mk-melee-arms-type tag name sprite to-hit-bonus damage deflect AP_cost AP_mod slots 
+                            num-hands range weight
+                            stratt_mod dexatt_mod
+                            damage_mod avoid_mod)
+  (kern-mk-arms-type tag name sprite to-hit-bonus damage "0" deflect slots 
+                     num-hands range AP_cost AP_mod nil nil #f #f weight nil
+                                        obj-ifc-cap obj-ifc stratt_mod dexatt_mod damage_mod avoid_mod mmode-smallobj))
+
+(mk-melee-arms-type  't_hands          "bare hands"     nil              "1d2"    "1d2"    "1d2"    (weap-ap 0.67) 0 slot-nil      1      1     0        50      20       10      1.0  )
+
+;(load "powers.scm")
+;(load "ability.scm")
+;(load "cast-ui.scm")
+;(load "spells.scm")
+;(load "items.scm")
+;(load "vehicles.scm")
+;(load "beds.scm")
+;(load "money.scm")
+;(load "skills.scm")
+
+;; occs
+(define (mk-occ tag name hit def dam arm xp skset)
+  (kern-mk-occ tag name 1.0 0 0 0 0 hit def dam arm xp skset)
+  (kern-occ-set-gob (eval tag) (list nil nil nil nil nil nil nil nil)))
+
+;;            /           /         / t  / f / e /   /
+;;           /           /         / i  / e / g / r /
+;;          /           / e       / h  / d / a / o /
+;;         / g         / m       / -  / - / m / m /
+;;        / a         / a       / o  / o / a / r / p
+;;       / t         / n       / t  / t / d / a / x
+(mk-occ 'oc_wanderer "wanderer"  5   5   5   5   8 nil)
+
+
+;(load "ai.scm")
+
+;; species
+(define humanoid
+  (list 
+   slot-armor
+   slot-boot
+   slot-helm
+   slot-amulet
+   slot-ring
+   slot-ring
+   slot-weapon-or-shield
+   slot-weapon-or-shield
+   ))
+
+(define (rel-spd speed)
+       (/ (* speed-human speed) 100))
+
+;; mk-species -- register a species type with the kernel
+(define (mk-species tag name str int dex spd con mag vr mmode weap morph xp sspr armordice mvsnd)
+  (kern-mk-species tag name str int dex (rel-spd spd) vr mmode 
+                   con 
+                   (max (round (/ con 10)) 1)
+                   mag 
+                   (max (round (/ mag 2)) 1)
+                   sspr
+                   weap #t sound-damage 
+                   mvsnd
+                   xp
+                   #f ;; stationary?
+                   armordice
+                   morph nil)) 
+(mk-species 'sp_human "human" 10 10 10 100 10 2 13 mmode-walk t_hands humanoid  2 s_asleep nil sound-walking)
+
+
+(load "conv.scm") ;; basic conversation
+;(load "yellow-slime.scm")
+;(load "troll.scm")
+;(load "spider.scm")
+;(load "npc-types.scm")
+;(load "mimic.scm")
+;(load "parties.scm")
+;(load "jewelry.scm")
+;(load "gate-guard.scm")
+
+;; Mechanism-like things
+;(load "bim.scm")
+;(load "step.scm")
+;(load "monster-generator.scm")
+;;(load "wilderness-manager.scm")
+; (load "terrain-to-ptype.scm")
+; (load "edge-spawn.scm")
+; (load "door.scm")
+; (load "portcullis.scm")
+; (load "hidden.scm")
+; (load "lever.scm")
+; (load "timer.scm")
+; (load "tblit.scm")
+; (load "portals.scm")
+; (load "moongate.scm")
+; (load "bridge.scm")
+; (load "drawbridge.scm")
+; (load "weather-vane.scm")
+;(load "wind-bridge.scm")
+
+;; Astronomy
+;(load "moon.scm")
+
+;; Quest system
+(load "tbl.scm")
+(load "ztats-quest-ui.scm")
+(load "quest-sys.scm")
+(load "quest-talk-to.scm")
+
+;; Miscellaneous crap
+(mk-obj-type 't_crosshair "crosshair" s_crosshair layer-crosshair nil)
+(kern-set-crosshair t_crosshair)
+(kern-set-frame s_frame_ulc
+                s_frame_urc
+                s_frame_llc
+                s_frame_lrc
+                s_frame_td
+                s_frame_tu
+                s_frame_tl
+                s_frame_tr
+                s_null
+                s_frame_horz
+                s_frame_vert
+                s_frame_endl
+                s_frame_endr)
+(kern-set-ascii ss_u4_charset 32)
+(kern-set-cursor ls_whirlpool)
+(kern-set-damage-sprite s_hit)
+(kern-add-hook 'combat_change_hook 'music-on-combat-change)
+(kern-add-hook 'session_start_hook 'music-on-combat-change)
+
+;; Setup the global effect sprites
+; (kern-set-quicken-sprite s_quicken)
+; (kern-set-time-stop-sprite s_time_stop)
+; (kern-set-magic-negated-sprite s_magic_negated)
+; (kern-set-reveal-sprite s_reveal)
+; (kern-set-xray-vision-sprite s_xray_vision)
+
+(kern-init-random)
+
+;;----------------------------------------------------------------------------
+;; this needs to be in a kern-loaded file so it's redefined on reload
+(define gregors-conv
+ (ifc nil
+      (method 'default (lambda (knpc kpc) (say knpc "Can't help you there.")))
+      (method 'hail (lambda (knpc kpc) (say knpc "Hullo.")))
+      (method 'heal (lambda (knpc kpc) (say knpc "[cough] Well enough, my granddaughter helps take care of me.")))
+      (method 'bye (lambda (knpc kpc) (say knpc "So long.")))
+      (method 'job (lambda (knpc kpc) (say knpc "I'm a charcoal burner. I also care for this ^c+rshrine^c-.")))
+      (method 'join (lambda (knpc kpc) (say knpc "Nope. Already got a job.")))
+      (method 'name (lambda (knpc kpc) (say knpc "Gregor's my name.")))
+      ))
+
diff --git a/worlds/haxima-1.002/minimal-start.scm b/worlds/haxima-1.002/minimal-start.scm
new file mode 100644 (file)
index 0000000..0b6cec2
--- /dev/null
@@ -0,0 +1,416 @@
+;;----------------------------------------------------------------------------
+;; The very first line of any session file should be (load "naz.scm"). This
+;; bootstraps some procedures that we need to continue. This is the only place
+;; you should use 'load'. Every other place you want to load a file you should
+;; user 'kern-load'. 'kern-load' ensures that a saved session will be able to
+;; load the file, too.
+;;----------------------------------------------------------------------------
+(load "naz.scm")
+
+
+;; Setup progress bar for loading. I arrived at the number by printing the
+;; current number of steps in src/foogod.c:foogod_progress_bar_finish().
+(kern-progress-bar-start "Loading" 205)
+
+;; Wrap the original definition of (load ...) with one that advances the
+;; progress bar.
+(define original-load load)  
+(define (load file)
+  (println (kern-get-ticks) ":" file "...")
+  (kern-progress-bar-advance 1)
+  (original-load file)
+  )
+
+
+;;----------------------------------------------------------------------------
+;; Load the read-only game data. See the note on 'kern-load' vs 'load' above.
+;;----------------------------------------------------------------------------
+(kern-load "minimal-game.scm")
+
+;;----------------------------------------------------------------------------
+;; Time -- this needs to be set before loading any dungeon rooms
+;;----------------------------------------------------------------------------
+(define hour 07)
+(define minutes 00)
+(define time-in-minutes (+ (* hour 60) minutes))
+(define game-start-time (time-mk 0 0 0 0 hour minutes))
+
+(kern-set-clock 
+ 0 ; year
+ 0 ; month
+ 0 ; week
+ 0 ; day
+ hour  ; hour
+ minutes ; minutes
+ )
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+ (kern-mk-char 
+  'ch_wanderer
+  "The Wanderer"        ; name
+  sp_human              ; species
+  oc_wanderer           ; occ
+  s_wanderer    ; sprite
+  faction-player        ; starting alignment
+  6 6 6                ; str/int/dex
+  pc-hp-off
+  pc-hp-gain
+  pc-mp-off
+  pc-mp-gain
+  max-health 0 max-health 0 1  ; hp/xp/mp/AP_per_turn/lvl
+  #f                    ; dead
+  nil                   ; conv
+  nil                   ; sched
+  nil                   ; special ai
+  nil                   ; container
+  nil                   ; readied
+  )
+
+;;----------------------------------------------------------------------------
+;; Player Party
+;;----------------------------------------------------------------------------
+(bind 
+ (kern-mk-player
+  'player                     ; tag
+  s_wanderer         ; sprite
+  "Walk"                      ; movement description
+  sound-walking               ; movement sound
+  1                           ; food
+  0                           ; gold
+  (* 60 60 5)                 ; turns to next meal (5 hours)
+  nil                         ; formation
+  nil                         ; campsite map
+  nil                         ; campsite formation
+  nil                         ; vehicle
+  ;; inventory
+  (kern-mk-inventory nil)
+  nil ;; party members (should be nil for initial load file)
+  )
+ (tbl-mk) ; gob
+ )
+
+;;----------------------------------------------------------------------------
+;; Party members
+;;----------------------------------------------------------------------------
+(kern-party-add-member player ch_wanderer)
+;;(kern-party-add-member player ch_thorald_greybeard)
+
+;;----------------------------------------------------------------------------
+;; Astronomy
+;;----------------------------------------------------------------------------
+(kern-mk-astral-body
+ 'sun              ; tag
+ "Fyer (the sun)"  ; name
+ 1                 ; relative astronomical distance 
+ 1                 ; minutes per phase (n/a for sun)
+ (/ (* 24 60) 360) ; minutes per degree
+ 0                 ; initial arc
+ 0                 ; initial phase
+ '()               ; script interface
+ ;; phases:
+ (list 
+  (list s_sun 255 "full")
+  )
+ )
+
+; ;;----------------------------------------------------------------------------
+; ;; Lumis is the source gate, which means it opens the source moongates on its
+; ;; phases. We designate this by using the source-moon-ifc as its ifc.
+; ;;
+; ;; Note: the arc and phase are calculated to give the moon the right orientation
+; ;; with respect to phase vs sun position
+; ;;----------------------------------------------------------------------------
+; (mk-moon 'lumis  ; tag
+;          "Lumis" ; name
+;          5       ; hours per phase
+;          60      ; hours per revolution
+;          22      ; initial arc
+;          0       ; initial phase
+;          'source-moon-ifc ; ifc
+;          ;; gates (moons are fixed at 8 phases in mk-moon):
+;          (list 'mg-1 'mg-2 'mg-3 'mg-4
+;                'mg-5 'mg-6 'mg-7 'mg-8
+;                )
+;          "yellow")
+
+; ;;----------------------------------------------------------------------------
+; ;; Ord is the destination gate, which means its phase decides the destination
+; ;; when the player steps through a moongate. We designate this by giving it a
+; ;; nil ifc. Note that its gates do not need to be listed in the same order as
+; ;; Lumis. In fact, they don't even need to be the same set of gates.
+; ;;
+; ;; Note: the arc and phase are calculated to give the moon the right orientation
+; ;; with respect to phase vs sun position
+; ;;----------------------------------------------------------------------------
+; (mk-moon 'ord    ; tag
+;          "Ord"   ; name
+;          9       ; hours per phase
+;          36      ; hours per revolution
+;          67     ; initial arc
+;          7       ; initial phase
+;          nil     ; ifc
+;          ;; gates (moons are fixed at 8 phases in mk-moon):
+;          (list 'mg-1 'mg-2 'mg-3 'mg-4
+;                'mg-5 'mg-6 'mg-7 'mg-8
+;                )
+;          "blue")
+
+;; ----------------------------------------------------------------------------
+;; The diplomacy table. Each entry defines the attitude of the row to the
+;; column. Note that attitudes are not necessarily symmetric. Negative values
+;; are hostile, positive are friendly.
+;;
+;; Note: factions should always be allied with themselves in order for
+;; summoning AI to work properly.
+;;       
+;; Formatted for spreadsheet
+;; ----------------------------------------------------------------------------
+(kern-mk-dtable                                                                                                                                        
+        ;;      non pla men cgb acc mon tro spd out gnt dem fgb prs gla                
+        (list   2   0   0   0   -1  -2  -2  -2  0   -2  -2  0   0   0    ) ;; none
+        (list   0   2   2   -2  -2  -2  -2  -2  -2  -2  -2  -2  2   2    ) ;; player
+        (list   -1  2   2   -1  -2  -2  -2  -2  -2  -2  -2  -2  2   2    ) ;; men
+        (list   -1  -2  -2  2   -1  -2  0   -2  -2  -1  -2  -2  0   -2   ) ;; cave goblin
+        (list   -1  -2  -1  -1  2   -2  -1  -1  -2  -1  -2  -2  0   -2   ) ;; accursed
+        (list   -2  -2  -2  -2  -2  2   -2  0   -2  0   -2  0   0   -2   ) ;; monsters
+        (list   -2  -2  -2  0   -1  -2  2   -2  -2  -1  -2  -1  0   -2   ) ;; hill trolls
+        (list   -2  -2  -2  -2  -1  0   -2  2   -2  -1  -2  0   0   -2   ) ;; wood spiders
+        (list   0   -2  -2  -2  -2  -2  -2  -2  2   -2  -2  -1  0   -2   ) ;; outlaws
+        (list   -2  -2  -2  -1  -1  0   -1  -1  -2  2   -2  -1  0   -2   ) ;; gint
+        (list   -2  -2  -2  -2  -2  -2  -2  -2  -2  -2  2   -2  0   -2   ) ;; demon
+        (list   0   -2  -2  -2  -2  0   -2  0   -1  -1  -2  2   0   -2   ) ;; forest goblin
+        (list   0   2   2   0   0   0   0   0   0   0   0   0   2   2    ) ;; prisoners
+        (list   -1  2   2   -1  -2  -2  -2  -2  -2  -2  -2  -2  2   2    ) ;; glasdrin
+)                                                                                                                                      
+
+
+(kern-mk-place
+ 'p_minimal "Minimal Place" s_keep
+ (kern-mk-map 
+  nil 19 19 pal_expanded
+  (list
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .."
+   ))
+ #f      ; wraps
+ #f      ; underground
+ #f      ; large-scale (wilderness)
+ #f      ; tmp combat place
+ nil     ; subplaces
+ nil     ; neighbors
+ nil ; objects
+ nil ; hooks
+ nil ; edge entrances
+ )
+
+(define (mk-npc name)
+  (bind 
+   (kern-mk-char (string->symbol (string-append "ch_" 
+                                                (string-lower name))) ; tag
+                 name              ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_wanderer          ; sprite
+                 faction-men         ; starting alignment
+                 0 10 5              ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 2  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 nil        ; conv
+                 nil          ; sched
+                 nil                 ; special ai
+                 nil                 ; container
+                 nil ; readied
+                 )
+   nil ; gob
+   ))
+(mk-npc "Andrea")
+(mk-npc "Charlie")
+(mk-npc "Gregor")
+
+
+(kern-obj-set-conv ch_gregor 'gregors-conv)
+
+;;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
+;; Setup a quest-offer test
+
+;;;; (define (attach kobj val-tag)
+;;;;   (let ((val (eval val-tag))
+;;;;         (obj (gob kobj)))
+;;;;     (if (null? val) (error "attach: no val for " val-tag))
+;;;;     (if (null? obj) (error "attach: no gob for " (kern-obj-get-name kobj)))
+;;;;     (if (val 'can-attach? kobj)
+;;;;         (tbl-append! obj val-tag)
+;;;;         (val 'on-attach kobj)
+;;;;         )))
+;;;; 
+;;;; (define (attached? kobj val-tag)
+;;;;   (let ((obj (gob kobj)))
+;;;;     (if (null? obj)
+;;;;         #f
+;;;;         (tbl-get obj (val-tag 'key)))
+;;;;         ))
+;;;; 
+;;;; (define quest-offer-ifc
+;;;;   (ifc nil
+;;;;        (method 'can-attach? (lambda (knpc) (println "can-attach") #t))
+;;;;        (method 'key (lambda () 'quest-offer))
+;;;;        (method 'on-attach (lambda (knpc) ))
+;;;;        (method 'is-avail? (lambda (knpc kpc) #t))
+;;;;        (method 'offer (lambda (knpc kpc) ))
+;;;;        ))
+;;;; 
+;;;; (define (gregors-quest-make-offer kpc knpc)
+;;;;   (say knpc "Want a quest?")
+;;;;   (cond ((yes? kpc)
+;;;;          (say knpc "You got it.")
+;;;;          (quest-assign gregors-quest (gob (kern-get-player))))
+;;;;         (else
+;;;;          (say knpc "Fine. Loser.")
+;;;;          (kern-conv-end))
+;;;;         ))
+;;;; 
+;;;; (define gregors-quest-offer
+;;;;   (ifc quest-offer-ifc
+;;;;        (method 'on-attach (lambda (knpc) (kern-add-hook 'conv_end_hook gregors-quest-make-offer)))
+;;;;        (method 'key (lambda () 'gregors-quest))
+;;;;        ))
+
+;;----------------------------------------------------------------------------
+;; end-of-conv hook handling
+
+;; create the table for end-of-conv handlers
+(kern-define 'end-of-conv-handlers (tbl-mk))
+
+;; a procedure to run all the end-of-conv handlers
+(define (run-end-of-conv-handlers kpc knpc args)
+  (println "run-end-of-conv-handlers:args=" args)
+  (tbl-for-each-val (lambda (val)
+                      (println "val:" val)
+                      (apply (eval (car val)) (cons kpc (cons knpc (cdr val)))))
+                    (eval (car args))))
+
+;; setup the end-of-conv hook to run the handlers (this must be done only once
+;; per game, so keep it in the start-game file)
+(kern-add-hook 'conv_end_hook
+               'run-end-of-conv-handlers
+               '(end-of-conv-handlers))
+
+;;----------------------------------------------------------------------------
+;; Offer a predefined quest in a piece of dialogue. 'args' should be a list
+;; like this:
+;;
+;; (offer-string accept-string reject-string quest)
+;;
+;; Where 'quest' is an instance of a quest.
+(define (basic-quest-offer kpc knpc args)
+  (println "basic-quest-offer: args=" args)
+  (println "knpc=" knpc)
+  (define (offer t1 t2 t3 quest)
+    (println "offer")
+    (say knpc t1)
+    (cond ((yes? kpc)
+           (say knpc t2)
+           (quest-assign (eval quest)
+                         (gob (kern-get-player)))
+           (tbl-rm! end-of-conv-handlers quest)
+           )
+          (else
+           (say knpc t3)
+           )))    
+  (if (equal? knpc (safe-eval (car args)))
+      (apply offer (cdr args))))
+
+
+;;----------------------------------------------------------------------------
+;; gregor's quest (test)
+
+;; create the quest (for now)
+(kern-define 'gregors-quest
+             (quest-talk-to-for-xp-mk 'ch_gregor 10))
+
+;; Add an end-of-conv handler to offer gregor's quest 
+;;
+;; (note 1: that the entry must be a list in a list because of the way
+;; tbl-for-each and the apply within it work)
+;;
+;; (note 2: by convention, the key is the name of the quest; basic-quest-offer
+;; assumes this)
+(tbl-set! end-of-conv-handlers
+          'gregors-quest
+          '((basic-quest-offer (ch_gregor "Want a quest?" "You got it." "Fine. Loser" gregors-quest))))
+
+
+;;----------------------------------------------------------------------------
+;; random quest assignment (prototype)
+
+(define (random-mailman-quest-offer kpc knpc)
+  (say knpc 
+       "I need someone to deliver THIS PACKAGE"
+       " to SOMBEODY"
+       " by SOMETIME"
+       ". Will you do it?")
+  (cond ((yes? kpc)
+         (say knpc "GREAT")
+         ;; (quest-assign ...)
+         )
+        (else
+         (say knpc "WHAT? YOU SUCK!")
+         ))
+  (println "leaving")
+  )
+
+(define (select-random-quest-offer knpc)
+  (println "select-random-quest-offer")
+  (random-select (list random-mailman-quest-offer
+                   )))
+
+(define (offer-random-quest kpc knpc args)
+  (println "offer-random-quest")
+  (let ((offer (select-random-quest-offer knpc)))
+    (if (notnull? offer)
+        (offer kpc knpc))))
+    
+(tbl-set! end-of-conv-handlers 
+          'random-quest
+          '((offer-random-quest nil)))
+
+;;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+;;----------------------------------------------------------------------------
+;; Startup - this is a one-time only script that runs when the player starts
+;; the game for the first time (or whenever he starts over from scratch,
+;; loading the game from this file). It sets up the story a bit.
+;;----------------------------------------------------------------------------
+
+(define (simple-start kplayer)
+  (kern-obj-put-at kplayer (list p_minimal 0 0))
+  (kern-obj-put-at ch_gregor (list p_minimal 1 1))
+  (quest-assign (quest-talk-to-for-xp-mk 'ch_gregor 10) (gob kplayer))
+  )
+      
+(kern-add-hook 'new_game_start_hook 'simple-start)
+
+(kern-progress-bar-finish)
diff --git a/worlds/haxima-1.002/money.png b/worlds/haxima-1.002/money.png
new file mode 100644 (file)
index 0000000..f4611ff
Binary files /dev/null and b/worlds/haxima-1.002/money.png differ
diff --git a/worlds/haxima-1.002/money.scm b/worlds/haxima-1.002/money.scm
new file mode 100644 (file)
index 0000000..f4b1cad
--- /dev/null
@@ -0,0 +1,20 @@
+;; ----------------------------------------------------------------------------
+;; money.scm - items that convert to gold
+;; ----------------------------------------------------------------------------
+
+(kern-mk-sprite-set 'ss_money 32 32 1 1 0 0 "money.png")
+
+(kern-mk-sprite 's_gold_coins ss_money 1 0 #f 0)
+
+(define money-ifc
+  (ifc '()
+       (method 'amount (lambda () 1))
+       (method 'get (lambda (kobj getter)
+                      (kern-obj-inc-ref kobj)
+                      (kern-obj-remove kobj)
+                      (kern-obj-add-gold getter
+                                         (* ((kobj-ifc kobj) 'amount)
+                                            (kern-obj-get-count kobj)))
+                      (kern-obj-dec-ref kobj)))))
+
+(mk-obj-type 't_gold_coins "gold coin" s_gold_coins layer-item money-ifc)
diff --git a/worlds/haxima-1.002/monster-generator.scm b/worlds/haxima-1.002/monster-generator.scm
new file mode 100644 (file)
index 0000000..eee0d7e
--- /dev/null
@@ -0,0 +1,477 @@
+(define (mk-ambush-gob x y w h msg) (list x y w h msg))
+(define (ambush-x gob) (list-ref gob 0))
+(define (ambush-y gob) (list-ref gob 1))
+(define (ambush-w gob) (list-ref gob 2))
+(define (ambush-h gob) (list-ref gob 3))
+(define (ambush-msg gob) (list-ref gob 4))
+
+;; ----------------------------------------------------------------------------
+;; mk-monster-generator-ifc -- make an interface for a monster generator in a
+;; town or dungeon
+;; ----------------------------------------------------------------------------
+(define (mk-monster-generator-ifc threshold max mk-monster is-monster?)
+  (define (roll-to-encounter)
+    (>= (modulo (random-next) 1000) threshold))
+  (define (not-too-many kobj)
+    (< (length (filter is-monster?
+                       (kern-place-get-beings (loc-place 
+                                               (kern-obj-get-location kobj)))))
+       max))
+  (define (player-out-of-sight? gen)
+    (define (can-see? members)
+      (if (null? members)
+          #f
+          (or (kern-in-los? (kern-obj-get-location (car members))
+                            (kern-obj-get-location gen))
+              (can-see? (cdr members)))))
+    (not (can-see? (kern-party-get-members (kern-get-player)))))
+  (define (generate gen)
+    (if (and (roll-to-encounter)
+             (not-too-many gen)
+             (player-out-of-sight? gen)
+             (not (occupied? (kern-obj-get-location gen))))
+        (kern-obj-put-at (mk-monster)
+                         (kern-obj-get-location gen))))
+  (ifc '() 
+       (method 'exec generate)))
+
+
+;; ----------------------------------------------------------------------------
+;; mk-wilderness-monster-generator -- make an object type for spawning random
+;; encounters
+;; ----------------------------------------------------------------------------
+(define (mk-wilderness-monster-generator tag threshold max party faction 
+                                         vehicle)
+  (mk-obj-type tag                                  ;; tag
+               nil                                  ;; name
+               nil                                  ;; sprite
+               layer-none                           ;; layer
+               (mk-wilderness-monster-generator-ifc threshold  ;; ifc
+                                                    max
+                                                    party
+                                                    faction
+                                                    vehicle)))
+
+;; ----------------------------------------------------------------------------
+;; mk-wilderness-ambush-generator -- make an object type for spawning random
+;; ambush encounters
+;; ----------------------------------------------------------------------------
+(define (mk-wilderness-ambush-generator-type tag threshold party faction)
+  (mk-obj-type tag                ;; tag
+               nil                ;; name
+               nil                ;; sprite
+               layer-none         ;; layer
+               (mk-wilderness-ambush-generator-ifc threshold  ;; ifc
+                                                   max
+                                                   party
+                                                   faction)))
+
+;; ----------------------------------------------------------------------------
+;; mk-wilderness-ambush-generator -- make an instance of a wilderness ambush
+;; generator type which monitors the given rectangle
+;; ----------------------------------------------------------------------------
+(define (mk-wilderness-ambush-generator type x y w h msg)
+  (bind (kern-obj-set-visible (kern-mk-obj type 1) #f)
+        (mk-ambush-gob x y w h msg)))
+
+;;----------------------------------------------------------------------------
+;; mk-monster-generator -- make an instance of a town or dungeon monster
+;; generator
+;;----------------------------------------------------------------------------
+(define (mk-monster-generator tag threshold max mk-monster is-monster?)
+  (mk-obj-type tag                                  ;; tag
+               nil                                  ;; name
+               nil                                  ;; sprite
+               layer-none                           ;; layer
+               (mk-monster-generator-ifc threshold  ;; ifc
+                                         max
+                                         mk-monster
+                                         is-monster?)))
+
+;;----------------------------------------------------------------------------
+;; Newer, improveder monster generator
+;;----------------------------------------------------------------------------
+(define (mongen2-mk thresh max is-monster-tag mk-monster-tag mk-args
+                    out-of-sight-only? targ-loc)
+  (list thresh max is-monster-tag mk-monster-tag mk-args out-of-sight-only?
+        targ-loc))
+(define (mongen2-thresh gen) (car gen))
+(define (mongen2-max gen) (cadr gen))
+(define (mongen2-mk-monster gen)
+  (apply (eval (cadddr gen)) (list-ref gen 4)))
+(define (mongen2-out-of-sight-only? gen) (list-ref gen 5))
+(define (mongen2-targ-loc gen) 
+  (let ((tag-loc (list-ref gen 6)))
+    (if (null? tag-loc)
+        nil
+        (eval-loc tag-loc))))
+
+(define (mongen2-exec kgen)
+  (let* ((gen (kobj-gob-data kgen))
+        (targ-loc (if (null? (mongen2-targ-loc gen)) 
+                      (kern-obj-get-location kgen)
+                      (mongen2-targ-loc gen)))
+        )
+    (define (roll-to-encounter)
+      (>= (modulo (random-next) 1000) (mongen2-thresh gen)))
+    (define (not-too-many?)
+      (< (length (filter (eval (caddr gen))
+                         (kern-place-get-beings (loc-place 
+                                                 (kern-obj-get-location 
+                                                  kgen)))))
+         (mongen2-max gen)))
+    (if (and (roll-to-encounter)
+             (not-too-many?)
+             (not (occupied? targ-loc))
+             (or (not (mongen2-out-of-sight-only? gen))
+                 (player-out-of-sight? kgen)))
+        (begin
+          (kern-obj-put-at (mongen2-mk-monster gen)
+                           (if (null? targ-loc)
+                               (kern-obj-get-location kgen)
+                               targ-loc))))))
+
+(define mongen2-ifc
+  (ifc nil
+       (method 'exec mongen2-exec)))
+
+(mk-obj-type 't_mongen2 nil nil layer-none mongen2-ifc)
+
+(define (mk-mongen2 thresh max is-monster? mk-monster mk-args)
+  (bind (kern-obj-set-visible (kern-mk-obj t_mongen2 1) #f)
+        (mongen2-mk thresh max is-monster? mk-monster mk-args #t nil)))
+
+;; same, only doesn't care if player is in sight
+(define (mk-edge-gen thresh max is-monster? mk-monster mk-args)
+  (bind (kern-obj-set-visible (kern-mk-obj t_mongen2 1) #f)
+        (mongen2-mk thresh max is-monster? mk-monster mk-args #f nil)))
+
+
+;;----------------------------------------------------------------------------
+;; Guard Generator
+;;
+;; Monitors a list of posts (x y) and guards. If a post is empty it creates
+;; a new guard and assigns it to that post.
+;;----------------------------------------------------------------------------
+(define (ggen-mk freq is-guard-tag? mk-guard-tag posts)
+  (list freq is-guard-tag? mk-guard-tag posts))
+(define (ggen-freq ggen) (car ggen))
+(define (ggen-get-is-guard-tag ggen) (cadr ggen))
+(define (ggen-get-mk-guard-tag ggen) (caddr ggen))
+(define (ggen-posts ggen) (cadddr ggen))
+
+(define (ggen-exec kgen)
+
+  ;;(display "ggen-exec")(newline)
+
+  (let ((ggen (kobj-gob-data kgen)))
+
+    (define (time-to-check?)
+      ;;(display "time-to-check")(newline)
+      (< (modulo (random-next)
+                 100)
+         (ggen-freq ggen)))
+
+    (define (fill-empty-posts)
+      ;;(display "fill-empty-posts")(newline)
+      (let ((guards (filter (eval (ggen-get-is-guard-tag ggen))
+                            (kern-place-get-beings (loc-place 
+                                                    (kern-obj-get-location 
+                                                     kgen))))))
+        ;;(display "guard:")(display guards)(newline)
+
+        (define (post-filled? post)
+          ;;(display "post-filled?:")(display post)(newline)
+          (foldr (lambda (a kguard) 
+                   (or a
+                       (equal? post
+                               (guard-post (kobj-gob-data kguard)))))
+                 #f
+                 guards))
+
+        (define (fill-post post)
+          ;;(display "fill-post:")(display post)(newline)
+          (let ((kguard (post-guard (apply (eval (ggen-get-mk-guard-tag ggen))
+                                           nil)
+                                    (car post)
+                                    (cadr post)))
+                (loc (kern-obj-get-location kgen)))
+            (kern-obj-put-at kguard loc)))
+
+        (map (lambda (post)
+               (if (not (post-filled? post))
+                   (fill-post post)))
+             (ggen-posts ggen))))
+
+    (if (and (time-to-check?)
+             (player-out-of-sight? kgen)
+             (not (occupied? (kern-obj-get-location kgen))))
+        (fill-empty-posts))))
+
+(define ggen-ifc
+  (ifc nil
+       (method 'exec ggen-exec)))
+
+(mk-obj-type 't_ggen nil nil layer-none ggen-ifc)
+
+(define (mk-post x y) (list x y))
+
+(define (mk-ggen freq is-guard? mk-guard posts)
+  (bind (kern-obj-set-visible (kern-mk-obj t_ggen 1) #f)
+        (ggen-mk freq is-guard? mk-guard posts)))
+
+;;----------------------------------------------------------------------------
+;; Special generator which responds to the 'raise signal generated by a "Vas 
+;; Uus Ylem" spell invocation on a wilderness location
+;;----------------------------------------------------------------------------
+(define (raise-mk proc-tag args) (list proc-tag args))
+(define (raise-proc-tag raise) (car raise))
+(define (raise-args raise) (cadr raise))
+
+(define (raise-exec kraise)
+  (display "raise-exec")(newline)
+  (let ((raise (kobj-gob-data kraise)))
+    (apply (eval (raise-proc-tag raise)) (raise-args raise))
+    (kern-obj-remove kraise)))
+
+(define raise-ifc
+  (ifc nil
+       (method 'raise raise-exec)))
+
+(mk-obj-type 't_raise_listener nil nil layer-none raise-ifc)
+
+(define (can-raise-vessel? kobj)
+  (eqv? (kern-obj-get-type kobj)
+        t_raise_listener))
+
+(define (mk-raise-listener proc-tag args)
+  (bind (kern-mk-obj t_raise_listener 1)
+        (raise-mk proc-tag args)))
+
+;;----------------------------------------------------------------------------
+;; Random treasure drops
+;;----------------------------------------------------------------------------
+(define (treasure-prob tr) (car tr))
+(define (treasure-type tr) (cadr tr))
+(define (treasure-quan tr) (caddr tr))
+
+(define treasure-list
+  (list
+   (list 32 't_gold_coins 5)
+   (list 32 't_arrow 5)
+   (list 32 't_bolt 5)
+   (list 32 't_food 1)
+   (list 8  't_heal_potion 1)
+   (list 8  't_mana_potion 1)
+   (list 4  't_cure_potion 1)
+   (list 4  't_torch 1)
+   (list 2  't_gem 1)
+   (list 4  't_picklock 1)
+   ))
+
+(define treasure-modulus
+  (foldr (lambda (n entry) (+ n (car entry)))
+         0
+         treasure-list))
+
+(define (treasure-lookup index)
+  (define (search n list)
+    (if (null? list)
+        (error "treasure-lookup not found")
+        (let ((next (+ n (treasure-prob (car list)))))
+          (if (<= index next)
+              (car list)
+              (search next (cdr list))))))
+  (search 0 treasure-list))
+    
+;; pick-random-treasure -- returns a (quantity 'type) list
+(define (pick-random-treasure)
+  (let ((trsr (treasure-lookup (modulo (random-next) treasure-modulus))))
+    (list (+ 1 (modulo (random-next) (treasure-quan trsr)))
+          (treasure-type trsr)
+          )))
+
+;; eval-treasure-entry -- given a list of type (quantity 'type) it returns a
+;; list of type (quantity type)
+(define (eval-treasure-entry entry)
+  (list (car entry) (eval (cadr entry))))
+
+;; mk-random-treasure -- makes a treasure object
+(define (mk-random-treasure)
+  (let ((pair (eval-treasure-entry (pick-random-treasure))))
+    (kern-mk-obj (car pair)
+                 (+ 1 (modulo (random-next) 
+                              (cadr pair))))))
+
+;; mk-treasure-heap -- creates a list of n treasure objects
+(define (mk-treasure-heap n)
+  (if (> n 0)
+      (cons (mk-random-treasure)
+            (mk-treasure-heap (- n 1)))))
+
+;; mk-quoted-treasure-list -- returns a list of n (quantity 'type) lists
+;; suitable in corpses and other gobs
+(define (mk-quoted-treasure-list n)
+  (if (> n 0)
+      (cons (pick-random-treasure)
+            (mk-quoted-treasure-list (- n 1)))))
+
+;;----------------------------------------------------------------------------
+;; spawn-pt -- generates a monster when triggered externally. The level of the
+;; monsters is calculated on-the-fly based on the player party level. The
+;; faction and npc type mix are determined by the "factory", which is passed to
+;; the spawn-pt constructor.
+(define (spawn-pt-mk npct-tag)
+  (list 'spawn-pt npct-tag))
+(define (spawn-pt-npct-tag sppt) (cadr sppt))
+
+(define (spawn-pt-exec ksppt)
+  (let* ((sppt (gob ksppt)))
+    (let ((npc (spawn-npc (spawn-pt-npct-tag sppt) (calc-level))))
+      (kern-obj-put-at npc (kern-obj-get-location ksppt))
+      npc)
+    ))
+
+(define spawn-pt-ifc
+  (ifc nil
+       (method 'on spawn-pt-exec)))
+
+(mk-obj-type 't_spawn_pt nil nil layer-none spawn-pt-ifc)
+
+(define (spawn-pt npct-tag)
+  (bind (kern-obj-set-visible (kern-mk-obj t_spawn_pt 1) #f)
+        (spawn-pt-mk npct-tag)))
+
+;;----------------------------------------------------------------------------
+;; guard-pt -- a spawn pt which creates an npc with a guard post
+(define (guard-pt-exec kgen)
+  (let ((kchar (spawn-pt-exec kgen)))
+    (npcg-set-post! (gob kchar)
+                    (cdr (kern-obj-get-location kgen)))
+    kchar))
+
+(define guard-pt-ifc
+  (ifc nil
+       (method 'on guard-pt-exec)))
+
+(mk-obj-type 't_guard_pt nil nil layer-none guard-pt-ifc)
+
+(define (guard-pt npct-tag)
+  (bind (kern-obj-set-visible (kern-mk-obj t_guard_pt 1) #f)
+        (spawn-pt-mk npct-tag)))
+
+;;----------------------------------------------------------------------------
+;; step-pt -- triggered when a kchar steps on it; spawns one or more npcs at
+;; different locations and prints some flavor text
+
+(define (step-pt-mk msg time sets)
+  (list 'step-pt msg time sets))
+(define (step-pt-msg sppt) (cadr sppt))
+(define (step-pt-time sppt) (caddr sppt))
+(define (step-pt-sets sppt) (cadddr sppt))
+(define (step-pt-set-time! sppt val) (set-car! (cddr sppt) val))
+
+(define (set-npct-tag set) (car set))
+(define (set-x set) (cadr set))
+(define (set-y set) (caddr set))
+
+(define (step-pt-exec ksppt kbeing)
+  (let ((sppt (gob ksppt))
+        (kplace (loc-place (kern-obj-get-location ksppt))))
+    (cond ((time-to-respawn? (step-pt-time sppt))
+           (kern-log-msg (step-pt-msg sppt))
+           (step-pt-set-time! sppt (kern-get-time))
+           (for-each (lambda (set)
+                       (kern-obj-put-at (spawn-npc (set-npct-tag set)
+                                                   (calc-level))
+                                        (mk-loc kplace 
+                                                (set-x set)
+                                                (set-y set))))
+                     (step-pt-sets sppt)))
+    )))
+
+(define step-pt-ifc
+  (ifc nil
+       (method 'step step-pt-exec)))
+
+(mk-obj-type 't_step_pt nil nil layer-mechanism step-pt-ifc)
+
+(define (step-pt msg . sets)
+  (bind (kern-obj-set-visible (kern-mk-obj t_step_pt 1) #f)
+        (step-pt-mk msg 
+                    (map - game-start-time
+                         (time-mk 0 0 0 1 1 1))
+                    sets)))
+  
+
+;;----------------------------------------------------------------------------
+;; custom-pt -- a generic 'on trigger which is run by the respawn manager
+(define custom-pt-ifc
+  (ifc nil
+       (method 'on on-trig-exec)))
+
+(mk-obj-type 't_custom_pt nil nil layer-none custom-pt-ifc)
+
+(define (custom-pt proc-tag . args)
+  (bind (kern-obj-set-visible (kern-mk-obj t_custom_pt 1) #f)
+        (trig-mk proc-tag args)))
+
+;;----------------------------------------------------------------------------
+;; time-to-respawn? -- checks if an hour and a minute has passed
+(define (time-to-respawn? oldtime)
+  (let ((curtime (kern-get-time)))
+    (or (> (time-year curtime) (time-year oldtime))
+        (> (time-month curtime) (time-month oldtime))
+        (> (time-week curtime) (time-week oldtime))
+        (>= (- (time-day curtime) (time-day oldtime)) 2)
+        (and (> (time-day curtime) (time-day oldtime))
+             (>= (time-hour curtime) (time-hour oldtime))))))
+
+;;----------------------------------------------------------------------------
+;; monman -- monster manager object
+
+(define (monman-mk time)
+  (list 'monman time))
+(define (monman-time mm) (cadr mm))
+(define (monman-set-time! mm val) (set-car! (cdr mm) val))
+
+(define (monman-exec kmm)
+  (let ((mm (gob kmm))
+        (kplace (loc-place (kern-obj-get-location kmm))))
+    (define (cleanup-old-spawn)
+      (map kern-obj-remove
+           (filter (lambda (kbeing)
+                     (or (kbeing-was-spawned? kbeing)
+                         (char-is-gate-guard? kbeing)))
+                   (kern-place-get-beings kplace)))
+      )
+
+    (define (trigger-spawn-pt sppt)
+      (signal-kobj sppt 'on sppt nil))
+
+    (define (respawn)
+      (monman-set-time! mm (kern-get-time))
+      (map trigger-spawn-pt
+           (kplace-get-objects-of-type kplace t_spawn_pt))
+      (map trigger-spawn-pt
+           (kplace-get-objects-of-type kplace t_guard_pt))
+      (map trigger-spawn-pt
+           (kplace-get-objects-of-type kplace t_custom_pt))
+      )
+
+    (if (time-to-respawn? (monman-time mm))
+        (and (cleanup-old-spawn)
+             (respawn)))
+
+  ))
+
+(define monman-ifc
+  (ifc nil
+       (method 'on monman-exec)))
+
+(mk-obj-type 't_monman nil nil layer-none monman-ifc)
+
+(define (mk-monman)
+  (bind (kern-obj-set-visible (kern-mk-obj t_monman 1) #f)
+        (monman-mk (map - game-start-time
+                        (time-mk 0 0 0 1 1 1)))))
diff --git a/worlds/haxima-1.002/monsters.png b/worlds/haxima-1.002/monsters.png
new file mode 100644 (file)
index 0000000..dfe9eef
Binary files /dev/null and b/worlds/haxima-1.002/monsters.png differ
diff --git a/worlds/haxima-1.002/moon.scm b/worlds/haxima-1.002/moon.scm
new file mode 100644 (file)
index 0000000..ab4ae72
--- /dev/null
@@ -0,0 +1,68 @@
+
+;; Given a kernel moon object, find the gate associated with the current
+;; phase. This is for the benefit of moongates trying to find a destination
+;; gate.
+(define (moon-get-current-gate kmoon)
+  (let ((gates (gob-data (kern-astral-body-get-gob kmoon)))
+        (phase (kern-astral-body-get-phase kmoon)))
+    (safe-eval (list-ref gates phase))))
+
+(define (moon-signal-gate moon phase signal)
+  (let ((kgate (safe-eval (list-ref moon phase))))
+    (if (not (null? kgate))
+        (signal-kobj kgate signal kgate))))
+
+(define (moon-phase-change kmoon old-phase new-phase)
+  (let ((moon (gob-data (kern-astral-body-get-gob kmoon))))
+    (moon-signal-gate moon old-phase 'off)
+    (moon-signal-gate moon new-phase 'on)))
+
+(define source-moon-ifc
+  (ifc '()
+       (method 'phase-change moon-phase-change)))
+
+(define dest-moon-ifc nil)
+       
+
+(define (mk-moon tag name hours-per-phase hours-per-rev arc phase ifc gates color)
+  (bind-astral-body (kern-mk-astral-body 
+                     tag                          ; tag
+                     name                         ; name
+                     2                            ; relative distance
+                     (* hours-per-phase 60)       ; minutes per phase
+                     (/ (* hours-per-rev 60) 360) ; minutes per degree
+                     arc                          ; initial arc
+                     phase                        ; initial phase
+                     ifc                          ; script interface
+                     ;; phase sprites
+                     (cond ((string=? color "yellow")
+                            (list 
+                             (list s_yellow_new_moon                0   "new")
+                             (list s_yellow_wax_quarter_moon        16  "1/4 waxing")
+                             (list s_yellow_wax_half_moon           32  "1/2 waxing")
+                             (list s_yellow_wax_three_quarter_moon  64  "3/4 waxing")
+                             (list s_yellow_full_moon               96 "full")
+                             (list s_yellow_wane_three_quarter_moon 64  "3/4 waning")
+                             (list s_yellow_wane_half_moon          32  "1/2 waning")
+                             (list s_yellow_wane_quarter_moon       16  "1/4 waning")))
+                           ((string=? color "blue")
+                            (list 
+                             (list s_blue_new_moon                0   "new")
+                             (list s_blue_wax_quarter_moon        16  "1/4 waxing")
+                             (list s_blue_wax_half_moon           32  "1/2 waxing")
+                             (list s_blue_wax_three_quarter_moon  64  "3/4 waxing")
+                             (list s_blue_full_moon               96 "full")
+                             (list s_blue_wane_three_quarter_moon 64  "3/4 waning")
+                             (list s_blue_wane_half_moon          32  "1/2 waning")
+                             (list s_blue_wane_quarter_moon       16  "1/4 waning")))
+                           (else
+                            (list 
+                             (list s_new_moon                0   "new")
+                             (list s_wax_quarter_moon        16  "1/4 waxing")
+                             (list s_wax_half_moon           32  "1/2 waxing")
+                             (list s_wax_three_quarter_moon  64  "3/4 waxing")
+                             (list s_full_moon               96 "full")
+                             (list s_wane_three_quarter_moon 64  "3/4 waning")
+                             (list s_wane_half_moon          32  "1/2 waning")
+                             (list s_wane_quarter_moon       16  "1/4 waning")))))
+                    gates))
diff --git a/worlds/haxima-1.002/moongate-clearing.scm b/worlds/haxima-1.002/moongate-clearing.scm
new file mode 100644 (file)
index 0000000..004caf3
--- /dev/null
@@ -0,0 +1,118 @@
+(kern-load "gregor.scm")
+
+;;-----------------------------------------------------------------------------
+;; Make some chests containing items to get the player started. 
+;; These will be placed on the map in the shrine room in the SW.
+;;-----------------------------------------------------------------------------
+(define supplies_chest
+  (mk-chest
+   nil ;; trap
+
+   '(
+    
+    ;; Food
+    (10 t_food)
+
+    ;; Gold
+    (10 t_gold_coins)
+
+    ;; Reagents
+    (10 sulphorous_ash)
+    (10 ginseng)
+    (10 garlic)
+    (10 spider_silk)
+    (6 blood_moss)
+    (6 black_pearl)
+    (3 nightshade)
+    (3 mandrake)
+    
+    ;; Items
+    (2 t_heal_potion)
+    (2 t_cure_potion)
+    (2 t_mana_potion)
+    (6 t_torch)
+    (3 t_picklock)
+    
+    ;; Arms
+    (1  t_sword)
+    (1  t_shield)
+    (1  t_staff)
+
+    (1  t_sling)
+    (1  t_self_bow)
+    (20 t_arrow)
+
+    ;; Hints/instructions
+    (1 t_manual)
+    (1 t_letter_from_enchanter)
+    (1 t_spell_book_white_magick_1   )
+    (1 t_spell_book_force_magick_12 )
+    )
+   ))
+
+
+
+;;----------------------------------------------------------------------------
+;; Moongate Clearing
+;;
+;; This is where the player starts out.
+;;----------------------------------------------------------------------------
+(kern-mk-place 'p_moongate_clearing "Moongate Clearing"
+  s_shrine ;; sprite
+  (kern-mk-map 'm_moongate_clearing 23 28 pal_expanded
+    (list
+               "^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^d t3 tt tt tt td ^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^5 "
+               "^^ {{ {{ {{ ^^ ^^ ^^ ^c t3 tt tt || || ^b ^^ ^^ {{ {{ {{ ^^ {{ {{ ^^ "
+               "^^ {{ {{ {{ {{ ^^ t3 tt tt || tt tt || |% ^a ^^ {C t7 {{ ^^ ^^ {{ ^^ "
+               "^^ {{ {{ {{ {{ {C tt || || || || tt || || |% ^e t3 tt {A {{ ^^ {{ ^^ "
+               "^^ ^^ {{ {{ {C t3 || || || || tt tt tt || || tt tt tt t5 {A {{ {{ ^^ "
+               "^^ ^^ ^^ ^^ t3 tt || || || tt tt tt tt tt tt tt tt tt tt td {{ ^^ ^^ "
+               "^^ ^^ ^^ ^^ || || || || tt tt tc bb ta tt tt tt tt tt || ^b ^^ ^^ ^c "
+               "^^ ^^ ^^ ^^ || || || tt tt bb .. .. .. bb tt tt tt || || |% ^a ^c |& "
+               "^^ ^^ ^^ ^c || || tt tt tt td .. .. .. tb tt tt tt tt || || || || || "
+               "^^ ^c |# || || || tt tt bb .. .. .. .. .. bb tt tt tt tt tt tt tt tt "
+               "^^ |# || || || || tt tc .. .. .. .. .. .. .. ta tt tt tt tt tt tt tc "
+               "{{ |A || || || || tt bb .. .. .. .. .. .. .. bb tt tt tt tt tt tc {& "
+               "{{ {% |A || || tt tt t5 .. .. .. .. .. .. .. t3 tt tc {# {% te {# {{ "
+               "^^ {{ {{ {{ {% ta tt tt bb .. .. .. .. .. bb tt tc {# {{ {{ {{ {{ {{ "
+               "^^ ^^ ^^ {{ {{ {% ta tt tt td .. .. .. tb tt tt {# ^^ ^^ {{ {{ ^^ ^^ "
+               "^^ ^^ ^^ ^^ {{ {{ {% ta tt bb .. .. .. bb tt tt {A ^^ ^^ ^^ {{ {{ ^^ "
+               "^^ ^^ {7 ^^ ^^ ^^ {{ {% tt td .. .. .. tb tt tt td {{ ^^ ^^ {{ {{ ^^ "
+               "^^ {3 .. {1 {5 ^^ {{ {{ tt bb .. .. .. bb tt tt {B {{ {{ {{ {{ ^^ ^^ "
+               "^^ {2 .. .. {4 ^^ {{ {{ tt td .. .. .. tb tt tt tt tt t5 {A ^^ ^^ ^^ "
+               "^^ {a .. {8 {c ^^ {{ {{ tt bb .. .. .. bb te bb te bb tt t5 ^^ ^^ ^^ "
+               "^^ ^^ {e ^^ ^^ ^^ {{ {{ tt td .. .. .. .. .. .. .. .. ta tt ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tt bb .. .. .. .. .. .. .. .. bb tt ^^ ^^ ^^ "
+               "^^ ^^ ,H ,A ,I ,L ^^ ^^ tt t5 .. .. .. .. .. .. .. .. tb tt ^a ^^ ^^ "
+               "^^ {3 .. .. .. .. {5 ^^ ta tc bb .. bb t7 bb .. .. .. bb tt t5 ^a ^^ "
+               "^^ {2 .. .. .. .. .. {9 .. .. .. tC t3 tt td .. .. .. tb tt tt t5 ^e "
+               "^^ {2 .. .. .. .. {4 ^^ t3 || tt tt tt tt bb .. .. .. bb tt tt tt t5 "
+               "^^ ,S ,E ,E ,K ,E ,R ^^ || || || tt tt tc .. .. .. .. .. ta tt tt tt "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ta || tt tt tc bb .. .. .. .. .. bb ta tt tc "
+     )
+    )
+  #f #f #f #f
+  ;; subplaces
+  nil
+  ;; neighbors
+  nil
+
+  ;; *** contents of the place ***
+  (list
+   (list (kern-tag 'black-gate (mk-moongate nil)) 11 11)
+   (list (mk-gregor) 1 23)
+   (list supplies_chest   1 24)
+   )
+
+  nil ;; hooks
+  (list  ;; edge entrances
+   (list north 16 27)
+   (list east   0 11)
+   (list west  22 10)
+   (list northeast 8 27)
+   (list southeast   9 0)
+   (list southwest  22 7)
+   )
+) ;; end of place p_moongate_clearing
+
+(mk-place-music p_moongate_clearing 'ml-small-town)
diff --git a/worlds/haxima-1.002/moongate.scm b/worlds/haxima-1.002/moongate.scm
new file mode 100644 (file)
index 0000000..3ad83c9
--- /dev/null
@@ -0,0 +1,206 @@
+;; ----------------------------------------------------------------------------
+;; Moongate sprites & light levels
+;; ----------------------------------------------------------------------------
+(define moongate-stages
+  (list (list '()                       0)
+        (list s_moongate_quarter        32)
+        (list s_moongate_half           64)
+        (list s_moongate_three_quarters 96)
+        (list s_moongate_full           128)))
+
+(define blackgate-stages
+  (list (list '()                       0)
+        (list s_blackgate_quarter        32)
+        (list s_blackgate_half           64)
+        (list s_blackgate_three_quarters 96)
+        (list s_blackgate_full           128)))
+
+(define (stage-sprite stage) (car stage))
+(define (stage-light stage) (* 10 (cadr stage)))
+(define moongate-default-ttl 10) ;; turns
+
+;; ----------------------------------------------------------------------------
+;; Moongate gob
+;; ----------------------------------------------------------------------------
+(define (moongate-mk moontag temp?)
+  (list moontag #f '() #f temp? moongate-default-ttl))
+
+(define (moongate-kdest gate) 
+  ;;(println "gate:" gate)
+  (let ((kmoon (safe-eval (car gate))))
+    ;;(println "moon:" kmoon)
+    (cond ((null? kmoon) nil)
+          (else (moon-get-current-gate kmoon)))))
+(define (moongate-open? gate) (cadr gate))
+(define (moongate-sequence gate) (caddr gate))
+(define (moongate-pending-open? gate) (car (cdddr gate)))
+(define (moongate-closed? gate) (and (not (moongate-open? gate))
+                                     (not (moongate-pending-open? gate))))
+(define (moongate-is-temporary? gate) (car (cddddr gate)))
+(define (moongate-get-ttl gate) (list-ref gate 5))
+(define (moongate-set-ttl! gate val) (set-car! (list-tail gate 5) val))
+
+(define (moongate-set-open! gate val)
+  (set-car! (cdr gate) val))
+(define (moongate-set-sequence! gate sequence)
+  (set-car! (cddr gate) sequence))
+(define (moongate-set-pending-open! gate open?)
+  (set-car! (cdddr gate) open?))
+
+(define (moongate-destroy kgate)
+  ;;(println "moongate-destroy")
+  (kern-obj-remove kgate))
+
+;; ----------------------------------------------------------------------------
+;; Moongate cut scene
+;; ----------------------------------------------------------------------------
+(define (moongate-animate kgate stages)
+  (let ((view (kern-map-view-create))
+        ;; Commented-these out to fix mouse.scm's moongate animation; doesn't
+        ;; seem to effect the starting scene animation which is the only other
+        ;; reference I see to this procedure. Leaving these as comments for now
+        ;; just in case.  Update: I think commenting these out causes the
+        ;; destination gate to remain open in normal moongate travel. Need to
+        ;; revisit and fix all cases here. SF bug #1520871. Update 2: this was
+        ;; fixed in moongate-cut-scene, below.
+        ;;(original-sprite (kern-obj-get-sprite kgate))
+        ;;(original-light (kern-obj-get-light kgate))
+        (loc (kern-obj-get-location kgate)))
+    (kern-map-view-add view)
+    (kern-map-view-center view loc)
+    (kern-map-center-camera loc)
+    (map (lambda (stage)
+           (kern-obj-set-sprite kgate (stage-sprite stage))
+           (kern-obj-set-light kgate (stage-light stage))
+           (kern-map-repaint)
+           (kern-sleep 250))
+         stages)
+    ;;(kern-obj-set-sprite kgate original-sprite)
+    ;;(kern-obj-set-light kgate original-light)
+    (kern-map-view-rm view)
+    (kern-map-view-destroy view)
+    ))
+
+(define (moongate-cut-scene src-kgate dest-kgate)
+  (moongate-animate src-kgate (reverse moongate-stages))
+  (kern-sound-play sound-moongate-enter)
+  (kern-map-flash 1000)
+  (kern-place-synch (car (kern-obj-get-location dest-kgate)))
+  (moongate-animate dest-kgate moongate-stages)
+  ;; "erase" the destination gate so it doesn't look like it remains open
+  (if (not (eqv? dest-kgate src-kgate))
+      (kern-obj-set-sprite dest-kgate (stage-sprite (car moongate-stages))))
+  (let ((gate (kobj-gob-data src-kgate)))
+    (if (moongate-is-temporary? gate)
+        (moongate-destroy src-kgate))))
+
+(define (mk-moongate-cut-scene src-kgate dest-kgate)
+  (lambda () (moongate-cut-scene src-kgate dest-kgate)))
+
+
+;; ----------------------------------------------------------------------------
+;; Moongate signal handlers
+;; ----------------------------------------------------------------------------
+(define (moongate-step kgate kstepper)
+  (let ((gate (kobj-gob-data kgate)))
+    (if (moongate-open? gate)
+        (let ((kdest (moongate-kdest gate)))
+          (cond ((null? kdest) (kern-print "Leads nowhere!\n"))
+                (else
+                 (kern-obj-relocate kstepper 
+                                    (kern-obj-get-location kdest)
+                                    (mk-moongate-cut-scene kgate kdest))))))))
+
+;; Opens/closes a moongate, running the animation on the timer tick (not to be
+;; confused with the cut-scene animation that plays when somebody steps through
+;; the gate)
+(define (moongate-run-sequence kgate)
+  (let* ((gate (kobj-gob-data kgate))
+         (stages (moongate-sequence gate)))
+    (if (null? stages)
+        (moongate-set-open! gate (moongate-pending-open? gate))
+        (let ((stage (car stages)))
+          (kern-obj-set-sprite kgate (stage-sprite stage))
+          (kern-obj-set-light kgate (stage-light stage))
+          (kern-map-set-dirty)
+          (moongate-set-sequence! gate (cdr stages))
+          (kern-add-tick-job 1 moongate-run-sequence kgate)))))
+
+;; The following version does not use the tick queue, however if you use any
+;; delay at all it noticeably pauses the game. This is especially annoying when
+;; the moongate is not visible or even in the same place as the player, who
+;; sees only inexplicable pauses in responsiveness. To make this work smoothly
+;; only moongates which have a visible or at least audible effect should cause
+;; a map repaint and a pause. It will require another kernel call to determine
+;; if this is the case.
+
+; (define (moongate-run-sequence kgate)
+;   (let* ((gate (kobj-gob-data kgate))
+;          (stages (moongate-sequence gate)))
+;     (if (null? stages)
+;         (moongate-set-open! gate (moongate-pending-open? gate))
+;         (let ((stage (car stages)))
+;           (kern-obj-set-sprite kgate (stage-sprite stage))
+;           (kern-obj-set-light kgate (stage-light stage))
+;           (kern-map-repaint)
+;           (kern-sleep 100)
+;           (moongate-set-sequence! gate (cdr stages))
+;           (moongate-run-sequence kgate)))))
+
+
+(define (moongate-setup-sequence kgate gate open? stages)
+  (moongate-set-pending-open! gate open?)
+  (moongate-set-sequence! gate stages)
+  (kern-add-tick-job 1 moongate-run-sequence kgate))
+
+(define (moongate-open kgate)
+  (let ((gate (kobj-gob-data kgate)))
+    ;;(println "moongate-open:gob=" gate)
+    (if (not (moongate-open? gate))
+        (moongate-setup-sequence kgate gate #t moongate-stages)
+        )))
+
+(define (moongate-close kgate)
+  ;;(println "moongate-close")
+  (let ((gate (kobj-gob-data kgate)))
+    (if (not (moongate-closed? gate))
+        (moongate-setup-sequence kgate gate #f (reverse moongate-stages))
+        )))
+
+(define (moongate-init kgate)
+  (let ((gate (kobj-gob-data kgate)))
+    (if (moongate-open? gate)
+        (moongate-setup-sequence kgate gate #t moongate-stages))))
+
+(define (moongate-exec kgate)
+  (let ((gate (gob kgate)))
+    (if (moongate-is-temporary? gate)
+        (let ((ttl (- (moongate-get-ttl gate) 1)))
+          (moongate-set-ttl! gate ttl)
+          (if (<= ttl 0)
+              (begin
+                (moongate-animate kgate (reverse moongate-stages))
+                (moongate-destroy kgate)
+                ))))))
+
+;; ----------------------------------------------------------------------------
+;; Moongate gifc, kobj-type & constructor
+;; ----------------------------------------------------------------------------
+(define moongate-ifc
+  (ifc '()
+       (method 'step moongate-step)
+       (method 'on moongate-open)
+       (method 'off moongate-close)
+       (method 'init moongate-init)
+       (method 'exec moongate-exec)
+       ))
+
+(mk-obj-type 't_moongate "moongate" '() layer-mechanism moongate-ifc)
+
+(define (mk-moongate moontag)
+  (bind (kern-mk-obj t_moongate 1)
+        (moongate-mk moontag #f)))
+
+(define (summon-moongate moontag)
+  (bind (kern-mk-obj t_moongate 1)
+        (moongate-mk moontag #t)))
diff --git a/worlds/haxima-1.002/moons.png b/worlds/haxima-1.002/moons.png
new file mode 100644 (file)
index 0000000..f2b7f3b
Binary files /dev/null and b/worlds/haxima-1.002/moons.png differ
diff --git a/worlds/haxima-1.002/mouse.scm b/worlds/haxima-1.002/mouse.scm
new file mode 100644 (file)
index 0000000..e0174d4
--- /dev/null
@@ -0,0 +1,292 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define mouse-start-lvl 8)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (mouse-mk) (list #t))
+(define (mouse-first-meeting? mouse) (car mouse))
+(define (mouse-set-first-meeting! mouse val) (set-car! mouse val))
+(define (mouse-talked)
+       (quest-data-update-with 'questentry-thiefrune 'talked 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+
+
+(define (mouse-meet-first-time knpc kpc)
+
+  (define (mouse-disappear)
+    (say knpc "Oh, bother. Not again!")
+    (kern-obj-add-effect knpc ef_invisibility nil)
+    (kern-conv-end kpc)
+    )
+
+  (define (mouse-query)
+    (say knpc "Hi. You weren't sent by the Red Lady, were you?")
+    (if (yes? kpc)
+        (mouse-disappear)
+        (begin
+               (say knpc "Whew! You scared me for a minute.")
+               (mouse-talked)
+        )
+    ))
+
+  (define (mouse-gratitude)
+    (say knpc "Praise be to Alopex! The Red Lady is dead! "
+         "You've done me a great favor.")
+         (mouse-talked)
+         )
+
+  (define (kathryn-speech)
+    (say ch_kathryn "Fool, you have led me right to the thief!")
+    (kern-obj-set-conv ch_kathryn nil)
+    (kern-being-set-base-faction ch_kathryn faction-monster))
+
+  (define (thud-speech)
+    (say ch_thud "Thief here! Kill! Kill! Kill!")
+    (kern-obj-set-conv ch_thud nil)
+    (kern-being-set-base-faction ch_thud faction-monster))
+
+  (define (open-gate)
+    (open-moongate (mk-loc (loc-place (kern-obj-get-location knpc)) 7 2)))
+  
+  (define (warp-in-kathryn kgate)
+    (warp-in ch_kathryn 
+             (kern-obj-get-location kgate)
+             south
+             faction-monster))
+
+  (define (warp-in-thud kgate)
+    (warp-in ch_thud 
+             (kern-obj-get-location kgate)
+             west
+             faction-monster))
+
+  (mouse-set-first-meeting! (kobj-gob-data knpc) #f)
+  (if (defined? 'ch_kathryn)
+      (if (is-alive? ch_kathryn)
+          (if (is-player-party-member? ch_kathryn)
+
+              ;; kathryn is alive in the party (if thud is defined then he must
+              ;; be in the party, too; see kathryn.scm)
+              (begin
+                (kern-char-leave-player ch_kathryn)
+                (kathryn-speech)
+                (if (defined? 'ch_thud)
+                    (begin
+                      (if (is-alive? ch_thud)
+                          (thud-speech))
+                      (kern-char-leave-player ch_thud)))
+                (mouse-disappear))
+
+              ;; kathryn is alive but not in the party so gate her in, and
+              ;; thud, too, if he's alive
+              (let ((kgate (open-gate))
+                    (use-thud? (and (defined? 'ch_thud)
+                                    (is-alive? ch_thud))))
+                (kern-sleep 1000)
+                (warp-in-kathryn kgate)
+                (if use-thud?
+                    (warp-in-thud kgate))
+                (kathryn-speech)
+                (if use-thud?
+                    (thud-speech))
+                (kern-sleep 1000)
+                (close-moongate kgate)
+                (mouse-disappear)))
+
+          ;; kathryn is dead
+          (if (is-player-party-member? ch_kathryn)
+
+              ;; but in the party so remove her and thud, too, if he's defined
+              (begin
+                (kern-char-leave-player ch_kathryn)
+                (if (defined? 'ch_thud)
+                    (if (is-alive? ch_thud)
+                        (begin
+                          (thud-speech)
+                          (kern-char-leave-player ch_thud)
+                          (mouse-disappear))
+                        (begin
+                          (kern-char-leave-player ch_thud)
+                          (mouse-gratitude)))
+                    (mouse-gratitude)))
+
+              ;; kathryn is dead but not in the party (since she is not in the
+              ;; party, thud cannot be either)
+              (mouse-query)))
+
+      ;; kathryn is undefined (so she could never have been in the party, and
+      ;; thus neither could thud)
+      (mouse-query)))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+(define (mouse-hail knpc kpc)
+  (let ((mouse (kobj-gob-data knpc)))
+    (if (mouse-first-meeting? mouse)
+        (mouse-meet-first-time knpc kpc)
+        (begin
+               (say knpc "Ah, hello. Heh.")
+               (mouse-talked)
+           )
+        )))
+
+(define (mouse-default knpc kpc)
+  (say knpc "Got me there."))
+
+(define (mouse-name knpc kpc)
+  (say knpc "I'm the Mouse."))
+
+(define (mouse-join knpc kpc)
+  (say knpc "Sorry, I'm not a team player. Heh."))
+
+(define (mouse-job knpc kpc)
+  (say knpc "I... uh... collect things."))
+
+
+(define (mouse-coll knpc kpc)
+  (say knpc "Some might even call me a thief."))
+
+(define (mouse-thie knpc kpc)
+  (say knpc "Until recently it was a good business. Somebody wants "
+       "something, they pay me to get it. But then I was hired by this "
+       "strange lady in red."))
+
+(define (mouse-lady knpc kpc)
+  (say knpc "The lady hired me to get something and then meet her to "
+       "exchange it for payment. All very typical, you know? But instead "
+       "of paying me, she tried to kill me!"))
+
+(define (mouse-kill knpc kpc)
+  (say knpc "That red lady and her brute were relentless! I can't thank you "
+       "enough for getting rid of them, but I have a bad feeling they weren't "
+       "working alone. I'll be hunted for the rest of my life unless I can "
+       "get rid of this stupid rune!"))
+
+(define (mouse-rune knpc kpc)
+  (if (not (in-inventory? knpc t_rune_k))
+      (say knpc "It's your problem now, buddy!")
+      (begin
+
+        (define (give-rune gold)
+          (let* ((pgold (kern-player-get-gold)))
+            (if (> pgold gold)
+                (kern-obj-add-gold kpc (- 0 gold))
+                (let ((price (min pgold gold)))
+                  (say knpc "You don't have enough! Oh well, I'll just take "
+                       "whatever you can give me for it.")
+                  (kern-obj-add-gold kpc (- 0 price)))))
+          (kern-obj-remove-from-inventory knpc t_rune_k 1)
+          (kern-obj-add-to-inventory kpc t_rune_k 1)
+          (quest-data-update-with 'questentry-thiefrune 'recovered 1 (quest-notify (grant-party-xp-fn 50)))
+          )
+        
+        (say knpc "This rune I got for the red lady has been nothing but "
+             "trouble since I first heard of it. I don't even know what "
+             "it's good for! I'll give you a really good deal on it. Say, "
+             "500 gold?")
+        (if (kern-conv-get-yes-no? kpc)
+            (give-rune 500)
+            (begin
+              (say knpc "Well, I guess I do owe you for saving me from "
+                   "that red lady. How about 250 gold?")
+              (if (kern-conv-get-yes-no? kpc)
+                  (give-rune 250)
+                  (begin
+                    (say knpc "You drive a hard bargain, buddy. 100 gold?")
+                    (if (kern-conv-get-yes-no? kpc)
+                        (give-rune 100)
+                        (begin
+                          (say knpc "50?")
+                          (if (kern-conv-get-yes-no? kpc)
+                              (give-rune 50)
+                              (begin
+                                (say knpc "Look, just take it ok?")
+                                (if (kern-conv-get-yes-no? kpc)
+                                    (give-rune 0)
+                                    (begin
+                                      (say knpc "I'm desperate! Here, "
+                                           "I'll pay YOU to take it! "
+                                           "Just get it away from me!")
+                                      (give-rune (- 0 100))))))
+                          )))))))))
+      
+(define (mouse-bye knpc kpc)
+  (say knpc "No offense, but I hope we never meet again."))
+
+(define (mouse-alopex knpc kpc)
+  (say knpc "Alopex? Oh, the old god of thieves. "
+       "Or so I've heard."))
+
+(define mouse-conv
+  (ifc nil
+       (method 'default mouse-default)
+       (method 'hail mouse-hail)
+       (method 'bye mouse-bye)
+       (method 'job mouse-job)
+       (method 'name mouse-name)
+       (method 'join mouse-join)
+
+       (method 'coll mouse-coll)
+       (method 'kill mouse-kill)
+       (method 'lady mouse-lady)
+       (method 'rune mouse-rune)
+       (method 'thie mouse-thie)
+       (method 'alop mouse-alopex)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-mouse)
+  (bind 
+   (kern-char-force-drop
+    (kern-char-arm-self
+     (kern-mk-char 
+      'ch_mouse ;;..tag
+      "Mouse" ;;....name
+      sp_human ;;.....species
+      nil ;;..........occupation
+      s_brigand ;;.....sprite
+      faction-men ;;..faction
+      0 ;;............custom strength modifier
+      0 ;;............custom intelligence modifier
+      6 ;;............custom dexterity modifier
+      2 ;;............custom base hp modifier
+      2 ;;............custom hp multiplier (per-level)
+      1 ;;............custom base mp modifier
+      1 ;;............custom mp multiplier (per-level)
+      max-health ;;..current hit points
+      -1 ;;...........current experience points
+      max-health ;;..current magic points
+      0
+      mouse-start-lvl  ;;..current level
+      #f ;;...........dead?
+      'mouse-conv ;;...conversation (optional)
+      nil ;;..........schedule (optional)
+      nil ;;..........custom ai (optional)
+      
+      ;;..........container (and contents)
+      (mk-inventory
+       (list
+        (list 1 t_rune_k)
+        (list 1 t_armor_leather)
+        (list 1 t_leather_helm)
+        (list 1 t_sword)
+        (list 1 t_bow)
+        (list 50 t_arrow)))
+      
+      nil ;;..........readied arms (in addition to the container contents)
+      nil ;;..........hooks in effect
+      ))
+    #t)
+   (mouse-mk)))
diff --git a/worlds/haxima-1.002/mushroom-cave.scm b/worlds/haxima-1.002/mushroom-cave.scm
new file mode 100644 (file)
index 0000000..cd5c805
--- /dev/null
@@ -0,0 +1,32 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(mk-dungeon-room
+ 'p_mushroom_cave "Mushroom Cave"
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn r8 r8 rn rn r8 r8 r8 r8 r8 rn rn rn r8 rn rn rn rn rn "
+               "r4 %3 %d r2 rc tf .. .. .. tf ra rn r4 {{ ra rn rn rn rn "
+               "r4 %% r3 rc |X t# .. .. .. t% |t ra r4 tf {A r2 rn rn rn "
+               "r4 %% r6 tf %7 bb .. .. .. bb %7 |% r6 t% t7 r2 rn rn rn "
+               "r4 %e r6 %b %% %% %5 .. .. %b %% te r6 .. te r2 rn rn rn "
+               "rn r9 rc t7 %% bb %e .. .. bb %% %5 r6 {c {{ r2 rn rn rn "
+               "r4 .. |B |X %% %d .. .. .. %b %% %% r6 {{ {{ r2 rn rn rn "
+               "r4 .. r7 || %% bb .. %b %5 bb %a %c r6 {{ {{ r2 rn rn rn "
+               "r4 t7 r6 te %% .. .. .. %a %d t3 t5 r6 {5 {{ r2 rn rn rn "
+               "r4 tt r6 %b %c bb .. .. .. bb |X |C r6 {4 {{ r2 rn rn rn "
+               "r4 te ra r5 tf %f .. .. .. tb |X r3 rc .. t7 r2 rn rn rn "
+               "r4 t% tf ra r9 r5 .. .. .. r3 r9 rc .. tC tt r2 rn rn rn "
+               "r4 .. .. .. && ra r5 .. r3 rc .. .. tC t3 |C r2 rn rn rn "
+               "r4 .. .. .. .. .. r2 r1 r4 {{ {2 tC t3 |C r3 rn rn rn rn "
+               "rn r5 tf .. .. r3 rn rn rn r5 tb tt |C r3 rn rn rn rn rn "
+               "rn rn r1 r1 r1 rn rn rn rn rn r1 r1 r1 rn rn rn rn rn rn "
+       )
+ (put (spawn-pt 'yellow-slime) 7 7)
+ (put (mk-ladder-up 'p_shard 78 74) 7 12)
+ (put (kern-mk-obj t_royal_cape 1) 4 15)
+ )
+
+(mk-place-music p_mushroom_cave 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/music/Lute-and-recorder-ballad.mid b/worlds/haxima-1.002/music/Lute-and-recorder-ballad.mid
new file mode 100644 (file)
index 0000000..7ec6ab6
Binary files /dev/null and b/worlds/haxima-1.002/music/Lute-and-recorder-ballad.mid differ
diff --git a/worlds/haxima-1.002/music/Lute-and-recorder-ballad.ogg b/worlds/haxima-1.002/music/Lute-and-recorder-ballad.ogg
new file mode 100644 (file)
index 0000000..defb441
Binary files /dev/null and b/worlds/haxima-1.002/music/Lute-and-recorder-ballad.ogg differ
diff --git a/worlds/haxima-1.002/music/Makefile.am b/worlds/haxima-1.002/music/Makefile.am
new file mode 100644 (file)
index 0000000..f055850
--- /dev/null
@@ -0,0 +1,7 @@
+musicdir = $(datadir)/nazghul/haxima/music
+
+music_DATA = credits.txt $(wildcard *.mid) $(wildcard *.scm) $(wildcard *.ogg)
+
+EXTRA_DIST = $(music_DATA)
+
+MAINTAINERCLEANFILES = Makefile.in
diff --git a/worlds/haxima-1.002/music/Makefile.in b/worlds/haxima-1.002/music/Makefile.in
new file mode 100644 (file)
index 0000000..35d1f90
--- /dev/null
@@ -0,0 +1,390 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009  Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+subdir = worlds/haxima-1.002/music
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/acinclude.m4 \
+       $(top_srcdir)/m4/sdl.m4 $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+       $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+    $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+    *) f=$$p;; \
+  esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+  srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+  for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+  for p in $$list; do echo "$$p $$p"; done | \
+  sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+  $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+    if (++n[$$2] == $(am__install_max)) \
+      { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+    END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+  sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+  sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__installdirs = "$(DESTDIR)$(musicdir)"
+DATA = $(music_DATA)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MKDIR_P = @MKDIR_P@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+SDL_CFLAGS = @SDL_CFLAGS@
+SDL_CONFIG = @SDL_CONFIG@
+SDL_LIBS = @SDL_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+musicdir = $(datadir)/nazghul/haxima/music
+music_DATA = credits.txt $(wildcard *.mid) $(wildcard *.scm) $(wildcard *.ogg)
+EXTRA_DIST = $(music_DATA)
+MAINTAINERCLEANFILES = Makefile.in
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am  $(am__configure_deps)
+       @for dep in $?; do \
+         case '$(am__configure_deps)' in \
+           *$$dep*) \
+             ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+               && { if test -f $@; then exit 0; else break; fi; }; \
+             exit 1;; \
+         esac; \
+       done; \
+       echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu worlds/haxima-1.002/music/Makefile'; \
+       $(am__cd) $(top_srcdir) && \
+         $(AUTOMAKE) --gnu worlds/haxima-1.002/music/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+       @case '$?' in \
+         *config.status*) \
+           cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+         *) \
+           echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+           cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+       esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+       cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-musicDATA: $(music_DATA)
+       @$(NORMAL_INSTALL)
+       test -z "$(musicdir)" || $(MKDIR_P) "$(DESTDIR)$(musicdir)"
+       @list='$(music_DATA)'; test -n "$(musicdir)" || list=; \
+       for p in $$list; do \
+         if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+         echo "$$d$$p"; \
+       done | $(am__base_list) | \
+       while read files; do \
+         echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(musicdir)'"; \
+         $(INSTALL_DATA) $$files "$(DESTDIR)$(musicdir)" || exit $$?; \
+       done
+
+uninstall-musicDATA:
+       @$(NORMAL_UNINSTALL)
+       @list='$(music_DATA)'; test -n "$(musicdir)" || list=; \
+       files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+       test -n "$$files" || exit 0; \
+       echo " ( cd '$(DESTDIR)$(musicdir)' && rm -f" $$files ")"; \
+       cd "$(DESTDIR)$(musicdir)" && rm -f $$files
+tags: TAGS
+TAGS:
+
+ctags: CTAGS
+CTAGS:
+
+
+distdir: $(DISTFILES)
+       @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+       list='$(DISTFILES)'; \
+         dist_files=`for file in $$list; do echo $$file; done | \
+         sed -e "s|^$$srcdirstrip/||;t" \
+             -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+       case $$dist_files in \
+         */*) $(MKDIR_P) `echo "$$dist_files" | \
+                          sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+                          sort -u` ;; \
+       esac; \
+       for file in $$dist_files; do \
+         if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+         if test -d $$d/$$file; then \
+           dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+           if test -d "$(distdir)/$$file"; then \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+             cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+             find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+           fi; \
+           cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+         else \
+           test -f "$(distdir)/$$file" \
+           || cp -p $$d/$$file "$(distdir)/$$file" \
+           || exit 1; \
+         fi; \
+       done
+check-am: all-am
+check: check-am
+all-am: Makefile $(DATA)
+installdirs:
+       for dir in "$(DESTDIR)$(musicdir)"; do \
+         test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+       done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+       @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+       $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+         install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+         `test -z '$(STRIP)' || \
+           echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+       -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+       -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+       @echo "This command is intended for maintainers to use"
+       @echo "it deletes files that may require special tools to rebuild."
+       -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+       -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-musicDATA
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+       -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-musicDATA
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic distclean \
+       distclean-generic distdir dvi dvi-am html html-am info info-am \
+       install install-am install-data install-data-am install-dvi \
+       install-dvi-am install-exec install-exec-am install-html \
+       install-html-am install-info install-info-am install-man \
+       install-musicDATA install-pdf install-pdf-am install-ps \
+       install-ps-am install-strip installcheck installcheck-am \
+       installdirs maintainer-clean maintainer-clean-generic \
+       mostlyclean mostlyclean-generic pdf pdf-am ps ps-am uninstall \
+       uninstall-am uninstall-musicDATA
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/worlds/haxima-1.002/music/Minuet-like-Mozart.mid b/worlds/haxima-1.002/music/Minuet-like-Mozart.mid
new file mode 100644 (file)
index 0000000..aaf02b5
Binary files /dev/null and b/worlds/haxima-1.002/music/Minuet-like-Mozart.mid differ
diff --git a/worlds/haxima-1.002/music/Minuet-like-Mozart.ogg b/worlds/haxima-1.002/music/Minuet-like-Mozart.ogg
new file mode 100644 (file)
index 0000000..eb49b24
Binary files /dev/null and b/worlds/haxima-1.002/music/Minuet-like-Mozart.ogg differ
diff --git a/worlds/haxima-1.002/music/ballad.mid b/worlds/haxima-1.002/music/ballad.mid
new file mode 100644 (file)
index 0000000..8d54003
Binary files /dev/null and b/worlds/haxima-1.002/music/ballad.mid differ
diff --git a/worlds/haxima-1.002/music/ballad.ogg b/worlds/haxima-1.002/music/ballad.ogg
new file mode 100644 (file)
index 0000000..037d205
Binary files /dev/null and b/worlds/haxima-1.002/music/ballad.ogg differ
diff --git a/worlds/haxima-1.002/music/bassoons-and-harpsichord.mid b/worlds/haxima-1.002/music/bassoons-and-harpsichord.mid
new file mode 100644 (file)
index 0000000..90a752e
Binary files /dev/null and b/worlds/haxima-1.002/music/bassoons-and-harpsichord.mid differ
diff --git a/worlds/haxima-1.002/music/bassoons-and-harpsichord.ogg b/worlds/haxima-1.002/music/bassoons-and-harpsichord.ogg
new file mode 100644 (file)
index 0000000..167a1cb
Binary files /dev/null and b/worlds/haxima-1.002/music/bassoons-and-harpsichord.ogg differ
diff --git a/worlds/haxima-1.002/music/credits.txt b/worlds/haxima-1.002/music/credits.txt
new file mode 100644 (file)
index 0000000..d49f01a
--- /dev/null
@@ -0,0 +1,22 @@
+Music Credits
+-------------
+
+ballad.mid
+bassoons-and-harpsichord.mid
+double-trios.mid
+dragon-slayer.mid
+dragon-quest.mid
+fair-camelot.mid
+game-music2.mid
+harpsichord-piece.mid
+into-battle.mid
+Lute-and-recorder-ballad.mid
+plainchant-recorder-trio.mid
+medieval-quest.mid
+minstrel-dance.mid
+Minuet-like-Mozart.mid
+wind-trio.mid
+
+Copyright Jim Paterson,
+www.mfiles.co.uk.
+Used for Haxima with his permission.
diff --git a/worlds/haxima-1.002/music/double-trios.mid b/worlds/haxima-1.002/music/double-trios.mid
new file mode 100644 (file)
index 0000000..64263d4
Binary files /dev/null and b/worlds/haxima-1.002/music/double-trios.mid differ
diff --git a/worlds/haxima-1.002/music/double-trios.ogg b/worlds/haxima-1.002/music/double-trios.ogg
new file mode 100644 (file)
index 0000000..150a8ab
Binary files /dev/null and b/worlds/haxima-1.002/music/double-trios.ogg differ
diff --git a/worlds/haxima-1.002/music/dragon-quest.mid b/worlds/haxima-1.002/music/dragon-quest.mid
new file mode 100644 (file)
index 0000000..13c3cdf
Binary files /dev/null and b/worlds/haxima-1.002/music/dragon-quest.mid differ
diff --git a/worlds/haxima-1.002/music/dragon-quest.ogg b/worlds/haxima-1.002/music/dragon-quest.ogg
new file mode 100644 (file)
index 0000000..64dbdb5
Binary files /dev/null and b/worlds/haxima-1.002/music/dragon-quest.ogg differ
diff --git a/worlds/haxima-1.002/music/dragon-slayer.mid b/worlds/haxima-1.002/music/dragon-slayer.mid
new file mode 100644 (file)
index 0000000..ba55547
Binary files /dev/null and b/worlds/haxima-1.002/music/dragon-slayer.mid differ
diff --git a/worlds/haxima-1.002/music/dragon-slayer.ogg b/worlds/haxima-1.002/music/dragon-slayer.ogg
new file mode 100644 (file)
index 0000000..c1dca98
Binary files /dev/null and b/worlds/haxima-1.002/music/dragon-slayer.ogg differ
diff --git a/worlds/haxima-1.002/music/fair-camelot.mid b/worlds/haxima-1.002/music/fair-camelot.mid
new file mode 100644 (file)
index 0000000..3af0885
Binary files /dev/null and b/worlds/haxima-1.002/music/fair-camelot.mid differ
diff --git a/worlds/haxima-1.002/music/fair-camelot.ogg b/worlds/haxima-1.002/music/fair-camelot.ogg
new file mode 100644 (file)
index 0000000..cda63c1
Binary files /dev/null and b/worlds/haxima-1.002/music/fair-camelot.ogg differ
diff --git a/worlds/haxima-1.002/music/game-music2.mid b/worlds/haxima-1.002/music/game-music2.mid
new file mode 100644 (file)
index 0000000..4463b05
Binary files /dev/null and b/worlds/haxima-1.002/music/game-music2.mid differ
diff --git a/worlds/haxima-1.002/music/game-music2.ogg b/worlds/haxima-1.002/music/game-music2.ogg
new file mode 100644 (file)
index 0000000..d08888f
Binary files /dev/null and b/worlds/haxima-1.002/music/game-music2.ogg differ
diff --git a/worlds/haxima-1.002/music/harpsichord-piece.mid b/worlds/haxima-1.002/music/harpsichord-piece.mid
new file mode 100644 (file)
index 0000000..de1c9ca
Binary files /dev/null and b/worlds/haxima-1.002/music/harpsichord-piece.mid differ
diff --git a/worlds/haxima-1.002/music/harpsichord-piece.ogg b/worlds/haxima-1.002/music/harpsichord-piece.ogg
new file mode 100644 (file)
index 0000000..6f782c9
Binary files /dev/null and b/worlds/haxima-1.002/music/harpsichord-piece.ogg differ
diff --git a/worlds/haxima-1.002/music/into-battle.mid b/worlds/haxima-1.002/music/into-battle.mid
new file mode 100644 (file)
index 0000000..0447001
Binary files /dev/null and b/worlds/haxima-1.002/music/into-battle.mid differ
diff --git a/worlds/haxima-1.002/music/into-battle.ogg b/worlds/haxima-1.002/music/into-battle.ogg
new file mode 100644 (file)
index 0000000..2cce004
Binary files /dev/null and b/worlds/haxima-1.002/music/into-battle.ogg differ
diff --git a/worlds/haxima-1.002/music/medieval-quest.mid b/worlds/haxima-1.002/music/medieval-quest.mid
new file mode 100644 (file)
index 0000000..89780a7
Binary files /dev/null and b/worlds/haxima-1.002/music/medieval-quest.mid differ
diff --git a/worlds/haxima-1.002/music/medieval-quest.ogg b/worlds/haxima-1.002/music/medieval-quest.ogg
new file mode 100644 (file)
index 0000000..4baaf45
Binary files /dev/null and b/worlds/haxima-1.002/music/medieval-quest.ogg differ
diff --git a/worlds/haxima-1.002/music/minstrel-dance.mid b/worlds/haxima-1.002/music/minstrel-dance.mid
new file mode 100644 (file)
index 0000000..1046771
Binary files /dev/null and b/worlds/haxima-1.002/music/minstrel-dance.mid differ
diff --git a/worlds/haxima-1.002/music/minstrel-dance.ogg b/worlds/haxima-1.002/music/minstrel-dance.ogg
new file mode 100644 (file)
index 0000000..86f56fd
Binary files /dev/null and b/worlds/haxima-1.002/music/minstrel-dance.ogg differ
diff --git a/worlds/haxima-1.002/music/music.scm b/worlds/haxima-1.002/music/music.scm
new file mode 100644 (file)
index 0000000..def339f
--- /dev/null
@@ -0,0 +1,89 @@
+;; You can replace these with your own music files if you like.
+;; It should be reasonably easy to keep thematically correct.
+;; You can use full paths for stuff outside the haxima directory
+;; Use '/' instead of '\' unless you know better
+
+;; SDL doesnt seem to like all mp3s- may be some encoding issues or something
+;; I get some playing half speed, turning a fast paced combat song into something
+;; more suitable for 'the Morgue of Satan'
+
+;; These should be a short fanfare
+(define ml-battle-intro
+       (music-list
+"music/dragon-quest.ogg"
+"music/into-battle.ogg"
+))
+
+;; These should be a short fanfare
+(define ml-battle-over
+       (music-list
+"music/game-music2.ogg"
+"music/dragon-slayer.ogg"
+))
+
+;; These should be a short fanfare
+(define ml-battle-lost
+       (music-list
+"music/fair-camelot.ogg"
+"music/dragon-slayer.ogg"
+))
+
+(define ml-battle-music
+       (music-list
+"music/double-trios.ogg"
+"music/ballad.ogg"
+))
+
+(define ml-outdoor-adventure
+       (music-list
+"music/double-trios.ogg"
+"music/ballad.ogg"
+))
+
+(define ml-dungeon-adventure
+       (music-list
+"music/double-trios.ogg"
+"music/ballad.ogg"     
+))
+
+(define ml-creepy-area
+       (music-list
+"music/double-trios.ogg"
+"music/ballad.ogg"     
+))
+
+(define ml-travelling
+       (music-list
+"music/plainchant-recorder-trio.ogg"
+"music/harpsichord-piece.ogg"
+))
+
+(define ml-small-town
+       (music-list
+"music/plainchant-recorder-trio.ogg"
+"music/minstrel-dance.ogg"
+"music/Minuet-like-Mozart.ogg"
+))
+
+(define ml-large-town
+       (music-list
+"music/bassoons-and-harpsichord.ogg"
+"music/Minuet-like-Mozart.ogg"
+))
+
+(define ml-castle
+       (music-list
+"music/double-trios.ogg"
+"music/ballad.ogg"     
+))
+
+(define ml-dungeon-town
+       (music-list
+"music/double-trios.ogg"
+"music/ballad.ogg"     
+))
+
+(define ml-sailing
+       (music-list
+"music/wind-trio.ogg"
+))
diff --git a/worlds/haxima-1.002/music/plainchant-recorder-trio.mid b/worlds/haxima-1.002/music/plainchant-recorder-trio.mid
new file mode 100644 (file)
index 0000000..24f19d7
Binary files /dev/null and b/worlds/haxima-1.002/music/plainchant-recorder-trio.mid differ
diff --git a/worlds/haxima-1.002/music/plainchant-recorder-trio.ogg b/worlds/haxima-1.002/music/plainchant-recorder-trio.ogg
new file mode 100644 (file)
index 0000000..2f18aef
Binary files /dev/null and b/worlds/haxima-1.002/music/plainchant-recorder-trio.ogg differ
diff --git a/worlds/haxima-1.002/music/wind-trio.mid b/worlds/haxima-1.002/music/wind-trio.mid
new file mode 100644 (file)
index 0000000..8b921f7
Binary files /dev/null and b/worlds/haxima-1.002/music/wind-trio.mid differ
diff --git a/worlds/haxima-1.002/music/wind-trio.ogg b/worlds/haxima-1.002/music/wind-trio.ogg
new file mode 100644 (file)
index 0000000..375c968
Binary files /dev/null and b/worlds/haxima-1.002/music/wind-trio.ogg differ
diff --git a/worlds/haxima-1.002/nate.scm b/worlds/haxima-1.002/nate.scm
new file mode 100644 (file)
index 0000000..d6a6df5
--- /dev/null
@@ -0,0 +1,184 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define nate-start-lvl 2)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (nate-mk) (list #f #f))
+(define (nate-caught? gob) (car gob))
+(define (nate-caught! gob) (set-car! gob #t))
+(define (nate-met? gob) (cadr gob))
+(define (nate-met! gob) (set-car! (cdr gob) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Nate is a ranger of the Fens. He camps at the Enchanter's Tower.
+;;----------------------------------------------------------------------------
+(define (nate-hail knpc kpc)
+  (let ((nate (kobj-gob-data knpc)))
+    (define (join)
+      (say knpc "When it is convenient, ask me of the secret, milord. "
+           "Meanwhile, you can trust me not to escape.")
+      (join-player knpc)
+      (give kpc t_arrow 20)
+      (nate-caught! nate)
+      (quest-data-update-with 'questentry-bandits 'captured-nate 1 (quest-notify nil))
+      )
+    (nate-met! nate)
+    (cond ((nate-caught? nate)
+           (say knpc "How can I be of service?")
+           )
+          (else
+           (say knpc "There's no need to kill me, adventurer. "
+                "I may have robbed, but I have slain no one. "
+                "Let me surrender, and I'll tell you a great secret. "
+                "Agreed?")
+           (cond ((yes? kpc) (join))
+                 (else
+                  (say knpc "Milord! Slay me and the secret will be lost with me. "
+                       "Spare me and I will join you, fight for you, and lead you to a source of ancient power. "
+                       "I will not try to escape. "
+                       "Afterwards, you can turn me in or set me free, as you like. "
+                       "Agreed?")
+                  (cond ((yes? kpc) (join))
+                        (else
+                         (say knpc "It is a bloodthirsty fiend who slays those who have surrendered!")
+                         (kern-conv-end)
+                         ))))))))
+
+(define (nate-secr knpc kpc)
+  (cond ((is-player-party-member? knpc)
+         (cond ((equal? (get-place knpc) p_shard)
+                (say knpc "I will tell you where to find the hidden entrance to Brundegardt!"))
+               (else
+                (say knpc "Merciful sir! It is not safe here! Let us escape to the wilderness and I will tell "
+                     "you there.")
+                )))
+        (else
+         (say knpc "The secret is safe with me.")
+         )))
+
+(define (nate-brun knpc kpc)
+  (if (is-player-party-member? knpc)
+      (say knpc "Milord, we must search for Brundegardt where the forest road passes north through the mountains. "
+           "I'll tell you the password when we are there.")
+      (say knpc "Mums the word!")))
+
+(define (nate-pass knpc kpc)
+  (if (is-player-party-member? knpc)
+      (cond ((equal? (get-place knpc) p_brundegardt)
+             (say knpc "Yes, here we are. You've done well, milord. The password... "
+                  "[he clenches his teeth] "
+                  "...NOOR. [He sighs] It is NOOR.")
+             (prompt-for-key)
+             (say knpc "Merciful sir, I beg of you a boon. "
+                  "Long have I yearned to enter Brundegardt and learn its "
+                  "secrets. Let us go together, and should we live, you "
+                  "may do with me as you see fit. Will you grant me this?")
+             (cond ((yes? kpc)
+                    (say knpc "I am forever in your debt! But this place has "
+                         "lain hidden for ages. We know not what awaits within. "
+                         "We had best supply ourselves as best we can, with "
+                         "torches, food and lockpicks.")
+                    (prompt-for-key)
+                    (say knpc "But most of all, we will need a goodly store of "
+                         "magical reagents for the mixing of spells. "
+                         "I hope you have some of the wizardly skill, "
+                         "for mark my words: we shall need it ere we are done."))
+                   (else
+                    (say knpc "I beg you to reconsider, but if you do not then heed "
+                         "my warning, for I bear you no ill will, "
+                         "you being a mere soldier of fortune like myself: "
+                         "do not enter Brundegardt alone, "
+                         "and take with you what supplies you can steal or purchase.")
+                    )))
+             (else
+              (say knpc "But sir! We have not reached Brundegardt!")
+              ))
+      (say knpc "Password? What password?")
+      ))
+
+(define nate-conv
+  (ifc basic-conv
+       (method 'name (lambda (knpc kpc) (say knpc "I am called Nate.")))
+       (method 'brun nate-brun)
+       (method 'hail nate-hail)
+       (method 'pass nate-pass)
+       (method 'secr nate-secr)
+       ))
+
+(define nate-greetings
+  (list
+   "I surrender!"
+   "Don't kill me!"
+   "You've caught me!"
+   "Please, take me prisoner!"
+   ))
+
+(define (nate-ai knpc)
+  (let ((nate (kobj-gob-data knpc)))
+    (cond ((nate-met? nate) (std-ai knpc))
+          ((any-player-party-member-visible? knpc)
+           (taunt knpc nil nate-greetings)
+           #t)
+          (else
+           (std-ai knpc)
+           )
+          )))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-nate)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_nate ;;..........tag
+     "Nate" ;;.......name
+     sp_human ;;.....species
+     oc_wrogue ;;.. .occupation
+     s_companion_bard ;;..sprite
+     faction-outlaw ;;..faction
+     +1 ;;...........custom strength modifier
+     0 ;;...........custom intelligence modifier
+     +6 ;;...........custom dexterity modifier
+     pc-hp-off ;;............custom base hp modifier
+     pc-hp-gain ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     nate-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'nate-conv ;;...conversation (optional)
+     nil ;;sch_nate ;;.....schedule (optional)
+     'nate-ai ;;..........custom ai (optional)
+
+     ;;..............container (and contents)
+     (mk-inventory
+      (list
+       (list 20 t_arrow)
+       (list 1   t_bow)
+       (list 1   t_dagger)
+       (list 1   t_sword)
+       (list 1   t_leather_helm)
+       (list 1   t_armor_leather)
+       (list 5   t_heal_potion)
+       ))
+
+     nil ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (nate-mk)))
diff --git a/worlds/haxima-1.002/naz.scm b/worlds/haxima-1.002/naz.scm
new file mode 100644 (file)
index 0000000..7ac5386
--- /dev/null
@@ -0,0 +1,1750 @@
+
+;; init.scm -- contains lots of common scheme utilities
+(load "init.scm")
+
+;; Result codes (these belong here because they are tied to kernel values, see
+;; result.h)
+(define result-ok          0)
+(define result-no-target   1)
+(define result-no-effect   2)
+(define result-no-hostiles 3)
+(define result-lacks-skill 4)
+(define result-failed      5)
+(define result-not-here    6)
+(define result-critical-fail 7)
+(define result-not-now     8)
+
+;; Test if a result code indicates that the action was not completed
+(define (abortive-result? result)
+  (or (eq? result result-no-target)
+      (eq? result result-not-here)))
+
+;; Override the default error hook to warn the loader when the interpreter
+;; encounters any errors during evaluation.
+(define (my-error-hook . x)
+  (kern-interp-error x)
+  (apply throw x))
+(define *error-hook* my-error-hook)
+
+;; kern-load -- loads a file but also tells the kernel to make a note of it so
+;; that saved sessions will know to use the file, too.
+(define (kern-load fname)
+  (kern-include fname)
+  (load fname))
+
+(define nil '())
+
+;; safe-eval -- evaluates an expression; bad expressions evaluate to '()
+;; instead of causing an interpreter error
+(define (safe-eval expr)
+  (cond ((null? expr) '())
+        ((symbol? expr)
+         (if (defined? expr)
+             (eval expr)
+             '()))
+        (eval expr)))
+
+;; filter -- filter-in elements from a list
+(define (filter pred seq)
+  (cond ((null? seq) nil)
+        ((pred (car seq))
+         (cons (car seq)
+               (filter pred (cdr seq))))
+        (else (filter pred (cdr seq)))))
+
+;; simple, non-prioritized, generic search (not very efficient, so don't try
+;; it on large search spaces)
+(define (search here? next start maxdepth)
+  (define (do-search queue visited depth)
+    (if (or (= depth 0) (null? queue)) nil
+        (let ((loc (car queue)))
+          (if (here? loc) loc
+              (do-search (append (cdr queue)
+                                 (filter (lambda (v) (not (member v visited)))
+                                         (next loc)))
+                         (append (list loc) visited)
+                         (- depth 1))))))
+  (do-search (list start) nil maxdepth))
+
+;; similar to search, but a) it's exhaustive and b) it runs a procedure on
+;; every entry (warning: not sure if or how well this works)
+(define (bfs-apply start next proc)
+  (define (do-search queue visited)
+    (if (null? queue) nil
+        (let ((loc (car queue)))
+          (proc loc)
+          (do-search (append (cdr queue)
+                             (filter (lambda (v) (not (member v visited)))
+                                     (next loc)))
+                     (append (list loc) visited)))))
+  (do-search (list start) nil))
+  
+;; Set element k of list x to val (zero-indexed)
+(define (list-set-ref! x k val)
+  (if (zero? k)
+      (set-car! x val)
+      (list-set-ref! (cdr x) (- k 1) val)))
+
+;; Check if a list contains an element.
+(define (in-list? elem lst)
+  (foldr (lambda (a b) (or a (eqv? b elem))) 
+         #f 
+         lst))
+         
+(define (in-text-list? elem lst)
+  (foldr (lambda (a b) (or a (equal? b elem))) 
+         #f 
+         lst))
+
+;; Check if a location is passable to a character
+(define (passable? loc kobj)
+  (kern-place-is-passable loc kobj))
+
+(define (obj-is-char? kobj) (kern-obj-is-being? kobj))
+(define (is-being? kobj) (kern-obj-is-being? kobj))
+
+;; Check if a location is occupied by a character or party
+(define (occupied? loc)
+  (foldr (lambda (val kobj) (or val (obj-is-char? kobj)))
+         #f 
+         (kern-get-objects-at loc)))
+
+(define (get-beings-at loc)
+  (filter kern-obj-is-being?
+          (kern-get-objects-at loc)))
+
+;; Given a starting location, search outward for a passable, unoccupied place
+;; to put a character.
+(define (pick-loc origin char)
+  (search (lambda (loc) (and (kern-is-valid-location? loc)
+                                                                       (passable? loc char)
+                                                                       (not (occupied? loc))))
+          neighbors 
+          origin
+          10))
+
+;; Generic proc to summon other beings. Used by spells and some special
+;; effects.
+(define (summon origin mk-critter faction count)
+  (define (run-loop n)
+    (if (= n 0) nil
+        (let* ((critter (kern-obj-set-temporary (kern-being-set-base-faction 
+                                                 (mk-critter) 
+                                                 faction) 
+                                                #t))
+               (loc (pick-loc origin critter)))
+          (cond ((null? loc) nil)
+                (else
+                 (kern-obj-put-at critter loc)
+                 (run-loop (- n 1)))))))
+  (run-loop count))
+
+;; Like summon but the beings are permanent, not temporary.
+(define (psummon origin mk-critter count)
+  ;;;(display "psummon")(newline)
+  (define (run-loop n)
+    (if (= n 0) nil
+        (let* ((critter (kern-obj-inc-ref (mk-critter)))
+               (loc (pick-loc origin critter)))
+          (cond ((null? loc) (kern-obj-dec-ref critter))
+               (else
+                (kern-obj-put-at critter loc)
+                (kern-obj-dec-ref critter)
+                (run-loop (- n 1)))))))
+  (run-loop count))
+
+;; check if klooker can see kobj
+(define (can-see? klooker kobj)
+  (let ((from (kern-obj-get-location klooker))
+        (to (kern-obj-get-location kobj)))
+    (and (kern-in-los? from to)
+         (<= (kern-get-distance from to)
+             (kern-obj-get-vision-radius klooker))
+         (kern-obj-is-visible? kobj))))
+
+;; check if klooker can can see anything in the list kobs
+(define (can-see-any? klooker kobjs)
+  (if (null? kobjs)
+      #f
+      (or (can-see? klooker (car kobjs))
+          (can-see-any? klooker (cdr kobjs)))))
+
+;; check if knpc can see any of the player party members
+(define (any-player-party-member-visible? knpc)
+  (can-see-any? knpc 
+                (kern-party-get-members (kern-get-player))))
+
+;; gets location of player character (not party- ie 'works' in temporary map)
+(define (player-member-loc)
+  (let ((loc (kern-obj-get-location (car (kern-party-get-members (kern-get-player))))))
+    (if (null? loc)
+        nil
+        (loc-place loc))))
+                
+(define (num-player-party-members)
+  ;;(display "num-player-party-members")(newline)
+  (length (kern-party-get-members (kern-get-player))))
+
+(define (is-only-living-party-member? kchar)
+  (and (is-alive? kchar)
+       (is-player-party-member? kchar)
+       (not (foldr (lambda (found kchar2)
+                     (println  found " " (kern-obj-get-name kchar2))
+                     (or found
+                         (and (not (eqv? kchar kchar2))
+                              (is-alive? kchar2))))
+                   #f
+                   (kern-party-get-members (kern-get-player))))
+       ))
+
+;; Check if an object is hostile toward a character
+(define (is-hostile? kbeing kobj)
+  (and (is-being? kobj)
+       (kern-being-is-hostile? kbeing kobj)))
+
+;; Check if an object is allied with a character
+(define (is-ally? kbeing kobj)
+  (kern-being-is-ally? kbeing kobj))
+
+;; Find all characters hostile to the given character
+(define (all-hostiles kchar)
+  (filter (lambda (kobj) (is-hostile? kchar kobj))
+          (kern-place-get-beings (loc-place (kern-obj-get-location kchar)))))
+
+;; Find all friendlies
+(define (all-allies kchar)
+  (filter (lambda (kobj) (is-ally? kchar kobj))
+          (kern-place-get-beings (loc-place (kern-obj-get-location kchar)))))
+  
+
+;; Count the number of hostiles
+(define (num-hostiles kchar)
+  (length (all-hostiles kchar)))
+
+;; Count the number of friendlies
+(define (num-allies kchar)
+  (length (all-allies kchar)))
+
+;; Find all beings hostile 
+(define (all-visible-hostiles kbeing)
+  (kern-being-get-visible-hostiles kbeing))
+
+(define (any-visible-hostiles? kchar)
+  (> (length (all-visible-hostiles kchar)) 0))
+
+(define (nearest-visible-hostile kchar)
+  (nearest-obj kchar (all-visible-hostiles kchar)))
+
+;; Find all allies
+(define (all-visible-allies kbeing)
+  (kern-being-get-visible-allies kbeing))
+
+;; Count the number of visible friendlies
+(define (num-visible-allies kchar)
+  (length (all-visible-allies kchar)))
+
+;; Count the number of hostiles
+(define (num-visible-hostiles kchar)
+  (length (all-visible-hostiles kchar)))
+
+
+;; Find all the characters in a place
+(define (all-chars kplace)
+  (kern-place-get-beings kplace))
+
+;; Check if an object is in the given range of the origin point
+(define (in-range? origin radius kobj)
+  (<= (kern-get-distance origin
+                         (kern-obj-get-location kobj))
+      radius))
+
+;; Check if a character's target is in range
+(define (can-hit? kchar ktarg range)
+  ;;(println "can-hit: " range)
+  (in-range? (kern-obj-get-location kchar)
+             range
+             ktarg))
+
+;; Filter objects out of range
+(define (all-in-range origin radius objlst)
+  (filter (lambda (kobj) 
+            (<= (kern-get-distance origin 
+                                   (kern-obj-get-location kobj))
+                radius))
+          objlst))
+
+;; Return a list of all hostiles in range of the given location
+(define (get-hostiles-in-range-of-loc kchar range loc)
+  (all-in-range loc
+                range
+                (kern-being-get-visible-hostiles kchar)))
+
+;; Return a list of all hostiles in range of the kchar's current location
+(define (get-hostiles-in-range kchar range)
+  (get-hostiles-in-range-of-loc kchar
+                                range
+                                (kern-obj-get-location kchar)))
+
+;; Return a list of beings within the given range
+(define (get-beings-in-range kobj range)
+  (let ((loc (kern-obj-get-location kobj)))
+  (all-in-range loc
+                range
+                (kern-place-get-beings (loc-place loc)))))
+
+;; Convenience proc for rolling dtables by hand
+(define (dtable-row . cols) cols)
+
+(define (distance kobj-a kobj-b)
+  (let ((loc-a (kern-obj-get-location kobj-a))
+        (loc-b (kern-obj-get-location kobj-b)))
+  (kern-get-distance loc-a loc-b)))
+
+;; Inefficient code to find nearest obj from a list
+(define (nearest-obj kobj klist)
+  (if (null? klist) nil
+      (foldr (lambda (a b) (if (< (distance kobj a) (distance kobj b)) a b))
+             (car klist) (cdr klist))))
+
+;; Inefficient code to find nearest location from a list
+(define (nearest-loc kobj klist)
+  (println "nearest-loc: " klist)
+  (if (null? klist) 
+      nil
+      (let ((kloc (kern-obj-get-location kobj)))
+        (foldr (lambda (a b) 
+                 (if (< (loc-city-block-distance kloc a) 
+                        (loc-city-block-distance kloc b)) 
+                     a 
+                     b))
+               (car klist) 
+               (cdr klist)))))
+
+;; Move an object one step along a path to a destination.
+(define (old-pathfind kobj dest)
+  ;;;;(display "pathfind")(newline)
+  (define (follow-path path)
+    (if (not (null? path))
+        (let ((coords (car path))
+              (origin (kern-obj-get-location kobj)))
+          ;;;;(display "pathfind:coords=");;(display coords)(newline)
+          (let ((dx (- (car coords) (loc-x origin)))
+                (dy (- (cdr coords) (loc-y origin))))
+            (kern-obj-move kobj dx dy)))))
+  (let ((path (kern-obj-find-path kobj dest)))
+    ;;;;(display "pathfind:path=");;(display path)(newline)
+    (if (not (null? path))
+        ;; skip the first location in the path
+        (follow-path (cdr path)))))
+
+;; pathfind - use the built-in kernel call that uses cached paths and tries to
+;; handle blocking mechanisms
+(define (pathfind kobj kdest)
+  ;;(println "pathfind(" (kern-obj-get-name kobj) "," kdest ")")
+  (and (kern-obj-is-being? kobj)
+       (kern-being-pathfind-to kobj kdest)))
+
+(define (can-pathfind? kobj dest)
+  (println "can-pathfind?")
+  (or (loc-8-adjacent? dest 
+                     (kern-obj-get-location kobj))
+      (not (null? (kern-obj-find-path kobj dest)))))
+
+(define (notnull? val) (not (null? val)))
+
+(define (being-at? loc)
+  (not (null? (filter kern-obj-is-being? (kern-get-objects-at loc)))))
+
+(define (get-being-at loc)
+  (let ((beings (filter kern-obj-is-being? (kern-get-objects-at loc))))
+    (if (null? beings)
+        nil
+        (car beings))))
+
+(define (is-dead? kchar)
+  (kern-char-is-dead? kchar))
+
+(define (is-alive? kchar)
+  (not (is-dead? kchar)))
+
+(define (has-ap? kobj) 
+  (> (kern-obj-get-ap kobj) 0))
+
+(define (has-ap-debt? kobj)
+  (< (kern-obj-get-ap kobj) 0))
+
+(define (has-skill? kchar kskill)
+  (in-list? kskill
+            (kern-char-get-skills kchar)))
+
+(define (flee kchar)
+  ;;;(display "flee")(newline)
+  (kern-char-set-fleeing kchar #t))
+
+(define (wander kchar)
+  (kern-obj-wander kchar))
+
+(define (weakest kchar-a kchar-b)
+  (if (< (kern-char-get-hp kchar-a)
+         (kern-char-get-hp kchar-b))
+      a
+      b))
+
+(define (join-player kchar)
+  (kern-char-join-player kchar))
+
+(define (random-select list)
+  (if (or (null? list)
+          (= 0 (length list)))
+      nil
+      (list-ref list (modulo (random-next) (length list)))))
+
+(define (taunt kchar ktarg taunts)
+  (say kchar (random-select taunts)))
+
+;; ----------------------------------------------------------------------------
+;; search-rect -- apply a procedure to every location in a rectangular region
+;; and return a list of its non-nil results.
+;; ----------------------------------------------------------------------------
+(define (search-rect kplace x y w h proc)
+  (filter notnull? (map proc (loc-enum-rect kplace x y w h))))
+
+;; ----------------------------------------------------------------------------
+;; foldr-rect -- similar to search-rect above, but the procedure must
+;; accumulate its own results. Faster because it doesn't have to run the
+;; filter.
+;; ----------------------------------------------------------------------------
+(define (foldr-rect kplace x y w h proc ival)
+  (foldr proc ival (loc-enum-rect kplace x y w h)))
+
+;;----------------------------------------------------------------------------
+;; Return a list of locations with matching terrain
+;;----------------------------------------------------------------------------
+(define (find-terrain kplace x y w h kter)
+  (define (check loc)
+    (if (eqv? (kern-place-get-terrain loc) kter)
+        loc
+        nil))
+  (search-rect kplace x y w h check))
+
+(define (on-terrain? kobj kter)
+  (eqv? kter (kern-place-get-terrain (kern-obj-get-location kobj))))
+
+(define (all-visible-terrain-of-type kobj kter)
+  (filter (lambda (x)
+            (eqv? kter
+                  (kern-place-get-terrain x)))
+          (kern-being-get-visible-tiles kobj)))
+
+(define (find-nearest-visible-terrain-of-type kobj kter)
+  (nearest-loc kobj (all-visible-terrain-of-type kobj kter)))
+    
+(define (hidden? kchar)
+  ;;(println "hidden?")
+  ;; Just check if the 8 neighbors are all los-blocking
+  (let ((loc (kern-obj-get-location kchar)))
+    (foldr-rect (loc-place loc)
+                (- (loc-x loc) 1) (- (loc-y loc) 1)
+                3 3
+               (lambda (val neighbor)
+                 ;;(println neighbor " neighbor? " (equal? neighbor loc) " blocks? " (kern-place-blocks-los? neighbor))
+                 (and val
+                      (or (eq? neighbor loc)
+                          (kern-place-blocks-los? neighbor))))
+                #t
+                )))
+  
+;; kobj-is-type -- check if the object is of the given type
+(define (kobj-is-type? kobj ktype)
+  (eqv? (kern-obj-get-type kobj)
+        ktype))
+
+;; kplace-get-objects-of-type -- return a list of all objects of the given type
+;; in the given place
+(define (kplace-get-objects-of-type kplace ktype)
+  (filter (lambda (kobj) (kobj-is-type? kobj ktype))
+          (kern-place-get-objects kplace)))
+
+;;----------------------------------------------------------------------------
+;; find-objects -- return a list of locations with the given object on them
+;;----------------------------------------------------------------------------
+(define (find-objects kplace x y w h ktype)
+  (define (check loc)
+    (define (scanobjlst lst)
+      (foldr (lambda (a b) 
+               (or a (kobj-is-type? b ktype)))
+             #f
+             lst))
+    (if (scanobjlst (kern-get-objects-at loc))
+        loc
+        nil))
+  (search-rect kplace x y w h check))
+
+(define (in-inventory? kchar ktype)
+  ;;(println (kern-type-get-name ktype))
+  (define (hasit? item inv)
+    (cond ((null? inv) #f)
+          ((eqv? item (car (car inv))) #t)
+          (else 
+           ;;(println " " (kern-type-get-name (car (car inv))))
+           (hasit? item (cdr inv)))))
+  (hasit? ktype (kern-char-get-inventory kchar)))
+
+(define (num-in-inventory kchar ktype)
+  (define (count-em item inv)
+    ;;;(display "inv: ");;(display inv)(newline)
+    (cond ((null? inv) 0)
+          ((eqv? item (car (car inv))) (cdr (car inv)))
+          (else (count-em item (cdr inv)))))
+  (count-em ktype (kern-char-get-inventory kchar)))
+
+(define (any-in-inventory? kchar lst)
+  (foldr (lambda (v k)
+           (or v
+               (in-inventory? kchar k)))
+         #f
+         lst))
+
+(define (all-in-inventory? kchar lst)
+  (foldr (lambda (v k)
+           (and v
+               (in-inventory? kchar k)))
+         #t
+         lst))
+
+;; Note: I commented out the remove-from-inventory call because the things
+;; should remove themselves (eg, potions do)
+(define (use-item-from-inventory-on-self kchar ktype)
+  ;;(kern-obj-remove-from-inventory kchar ktype 1)
+  ;;;(display "using")(newline)
+  (apply (kern-type-get-gifc ktype) (list 'use ktype kchar))
+  (kern-log-msg (kern-obj-get-name kchar)
+                " uses 1 "
+                (kern-type-get-name ktype))
+  #t)
+
+;;============================================================================
+;; Modulo system procedures -- useful on wrapping maps
+;;============================================================================
+(define (madd a b R) (modulo (+ a b) R))
+(define (msub a b R) (modulo (- a b) R))
+(define (minc a R) (modulo (+ a 1) R))
+(define (mdec a R) (modulo (- a 1) R))
+
+;;----------------------------------------------------------------------------
+;; mdist - find the distance between two numbers in a modulo system. There are
+;; always 2 distances (additive and subtractive). This picks the shortest
+;; distance..
+;;----------------------------------------------------------------------------
+(define (mdist a b R) (min (msub a b R) (msub b a R)))
+
+;; ----------------------------------------------------------------------------
+;; Turn on/off verbose scheme garbage collection. Useful if you think scheme is
+;; gc'ing some of your code behind your back.
+;; ----------------------------------------------------------------------------
+(gc-verbose #t)
+
+(define (profile proc . args)
+  (let ((t (kern-get-ticks))
+        (result (apply proc args)))
+    ;;(display "*** TIME: ");;(display (- (kern-get-ticks) t)) ;;(display " ms")
+    (newline)
+    result))
+
+;; ----------------------------------------------------------------------------
+;; find-object-types-at -- return a list of objects of the given type which can
+;; be found at the given location
+;; ----------------------------------------------------------------------------
+(define (find-object-types-at loc ktype)
+  (filter (lambda (a) (kobj-is-type? a ktype))
+          (kern-get-objects-at loc)))
+
+;; ----------------------------------------------------------------------------
+;; is-object-type-at? -- check for an object (by type) at a location
+;; ----------------------------------------------------------------------------
+(define (is-object-type-at? loc ktype)
+  (foldr (lambda (a b) (or a (kobj-is-type? b ktype)))
+         #f
+         (kern-get-objects-at loc)))
+
+;; ----------------------------------------------------------------------------
+;; any-object-types-at? -- returns #t iff one or more objects at loc is of one
+;; of the given types
+;; ----------------------------------------------------------------------------
+(define (any-object-types-at? loc ktypes)
+  (foldr (lambda (a b) (or a (is-object-type-at? loc b)))
+         #f
+         ktypes))
+
+;; is-player-party-member? -- #t iff kchar is in player party  
+(define (is-player-party-member? kchar)
+  (in-list? kchar
+            (kern-party-get-members (kern-get-player))))
+
+;; ----------------------------------------------------------------------------
+;; kobj-get -- remove an object from the map and put it into another object
+;; ----------------------------------------------------------------------------
+(define (kobj-get kobj kchar)
+  (if (kern-obj-put-into kobj kchar)
+      (begin
+        (if (not (is-player-party-member? kchar))        
+            (kern-log-msg (kern-obj-get-name kchar)
+                          " gets "
+                          (kern-obj-get-name kobj)))
+        (kern-obj-inc-ref kobj)
+        (kern-obj-remove kobj)
+        (kern-obj-dec-ref kobj)
+        (kern-obj-dec-ap kchar (/ norm 5))
+        (kern-map-repaint))))
+
+;; ----------------------------------------------------------------------------
+;; kobj-get-at -- get an object of a specific type from the location
+;; ----------------------------------------------------------------------------
+(define (kobj-get-at kchar loc ktype)
+  (let ((objs (find-object-types-at loc ktype)))
+    (if (notnull? objs)
+        (kobj-get (car objs) kchar))))
+
+;; ----------------------------------------------------------------------------
+;; place-random-corner -- randomly select a corner and return it as a location
+;; ----------------------------------------------------------------------------
+(define (place-random-corner kplace)
+  (case (kern-dice-roll "1d4")
+    ((1) (mk-loc kplace  0  0))
+    ((2) (mk-loc kplace  0  (- (kern-place-get-width kplace 1))))
+    ((3) (mk-loc kplace  (- (kern-place-get-height kplace) 1) 0))
+    ((4) (mk-loc kplace  
+                 (- (kern-place-get-height kplace) 1) 
+                 (- (kern-place-get-width kplace) 1)))))
+
+;; ----------------------------------------------------------------------------
+;; do-or-goto -- if the location is adjacent then the proc, otherwise have
+;; the char pathfind to it
+;; ----------------------------------------------------------------------------
+(define (do-or-goto kchar coords proc)
+  ;;;(display "do-or-goto")(newline)
+  (if (or (loc-4-adjacent? (kern-obj-get-location kchar) coords)
+          (eq? coords (kern-obj-get-location kchar)))
+      (proc kchar coords)
+      (pathfind kchar coords)))
+
+;; ----------------------------------------------------------------------------
+;; evade -- simple alg for evading melee foes
+;;
+;; Simple approach: each foe's coordinates forms a vector to the char's
+;; coordinates. Take the sum of these coordinates to get the evasion
+;; vector. "Normalize" the vector components by rounding them to the nearest 0,
+;; 1 or -1. This is the dx/dy to move. If the terrain is impassable in the
+;; preferred direction then try zeroing out the non-zero components and
+;; moving. This will give two backup vectors to try.
+;;
+;; ADDENDUM: I don't want to allow diagonal evasion, so the "normalized" vector
+;; must be skipped if it's a diagonal, thus causing us to try the fallbak
+;; vector(s).
+;;
+;; Now allowing diagonals, since that factor has changed
+;;
+;; TODO: probably shouldnt flee over dangerous terrains
+;;
+;; ----------------------------------------------------------------------------
+(define (evade kchar foes)
+  (let* ((tloc (kern-obj-get-location kchar))
+         (v (loc-canonical
+                               (foldr
+                                       (lambda (accum thisfoe) 
+                                               (loc-sum accum 
+                                                       (loc-diff (kern-obj-get-location thisfoe) tloc)
+                                               ))
+                                       (mk-loc (loc-place tloc) 0 0)
+                                       foes)
+                               ))
+                       )
+               (define (move dx dy)
+                       (if (kern-place-is-passable
+                                       (loc-sum
+                                               (mk-loc (loc-place tloc) dx dy) 
+                                               tloc) 
+                                       kchar)
+                               (kern-obj-move kchar dx dy)
+                               #f))
+               (define (evade-on-normal)
+                               (move (loc-x v) (loc-y v)))    
+                                  
+               (or (evade-on-normal)
+                       (and (not (eq? 0 (loc-y v)))
+                               (move (loc-x v) 0))
+                       (and (not (eq? 0 (loc-x v)))
+                               (move 0 (loc-y v))))
+               ))
+
+
+;; ----------------------------------------------------------------------------
+;; closest-obj -- given an origin and a list of objects, return the object from
+;; the list that is closest (in city-block distance) to the origin
+;; ----------------------------------------------------------------------------
+(define (closest-obj origin lst)
+  (if (null? lst) nil
+      (foldr (lambda (a b) 
+               (if (loc-closer? (kern-obj-get-location a)
+                                (kern-obj-get-location b)
+                                origin)
+                   a
+                   b))
+               (car lst)
+               (cdr lst))))
+
+;; ----------------------------------------------------------------------------
+;; blit-maps -- blit multiple maps to a single target map
+;; ---------------------------------------------------------------------------
+(define (blit-maps kmap . blits)
+  (define (blit dstx dsty srcmap srcx srcy w h)
+    (kern-blit-map kmap dstx dsty srcmap srcx srcy w h))
+  (foldr (lambda (a b) (apply blit b))
+         kmap
+         blits))
+
+(define (fill-terrain-prob kter kplace ox oy ow oh prob)
+  (define (fill x y w h)
+    (if (> h 0)
+        (if (> w 0)
+            (begin
+              (if (<= (modulo (random-next) 
+                              100) 
+                      prob)
+                  (kern-place-set-terrain (list kplace x y) kter))
+              (fill (+ x 1) y (- w 1) h))
+            (fill ox (+ y 1) ow (- h 1)))))
+  (fill ox oy ow oh))
+
+(define (fill-terrain kter kplace ox oy ow oh)
+  (fill-terrain-prob kter kplace ox oy ow oh 100))
+
+;;============================================================================
+;; rect 
+;;============================================================================
+(define (mk-rect x y w h) (list x y w h))
+(define (rect-x r) (car r))
+(define (rect-y r) (cadr r))
+(define (rect-w r) (caddr r))
+(define (rect-h r) (cadddr r))
+(define (rect-ex r) (+ (rect-x r) (rect-w r)))
+(define (rect-ey r) (+ (rect-y r) (rect-h r)))
+(define (x-in-rect? x r)
+  (and (>= x (rect-x r))
+       (< x (rect-ex r))))
+(define (y-in-rect? y r)
+  (and (>= y (rect-y r))
+       (< y (rect-ey r))))
+(define (xy-in-rect? x y r)
+  (and (x-in-rect? x r)
+       (y-in-rect? y r)))
+(define (rect-in-rect? a b)
+  (and (xy-in-rect? (rect-x a) (rect-y a) b)
+       (xy-in-rect? (rect-ex a) (rect-ey a) b)))
+(define (loc-in-rect? loc rect)
+  (xy-in-rect? (loc-x loc)
+               (loc-y loc)
+               rect))
+(define (rect-random rect)
+  (list (+ (rect-x rect) (modulo (random-next) (rect-w rect)))
+        (+ (rect-y rect) (modulo (random-next) (rect-h rect)))))
+
+;;;; (define original-load load)  
+;;;; (define (load file)
+;;;;    (display (kern-get-ticks))
+;;;;    (display " loading ")
+;;;;    (display file)(newline)
+;;;;    (original-load file))
+
+(define (put obj x y) (list obj x y))
+
+;; lookup-spell-by-handler -- find a spell in the list of all spells
+(define (lookup-spell handler)
+  (define (search-spells slist)
+    (if (null? slist)
+        nil
+        (let ((spell (car slist)))
+          (if (eqv? (spell-handler spell)
+                    handler)
+              spell
+              (search-spells (cdr slist))))))
+  (search-spells spells))
+
+;; generic lookup
+(define (lookup this? slist)
+  (if (null? slist)
+      nil
+      (if (this? (car slist))
+          (car slist)
+          (lookup this? (cdr slist)))))
+
+;; can-cast -- check if a char has enough mana to cast a spell
+(define (can-cast? kchar handler)
+  (let ((spell (lookup-spell handler)))
+    (if (null? spell)
+        #f
+        (and (>= (kern-char-get-mana kchar)
+                 (spell-cost spell))
+             (>= (kern-char-get-level kchar)
+                 (spell-level spell))))))
+  
+;; cast0 - cast a spell which requires no args if possible, assumes kchar has
+;; enough mana
+(define (cast0 kchar spell)
+  (apply (spell-handler spell) (list kchar))
+  (kern-char-dec-mana kchar (spell-cost spell))
+  (kern-obj-dec-ap kchar (spell-ap spell))
+  (kern-log-msg (kern-obj-get-name kchar) 
+                " casts " 
+                (spell-name spell)))
+
+;; cast1 - cast a spell which requires one arg if possible, assumes kchar has
+;; enough mana
+(define (cast1 kchar spell ktarg)
+  ;;;(display "cast1: ");;(display spell)(newline)
+  (apply (spell-handler spell) (list kchar ktarg))
+  (kern-char-dec-mana kchar (spell-cost spell))
+  (kern-obj-dec-ap kchar (spell-ap spell))
+  (kern-log-msg (kern-obj-get-name kchar) 
+                " casts " 
+                (spell-name spell)
+                " on "
+                (kern-obj-get-name ktarg)
+                "!"))
+  
+;; ----------------------------------------------------------------------------
+;; terrain-ok-for-field? -- check if the terrain at a given location will allow
+;; a field to be dropped on it. Terrains with passability class equivalent to
+;; Grass, trees and forest are ok, everything else is not.
+;; ----------------------------------------------------------------------------
+(define (terrain-ok-for-field? loc)
+  (let ((kter (kern-place-get-terrain loc)))
+    (println "kter: " kter)
+    (if (null? kter)
+        #f
+        (let ((pclass (kern-terrain-get-pclass kter)))
+          (foldr (lambda (a b) (or a (= pclass b)))
+                 #f
+                 (list pclass-grass pclass-trees pclass-forest))))))
+
+(define (get-8-neighboring-tiles loc)
+  (let ((kplace (loc-place loc))
+        (x (loc-x loc))
+        (y (loc-y loc)))
+    (filter kern-is-valid-location?
+            (map (lambda (offset) (mk-loc kplace 
+                                          (+ (car offset) x)
+                                          (+ (cdr offset) y)))
+                 (list (cons -1 -1)
+                       (cons  0 -1)
+                       (cons  1 -1)
+                       (cons -1  0)
+                       (cons  1  0)
+                       (cons -1  1)
+                       (cons  0  1)
+                       (cons  1  1))))))
+
+(define (get-4-neighboring-tiles loc)
+  (let ((kplace (loc-place loc))
+        (x (loc-x loc))
+        (y (loc-y loc)))
+    (filter kern-is-valid-location?
+            (map (lambda (offset) (mk-loc kplace 
+                                          (+ (car offset) x)
+                                          (+ (cdr offset) y)))
+                 (list (cons  0 -1)
+                       (cons -1  0)
+                       (cons  1  0)
+                       (cons  0  1)
+                       )))))
+
+(define (shake-map dur)
+  (if (> dur 0)
+      (begin
+        (kern-map-set-jitter #t)
+        (kern-map-repaint)
+        (shake-map (- dur 1)))
+      (begin
+        (kern-map-set-jitter #f)
+        (kern-map-repaint))))
+
+(define (random-vdir)
+  (random-select (list (cons -1 0) 
+                       (cons 1 0) 
+                       (cons 0 -1) 
+                       (cons 0 1))))
+
+(define (random-neighbor-loc kobj)
+  (let ((vdir (random-vdir)))
+    (loc-sum (kern-obj-get-location kobj)
+             (mk-loc nil (car vdir) (cdr vdir)))))
+
+(define (push kobj dx dy dist)
+  (let* ((loc (loc-sum (kern-obj-get-location kobj)
+                       (mk-loc nil dx dy))))
+    (if (and (kern-place-is-passable loc kobj)
+             (not (occupied? loc)))
+        (begin 
+          (kern-obj-relocate kobj loc nil)
+          #t)
+        #f)))
+
+(define (stagger kchar)
+  (let ((vdir (random-vdir)))
+    (push kchar (car vdir) (cdr vdir) 1)))
+
+(define (end-turn kobj)(kern-obj-set-ap kobj 0))
+
+(define (add-effect-multiple kobj keff fgob q)
+  (if (> q 0)
+      (begin
+        (kern-obj-add-effect kobj keff fgob)
+        (add-effect-multiple kobj keff fgob (- q 1)))))
+
+;; time procs for use with return value from kern-get-time:
+(define (time-mk yr mo we da hr mi)
+  (list yr mo we da hr mi))
+(define (time-year time) (list-ref time 0))
+(define (time-month time) (list-ref time 1))
+(define (time-week time) (list-ref time 2))
+(define (time-day time) (list-ref time 3))
+(define (time-hour time) (list-ref time 4))
+(define (time-minute time) (list-ref time 5))
+
+;; wants-healing? -- check if a char is <= 50% max hp
+(define (wants-healing? kchar)
+  (<= (kern-char-get-hp kchar)
+      (/ (kern-char-get-max-hp kchar) 2)))
+
+;; wants-healing? -- check if a char is <= 25% max hp
+(define (wants-great-healing? kchar)
+  (<= (kern-char-get-hp kchar)
+      (/ (kern-char-get-max-hp kchar) 4)))
+
+;; wants-mana? -- check if a char is <= 50% max mana
+(define (wants-mana? kchar)
+  (<= (kern-char-get-mana kchar)
+      (/ (kern-char-get-max-mana kchar) 2)))
+
+;; has-mana-potion? -- check if a char has a mana potion in inventory
+(define (has-mana-potion? kchar)
+  (in-inventory? kchar t_mana_potion))
+
+;; drink-mana-potion -- use a mana potion from inventory
+(define (drink-mana-potion kchar)
+  (use-item-from-inventory-on-self kchar t_mana_potion))
+
+;; has-heal-potion? -- check if a char has a heal potion in inventory
+(define (has-heal-potion? kchar)
+  (in-inventory? kchar t_heal_potion))
+
+;; drink-heal-potion -- use a heal potion from inventory
+(define (drink-heal-potion kchar)
+  (use-item-from-inventory-on-self kchar t_heal_potion))
+
+(define (set-max-hp kchar)
+  (kern-char-set-hp kchar 
+                    (kern-char-get-max-hp kchar)))
+
+;; max-hp -- calc max hp given species, level and occ
+(define (max-hp sp occ lvl mod mult)
+  (+ (kern-species-get-hp-mod sp)
+     (if (null? occ) 0 (kern-occ-get-hp-mod occ))
+     mod
+     (* lvl
+        (+ (kern-species-get-hp-mult sp)
+           (if (null? occ) 0 (kern-occ-get-hp-mult occ))
+           mult))))
+
+;; max-mp -- calc max mp given species, level and occ
+(define (max-mp sp occ lvl mod mult)
+  (+ (kern-species-get-mp-mod sp)
+     (if (null? occ) 0 (kern-occ-get-mp-mod occ))
+     mod
+     (* lvl
+        (+ (kern-species-get-mp-mult sp)
+           (if (null? occ) 0 (kern-occ-get-mp-mult occ))
+           mult))))
+  
+
+;; set-level -- set character to level and max out hp and mana (intended for
+;; new npc creation)
+(define (set-level kchar lvl)
+  (kern-char-set-level kchar lvl))
+
+;; use-potion? -- use potion on self if desired and available
+(define (use-potion? kchar)
+  (or (and (wants-healing? kchar)
+           (has-heal-potion? kchar)
+           (drink-heal-potion kchar))
+      (and (wants-mana? kchar)
+           (has-mana-potion? kchar)
+           (drink-mana-potion kchar))))
+
+(define (use-heal-spell-on-self? kchar)
+  ;;;;(display "use-heal-spell-on-self?")(newline)
+  (and (wants-healing? kchar)
+       (can-use-ability? heal-ability kchar)
+       (use-ability heal-ability kchar kchar)))
+
+(define (use-great-heal-spell-on-self? kchar)
+  ;;;;(display "use-great-heal-spell-on-self?")(newline)
+  (and (wants-great-healing? kchar)
+       (can-use-ability? great-heal-ability kchar)
+       (use-ability great-heal-ability kchar kchar)))
+
+(define (use-spell-on-self? kchar)
+  ;;;;(display "use-spell-on-self?")(newline)
+  (or (use-great-heal-spell-on-self? kchar)
+      (use-heal-spell-on-self? kchar)))
+
+(define (avoid-melee? kchar)
+  ;;;;(display "avoid-melee? kchar")(newline)
+  (let ((nearby-foes (get-hostiles-in-range kchar 1)))
+    (if (null? nearby-foes)
+        #f
+        (evade kchar nearby-foes))))
+
+(define (dump-char kchar)
+  (if (null? kchar)
+      (println "nil")
+      (begin
+        (println "npc: " (kern-obj-get-name kchar)
+                 "[" (kern-char-get-level kchar) "]"
+                 " hp=" (kern-char-get-hp kchar) "/" (kern-char-get-max-hp kchar)
+                 " mp=" (kern-char-get-mana kchar) "/" (kern-char-get-max-mana kchar)
+                 " @[" (loc-x (kern-obj-get-location kchar)) 
+                 "," (loc-y (kern-obj-get-location kchar)) "]"
+                 ))))
+           
+
+(define (get-nearest-patient kchar)
+  (let ((kloc (kern-obj-get-location kchar)))
+    (foldr (lambda (kpatient ktarg)
+             ;;(display "  checking ")(dump-char ktarg)
+             (if (and (wants-healing? ktarg)
+                      (or (null? kpatient)                      
+                          (< (kern-get-distance kloc 
+                                                (kern-obj-get-location ktarg))
+                             (kern-get-distance kloc 
+                                                (kern-obj-get-location kpatient)))))
+                 ktarg
+                 kpatient))
+           nil
+           (all-visible-allies kchar))))
+
+;; This is for medics. A patient is an ally that needs healing. If a patient is
+;; less than 2 tiles away then do nothing. If a patient is more than 2 tiles
+;; away then pathfind toward it.
+(define (move-toward-patient? kchar)
+  (let ((patient (get-nearest-patient kchar)))
+    (if (null? patient)
+        #f
+        (begin
+          ;;(display "selected ")(dump-char patient)
+          (if (in-range? (kern-obj-get-location kchar)
+                         2
+                         patient)
+              #f
+              (pathfind kchar (kern-obj-get-location patient)))))))
+
+(define (prompt-for-key)
+  (kern-log-msg "<Hit any key to continue>")
+  (kern-ui-waitkey))
+
+(define (ship-at? loc) (not (null? (kern-place-get-vehicle loc))))
+
+(define (take-player-gold q)
+  (kern-player-set-gold (- (kern-player-get-gold) q)))
+
+(define (give-player-gold q)
+  (kern-player-set-gold (+ (kern-player-get-gold) q)))
+
+(define (player-has-gold? q)
+  (>= (kern-player-get-gold) q))
+
+;; services -- used with trade-service below
+(define (svc-mk name price proc) (list name price proc))
+(define (svc-name svc) (car svc))
+(define (svc-price svc) (cadr svc))
+(define (svc-proc svc) (caddr svc))
+
+;; some standard healer services
+(define (heal-service kchar knpc)
+  ;;(display "heal-service")(newline)
+  (let ((hp (- (kern-char-get-max-hp kchar)
+               (kern-char-get-hp kchar))))
+    (if (> hp 0)
+        (begin
+          (say knpc "VAS MANI! Be healed, "
+               (kern-obj-get-name kchar))
+          (kern-map-flash hp)
+          (kern-obj-heal kchar hp)
+          #t)
+        (begin
+          (say knpc (kern-obj-get-name kchar)
+               " is not wounded!")
+          (prompt-for-key)
+          #f))))
+  
+(define (cure-service kchar knpc)
+  ;;(display "cure-service")(newline)
+  (if (is-poisoned? kchar)
+      (begin
+        (say knpc "AN NOX! You are cured, "
+             (kern-obj-get-name kchar))
+        (kern-map-flash 1)
+        (kern-obj-remove-effect kchar ef_poison))
+      (begin
+        (say knpc (kern-obj-get-name kchar)
+             " is not poisoned!")
+        (prompt-for-key)
+        #f)))
+
+(define (resurrect-service kchar knpc)
+  ;;(display "resurrect-service")(newline)
+  (if (is-dead? kchar)
+      (begin
+       (say knpc "IN MANI CORP! Arise, "
+            (kern-obj-get-name kchar))
+       (kern-map-flash 500)
+       (resurrect kchar)
+       (kern-obj-heal kchar 10))
+      (begin
+        (say knpc (kern-obj-get-name kchar)
+             " is not dead!")
+        (prompt-for-key)
+        #f)))
+
+;; trade-services -- take a list of services which operate on a party member
+;; and prompt the player, check prices, and otherwise handle the transaction
+(define (trade-services knpc kpc services)
+
+  (define (list-services)
+    (map (lambda (svc)
+           (string-append (svc-name svc) 
+                          "..." 
+                          (number->string (svc-price svc))
+                          " gold"))
+         services))
+
+  ;; line-name - convert a string like "Heal...30 gold" to "Heal"
+  (define (line-name line)
+    (define (extract l)
+      (if (null? l)
+          nil
+          (if (char=? (car l) #\.)
+              nil
+              (cons (car l) (extract (cdr l))))))
+    (if (null? line)
+        nil
+        (list->string (extract (string->list line)))))
+
+  (define (lookup-svc line)
+    (let ((name (line-name line)))
+      (if (null? name)        
+          nil
+          (lookup (lambda (svc) 
+                    (string=? name
+                              (svc-name svc)))
+                  services))))
+
+  (define (choose-svc)
+    (lookup-svc (apply kern-ui-select-from-list (list-services))))
+
+  (let ((svc (choose-svc)))
+
+    (define (can-pay?)
+      (if (player-has-gold? (svc-price svc))
+          #t
+          (begin
+            (say knpc "You don't have enough gold!")
+            #f)))
+
+    (define (apply-svc)
+      (let ((kchar (kern-ui-select-party-member)))
+        (if (null? kchar)
+            #f
+            (if (apply (svc-proc svc) (list kchar knpc))
+                (begin 
+                  (take-player-gold (svc-price svc))
+                  #t)))))
+    
+    (and (not (null? svc))
+         (can-pay?)
+         (apply-svc))))
+
+;; player-out-of-sight -- no LOS between kobj and any party member
+(define (player-out-of-sight? kobj)
+  (define (can-see? members)
+    (if (null? members)
+        #f
+        (or (kern-in-los? (kern-obj-get-location (car members))
+                          (kern-obj-get-location kobj))
+            (can-see? (cdr members)))))
+  (not (can-see? (kern-party-get-members (kern-get-player)))))
+
+(define (improve-relations kb1 kb2)
+  (kern-dtable-inc (kern-being-get-current-faction kb1)
+                   (kern-being-get-current-faction kb2)))
+
+(define (harm-relations kb1 kb2)
+  (kern-dtable-dec (kern-being-get-current-faction kb1)
+                   (kern-being-get-current-faction kb2)))
+
+(define (make-enemies kb1 kb2)
+  (harm-relations kb1 kb2)
+  (harm-relations kb1 kb2)
+  (harm-relations kb1 kb2)
+  (harm-relations kb1 kb2)
+  )
+
+(define (make-allies kb1 kb2)
+  (improve-relations kb1 kb2)
+  (improve-relations kb1 kb2)
+  (improve-relations kb1 kb2)
+  (improve-relations kb1 kb2)
+  )
+
+(define (is-bad-terrain-at? loc)
+  (is-bad-terrain? (kern-place-get-terrain loc)))
+
+;; put-random-stuff -- randomly generate locations within the given rectangle
+;; and, if pred? is satisfied, pass the loc to ctor.
+(define (put-random-stuff place rect pred? ctor n)
+  (if (> n 0)
+      (let ((loc (cons place (rect-random rect))))
+        (if (pred? loc)
+            (begin
+              (ctor loc)
+              (put-random-stuff place rect pred? ctor (- n 1)))
+            (put-random-stuff place rect pred? ctor n)))))
+
+(define (drop-random-corpses kplace n)
+  (put-random-stuff kplace
+                    (mk-rect 0 0 
+                             (kern-place-get-width kplace) 
+                             (kern-place-get-height kplace))
+                    (lambda (loc)
+                      (eqv? (kern-place-get-terrain loc)
+                            t_grass))
+                    (lambda (loc)
+                      (kern-obj-put-at (mk-corpse-with-loot)
+                                       loc))
+                    n))
+                    
+(define (webify kplace x y w h)
+  (define (drop-web x loc)
+    (let ((kter (kern-place-get-terrain loc)))
+      (if (or (eqv? kter t_grass)
+              (eqv? kter t_boulder))
+          (kern-obj-put-at (kern-mk-obj F_web_perm 1)
+                           loc))))
+  (foldr-rect kplace x y w h drop-web nil))
+
+;; Fill the rectangle with objects of the given type. If pred? is not null use
+;; it to filter out unsuitable locations.
+(define (rect-fill-with-npc kplace x y w h npct pred?)
+  (define (drop-obj x loc)
+    (if (or (null? pred?)
+            (pred? loc))
+        (kern-obj-put-at (kern-mk-obj ktype 1)
+                         loc)))
+(foldr-rect kplace x y w h drop-obj #f))
+
+;; on-entry-to-dungeon-room -- generic place on-enty procedure for dungeon
+;; rooms. When the player enters (or re-enters) a dungeon this looks for a
+;; monster manager object and triggers it.
+(define (on-entry-to-dungeon-room kplace kplayer)
+  ;;(println "on-entry-to-dungeon-room")
+  (map (lambda (kmm)
+         ;;(println " signal")
+         (signal-kobj kmm 'on kmm nil))
+       (kplace-get-objects-of-type kplace t_monman))
+  )
+       
+;; trigger anything with an 'on-entry' ifc
+(define (on-entry-trigger-all kplace kplayer)
+  (map (lambda (kobj)
+         (signal-kobj kobj 'on-entry kobj))
+       (kern-place-get-objects kplace))
+  )
+     
+  
+;; mk-dungeon-room -- make a 19x19 dungeon room (simplified form of
+;; kern-mk-place)
+(define (mk-dungeon-room tag name terrain . objects)
+  (kern-mk-place tag
+                 name
+                 nil     ; sprite
+                 (kern-mk-map nil 19 19 pal_expanded terrain)
+                 #f      ; wraps
+                 #t      ; underground
+                 #f      ; large-scale (wilderness)
+                 #f      ; tmp combat place
+                 nil     ; subplaces
+                 nil     ; neighbors
+
+                 ;; objects -- automatically add a monster manager
+                 (cons (put (mk-monman) 0 0)
+                       objects)
+                 (list 'on-entry-to-dungeon-room) ; hooks
+                 nil     ; edge entrances
+                 ))
+
+(define (mk-combat-map tag . terrain)
+  (kern-mk-map tag 19 19 pal_expanded terrain))
+
+(define (mk-tower tag name terrain entrances . objects)
+  (kern-mk-place tag
+                 name
+                 s_keep     ; sprite
+                 (kern-mk-map nil 19 19 pal_expanded terrain)
+                 #f      ; wraps
+                 #f      ; underground
+                 #f      ; large-scale (wilderness)
+                 #f      ; tmp combat place
+                 nil     ; subplaces
+                 nil     ; neighbors
+
+                 ;; objects -- automatically add a monster manager
+                 (cons (put (mk-monman) 0 0)
+                       objects)
+                 (list 'on-entry-to-dungeon-room) ; hooks
+                 entrances     ; edge entrances
+                 ))
+
+;; Just like mk-tower but make the sprite configurable
+(define (mk-19x19-town tag name sprite terrain entrances . objects)
+  (kern-mk-place tag
+                 name
+                 sprite
+                 (kern-mk-map nil 19 19 pal_expanded terrain)
+                 #f      ; wraps
+                 #f      ; underground
+                 #f      ; large-scale (wilderness)
+                 #f      ; tmp combat place
+                 nil     ; subplaces
+                 nil     ; neighbors
+                 ;; objects -- automatically add a monster manager
+                 (cons (put (mk-monman) 0 0) objects)
+                 (list 'on-entry-to-dungeon-room 'on-entry-trigger-all) ; hooks
+                 entrances     ; edge entrances
+                 ))
+
+
+;; mk-dungeon-level -- given a 2d list of rooms, connect them up as neighbors
+(define (mk-dungeon-level . rooms)
+  (define (bind-dir r1 r2 dir)
+    (if (and (not (null? r1))
+             (not (null? r2)))
+        (kern-place-set-neighbor dir r1 r2)))
+  (define (bind-row top bot)
+    (if (not (null? top))
+        (begin
+          (if (not (null? (cdr top)))
+              (bind-dir (car top) (cadr top) east))
+          (if (null? bot)
+              (bind-row (cdr top) nil)
+              (begin
+                (bind-dir (car top) (car bot) south)
+                (if (not (null? (cdr bot))) 
+                    (bind-dir (car top) (cadr bot) southeast))
+                (if (not (null? (cdr top))) 
+                    (bind-dir (cadr top) (car bot) southwest))
+                (bind-row (cdr top) (cdr bot)))))))
+  (define (bind-rooms rooms)
+    (if (not (null? rooms))
+        (begin
+          (bind-row (car rooms) 
+                    (if (null? (cdr rooms))
+                        nil
+                        (cadr rooms)))
+          (bind-rooms (cdr rooms)))))
+  (bind-rooms rooms))
+
+
+(define (println . args)
+  (map display args)
+  (newline))
+
+
+(define (is-bad-field-at? kchar loc)
+  (define (is-bad-field? val ktype)
+    (or val
+        (and (is-field? ktype)
+             (not (is-immune-to-field? kchar ktype)))))
+  (foldr is-bad-field?
+         #f
+         (kern-get-objects-at loc)))
+
+(define (is-bad-loc? kchar loc)
+  (or
+   (is-bad-terrain-at? loc)
+   (is-bad-field-at? kchar loc)
+   ))
+
+(define (is-good-loc? kchar loc)
+  ;;(println "is-good-loc?")
+  (and (passable? loc kchar)
+       (not (occupied? loc))
+       (not (is-bad-loc? kchar loc))))
+
+(define (get-off-bad-tile? kchar)
+  ;;(println "get-off-bad-tile")
+  
+  (define (choose-good-tile tiles)
+    ;;(display "choose-good-tile")(newline)
+    (if (null? tiles)
+        nil
+        (if (is-good-loc? kchar (car tiles))
+            (car tiles)
+            (choose-good-tile (cdr tiles)))))
+
+  (define (move-to-good-tile)
+    ;;(display "move-to-good-tile")(newline)
+    (let* ((curloc (kern-obj-get-location kchar))
+           (tiles (get-4-neighboring-tiles curloc))
+           (newloc (choose-good-tile tiles)))
+      (if (null? newloc)
+          #f
+          (begin
+            ;;(display "moving")(newline)
+            (kern-obj-move kchar 
+                           (- (loc-x newloc) (loc-x curloc))
+                           (- (loc-y newloc) (loc-y curloc)))
+            #t))))
+
+  (and
+   (is-bad-loc? kchar (kern-obj-get-location kchar))
+   (move-to-good-tile)))
+
+(define (move-away-from-foes? kchar)
+  ;;(println "move-away-from-foes?")
+  (evade kchar (all-visible-hostiles kchar)))
+
+;; random-loc -- choose a random location
+(define (random-loc kplace x y w h)
+  (mk-loc kplace 
+          (+ x (modulo (random-next) w))
+          (+ y (modulo (random-next) h))))
+
+;; random-loc -- choose a random location anywhere in the given place
+(define (random-loc-in-place kplace)
+  (random-loc kplace
+              0
+              0
+              (kern-place-get-width kplace)
+              (kern-place-get-height kplace)))
+
+;; random-loc-place-iter -- try up to n times to find a random location which
+;; satisfies pred?
+(define (random-loc-place-iter kplace pred? n)
+  (if (<= n 0)
+      nil
+      (let ((loc (random-loc-in-place kplace)))
+        (if (pred? loc)
+            loc
+            (random-loc-place-iter kplace pred? (- n 1))))))
+
+(define (is-floor? loc)
+  (let ((kter (kern-place-get-terrain loc)))
+    (or (eqv? kter t_flagstones)
+        (eqv? kter t_cobblestone))))
+
+(define (loc-is-empty? loc)
+  (null? (kern-get-objects-at loc)))
+
+(define (mean-player-party-level)
+  (let ((members (kern-party-get-members (kern-get-player))))
+    (if (= 0 (length members))
+        1
+        (/ (foldr (lambda (sum kchar)
+                    ;;(println "level:" (kern-char-get-level kchar))
+                    (+ sum (kern-char-get-level kchar)))
+                  0
+                  members)
+           (length members)))))
+
+(define (calc-level)
+  (max 1
+       (+ (mean-player-party-level)
+          (num-player-party-members)
+          (kern-dice-roll "1d5-3"))))
+
+(define (get-mech-at loc)
+  (let ((mechs (filter kern-obj-is-mech?
+                       (kern-get-objects-at loc))))
+    (if (null? mechs)
+        nil
+        (car mechs))))
+
+(define (handle-mech-at loc kchar)
+  (let ((kmech (get-mech-at loc)))
+    (if (null? kmech)
+        #f
+        (signal-kobj kmech 'handle kmech kchar))))
+
+(define (get-place kobj)
+  (loc-place (kern-obj-get-location kobj)))
+
+;; xp to reach the given level
+(define (power base exp)
+  (if (= 0 exp)
+      1
+      (* base (power base (- exp 1)))))
+
+(define (lvl-xp lvl)
+  (power 2 (+ 5 lvl)))
+
+(define (random-faction)
+  (modulo (random-next) faction-num))
+
+(define (get-target-loc caster range)
+  (kern-ui-target (kern-obj-get-location caster)
+                  range))
+
+;;----------------------------------------------------------------------------
+;; code for opening a moongate, warping in a monster, and re-closing it
+(define (open-moongate loc)
+  (let ((kgate (mk-moongate nil)))
+    (kern-obj-relocate kgate loc nil)
+    (moongate-animate kgate moongate-stages)
+    kgate))
+(define (close-moongate kgate)
+  (moongate-animate kgate (reverse moongate-stages))
+  (moongate-destroy kgate))
+(define (warp-in kchar loc dir faction)
+  (display "warp-in")(newline)
+  (kern-char-set-schedule kchar nil)
+  (kern-obj-inc-ref kchar)
+  (kern-obj-remove kchar)
+  (kern-obj-relocate kchar loc nil)
+  (kern-obj-dec-ref kchar)
+  (kern-map-repaint)
+  (kern-sleep 250)
+  (kern-obj-relocate kchar (loc-offset loc dir) nil)
+  (kern-being-set-base-faction kchar faction)
+  (kern-map-repaint))
+
+;;-----------------------------------------------------------------------------
+;; re-mk-composite-sprite -- combine all the sprites into one layered sprite,
+;; cloning ALL BUT the first sprite. Useful for re-decorating base sprites that
+;; have already been cloned.
+(define (re-mk-composite-sprite sprites)
+  (foldr (lambda (s1 s2) (kern-sprite-append-decoration s1 s2))
+         (car sprites)
+         (cdr sprites)))
+
+;;-----------------------------------------------------------------------------
+;; mk-composite-sprite -- combine all the sprites into one composite sprite,
+;; cloning all the sprites in the list.
+(define (mk-composite-sprite sprites)
+  (re-mk-composite-sprite (cons (kern-sprite-clone (car sprites)
+                                                   nil)
+                                (cdr sprites))))
+
+;   (foldr (lambda (s1 s2) (kern-sprite-append-decoration s1 s2))
+;          (kern-sprite-clone (car sprites) nil)
+;          (cdr sprites)))
+
+(define (kchar-in-vehicle? kchar)
+  (let ((kparty (kern-char-get-party kchar)))
+    (if (null? kparty)
+        #f
+        (not (null? (kern-party-get-vehicle kparty))))))
+
+;; is-in-darkness? -- #t iff light on this object's tile is less than the
+;; threshold for "dark"
+(define (is-in-darkness? kobj)
+  (< (kern-place-get-light (kern-obj-get-location kobj))
+     64))
+
+;; Convenience wrapper for kern-obj-add-to-inventory
+(define (give kpc ktype quantity)
+  (kern-obj-add-to-inventory kpc ktype quantity))
+
+;; Convenience wrapper for kern-obj-remove-from-inventory
+(define (take kobj ktype quantity)
+  (kern-obj-remove-from-inventory kobj ktype quantity))
+
+;; Return #t iff object has at least that many in inventory
+(define (has? kobj ktype quantity)
+  (>= (num-in-inventory kobj ktype) quantity))
+
+;; Safely if a character is in the player party. char-tag should be the
+;; character's quoted scheme variable name, for example 'ch_dude.
+(define (in-player-party? kchar-tag)
+  (println "in-player-party? " kchar-tag)
+  (and (defined? kchar-tag)
+       (let ((kchar (eval kchar-tag)))
+         (and (is-alive? kchar)
+              (is-player-party-member? kchar)))))
+
+(define (set-wind-north)
+  (println "set-wind-north")
+  (kern-set-wind north 10))
+
+;; block-teleporting takes a place and a list of strings that looks
+;; suspiciously like a terrain map, and uses the map to apply blocking
+;; mechanisms to the place. Every "x#" entry in the map will cause a blocking
+;; mechanism to be placed on that location. All other entries are ignored. The
+;; blocking mechanisms prevent spells like blink from letting the player break
+;; the fiction of a simulated multi-story place.
+(define (block-teleporting kplace map)
+  (define (doline y lines)
+    (define (docol x tokens)
+      (cond ((null? tokens) nil)
+            (else
+             (if (and (char=? #\x (car tokens))
+                       (char=? #\# (cadr tokens)))
+                 (begin
+                   (kern-obj-put-at (mk-blocker) (list kplace x y))
+                 ))
+             (docol (+ x 1) (cdddr tokens)))))
+    (cond ((null? lines) nil)
+          (else
+           (docol 0 (string->list (car lines)))
+           (doline (+ y 1) (cdr lines)))))
+    (doline 0 map))
+
+;; Find the visible object of the given type nearest to the kchar.
+(define (find-nearest kchar ktype)
+  (let ((objects (filter (lambda (kobj)
+                           (and (kobj-is-type? kobj ktype)
+                                (can-see? kchar kobj)))
+                         (kern-place-get-objects (loc-place (kern-obj-get-location kchar))))))
+    (cond ((null? objects) nil)
+          (else
+           (nearest-obj kchar objects)))))
+
+;; Return an integer describing the sign of x
+(define (sgn x)
+  (cond ((> x 0) 1)
+        ((< x 0) -1)
+        (else 0)))
+
+;; Return a list of (x . y) pairs that constitute a line between two
+;; points. Uses Bresenhaum's line-drawing algorithm.
+(define (line x1 y1 x2 y2)
+  (let* ((dx (- x2 x1))
+         (dy (- y2 y1))
+         (adx (abs dx))
+         (ady (abs dy))
+         (sdx (sgn dx))
+         (sdy (sgn dy))
+         (x (/ ady 2))
+         (y (/ adx 2))
+         (px x1)
+         (py y1))
+    (define (f1 i)
+      ;;(println "f1 i=" i " px=" px " py=" py)
+      (cond ((>= i adx)
+             nil)
+            (else
+             (set! y (+ y ady))
+             (cond ((>= y adx)
+                    (set! y (- y adx))
+                    (set! py (+ py sdy))))
+             (set! px (+ px sdx))
+             (cons (cons px py)
+                   (f1 (+ 1 i))))))
+    (define (f2 i)
+      ;;(println "f2 i=" i " px=" px " py=" py)
+      (cond ((>= i ady)
+             nil)
+            (else
+             (set! x (+ x adx))
+             (cond ((>= x ady)
+                    (set! x (- x ady))
+                    (set! px (+ px sdx))))
+             (set! py (+ py sdy))
+             (cons (cons px py)
+                   (f2 (+ 1 i))))))
+    (cond ((>= adx ady)
+           (cons (cons x1 y1) (f1 0)))
+          (else
+           (cons (cons x1 y1) (f2 0))))))
+
+;; Utility for generating dice from numbers easily
+;;
+(define (mkdice dice size)
+       (let ((numstr (if (number? dice)
+                                               (number->string dice)
+                                               dice))
+                       (sizestr (if (number? size)
+                                               (number->string size)
+                                               size)))
+                       (string-append numstr "d" sizestr)))
+
+;; output for effects that should only be noted if visible
+
+(define (msg-log-visible loc . args)
+       (if (kern-place-is-visible? loc)
+               (apply kern-log-msg args)
+               )
+       )
+
+;; Print dots across the console (similar to the u4 shrine meditation)
+(define (log-dots n delay)
+  (define (dots n)
+    (cond ((> n 0)
+           (kern-log-continue ".")
+           (kern-log-flush)
+           (kern-sleep delay)
+           (dots (- n 1)))))
+  (kern-log-begin)
+  (dots n)
+  (kern-log-end)
+  )
+
+(define (find-first fn? lst)
+  (if (null? lst)
+      nil
+      (if (fn? (car lst))
+          (car lst)
+          (find-first fn? (cdr lst)))))
+
+(define (append! lst val)
+  (cond ((null? lst) nil)
+        ((null? (cdr lst)) (set-cdr! lst val))
+        (else (append! (cdr lst) val))))
+
+(define (repeat fn n)
+  (if (> n 0)
+      (begin
+        (fn)
+        (repeat fn (- n 1)))))
+
+(define (string-lower str)
+  (list->string (map char-downcase (string->list str))))
+
+(define (!= a b) 
+  (not (= a b)))
+
+(define (rect-x r) (car r))
+(define (rect-y r) (cadr r))
+(define (rect-w r) (caddr r))
+(define (rect-h r) (cadddr r))
+
+(define (rect-down r v)
+  (list (rect-x r) (+ v (rect-y r)) (rect-w r) (rect-h r)))
+  
+(define (rect-crop-down r v)
+  (list (rect-x r) (+ v (rect-y r)) (rect-w r) (- (rect-h r) v)))
+(define (rect-offset r x y)
+  (list (+ x (rect-x r)) (+ y (rect-y r)) (rect-w r) (rect-h r)))
+
+(define (rect-crop-offset r x y)
+  (list (+ x (rect-x r)) (+ y (rect-y r)) (- (rect-w r) x) (- (rect-h r) y))) 
+  
+(define (1- x) (- x 1))
+(define (1+ x) (+ x 1))
+
+;; Standard dc vs 1d20 + bonus, with a perfect roll granting automatic success.
+(define (check-roll dc bonus)
+  (let ((roll (kern-dice-roll "1d20")))
+    (or (= 20 roll)
+        (> (+ roll bonus) dc))))
+
diff --git a/worlds/haxima-1.002/necromancer.scm b/worlds/haxima-1.002/necromancer.scm
new file mode 100644 (file)
index 0000000..2545bf5
--- /dev/null
@@ -0,0 +1,370 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define necr-lvl 8)
+(define necr-species sp_human)
+(define necr-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;----------------------------------------------------------------------------
+(define necr-bed nl-bed)
+(define necr-mealplace nl-tbl)
+(define necr-workplace nl-lab)
+(define necr-leisureplace nl-lib)
+(kern-mk-sched 'sch_necr
+               (list 0  0 necr-bed          "sleeping")
+               (list 7  0 necr-mealplace    "eating")
+               (list 8  0 necr-workplace    "working")
+               (list 12 0 necr-mealplace    "eating")
+               (list 13 0 necr-workplace    "working")
+               (list 18 0 necr-mealplace    "eating")
+               (list 19 0 necr-leisureplace "idle")
+               (list 22 0 necr-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (necr-mk) 
+  (mk-quest))
+(define (necr-quest gob) gob)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (necr-hail knpc kpc)
+  (let ((quest (necr-quest (kobj-gob-data knpc))))
+    (if (and (quest-offered? quest)
+             (not (quest-done? quest))
+             (in-inventory? kpc t_lich_skull)
+             )
+        (necr-meet-lich knpc kpc)
+        (say knpc "[You meet a thin, pale wizard dressed all in black] "
+             "(COUGH) Hello, Wanderer."))))
+
+(define (necr-default knpc kpc)
+  (say knpc "[He is seized by a fit of coughing]"))
+
+(define (necr-heal knpc kpc)
+  (begin
+    (say knpc "\n[He is seized by a fit of coughing]\n"
+        "I'm fine [COUGH] [WHEEZE]")
+    (prompt-for-key)
+
+    (say knpc "Really.\n")
+    (prompt-for-key)
+
+    (say knpc "\nI am quite wel...[COUGH]")
+    (prompt-for-key)
+
+    (say knpc "\n  [WHEEZE]...")
+    (prompt-for-key)
+
+    (say knpc "[CHOKE]")
+    (kern-sleep 100)
+    (say knpc "[the slight figure slumps]")
+    (kern-sleep 100)
+    (say knpc "[GASP]")
+    (kern-sleep 3000)
+    (say knpc " ...")
+    (prompt-for-key)
+
+    (say knpc "\n[All is silence]")
+    (prompt-for-key)
+
+    (if (in-player-party? 'ch_mesmeme)
+       (begin  
+         (say knpc "\n[The silence stretches on...]")
+         (kern-sleep 3000)
+         (aside kpc 'ch_mesmeme "[Looks at the slumped figure]\nFood now?")
+         (aside kpc 'ch_amy "EEEWWW!  Bad Gazer!")
+         (prompt-for-key)
+         )
+       )
+
+    (if (in-player-party? 'ch_nate)
+       (begin
+         (say knpc "\n[The dead sound of the crypt presses on]")
+         (kern-sleep 3000)
+         (aside kpc 'ch_nate "Erm...")
+         (kern-sleep 100)
+         (aside kpc 'ch_nate "  should we maybe...")
+         (kern-sleep 1000)
+         (aside kpc 'ch_nate "  take his stuff?")
+         (kern-sleep 500)
+         (aside kpc 'ch_roland "Nay!  'Twould be dishonour!")
+         (prompt-for-key)
+         )
+       )
+    
+    (if (in-player-party? 'ch_amy)
+       (begin
+         (aside kpc 'ch_amy "I could maybe...dig a hole, somewhere?")
+         (prompt-for-key)
+         )
+       )
+
+    (kern-sleep 3000)
+    (say knpc
+        "\n[His still form twitches]\n"
+        "[His arm gropes for his chest]\n"
+        "  ^c+bIN VAS MANI CORP XEN^c-\n"
+        "")
+    ;; (vas-mani knpc)  ;; SAM: Alas, this invoked UI, and emitted extra messages
+    (say knpc
+        "\n[He straightens, and breathes deeply]\n"
+        "As I was saying, I am quite well, thank you.")
+    ))
+
+(define (necr-name knpc kpc)
+  (say knpc "I am the Necromancer."))
+
+(define (necr-join knpc kpc)
+  (say knpc "I am not an adventurer."))
+
+(define (necr-job knpc kpc)
+  (say knpc "I investigate the secrets of the dead."))
+
+(define (necr-bye knpc kpc)
+  (say knpc "[He waves you off in a fit of coughing]"))
+
+;; L2
+(define (necr-dead knpc kpc)
+  (say knpc "Dead? No, not yet. You?")
+  (if (yes? knpc)
+      (say knpc "You look a bit firm for a spirit.")
+      (say knpc "I didn't think so, but I talk to so many spirits I can't "
+           "really tell any more.")))
+
+(define (necr-coug knpc kpc)
+  (say knpc "I smoked a pipe for years. Still do, sometimes."))
+
+(define (necr-spir knpc kpc)
+  (say knpc "Some spirits are so old they remember things before recorded "
+       "history. (COUGH) If you want to know something, there's a spirit "
+       "somewhere that knows it."))
+
+;; Quest-related
+(define (necr-meet-lich knpc kpc)
+  (if (quest-done? (necr-quest (kobj-gob-data knpc)))
+      (begin
+        (say knpc "Ask the spirit of King Luximene! Can't you see him?")
+        (if (no? kpc)
+            (begin
+              (say knpc "Oh, sorry. Let me fix that:\n"
+                  "[He intones words of magic]"
+                  "  ^c+bWIS QUAS^c-!")
+              (wis-quas knpc))
+            (say knpc "Well...")))
+      (begin
+        (say knpc "Ah! You have the skull of King Luximene! "
+             "No doubt there's a good story to go along with this, "
+             "but let's hear about that later. For now...")
+        (kern-obj-remove-from-inventory kpc t_lich_skull 1)
+        (say knpc "\n[He intones words of magic]\n"
+            "  ^c+bKAL AN XEN CORP^c-!\n"
+            "Luximene, come forth!")
+        (kern-obj-put-at (mk-luximene)
+                         (loc-offset (kern-obj-get-location knpc)
+                                     south))
+        (quest-done! (necr-quest (kobj-gob-data knpc)) #t)
+        (say knpc "There! Do you see him?")
+        (if (no? kpc)
+            (begin
+              (say knpc "Of course, his spirit is invisible to the uninitiated.\n"
+                   "Let me fix that:\n"
+                  "[He intones words of magic]"
+                  "  ^c+bWIS QUAS^c-!")
+              (wis-quas knpc))
+            (say knpc "Ask him of the rune now.")))))
+
+(define (necr-rune knpc kpc)
+  (let ((quest (necr-quest (kobj-gob-data knpc))))
+    (if (quest-offered? quest)
+        (if (in-inventory? kpc t_lich_skull)
+            (necr-meet-lich knpc kpc)
+            (if (quest-done? quest)
+                (begin
+                  (say knpc "Ask the spirit of King Luximene! Can't you see him?")
+                  (if (no? kpc)
+                      (begin
+                        (say knpc "Try a Reveal spell...\n"
+                            "[He intones words of magic]\n"
+                            "  ^c+bWIS QUAS^c-\n"
+                            "Speak to his shade, ask of the RUNE.")
+                       (wis-quas knpc)
+                       (kern-conv-end)
+                       )
+                      (begin
+                       (say knpc "Well then, ask his shade.")
+                       (kern-conv-end)
+                     )
+                 ))
+                (say knpc "Bring me the skull of King Luximene the lich "
+                     "and we can learn more.")))
+        (if (not (any-in-inventory? kpc rune-types))
+            (say knpc "I've encountered many runes. (COUGH) Bring me an example "
+                 "of one and perhaps I can tell you of it.")
+            (begin
+              (say knpc "Hm. Yes. This rune reminds me of writings I once saw in "
+                   "the tomb of King Luximene. (COUGH) If I could speak to his "
+                   "spirit perhaps it would tell us more. Are you brave, Wanderer?")
+              (if (no? kpc)
+                  (say knpc "Me neither. More's the pity, for I am most curious "
+                       "now about this rune. (COUGH)")
+                  (begin
+                    (say knpc "I thought so. King Luximene is a lich nowadays. "
+                         "Most unruly! His tomb is in a crypt beneath Green Tower. "
+                         "If you bring me his skull I can tame his spirit and speak "
+                         "with him. (COUGH) You'll have to defeat him first, "
+                         "of course, as well as his undead army. "
+                         "Do you know how to repel the undead?")
+                    (quest-offered! quest #t)
+                    (if (yes? kpc)
+                        (say knpc "A most useful spell when dealing with the angry dead.")
+                        (say knpc "Learn ye [An Xen Corp].\n"
+                            "A most useful spell.\n"
+                            "Mix ^c+ggarlic^c- and ^c+gsulphurous ash^c-\n"
+                            "to make it.\n"
+                             "(COUGH)\n"
+                            "I probably have some "
+                             "around here.\n"
+                            "You may borrow it."))
+                   )))))))
+
+(define (necr-absa knpc kpc)
+  (say knpc "Ah, Absalot, ancient city of Wisdom, now fallen. "
+       "Have you been there?")
+  (if (yes? kpc)
+      (say knpc "It is only a shameful ruin now.")
+      (begin
+        (say knpc "Are you an ally of Glasdrin?")
+        (if (yes? kpc)
+            (say knpc "[He coughs and mutters] Well, "
+                 "there is nothing to see there now.")
+            (say knpc "There is a secret way in. Ask the Alchemist, he knows.")))))
+
+;; the wise
+(define (necr-ench knpc kpc)
+  (say knpc "The old fool thinks me one of the Accursed! "
+       "He does not understand that his ways are not the only ways.")
+       )
+
+(define (necr-man knpc kpc)
+  (say knpc "She comes to me sometimes when she needs information... "
+       "and in return she sometimes... acquires things for me.")
+  (quest-data-update 'questentry-the-man 'common 1)
+  )
+
+(define (necr-alch knpc kpc)
+  (say knpc "A clever man. A deep man, good in his own way.")
+  (quest-data-update 'questentry-alchemist 'common 1)
+  )
+
+(define (necr-engi knpc kpc)
+  (say knpc "Smart fellow, and very curious, "
+       "but always has to be making something. "
+       "And as soon as he's done, he starts on another! "
+       "(COUGH) Never time to reflect on anything worthy.")
+       (quest-data-update 'questentry-engineer 'common 1)
+       )
+
+(define (necr-warr knpc kpc)
+       (if (quest-data-assigned? 'questentry-wise)
+               (begin
+                 (say knpc "Alas, she is fallen. I have met her spirit in the void. "
+                      "She was betrayed by the leadership of Glasdrin. "
+                      "Would that the gods had not abandoned us, "
+                      "and Vale, lord of vengeance, still stalked the Shard!")
+                      (quest-data-update 'questentry-warritrix 'slain 1)
+                )
+                (say knpc "The hasn't been another knight so noble and so strong in "
+                "a long, long time.")
+       ))
+
+(define (necr-vale knpc kpc)
+  (say knpc "An ancient god, known only to the dead now."))
+
+(define (necr-wise knpc kpc)
+  (say knpc "It is an ancient and worthy tradition that those "
+       "who have mastered the ways of Warrior, Wizard, Wright "
+       "and Wrogue should influence the affairs of the Shard. "
+       "Long is the chain of that tradition, "
+       "back to the oldest spirits in the void."))
+
+(define (necr-accu knpc kpc)
+  (say knpc "They are a wretched abomination! (COUGH) Their order "
+       "began about 500 years ago, or at least those are the oldest "
+       "spirits that speak of them. But I do not know their secrets "
+       "because their spirits do not return to the void!")
+  (prompt-for-key)
+  (say knpc "[He looks troubled] "
+       "I cannot find any among the dead who were Accursed in life. "
+       "It is a most disturbing conundrum."))
+
+(define (necr-gate knpc kpc)
+  (say knpc "Ah, the fabled Demon Gate. I thought it was only a legend. "
+       "Ask the Enchanter, he surely knows more of it than I. "
+       "Meanwhile I will confer with the dead to see what I can discover."))
+
+(define (necr-necr knpc kpc)
+  (say knpc "[Cough] I specialize in magic relating to the dead."))
+
+(define necr-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default necr-default)
+       (method 'hail necr-hail)
+       (method 'bye necr-bye)
+       (method 'job necr-job)
+       (method 'name necr-name)
+       (method 'join necr-join)
+       (method 'heal necr-heal)
+       
+       (method 'dead necr-dead)
+       (method 'coug necr-coug)
+       (method 'spir necr-spir)
+       (method 'rune necr-rune)
+       (method 'absa necr-absa)
+       (method 'ench necr-ench)
+       (method 'man necr-man)
+       (method 'alch necr-alch)
+       (method 'engi necr-engi)
+       (method 'warr necr-warr)
+       (method 'vale necr-vale)
+       (method 'wise necr-wise)
+       (method 'accu necr-accu)
+       (method 'gate necr-gate)
+       (method 'demo necr-gate)
+       (method 'necr necr-necr)
+       ))
+
+(define (mk-necromancer)
+  (bind 
+   (kern-mk-char 
+    'ch_necr           ; tag
+    "Necromancer"    ; name
+    necr-species         ; species
+    necr-occ              ; occ
+    s_necromancer     ; sprite
+    faction-men      ; starting alignment
+    1 6 0            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    necr-lvl
+    #f               ; dead
+    'necr-conv         ; conv
+    sch_necr         ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_staff)              ; readied
+    )
+   (necr-mk)))
diff --git a/worlds/haxima-1.002/necromancers-lair.scm b/worlds/haxima-1.002/necromancers-lair.scm
new file mode 100644 (file)
index 0000000..c044ccc
--- /dev/null
@@ -0,0 +1,122 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_necromancers_lair 19 19 pal_expanded
+ (list
+      "xx xx xx xx xx xx xx xx xx && xx xx xx xx xx x! xx xx xx "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, x! ,, ,, ,, ,, [[ @@ ]] ,, xx ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx xx xx xx xx xx xx xx x! ,, x! xx xx xx x! ,, x! xx xx "
+      "xx xx .. .. .. xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx .. .. .. ,, .. xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx .. ,, ,, .. .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx .. .. ,, .. .. xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+      "xx xx .. .. .. xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx xx xx ,, xx xx xx xx x! ,, x! xx xx xx x! ,, x! xx xx "
+      "xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx xx ,, ,, ,, xx xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ~~ ee ~~ ~~ xx 00 ,, ,, ,, 00 xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ee ee ~~ ~~ xx 00 ,, ,, ,, 00 xx "
+      "xx ,, ,, ,, ,, ,, x! ,, ~~ ~~ ~~ ~~ xx 00 ,, ,, ,, 00 xx "
+      "xx x! [[ @@ ]] x! xx xx ~~ ~~ ~~ xx xx x! 00 00 00 x! xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+))
+
+;;----------------------------------------------------------------------------
+;; NPC's
+;;----------------------------------------------------------------------------
+(kern-load "luximene.scm")
+(kern-load "necromancer.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_necromancers_lair     ; tag
+ "Necromancers Lair" ; name
+ nil      ; sprite
+ m_necromancers_lair      ; map
+ #f              ; wraps
+ #t              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+
+  (put (mk-ladder-up 'p_shard 40 70) 9 9)
+
+  ;; npc's
+  (put (mk-necromancer) 9 9)
+
+  ;; bedroom
+  (put (mk-bed) 15 3)
+  (put (mk-door) 15 6)
+
+  ;; galley
+  (put (mk-chest
+        nil
+        '((5 t_food))) 10 1)
+
+  ;; library
+  (put (mk-door) 15 12)
+
+  (put (kern-mk-obj t_spell_book_white_magick_1 1) 13 14)
+  (put (kern-mk-obj t_spell_book_white_magick_2 1) 13 15)
+  (put (kern-mk-obj t_spell_book_white_magick_3 1) 13 16)
+
+  (put (kern-mk-obj t_spell_book_necromancy        1) 15 17)
+  (put (kern-mk-obj t_spell_book_enchantment_wards 1) 16 17)
+
+  (put (kern-mk-obj t_spell_book_summoning   1) 17 14)
+  (put (kern-mk-obj t_spell_book_gate_magick 1) 17 15)
+  (put (kern-mk-obj t_spell_book_divination  1) 17 16)
+
+  ;; center
+  (put (mk-door) 9 12)
+  (put (mk-door) 9 6)
+  (put (mk-door) 12 9)
+
+  ;; lab
+  (put (mk-door) 6 15)
+  (put (mk-locked-door) 3 12)
+
+  ;; morgue
+  (put (mk-corpse) 2 7)
+  (put (mk-corpse) 3 7)
+  (put (mk-corpse) 4 7)
+  (put (mk-corpse) 1 8)
+  (put (mk-corpse) 2 8)
+  (put (mk-corpse) 5 8)
+  (put (mk-corpse) 1 10)
+  (put (mk-corpse) 5 9)
+
+  ;; potion room
+  (put (mk-magic-locked-door) 6 3)
+  (put (kern-mk-obj mandrake 6) 2 1)
+  (put (kern-mk-obj nightshade 4) 3 1)
+  (put (kern-mk-obj blood_moss 12) 4 1)
+  (put (kern-mk-obj black_pearl 14) 2 5)
+  (put (kern-mk-obj spider_silk 21) 3 5)
+  (put (kern-mk-obj garlic 18) 4 5)
+  (put (kern-mk-obj ginseng 17) 1 4)
+  (put (kern-mk-obj sulphorous_ash 26) 1 3)
+  (put (kern-mk-obj t_mana_potion 8) 1 2)
+  )
+
+ nil ; hooks
+ (list  ;; edge entrances
+  (list east  0 9)
+  (list south 9 0) 
+  (list north 9 18)
+  (list west  18 9)
+  )
+ )
+
+
+(mk-place-music p_necromancers_lair 'ml-creepy-area)
+
diff --git a/worlds/haxima-1.002/newfolks.png b/worlds/haxima-1.002/newfolks.png
new file mode 100644 (file)
index 0000000..ea173fd
Binary files /dev/null and b/worlds/haxima-1.002/newfolks.png differ
diff --git a/worlds/haxima-1.002/newmonst.png b/worlds/haxima-1.002/newmonst.png
new file mode 100644 (file)
index 0000000..c66d425
Binary files /dev/null and b/worlds/haxima-1.002/newmonst.png differ
diff --git a/worlds/haxima-1.002/newterrain.png b/worlds/haxima-1.002/newterrain.png
new file mode 100644 (file)
index 0000000..c448889
Binary files /dev/null and b/worlds/haxima-1.002/newterrain.png differ
diff --git a/worlds/haxima-1.002/nossifer.scm b/worlds/haxima-1.002/nossifer.scm
new file mode 100644 (file)
index 0000000..85b4989
--- /dev/null
@@ -0,0 +1,99 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define nossifer-x 16)
+(define nossifer-y 6)
+(define noss-lvl 20)
+(define noss-species sp_balron)
+(define noss-occ oc_wizard)
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (noss-mk) (list #f))
+(define (noss-spoke? gob) (car gob))
+(define (noss-spoke! gob) (set-car! gob #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (noss-hail knpc kpc)
+  (say knpc "I am summoned at last! Whom shall I punish for this delay?"))
+
+(define (noss-default knpc kpc)
+  (say knpc "I slay fools who waste words with me."))
+
+(define (noss-name knpc kpc)
+  (say knpc "I am Nossifer, the Sleeper."))
+
+(define (begin-last-battle knpc kpc)
+  (say knpc "Your soul will never know the bliss of the Void. "
+       "I will torment it FOREVER!")
+  (kern-being-set-base-faction knpc faction-demon)
+  (kern-conv-end))
+
+(define (noss-job knpc kpc)
+  (say knpc "I bring oblivion to worlds. You've heard of wizards who summon demons to do their bidding?")
+  (yes? kpc)
+  (say knpc "I summon men to do mine. What do you think YOU are?")
+  (kern-log-msg "He laughs, and the air reeks of sulphur.")
+  (say knpc "You have opened the way, and served your purpose well. "
+       "Now, receive your reward... ")
+  (quest-data-update 'questentry-whereami 'nossifer 1)
+  (kern-being-set-base-faction knpc faction-demon)
+  (kern-conv-end))
+
+(define (noss-bye knpc kpc)
+  (say knpc "Not yet. We have unfinished business to discuss.")
+  (prompt-for-key)
+  (noss-job knpc kpc))
+
+(define noss-conv
+  (ifc nil
+
+       ;; basics
+       (method 'default noss-default)
+       (method 'hail noss-hail)
+       (method 'bye noss-bye)
+       (method 'job noss-job)
+       (method 'name noss-name)
+
+       ))
+
+(define (noss-ai kchar)
+  (warlock-ai kchar))
+
+(define (mk-nossifer)
+  (let ((kchar (bind 
+                 (kern-mk-char 
+                  'ch_nossifer           ; tag
+                  "Nossifer"             ; name
+                  noss-species         ; species
+                  noss-occ              ; occ
+                  s_balron          ; sprite
+                  faction-men      ; starting alignment
+                  20 5 20            ; str/int/dex
+                  0 5              ; hp mod/mult
+                  0 2              ; mp mod/mult
+                  max-health ; hp
+                  0                   ; xp
+                  max-health ; mp
+                  0
+                  noss-lvl
+                  #f               ; dead
+                  'noss-conv       ; conv
+                  nil           ; sched
+                  'noss-ai  ; special ai
+                  nil              ; container
+                  (list
+                   t_flaming_sword
+                   t_armor_plate
+                   ))
+                (noss-mk))))
+    (map (lambda (eff) (kern-obj-add-effect kchar eff nil))
+         demon-effects)
+    (kern-obj-add-effect kchar ef_charm_immunity nil)
+    kchar
+    ))
diff --git a/worlds/haxima-1.002/npc-types.scm b/worlds/haxima-1.002/npc-types.scm
new file mode 100644 (file)
index 0000000..48f93a1
--- /dev/null
@@ -0,0 +1,933 @@
+;;----------------------------------------------------------------------------
+;; NPC type constructors
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Local Constants
+;;----------------------------------------------------------------------------
+(define default-level 1)
+
+;;----------------------------------------------------------------------------
+;; Local Procedures
+;;----------------------------------------------------------------------------
+
+;; mk-stock-char -- convenience wrapper for kern-mk-char. Handles the
+;; boilerplate associated with first-time "stock" character creations. A stock
+;; character is a monster, guard or similar cannon-fodder NPC, with no
+;; interesting conversation, no schedule of appointments, etc.
+(define (mk-stock-char name species occupation sprite faction ai container 
+                       arms conv)
+  (kern-mk-char
+   nil ;;..........tag
+   name ;;.........name
+   species ;;.......species
+   occupation ;;...occupation
+   sprite ;;.......sprite
+   faction ;;....;.faction
+   0 ;;............custom strength modifier
+   0 ;;............custom intelligence modifier
+   0 ;;............custom dexterity modifier
+   0 ;;............custom base hp modifier
+   0 ;;............custom hp multiplier (per-level)
+   0 ;;............custom base mp modifier
+   0 ;;............custom mp multiplier (per-level)
+   (max-hp species occupation default-level 0 0) ;;.current hit points
+   -1  ;;...........current experience points
+   (max-mp species occupation default-level 0 0) ;;.current magic points
+   0  ;; AP_per_turn
+   default-level  ;;............current level
+   #f ;;...........dead?
+   conv ;;.........conversation (optional)
+   nil ;;..........schedule (optional)
+   ai ;;...........custom ai (optional)
+   container ;;....container (and contents)
+   arms ;;.........readied arms (in addition to the container contents)
+   nil ;;..........hooks in effect
+   ))
+
+;; Curried version of mk-stock-char for characters without an occupation, ai,
+;; container or armamenets
+(define (mk-animal name species sprite)
+  (mk-stock-char name species nil sprite faction-none nil nil nil nil))
+
+(define (mk-readied-items . items)
+  items)
+
+(define (mk-at-level ctor-tag lvl-dice . args)
+  (set-level (apply (eval ctor-tag) args) 
+             (kern-dice-roll lvl-dice)))
+
+;; npct -- NPC type
+(define (mk-npct2 name spec occ spr traps equip eff ai faction conv drop-fx drop-fx-parms)
+  (list name spec occ spr traps equip eff ai faction conv drop-fx drop-fx-parms))
+(define (mk-npct name spec occ spr traps equip eff ai faction conv)
+  (mk-npct2 name spec occ spr traps equip eff ai faction conv nil nil))
+(define (npct-name npct) (car npct))
+(define (npct-spec npct) (cadr npct))
+(define (npct-occ npct) (caddr npct))
+(define (npct-spr npct) (cadddr npct))
+(define (npct-traps npct) (list-ref npct 4))
+(define (npct-eqp npct) (list-ref npct 5))
+(define (npct-effects npct) (list-ref npct 6))
+(define (npct-ai npct) (list-ref npct 7))
+(define (npct-faction npct) (list-ref npct 8))
+(define (npct-conv npct) (list-ref npct 9))
+(define (npct-drop-fx npct) (list-ref npct 10))
+(define (npct-drop-fx-parms npct) (list-ref npct 11))
+
+
+
+;; npcg -- generic NPC gob
+(define (npcg-mk type) 
+  (list 'npcg 
+        type 
+        #f  ;; taunted
+        #f  ;; spawned
+        nil ;; post
+        nil ;; subgob
+        ))
+(define (npcg-type npcg) (cadr npcg))
+(define (npcg-taunted? npcg) (caddr npcg))
+(define (npcg-spawned? npcg) (cadddr npcg))
+(define (npcg-is-type? npcg type) (equal? type (npcg-type npcg)))
+(define (npcg-set-taunted! npcg val) (set-car! (cddr npcg) val))
+(define (npcg-set-spawned! npcg val) (set-car! (cdddr npcg) val))
+(define (npcg-set-post! npcg val) (set-car! (list-tail npcg 4) val))
+(define (npcg-has-post? npcg) (not (null? (npcg-get-post npcg))))
+(define (npcg-get-post npcg) (list-ref npcg 4))
+(define (npcg-get-subgob npcg) (list-ref npcg 5))
+(define (npcg-set-subgob! npcg val) (set-car! (list-tail npcg 5) val))
+(define (is-npcg? gob) (eq? (car gob) 'npcg))
+
+(define (kbeing-is-npc-type? kbeing type)
+  (let ((npcg (gob kbeing)))
+    (and (not (null? npcg))
+         (is-npcg? npcg)
+         (npcg-is-type? npcg type))))
+
+(define (kbeing-was-spawned? kbeing)
+  (let ((npcg (gob kbeing)))
+    (and (not (null? npcg))
+         (is-npcg? npcg)
+         (npcg-spawned? npcg))))
+
+;; An NPC inventory is kind of an abstract container. It should never appear on
+;; the world map.
+(define (mk-inventory contents)
+  (kern-mk-inventory contents))
+
+;; mk-npc -- create a kernel character of the given type, faction and level
+(define (mk-npc npct-tag lvl)
+  (let* ((npct (eval npct-tag))
+         (npc (bind
+               (set-level
+                (kern-char-arm-self
+                 (mk-stock-char
+                  (npct-name npct)
+                  (npct-spec npct)
+                  (npct-occ npct)
+                  (npct-spr npct)
+                  (npct-faction npct)
+                  (npct-ai npct)
+                  (mk-inventory
+                   (filter notnull?
+                           (map (lambda (x)
+                                  (apply roll-to-add x))
+                                (npct-eqp npct))))
+                  nil
+                  (npct-conv npct)))
+                lvl)
+               (npcg-mk npct-tag))))
+    ;; revisit -- will this work or will effects need to be symbol-tags?
+    (map (lambda (eff) (apply-eff-pkg npc eff))
+         (npct-effects npct))
+    (if (not (null? (npct-drop-fx npct)))
+        (kern-obj-add-effect npc 
+                             ef_loot_drop 
+                             (loot-drop-mk (npct-drop-fx npct)
+                                           (npct-drop-fx-parms npct))))
+    npc))
+
+;; spawn-npc -- like mk-npc but mark the npc as spawned (this allows monster
+;; managers to periodically clean up old spawned NPC's)
+(define (spawn-npc npct-tag lvl)
+  
+  (let ((kchar (mk-npc npct-tag lvl)))
+    (npcg-set-spawned! (gob kchar) #t)
+    kchar))
+
+;;----------------------------------------------------------------------------
+;; trap packages
+(define no-traps (list nil))
+(define basic-traps  (list nil 'burn 'spike-trap))
+(define wizard-traps (list nil 'poison-trap 'sleep-trap 'lightning-trap))
+(define wrogue-traps (list nil 'self-destruct-trap 'bomb-trap 'sleep-trap 'poison-trap 'spike-trap 'sleep-trap 'burn))
+
+;;----------------------------------------------------------------------------
+;; effect packages
+(define slime-effects  (list ef_poison_immunity 
+                             (list ef_split split-gob-mk 'green-slime)))
+(define yellow-slime-effects  (list ef_poison_immunity))
+(define undead-effects (list ef_poison_immunity 
+                             ef_fire_immunity 
+                             ef_disease_immunity 
+                             ef_sleep_immunity 
+                             ef_magical_kill_immunity))
+(define demon-effects (list ef_poison_immunity 
+                            ef_fire_immunity 
+                            ef_disease_immunity 
+                            ef_sleep_immunity
+                            ef_magical_kill_immunity))
+(define hydra-effects (list ef_poison_immunity ef_grow_head))
+(define drag-effects (list ef_fire_immunity))
+(define wisp-effects (list ef_poison_immunity 
+                           ef_disease_immunity))
+(define fire-slime-effects (list ef_fire_immunity
+                                 (list ef_split split-gob-mk 'fire-slime)))
+(define sludge-kraken-effects (list ef_cleanup_tentacles))
+
+(define (apply-eff-pkg knpc pkg)
+  (if (pair? pkg)
+      (let* ((eff (car pkg))
+             (gob-ctor (cadr pkg))
+             (gob-args (cddr pkg))
+             (gob (apply gob-ctor gob-args)))
+        (kern-obj-add-effect knpc eff gob))
+      (kern-obj-add-effect knpc pkg nil)))
+
+;;----------------------------------------------------------------------------
+;; equipment packages for different types of npcs
+(define wizard-equip 
+  (list (list 100 "1"     t_dagger)
+        ))
+(define archer-equip 
+  (list (list 100 "1"     t_bow)
+        (list 100 "1d6"   t_arrow)
+        (list 100 "1"     t_dagger)
+        ))
+(define stalker-equip 
+  (list (list 100 "2"     t_dagger)
+        (list 100 "2"     t_dagger)
+        ))
+(define slinger-equip 
+  (list (list 100 "1"     t_sling)
+        ))
+(define berserker-equip 
+  (list (list 100 "2"     t_axe)         
+        (list 100 "1d2"   t_heal_potion)
+        ))
+(define ranger-equip
+  (list (list 100 "1"     t_sword)
+        (list 100 "1"     t_bow)
+        (list 100 "20"    t_arrow)
+        (list 100 "1"     t_leather_helm)
+        (list 100 "1"     t_armor_leather)
+        (list 100 "1d3-1" t_heal_potion)
+        ))
+(define skeletal-warrior-equip
+  (list (list 100 "1"     t_sword)
+        (list 100 "1"     t_shield)
+        (list 100 "1"     t_iron_helm)
+        ))
+(define spear-thrower-equip
+  (list (list 100 "1d20"  t_spear)
+        (list 100 "1"     t_iron_helm)
+        (list 100 "1"     t_axe)
+        ))
+(define death-knight-equip
+  (list (list 100 "1"     t_2h_axe)
+        (list 100 "1"     t_armor_plate)
+        (list 100 "1"     t_iron_helm)
+        (list 100 "1d3-1" t_mana_potion)
+        ))
+(define knight-equip
+  (list (list 100 "1"     t_2h_sword)
+        (list 100 "1"     t_armor_plate)
+        (list 100 "1"     t_iron_helm)
+        (list 100 "1d3-1" t_heal_potion)
+        ))
+(define squire-equip
+  (list (list 100 "1"     t_crossbow)
+        (list 100 "1d10"  t_bolt)
+        (list 100 "1"     t_dagger)
+        (list 100 "1"     t_armor_chain)
+        (list 100 "1"     t_chain_coif)
+        (list 100 "1d2-1" t_heal_potion)
+        ))
+(define halberdier-equip
+  (list (list 100 "1"     t_halberd)
+        (list 100 "1"     t_chain_coif)
+        (list 100 "1"     t_armor_chain)
+        (list 100 "1d3-1" t_heal_potion)
+        (list 10  "1"     t_vas_mani_scroll)
+        (list 10  "1"     t_in_an_scroll)
+        ))
+(define crossbowman-equip
+  (list (list 100 "1"     t_crossbow)
+        (list 100 "10"    t_bolt)
+        (list 100 "1"     t_chain_coif)
+        (list 100 "1"     t_dagger)
+        (list 100 "1"     t_armor_chain)
+        (list 100 "1d3-1" t_heal_potion)
+        (list 10  "1"     t_vas_mani_scroll)
+        (list 10  "1"     t_in_an_scroll)
+        ))
+(define wrogue-1-equip
+  (list (list 100 "1"     t_dagger)
+        (list 100 "2d6-2" t_gold_coins)
+        (list 50  "1d5"   t_food)
+        (list 10  "1d3"   t_torch)
+        ))
+(define wrogue-2-equip
+  (list (list 100 "1"     t_sword)
+        (list 100 "1"     t_sling)
+        (list 100 "1"     t_leather_helm)
+        (list 100 "1"     t_armor_leather)
+        ))
+(define wrogue-3-equip
+  (list (list 100 "1"     t_sword)
+        (list 100 "1"     t_leather_helm)
+        (list 100 "1"     t_armor_leather)
+        (list 100 "1d10"  t_arrow)
+        (list 75  "1"     t_bow)
+        ))
+(define wrogue-4-equip
+  (list (list 100 "1"     t_armor_chain)
+        (list 100 "1"     t_chain_coif)
+        (list 100 "1"     t_sword)
+        (list 100 "1d10"  t_bolt)
+        (list 75  "1"     t_crossbow)
+        ))
+(define medik-equip
+  (list (list 100 "1d3"   t_heal_potion)
+        (list 100 "1d2"   t_mana_potion)
+        (list 25  "1d2"   t_cure_potion)
+        (list 100 "1"     t_chain_coif)
+        (list 100 "1"     t_staff)
+        (list 100 "1"     t_armor_chain)
+        ))
+(define troll-equip
+  (list (list 100 "1d3" t_thrown_boulder)
+        ))
+(define geomancer-equip
+  (list (list 100 "1d3-1" t_mana_potion)
+        ))
+(define gint-warrior-equip
+  (list (list 100 "1"     t_2h_axe)
+        (list 100 "1"     t_2h_sword)
+        (list 100 "1d3-1" t_heal_potion)
+        ))
+(define headless-equip
+  (list (list 100 "1"     t_axe)
+        (list 100 "1"     t_shield)
+        ))
+(define craven-archer-equip
+  (list (list 100 "1"     t_bow)
+        (list 100 "20"    t_arrow)
+        (list 100 "1"     t_armor_plate)
+        (list 100 "1"     t_iron_helm)
+        (list 100 "1"     t_dagger)
+        (list 100 "1d3-1" t_mana_potion)
+        ))
+(define nixie-1-equip
+  (list (list 100 "1d20" t_spear)
+        ))
+(define nixie-2-equip
+  (list (list 100 "1d20" t_sword)
+        ))
+(define bomber-equip
+  (list (list 100 "1d5" t_oil)
+        (list 100 "1"   t_dagger)
+        (list 25  "1d3" t_smoke_bomb)
+        ))
+
+(define accursed-1-equip
+  (list (list 100 "1" t_dagger)
+        ))
+(define accursed-2-equip
+  (list (list 100 "1" t_dagger)
+        (list 75  "1" t_sling)
+        ))
+(define accursed-3-equip
+  (list (list 100 "1" t_staff)
+        (list 75  "1" t_sling)
+        ))
+(define accursed-4-equip
+  (list (list 100 "1" t_sword)
+        (list 100 "1" t_shield)
+        (list 100 "1" t_leather_helm)
+        (list 100 "1" t_armor_leather)
+        ))
+(define accursed-5-equip
+  (list (list 100 "1" t_sword)
+        (list 100 "1" t_shield)
+        (list 100 "1" t_chain_coif)
+        (list 100 "1" t_armor_chain)
+        (list 100 "1" t_crossbow)
+        (list 100 "1d10" t_bolt)
+        ))
+(define accursed-6-equip
+  (list (list 100 "1" t_sword)
+        (list 100 "1" t_morning_star)
+        (list 100 "1" t_iron_helm)
+        (list 100 "1" t_armor_plate)
+        ))
+        
+(define demon-equip
+  (list (list 100 "1" t_flaming_sword)
+        ))
+
+;;----------------------------------------------------------------------------
+;; Loot drops
+(define animal-loot
+  (list (list 25 "1" 't_food)
+        ))
+
+(define deer-loot
+  (list (list 100 "1" 't_animal_corpse)
+        ))
+
+(define bull-loot
+  (list (list 100 "5" 't_food)
+        ))
+
+(define wizard-loot
+  (list (list 100 "1d2-1" 't_heal_potion)
+        (list 100 "1d2+1" 't_mana_potion)
+        (list 100 "1d20"  't_gold_coins)
+        (list 10  "1d3"   't_food)
+        (list 10  "1"     't_cure_potion)
+        (list 10  "1"     't_poison_immunity_potion)
+        (list 20  "1d5"   'sulphorous_ash)
+        (list 20  "1d5"   'ginseng)
+        (list 20  "1d5"   'garlic)
+        (list 10  "1d3"   'spider_silk)
+        (list 10  "1d3"   'blood_moss)
+        (list 10  "1d3"   'black_pearl)
+        (list 5   "1d2"   'nightshade)
+        (list 5   "1d2"   'mandrake)
+        (list 5   "1"     't_in_mani_corp_scroll)
+        (list 5   "1"     't_xen_corp_scroll)
+        (list 10  "1"     't_in_quas_xen_scroll)
+        (list 10  "1"     't_an_xen_ex_scroll)
+        (list 20  "1"     't_in_an_scroll)
+        (list 20  "1"     't_vas_mani_scroll)
+        (list 5   "1"     't_dagger)
+        ))
+
+(define std-loot
+  (list (list 25 "1d2" 't_food)
+        (list 100 "1d10" 't_gold)
+        (list 25 "1" 't_heal_potion)
+        (list 10 "1" 't_torch)
+        (list 1 "1" 't_gem)
+        ))
+
+(define archer-loot 
+  (list
+        (list 100 "1d6"   't_arrow)
+        (list 100 "1d10"  't_gold_coins)
+        (list 20  "1d3"   't_food)
+        (list 10  "1"   't_bow)
+        ))
+(define stalker-loot 
+  (list
+        (list 100 "1d15"  't_gold_coins)
+        (list 30  "1d3"   't_food)
+        (list 10  "1d2"    't_dagger)
+        ))
+(define slinger-loot 
+  (list (list 100 "1d10"  't_gold_coins)
+        (list 20  "1d3"   't_food)
+        (list 10  "1"     't_sling)
+        ))
+(define berserker-loot 
+  (list (list 100 "1d2"   't_heal_potion)
+        (list 100 "1d15"  't_gold_coins)
+        (list 30  "1d3"   't_food)
+        (list 10  "1"   't_axe)
+        ))
+(define ranger-loot
+  (list (list 100 "1d10" 't_gold_coins)
+        (list 100 "1d10" 't_arrow)
+        (list 30  "1d3"   't_food)
+        (list 100 "1d3-1" 't_heal_potion)
+        (list 3 "1"     't_sword)
+        (list 6 "1"     't_bow)
+        (list 7 "1"     't_leather_helm)
+        (list 4 "1"     't_armor_leather)
+        ))
+(define skel-war-loot
+  (list (list 100 "1d20"  't_gold_coins)
+                 (list 3 "1"     't_sword)
+        (list 3 "1"     't_shield)
+        (list 3 "1"     't_iron_helm)
+        ))
+(define spear-thrower-loot
+  (list (list 50 "1d3" 't_spear)
+        (list 100 "1d20"  't_gold_coins)
+        (list 3  "1"     't_iron_helm)
+        (list 3  "1"     't_axe)
+        ))
+(define dea-kni-loot
+  (list
+        (list 100 "1d20"  't_gold_coins)
+        (list 100 "1d3-1" 't_mana_potion)
+        (list 2 "1"     't_2h_axe)
+        ;;(list 1 "1"     't_armor_plate)  if you wear anything that comes off one of these, something *really* nasty should happen
+        (list 4 "1"     't_iron_helm)
+        ))
+(define cra-arch-loot
+  (list (list 100 "1d5" 't_bolt)
+        (list 100 "1d20"  't_gold_coins)
+        (list 100 "1d3-1" 't_mana_potion)
+                 (list 10  "1"   't_bow)
+        ;;(list 1 "1"     't_armor_plate)  if you wear anything that comes off one of these, something *really* nasty should happen
+        (list 4   "1"     't_iron_helm)
+        ))
+(define knight-loot
+  (list (list 100 "1d20"  't_gold_coins)
+        (list 100 "1d3-1" 't_heal_potion)
+        (list 2 "1"     't_2h_sword)
+        (list 1 "1"     't_armor_plate)
+        (list 4 "1"     't_iron_helm)
+        ))
+(define squire-loot
+  (list (list 100 "1d10"  't_bolt)
+        (list 100 "1d10"  't_gold_coins)
+        (list 100 "1d2-1" 't_heal_potion)
+        (list 2  "1"     't_crossbow)
+        (list 10 "1"     't_dagger)
+        (list 3 "1"     't_armor_chain)
+        (list 5 "1"     't_chain_coif)
+        ))
+(define halberdier-loot
+  (list (list 100 "1d3-1" 't_heal_potion)
+        (list 10  "1"     't_vas_mani_scroll)
+        (list 10  "1"     't_in_an_scroll)
+        (list 50  "1d5"   't_food)
+        (list 1   "1"     't_halberd)
+        (list 5   "1"     't_chain_coif)
+        (list 3   "1"     't_armor_chain)
+        ))
+(define crossbowman-loot
+  (list (list 100 "1d10"    't_bolt)
+        (list 100 "1d3-1" 't_heal_potion)
+        (list 10  "1"     't_vas_mani_scroll)
+        (list 10  "1"     't_in_an_scroll)
+        (list 50  "1d5"   't_food)
+        (list 2   "1"     't_crossbow)
+        (list 5   "1"     't_chain_coif)
+        (list 10  "1"     't_dagger)
+        (list 3   "1"     't_armor_chain)
+        ))
+(define wrogue-1-loot
+  (list (list 100 "2d6-2" 't_gold_coins)
+        (list 50  "1d5"   't_food)
+        (list 10  "1d3"   't_torch)
+        (list 10  "1"     't_dagger)
+        (list 15  "1d3"   't_smoke_bomb)
+        ))
+(define wrogue-2-loot
+  (list (list 100 "2d6-2" 't_gold_coins)
+        (list 100 "1d3-1" 't_picklock)
+        (list 50  "1d5"   't_food)
+        (list 10  "1d3"   't_torch)
+        (list 5   "1"     't_sword)
+        (list 7   "1"     't_sling)
+        (list 5   "1"     't_leather_helm)
+        (list 4   "1"     't_armor_leather)
+        (list 10  "1d3"  't_smoke_bomb)
+        ))
+(define wrogue-3-loot
+  (list (list 100 "2d6-2" 't_gold_coins)
+        (list 100 "1d3-1" 't_picklock)
+        (list 50  "1d5"   't_food)
+        (list 10  "1d3"   't_torch)
+        (list 100 "1d10"  't_arrow)
+        (list 5   "1"     't_sword)
+        (list 6   "1"     't_leather_helm)
+        (list 7   "1"     't_armor_leather)
+        (list 3   "1"   't_bow)
+        (list 5   "1d3"   't_smoke_bomb)
+        ))
+(define wrogue-4-loot
+  (list (list 100 "2d6-2" 't_gold_coins)
+        (list 100 "1d3-1" 't_picklock)
+        (list 50  "1d5"   't_food)
+        (list 50  "1d10"  't_bolt)
+        (list 10  "1"     't_in_ex_por_scroll)
+        (list 10  "1"     't_wis_quas_scroll)
+        (list 5   "1"     't_sanct_lor_scroll)
+        (list 5   "1"     't_an_tym_scroll)
+        (list 5   "1"     't_vas_rel_por_scroll)
+        (list 20  "1"     't_mana_potion)
+        (list 10  "1"     't_cure_potion)
+        (list 10  "1"     't_poison_immunity_potion)
+        (list 10  "1d3"   't_torch)
+        (list 3   "1"     't_armor_chain)
+        (list 5   "1"     't_chain_coif)
+        (list 5   "1"     't_sword)
+        (list 3   "1"     't_crossbow)
+        (list 2   "1d3"   't_smoke_bomb)
+        ))
+(define medik-loot
+  (list (list 100 "1d3"   't_heal_potion)
+        (list 100 "1d2"   't_mana_potion)
+        (list 25  "1d2"   't_cure_potion)
+        (list 25  "1d2"   't_vas_mani_scroll)
+        (list 20  "1d5"   'sulphorous_ash)
+        (list 20  "1d5"   'ginseng)
+        (list 20  "1d5"   'garlic)
+        (list 10  "1d3"   'spider_silk)
+        (list 10  "1d3"   'blood_moss)
+        (list 10  "1d3"   'black_pearl)
+        (list 5   "1d2"   'nightshade)
+        (list 5   "1d2"   'mandrake)
+        (list 5   "1"     't_chain_coif)
+        (list 7   "1"     't_staff)
+        (list 3   "1"     't_armor_chain)
+        ))
+(define troll-loot
+  (list (list 100 "1d3-1" 't_thrown_boulder)
+        (list 25  "1d3"   't_food)
+        (list 100 "2d10"  't_gold_coins)
+        ))
+(define geomancer-loot
+  (list (list 50  "1d3"   't_gem)
+        (list 50  "1d20"  't_gold_coins)
+        (list 100 "1d3-1" 't_mana_potion)
+        ))
+(define gint-loot
+  (list (list 100 "4d25"  't_gold_coins)
+        (list 100 "1d5"   't_food)
+        (list 100 "1d3-1" 't_heal_potion)
+        (list 3   "1"      't_2h_axe)
+        (list 3   "1"      't_2h_sword)
+        ))
+(define reaper-loot
+  (list (list 100 "1d5"   't_torch)
+        ))
+(define headless-loot
+  (list (list 100 "1d5-1" 't_gold_coins)
+                 (list 2 "1"     't_axe)
+        (list 2 "1"     't_shield)
+        ))
+(define dragon-loot
+  (list (list 100 "1d100+19" 't_gold_coins)
+        (list 100 "1d20"     't_food)
+        (list 100 "1d5-1"    't_gem)
+        (list 100 "1"        't_dragons_blood)
+        ;; none of this is logical, beyond 'dragons oughta have the good stuff'
+        (list 10  "1"     't_in_ex_por_scroll)
+        (list 10  "1"     't_wis_quas_scroll)
+        (list 5   "1"     't_sanct_lor_scroll)
+        (list 5   "1"     't_an_tym_scroll)
+        (list 5   "1"     't_vas_rel_por_scroll)
+        (list 20  "1"     't_mana_potion)
+        (list 10  "1"     't_cure_potion)
+        (list 20  "1d5"   'sulphorous_ash)
+        (list 20  "1d5"   'ginseng)
+        (list 20  "1d5"   'garlic)
+        (list 10  "1d3"   'spider_silk)
+        (list 10  "1d3"   'blood_moss)
+        (list 10  "1d3"   'black_pearl)
+        (list 5   "1d2"   'nightshade)
+        (list 5   "1d2"   'mandrake)
+        ))
+
+(define hydra-loot
+  (list (list 100 "1" 't_hydras_blood)
+        ))
+
+(define lich-loot
+  (cons (list 100 "1" 't_lichs_blood)
+        wizard-loot))
+
+(define zorn-loot
+  (list (list 100 "1d20+9" 't_gold_coins)
+        ))
+
+(define bomber-loot
+  (list (list 50 "1d3" 't_oil)
+        ))
+        
+(define dryad-loot
+  (list (list 100 "1d5" 't_torch)
+        ))
+        
+(define demon-loot
+  (list (list 100 "2d20" 't_gold_coins)
+        (list 5   "1"    't_flaming_sword)
+        ))
+        
+(define ghast-loot
+  (list (list 50 "1" 't_mana_potion)
+        ))
+        
+(define yellow-slime-loot
+  (list (list 50 "1" 't_royal_cape)
+        ))
+        
+(define fire-slime-loot
+  (list (list 100 "1" 't_oil)
+        ))
+        
+(define spider-loot
+  (list (list 50 "1" 'spider_silk)
+        ))
+        
+(define queen-spider-loot
+  (list (list 50 "1d3" 'spider_silk)
+        (list 25 "1" 't_poison_immunity_potion)
+        ))
+
+(define accursed-1-loot
+  (list (list 50 "1d2-1" 't_heal_potion)
+        (list 50 "1d2" 't_mana_potion)
+        (list 100 "1d10"  't_gold_coins)
+        (list 10  "1d2"   't_food)
+        (list 5  "1"     't_cure_potion)
+        (list 5  "1"     't_poison_immunity_potion)
+        (list 10  "1d3"   'sulphorous_ash)
+        (list 10  "1d3"   'ginseng)
+        (list 10  "1d3"   'garlic)
+        (list 5  "1d2"   'spider_silk)
+        (list 5  "1d2"   'blood_moss)
+        (list 5  "1d2"   'black_pearl)
+        (list 5  "1"     't_in_quas_xen_scroll)
+        (list 5  "1"     't_an_xen_ex_scroll)
+        (list 5  "1"     't_in_an_scroll)
+        (list 5  "1"     't_vas_mani_scroll)
+        )) 
+
+(define accursed-5-loot
+  (list (list 100 "1d10"    't_bolt)
+        (list 10 "1d3-1" 't_heal_potion)
+        (list 50  "1d5"   't_food)
+        (list 100 "2d10" 't_gold_coins)
+        (list 4 "1" 't_sword)
+        (list 6 "1" 't_shield)
+        (list 5 "1" 't_chain_coif)
+        (list 7 "1" 't_armor_chain)
+        (list 3 "1" 't_crossbow)
+        ))  
+        
+        
+(define (drop-generic knpc loot)
+  (if (not (kern-place-is-wilderness? (loc-place (kern-obj-get-location knpc))))
+           (let ((loc (kern-obj-get-location knpc)))
+             (map (lambda (triple)
+                    (println triple)
+                    (let ((thresh (car triple))
+                          (dice (cadr triple))
+                          (type-tag (caddr triple)))
+                      (if (< (modulo (random-next) 100) thresh)
+                          (let ((quantity (kern-dice-roll dice)))
+                            (if (> quantity 0)
+                                       (let ((obj (kern-mk-obj (eval type-tag) quantity)))
+                                               (if (can-be-dropped? obj loc cant)
+                                                       (kern-obj-put-at obj loc)
+                                               )))))))
+                  loot)
+             )))
+  
+;; npc types
+;;      scheme variable                 name                       species          occup.     sprite             chest traps  equipment              effects       ai               faction
+;;      ======================          ========================== ================ ========== ================== ============ ====================== ============= ==============   ========
+(define forest-goblin-shaman  (mk-npct2 "forest goblin shaman"  sp_forest_goblin oc_wizard  s_fgob_shaman wizard-traps wizard-equip  nil 'shaman-ai  faction-forest-goblin nil 'drop-generic wizard-loot ))
+(define forest-goblin-hunter  (mk-npct2 "forest goblin hunter"  sp_forest_goblin oc_warrior s_fgob_archer  basic-traps  archer-equip  nil 'generic-ai faction-forest-goblin nil 'drop-generic archer-loot ))
+(define forest-goblin-stalker (mk-npct2 "forest goblin stalker" sp_forest_goblin oc_warrior s_fgob_stalker  basic-traps  stalker-equip nil 'generic-ai faction-forest-goblin nil 'drop-generic stalker-loot))
+
+(define cave-goblin-slinger   (mk-npct2 "cave goblin slinger"   sp_cave_goblin  oc_warrior s_cgob_slinger    basic-traps  slinger-equip    nil 'generic-ai faction-cave-goblin  nil 'drop-generic slinger-loot))
+(define cave-goblin-berserker (mk-npct2 "cave goblin berserker" sp_cave_goblin  oc_warrior s_cgob_berserk    basic-traps  berserker-equip  nil 'generic-ai faction-cave-goblin  nil 'drop-generic berserker-loot))
+(define cave-goblin-priest    (mk-npct2 "cave goblin priest"    sp_cave_goblin  oc_wizard  s_cgob_shaman    wizard-traps wizard-equip     nil 'priest-ai  faction-cave-goblin  nil 'drop-generic wizard-loot))
+
+(define ranger                (mk-npct2 "ranger"                sp_human        oc_ranger s_ranger basic-traps  ranger-equip     nil 'ranger-ai  faction-men  'ranger-conv 'drop-generic ranger-loot))
+
+(define skeletal-spear-thrower (mk-npct2 "skeletal spear-thrower" sp_skeleton oc_warrior s_spearskeleton basic-traps spear-thrower-equip    undead-effects 'nolight-ai faction-monster nil 'drop-generic spear-thrower-loot))
+(define skeletal-warrior (mk-npct2 "skeletal warrior" sp_skeleton oc_warrior s_skeleton basic-traps skeletal-warrior-equip undead-effects 'nolight-ai faction-monster nil 'drop-generic skel-war-loot))
+(define skeletal-archer (mk-npct2 "skeletal archer" sp_skeleton oc_warrior s_skeletonarcher basic-traps archer-equip undead-effects 'nolight-ai faction-monster nil 'drop-generic archer-loot))
+
+(define death-knight  (mk-npct2 "death knight"  sp_skeleton oc_warrior s_deathknight   basic-traps death-knight-equip  undead-effects 'death-knight-ai faction-monster  nil 'drop-generic dea-kni-loot))
+(define craven-archer (mk-npct2 "craven archer" sp_skeleton oc_warrior s_deatharcher   basic-traps craven-archer-equip nil            'craven-archer-ai faction-monster nil 'drop-generic cra-arch-loot))
+
+(define halberdier    (mk-npct2 "halberdier"    sp_human    oc_warrior s_guard        no-traps halberdier-equip   nil 'guard-ai faction-men   nil 'drop-generic halberdier-loot))
+(define crossbowman   (mk-npct2 "crossbowman"   sp_human    oc_warrior s_xbowguard        no-traps crossbowman-equip  nil 'guard-ai faction-men   nil 'drop-generic crossbowman-loot))
+(define medik         (mk-npct2 "medik"         sp_human    oc_wizard  s_blue_wizard  no-traps medik-equip        nil 'medik-ai faction-men   nil 'drop-generic medik-loot))
+(define troll         (mk-npct2 "troll"         sp_troll    oc_warrior s_troll        no-traps troll-equip        nil 'std-ai   faction-troll nil 'drop-generic troll-loot))
+(define glasdrin-halberdier    (mk-npct2 "halberdier"    sp_human    oc_warrior s_guard        no-traps halberdier-equip   nil 'guard-ai faction-glasdrin   nil 'drop-generic halberdier-loot))
+(define glasdrin-crossbowman   (mk-npct2 "crossbowman"   sp_human    oc_warrior s_xbowguard        no-traps crossbowman-equip  nil 'guard-ai faction-glasdrin   nil 'drop-generic crossbowman-loot))
+
+;; Bandit types
+(define footpad    (mk-npct2 "footpad"    sp_human oc_wrogue s_brigand wrogue-traps wrogue-1-equip nil 'std-ai faction-outlaw nil 'drop-generic wrogue-1-loot))
+(define bandit     (mk-npct2 "bandit"     sp_human oc_wrogue s_brigand wrogue-traps wrogue-2-equip nil 'std-ai faction-outlaw nil 'drop-generic wrogue-2-loot))
+(define highwayman (mk-npct2 "highwayman" sp_human oc_wrogue s_brigand wrogue-traps wrogue-3-equip nil 'std-ai faction-outlaw nil 'drop-generic wrogue-3-loot))
+(define blackguard (mk-npct2 "blackguard" sp_human oc_wrogue s_brigand wrogue-traps wrogue-4-equip nil 'std-ai faction-outlaw nil 'drop-generic wrogue-4-loot))
+(define bomber     (mk-npct2 "mad jester" sp_human oc_wrogue s_jester  wrogue-traps bomber-equip   nil 'std-ai faction-outlaw nil 'drop-generic bomber-loot))
+
+(define bat (mk-npct2 "bat" sp_bat nil s_bat nil nil nil 'animal-ai faction-monster nil 'drop-generic animal-loot))
+(define rat (mk-npct2 "dire rat" sp_rat nil s_rat nil nil nil 'rat-ai faction-monster nil 'drop-generic animal-loot))
+(define zorn (mk-npct2 "zorn" sp_zorn oc_wrogue s_zorn wrogue-traps nil nil 'animal-ai faction-monster nil 'drop-generic zorn-loot))
+(define bull (mk-npct "bull" sp_bull nil s_bull nil nil nil 'animal-ai faction-none nil 'drop-generic bull-loot))
+(define lich (mk-npct2 "lich" sp_lich oc_wizard s_lich wizard-traps wizard-equip undead-effects 'spell-sword-ai faction-monster nil 'drop-generic lich-loot))
+(define dryad (mk-npct2 "dryad" sp_dryad nil s_reaper nil nil nil 'dryad-ai faction-monster nil 'drop-generic dryad-loot))
+(define gazer (mk-npct2 "gazer" sp_gazer oc_wizard s_gazer wizard-traps nil nil 'gazer-ai faction-monster nil 'drop-generic wizard-loot))
+(define demon (mk-npct2 "demon" sp_demon nil s_demon basic-traps demon-equip demon-effects 'demon-ai faction-monster nil 'drop-generic demon-loot))
+(define ghast (mk-npct2 "ghast" sp_ghast nil s_ghost nil nil undead-effects 'std-ai faction-monster nil 'drop-generic ghast-loot))
+(define snake (mk-npct "snake" sp_snake nil s_snake nil nil nil 'snake-ai faction-monster nil 'drop-generic animal-loot))
+(define insect (mk-npct "insect swarm" sp_insect nil s_insects nil nil nil 'animal-ai faction-monster nil 'drop-generic animal-loot))
+(define dragon (mk-npct2 "dragon" sp_dragon nil s_dragon wizard-traps nil drag-effects 'dragon-ai faction-monster nil 'drop-generic dragon-loot))
+(define knight (mk-npct2 "knight" sp_human oc_warrior s_knight no-traps knight-equip nil 'guard-ai faction-trigrave 'knight-conv 'drop-generic knight-loot))
+(define paladin (mk-npct2 "paladin" sp_human oc_warrior s_companion_paladin no-traps knight-equip nil 'std-ai faction-men 'knight-conv 'drop-generic knight-loot))
+(define tinker (mk-npct2 "tinker" sp_human oc_warrior s_companion_tinker no-traps wrogue-4-equip nil 'std-ai faction-men nil 'drop-generic wrogue-4-loot))
+(define squire (mk-npct2 "squire" sp_human oc_warrior s_xbowguard no-traps squire-equip nil 'guard-ai faction-trigrave 'knight-conv 'drop-generic squire-loot))
+(define warlock (mk-npct2 "warlock" sp_human oc_wizard s_wizard wizard-traps wizard-equip nil 'warlock-ai faction-monster nil 'drop-generic wizard-loot))
+(define wizard (mk-npct2 "wizard" sp_human oc_wizard s_companion_wizard wizard-traps wizard-equip nil 'spell-sword-ai faction-men nil 'drop-generic wizard-loot))
+(define headless (mk-npct2 "headless" sp_headless oc_warrior s_headless basic-traps headless-equip nil 'animal-ai faction-monster nil 'drop-generic headless-loot))
+(define gint-mage (mk-npct2 "gint mage" sp_gint oc_wizard s_gint_mage wizard-traps wizard-equip nil 'shaman-ai faction-gint nil 'drop-generic wizard-loot))
+(define gint-warrior (mk-npct2 "gint warrior" sp_gint oc_warrior s_gint basic-traps gint-warrior-equip nil 'std-ai faction-gint nil 'drop-generic gint-loot))
+(define yellow-slime (mk-npct2 "yellow slime" sp_yellow_slime nil s_yellow_slime nil nil yellow-slime-effects 'yellow-slime-ai faction-monster nil 'drop-generic yellow-slime-loot))
+(define troll-geomancer (mk-npct2 "troll geomancer" sp_troll oc_wizard s_troll_geomancer no-traps geomancer-equip nil 'geomancer-ai faction-troll nil 'drop-generic geomancer-loot))
+(define corrupt-halberdier (mk-npct2 "halberdier" sp_human oc_warrior s_guard no-traps halberdier-equip nil 'guard-ai faction-monster nil 'drop-generic halberdier-loot))
+(define corrupt-crossbowman (mk-npct2 "crossbowman" sp_human oc_warrior s_guard no-traps crossbowman-equip nil 'guard-ai faction-monster nil 'drop-generic crossbowman-loot))
+(define giant-spider (mk-npct2 "giant spider" sp_spider nil s_spider nil nil nil 'spider-ai faction-monster nil 'drop-generic spider-loot))
+(define queen-spider (mk-npct2 "queen spider" sp_queen_spider nil s_queen_spider nil nil nil 'spider-ai faction-monster nil 'drop-generic queen-spider-loot))
+(define fire-slime (mk-npct2 "fire slime" sp_fire_slime nil s_red_slime nil nil fire-slime-effects 'animal-ai faction-monster nil 'drop-generic fire-slime-loot))
+(define hydra (mk-npct2 "hydra" sp_hydra nil s_hydra no-traps nil hydra-effects 'hydra-ai faction-monster nil 'drop-generic hydra-loot))
+(define mimic (mk-npct2 "mimic" sp_mimic nil s_mimic no-traps nil nil 'animal-ai faction-monster nil 'drop-generic zorn-loot))
+(define ratling-swarmer (mk-npct2 "ratling swarmer" sp_ratling nil s_mouse no-traps nil nil 'ratling-ai faction-monster nil 'drop-generic animal-loot))
+(define ratling-sorcerer (mk-npct2 "ratling sorcerer"  sp_ratling oc_wizard s_ratling_sorcerer wizard-traps wizard-equip  nil 'ratling-sorcerer-ai faction-monster nil 'drop-generic animal-loot))
+(define carabid (mk-npct2 "carabid" sp_carabid nil s_carabid nil nil nil 'carabid-ai faction-monster nil 'drop-generic animal-loot))
+(define deer (mk-npct2 "deer" sp_deer nil s_deer nil nil nil nil faction-none nil 'drop-generic deer-loot))
+(define chicken (mk-npct2 "chicken" sp_chicken nil s_chicken nil nil nil 'animal-ai faction-none nil 'drop-generic animal-loot))
+
+;; NPC's with no drops
+
+(define green-slime     (mk-npct "green slime"            sp_green_slime   nil        s_slime        nil          nil           slime-effects 'animal-ai       faction-monster       nil))
+(define kraken          (mk-npct "kraken"                 sp_kraken        nil        s_kraken       nil          nil           nil           'kraken-ai       faction-monster       nil))
+(define sea-serpent     (mk-npct "sea serpent"            sp_sea_serpent   nil        s_sea_serpent  nil          nil           nil           'sea-serpent-ai  faction-monster       nil))
+(define wolf            (mk-npct "wolf"                   sp_wolf          nil        s_wolf         nil          nil           nil           'wolf-ai       faction-monster       nil))
+(define wisp            (mk-npct "wisp"                   sp_wisp          nil        s_wisp         nil          nil           wisp-effects  'wisp-ai         faction-monster       nil))
+(define nixie-spearman  (mk-npct "nixie spearman"         sp_nixie         oc_warrior s_nixie_spear  no-traps     nixie-1-equip nil           'nixie-ai        faction-monster       nil))
+(define nixie-swordsman (mk-npct "nixie swordsman"        sp_nixie         oc_warrior s_nixie_sword  no-traps     nixie-2-equip nil           'nixie-ai        faction-monster       nil))
+(define sludge-kraken   (mk-npct "sludge kraken"          sp_great_kraken  nil        s_great_kraken nil          nil           sludge-kraken-effects 'sludge-kraken-ai faction-monster nil))
+(define sludge-tentacle (mk-npct "sludge kraken tentacle" sp_kraken_tentacle nil      s_tentacle     nil          nil           nil           'sludge-tentacle-ai faction-monster    nil))
+(define griffin         (mk-npct "griffin"                sp_griffin       nil        s_griffin      nil          nil           nil           'griffin-ai      faction-monster       nil))
+(define griffin-chick   (mk-npct "griffin chick"          sp_griffin_chick nil        s_griffin_chick nil         nil           nil           'griffin-ai      faction-monster       nil))
+
+;; accursed
+(define accursed-acolyte    (mk-npct2 "an accursed acolyte"    sp_human oc_wizard s_shepherd nil accursed-1-equip nil 'spell-sword-ai faction-accursed nil 'drop-generic accursed-1-loot))
+(define accursed-apprentice (mk-npct2 "an accursed apprentice" sp_human oc_wizard s_shepherd nil accursed-2-equip nil 'spell-sword-ai faction-accursed nil 'drop-generic accursed-1-loot))
+(define accursed-journeyman (mk-npct2 "an accursed journeyman" sp_human oc_wizard s_wizard   nil accursed-3-equip nil 'spell-sword-ai faction-accursed nil 'drop-generic wizard-loot))
+(define accursed-master     (mk-npct2 "an accursed master"     sp_human oc_wizard s_wizard   nil accursed-3-equip nil 'spell-sword-ai faction-accursed nil 'drop-generic wizard-loot))
+(define accursed-adept      (mk-npct2 "an accursed adept"      sp_human oc_wizard s_wizard   nil accursed-3-equip nil 'spell-sword-ai faction-accursed nil 'drop-generic wizard-loot))
+(define accursed-guardian   (mk-npct2 "an accursed guardian"   sp_human oc_warrior s_fighter nil accursed-4-equip nil 'std-ai         faction-accursed nil 'drop-generic wrogue-1-loot))
+(define accursed-defender   (mk-npct2 "an accursed defender"   sp_human oc_warrior s_knight  nil accursed-5-equip nil 'std-ai         faction-accursed nil 'drop-generic accursed-5-loot))
+(define accursed-templar    (mk-npct2 "an accursed templar"    sp_human oc_warrior s_avatar  nil accursed-6-equip nil 'std-ai         faction-accursed nil 'drop-generic wrogue-4-loot))
+
+;; npcs with odd alignments
+(define gint-warrior-m (mk-npct2 "gint warrior" sp_gint oc_warrior s_gint basic-traps gint-warrior-equip nil 'std-ai faction-monster nil 'drop-generic gint-loot))
+(define troll-m         (mk-npct2 "troll"         sp_troll    oc_warrior s_troll        no-traps troll-equip        nil 'std-ai   faction-monster nil 'drop-generic troll-loot))
+(define cave-goblin-slinger-m   (mk-npct2 "cave goblin slinger"   sp_cave_goblin  oc_warrior s_cgob_slinger    basic-traps  slinger-equip    nil 'generic-ai faction-monster  nil 'drop-generic slinger-loot))
+(define cave-goblin-berserker-m (mk-npct2 "cave goblin berserker" sp_cave_goblin  oc_warrior s_cgob_berserk    basic-traps  berserker-equip  nil 'generic-ai faction-monster  nil 'drop-generic berserker-loot))
+(define gint-mage-m (mk-npct2 "gint mage" sp_gint oc_wizard s_gint_mage wizard-traps wizard-equip nil 'shaman-ai faction-monster nil 'drop-generic wizard-loot))
+(define troll-geomancer-m (mk-npct2 "troll geomancer" sp_troll oc_wizard s_troll_geomancer no-traps geomancer-equip nil 'std-ai faction-monster nil 'drop-generic geomancer-loot))
+
+
+;;define                        (mk-npct "                          sp_              oc_        s_                 nil          nil                    nil           'std-ai           ))
+
+;;----------------------------------------------------------------------------
+;; Type queries
+;;----------------------------------------------------------------------------
+(define (is-species? kchar species)
+  (eqv? (kern-char-get-species kchar) species))
+
+(define (is-occ? kchar occ)
+  (eqv? (kern-char-get-occ kchar) occ))
+
+(define (is-yellow-slime? kchar)
+  (is-species? kchar sp_yellow_slime))
+
+(define (is-green-slime? kchar)
+  (is-species? kchar sp_green_slime))
+
+(define (is-spider? kchar)
+  (or (is-species? kchar sp_spider)
+      (is-species? kchar sp_queen_spider)))
+
+(define (is-troll? kchar)
+  (is-species? kchar sp_troll))
+
+(define (is-goblin? kchar)
+  (or (is-species? kchar sp_cave_goblin)
+      (is-species? kchar sp_forest_goblin)))
+
+(define (is-skeleton? kchar)
+  (is-species? kchar sp_skeleton))
+
+(define (is-death-knight? kchar)
+  (and (is-species? kchar sp_skeleton)
+       (is-occ? kchar oc_warrior)))
+
+(define (is-bandit? kchar)
+  (is-occ? kchar oc_wrogue))
+
+(define (is-halberdier? kchar)
+  (is-guard-type? kchar 'halberdier))
+
+(define (is-crossbowman? kchar)
+  (is-guard-type? kchar 'crossbowman))
+
+(define (is-gint? kchar)
+  (is-species? kchar sp_gint))
+
+(define (is-forest-goblin-shaman? kchar)
+  (and (is-species? kchar sp_forest_goblin)
+       (is-occ? kchar oc_wizard)))
+
+(define (is-forest-goblin-hunter? kchar)
+  (and (is-species? kchar sp_forest_goblin)
+       (is-occ? kchar oc_warrior)))
+
+;; fixme -- same as forest-goblin-hunter above
+(define (is-forest-goblin-stalker? kchar)
+  (and (is-species? kchar sp_forest_goblin)
+       (is-occ? kchar oc_warrior)))
+
+(define (is-skeletal-warrior? kchar)
+  (let ((gob (kobj-gob-data kchar)))
+    (and (not (null? gob))
+         (eq? (car gob)
+              'skeletal-warrior))))
+
+(define (post-guard kguard x y)
+  (npcg-set-post! (gob kguard) (list x y))
+  kguard)
+
+(define (mk-bull)
+  (mk-npc 'bull 8))
+
+(define (is-undead? kchar)
+  (or (is-species? kchar sp_skeleton)
+      (is-species? kchar sp_lich)))
+      
+(define (is-snake? kchar)
+  (is-species? kchar sp_snake))
+
+(define (is-rat? kchar)
+  (or (is-species? kchar sp_rat)
+      (is-species? kchar sp_ratling)))
+
+(define (is-sludge-tentacle? kchar)
+  (kbeing-is-npc-type? kchar 'sludge-tentacle))
+
+(define (can-fly? kobj)
+  (eqv? (kern-obj-get-movecost kobj pclass-canfly) norm))
+
+(define (can-phase? kobj)
+  (eqv? (kern-obj-get-mmode kobj)
+        mmode-phase))
+
+(define (is-abstract? kobj)
+  (null? (kern-obj-get-name kobj)))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/objs.scm b/worlds/haxima-1.002/objs.scm
new file mode 100644 (file)
index 0000000..fb9431a
--- /dev/null
@@ -0,0 +1,8 @@
+;; ----------------------------------------------------------------------------
+;; objs.scm -- basic object types and hooks
+;;----------------------------------------------------------------------------
+
+;; Make the basic object interface which supports g)et
+(define obj-ifc
+  (ifc '()
+       (method 'get kobj-get)))
diff --git a/worlds/haxima-1.002/occs.scm b/worlds/haxima-1.002/occs.scm
new file mode 100644 (file)
index 0000000..7b48595
--- /dev/null
@@ -0,0 +1,361 @@
+;;----------------------------------------------------------------------------
+;; occupations
+
+;; Occupation gob fields (these are all procedures for evaluating a kchar's
+;; ability at something):
+;;
+;; 0 thief
+;; 1 white magic
+;; 2 black magic
+;; 3 magic defense
+;; 4 strength-based attack
+;; 5 dexterity-based attack
+;; 6 dexterity-based defense
+;; 7 crafting
+
+(define (mk-occ tag name hit def dam arm xp skset)
+  (kern-mk-occ tag name 1.0 0 0 0 0 hit def dam arm xp skset)
+  (kern-occ-set-gob (eval tag) (list nil nil nil nil nil nil nil nil)))
+
+;;            /           /         / t  / f / e /   /
+;;           /           /         / i  / e / g / r /
+;;          /           / e       / h  / d / a / o /
+;;         / g         / m       / -  / - / m / m /
+;;        / a         / a       / o  / o / a / r / p
+;;       / t         / n       / t  / t / d / a / x
+(mk-occ 'oc_wizard   "wizard"   -1  -1  -1  -1   4 nil)
+(mk-occ 'oc_warrior  "warrior"   1   0   1   0   4 sks_warrior)
+(mk-occ 'oc_wright   "wright"    0   1   0   1   4 sks_wright)
+(mk-occ 'oc_wrogue   "wrogue"    1   1   0   0   4 sks_wrogue)
+(mk-occ 'oc_wanderer "wanderer"  5   5   5   5   8 sks_wanderer)
+(mk-occ 'oc_ranger   "ranger"    1   1   0   0   4 sks_ranger)
+
+(define (occ-get-abil kocc ability)
+       (if (null? kocc)
+               nil
+               (list-ref (kern-occ-get-gob kocc) ability)))
+               
+(define (occ-set-abil kocc ability calc)
+       (set-car! 
+               (list-tail 
+                       (kern-occ-get-gob kocc) 
+                       ability)
+               calc))
+
+;---------------------------------
+;Thiefliness
+
+(define (occ-ability-thief kchar)
+  (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 0)))
+    (if (null? occ-abil)
+        (floor 
+         (/ (+ (kern-char-get-level kchar) 
+               (kern-char-get-dexterity kchar)) 4))
+        (occ-abil kchar)
+        )))
+
+
+(occ-set-abil oc_wrogue 0
+              (lambda (kchar)
+               (floor 
+                 (+ (kern-char-get-level kchar)
+                    (/ (kern-char-get-dexterity kchar) 3)))
+                ))
+
+(let ((partskill
+       (lambda (kchar)
+         (floor 
+          (+ (/ (kern-char-get-level kchar) 2)
+             (/ (kern-char-get-dexterity kchar) 4)
+             )))))
+  (occ-set-abil oc_wright 0 partskill)
+  (occ-set-abil oc_ranger 0 partskill)
+  (occ-set-abil oc_wanderer 0 partskill)
+  )
+
+(define (occ-thief-dice-roll kchar)
+  (kern-dice-roll (string-append "1d" 
+                                 (number->string (occ-ability-thief kchar)))))
+
+;-----------------------------
+;Magic output
+
+(define (occ-ability-whitemagic kchar)
+       (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 1)))
+               (if (null? occ-abil)
+                       (floor 
+                               (+ (/ (kern-char-get-level kchar) 3)
+                                       (/ (kern-char-get-intelligence kchar) 3)))
+                       (occ-abil kchar)
+                       )))
+                       
+(define (occ-ability-blackmagic kchar)
+       (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 2)))
+               (if (null? occ-abil)
+                       (floor 
+                               (/ (+ (kern-char-get-level kchar) 
+                                       (kern-char-get-intelligence kchar)) 4))
+                       (occ-abil kchar)
+                       )))
+                       
+(let (
+       (highskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (kern-char-get-level kchar)
+                                       (/ (kern-char-get-intelligence kchar) 2))
+                       )))
+       (modskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (* (kern-char-get-level kchar) 0.75)
+                                       (/ (kern-char-get-intelligence kchar) 3))
+                       )))
+       (someskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (/ (kern-char-get-level kchar) 3)
+                                       (/ (kern-char-get-intelligence kchar) 3))
+                       )))     
+       (poorskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (/ (kern-char-get-level kchar) 4)
+                                       (/ (kern-char-get-intelligence kchar) 4))
+                       )))
+       (noskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (/ (kern-char-get-level kchar) 6)
+                                       (/ (kern-char-get-intelligence kchar) 4))
+                       )))
+       )
+       (occ-set-abil oc_wizard 1 highskill)
+       (occ-set-abil oc_wizard 2 highskill)
+       (occ-set-abil oc_wanderer 1 modskill)
+       (occ-set-abil oc_wanderer 2 modskill)
+       (occ-set-abil oc_warrior 1 poorskill)
+       (occ-set-abil oc_warrior 2 noskill)
+       (occ-set-abil oc_ranger 2 someskill)
+)
+
+;-----------------------------
+; Magic defense
+
+(define (occ-ability-magicdef kchar)
+       (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 3)))
+               (if (null? occ-abil)
+                       (floor 
+                               (+ (/ (kern-char-get-level kchar) 3)
+                                       (/ (kern-char-get-intelligence kchar) 2)))
+                       (occ-abil kchar)
+                       )))
+                       
+(let (
+       (highskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (/ (kern-char-get-level kchar) 2)
+                                       (/ (kern-char-get-intelligence kchar) 2))
+                       )))
+       (modskill
+               (lambda (kchar)
+                       (floor 
+                               (+ (* (kern-char-get-level kchar) 0.4)
+                                       (/ (kern-char-get-intelligence kchar) 2))
+                       )))
+       )
+       (occ-set-abil oc_wizard 3 highskill)
+       (occ-set-abil oc_wanderer 3 modskill)
+)
+
+;----------------------------
+; Combat
+
+(define (occ-ability-strattack kchar)
+       (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 4)))
+                (if (null? occ-abil)
+                     (floor (/ (* (kern-char-get-level kchar)
+                                  (+ (kern-char-get-strength kchar) 15))
+                               30))
+                     (occ-abil kchar)
+                     )))
+
+(let (
+       (highskill
+               (lambda (kchar)
+                  (floor (/ (* (kern-char-get-level kchar)
+                               (+ (kern-char-get-strength kchar) 10))
+                            20))
+                         ))
+       (modskill
+               (lambda (kchar)
+                  (floor (/ (* (kern-char-get-level kchar)
+                               (+ (kern-char-get-strength kchar) 12))
+                            24))
+                       ))
+       (lowskill
+               (lambda (kchar) 
+                  (floor (/ (* (kern-char-get-level kchar)
+                               (+ (kern-char-get-strength kchar) 10))
+                             30))
+                         ))
+       )
+       (occ-set-abil oc_wizard 4 lowskill)
+       (occ-set-abil oc_wright 4 modskill)
+       (occ-set-abil oc_wanderer 4 modskill)
+       (occ-set-abil oc_warrior 4 highskill)
+       (occ-set-abil oc_ranger 4 modskill)
+)
+
+
+(define (occ-ability-dexattack kchar)
+  (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 5)))
+    (if (null? occ-abil)
+        (floor (/ (* (kern-char-get-level kchar)
+                     (+ (kern-char-get-dexterity kchar) 15))
+                  30))
+        (occ-abil kchar)
+        )))
+
+(let (
+      (highskill
+       (lambda (kchar)
+         (floor (/ (* (kern-char-get-level kchar)
+                      (+ (kern-char-get-dexterity kchar) 10))
+                   20))
+         ))
+      (modskill
+       (lambda (kchar)
+         (floor (/ (* (kern-char-get-level kchar)
+                      (+ (kern-char-get-dexterity kchar) 12))
+                   24))
+         ))
+      (lowskill
+       (lambda (kchar) 
+           (floor (/ (* (kern-char-get-level kchar)
+                        (+ (kern-char-get-dexterity kchar) 10))
+                     30))
+           ))
+      )
+  (occ-set-abil oc_wizard 5 lowskill)
+  (occ-set-abil oc_wrogue 5 modskill)
+  (occ-set-abil oc_wanderer 5 modskill)
+  (occ-set-abil oc_warrior 5 highskill)
+  (occ-set-abil oc_ranger 5 modskill)
+)
+
+(define (occ-ability-strdamage kchar)
+  (floor (* 2 (-  (log (+ 2 (occ-ability-strattack kchar)))))))
+
+(define (occ-ability-dexdefend kchar)
+  (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 6)))
+    (if (null? occ-abil)
+        (floor (+ (/ (kern-char-get-level kchar) 2)
+                  (/ (kern-char-get-dexterity kchar) 3)))
+               (occ-abil kchar)
+               )))
+
+(let (
+       (highskill
+         (lambda (kchar)
+           (floor (+ (* (kern-char-get-level kchar) 0.8)
+                     (/ (kern-char-get-dexterity kchar) 2)))
+           ))
+       (modskill
+         (lambda (kchar)
+           (floor (+ (* (kern-char-get-level kchar) 0.6)
+                     (* (kern-char-get-dexterity kchar) 0.4)))
+           ))
+       (lowskill
+         (lambda (kchar) 
+           (floor (+ (/ (kern-char-get-level kchar) 3)
+                     (/ (kern-char-get-dexterity kchar) 4)))
+                  ))
+       )
+       (occ-set-abil oc_wizard 6 lowskill)
+       (occ-set-abil oc_wrogue 6 highskill)
+       (occ-set-abil oc_wanderer 6 modskill)
+       (occ-set-abil oc_warrior 6 modskill)
+       (occ-set-abil oc_ranger 6 highskill)
+)
+
+(define (proc-stratt kchar)
+       (* 1000 (occ-ability-strattack kchar)))
+
+(define (proc-dexatt kchar)
+       (* 1000 (occ-ability-dexattack kchar)))
+
+(define (proc-strdam kchar)
+       (* 1000 (occ-ability-strdamage kchar)))
+
+(define (proc-dexdef kchar)
+       (* 1000 (occ-ability-dexdefend kchar)))
+
+;----------------------------
+; Crafting
+
+;; Note: I'm not sure this is really how we want to handle wright skills, but
+;; it serves as a starting point. For one thing, we probably need to break the
+;; skills up into different abilities. Eg, a wizard might not be able to skin a
+;; deer as well as a ranger, but he can do a better job of whittling a magic
+;; wand. Also, I just used all the core attributes and divided them
+;; evenly. Different types of wright skills might emphasize dexterity over
+;; intelligence, or vice versa, and etc.
+
+(define (occ-ability-crafting kchar)
+  (let ((occ-abil (occ-get-abil (kern-char-get-occ kchar) 7)))
+    (if (null? occ-abil)
+        (floor (/ (* (kern-char-get-level kchar)
+                     (+ (/ (kern-char-get-dexterity kchar) 3)
+                        (/ (kern-char-get-strength kchar) 3)
+                        (/ (kern-char-get-intelligence kchar) 3)
+                        15))
+                  30))
+        (occ-abil kchar)
+        )))
+
+(let (
+      (highskill
+       (lambda (kchar)
+         (floor (/ (* (kern-char-get-level kchar)
+                      (+ (/ (kern-char-get-dexterity kchar) 3)
+                         (/ (kern-char-get-strength kchar) 3)
+                         (/ (kern-char-get-intelligence kchar) 3)
+                         10))
+                   20))
+         ))
+      (modskill
+       (lambda (kchar)
+         (floor (/ (* (kern-char-get-level kchar)
+                      (+ (/ (kern-char-get-dexterity kchar) 3)
+                         (/ (kern-char-get-strength kchar) 3)
+                         (/ (kern-char-get-intelligence kchar) 3)
+                         12))
+                   24))
+         ))
+      (lowskill
+       (lambda (kchar) 
+           (floor (/ (* (kern-char-get-level kchar)
+                        (+ (/ (kern-char-get-dexterity kchar) 3)
+                           (/ (kern-char-get-strength kchar) 3)
+                           (/ (kern-char-get-intelligence kchar) 3)
+                           10))
+                     30))
+           ))
+      )
+  (occ-set-abil oc_wizard 7 lowskill)
+  (occ-set-abil oc_wrogue 7 highskill)
+  (occ-set-abil oc_wanderer 7 modskill)
+  (occ-set-abil oc_warrior 7 lowskill)
+  (occ-set-abil oc_ranger 7 modskill)
+)
+
+;----------------------------
+; Acrobatics
+
+;; These are for physical feats like sprinting and wriggling through
+;; bars. Piggyback on some of the other abilities for now.
+
+(define (occ-ability-stracro kchar) (occ-ability-strattack kchar))
+(define (occ-ability-dexacro kchar) (occ-ability-dexdef kchar))
diff --git a/worlds/haxima-1.002/old-absalot.scm b/worlds/haxima-1.002/old-absalot.scm
new file mode 100644 (file)
index 0000000..d3162c7
--- /dev/null
@@ -0,0 +1,144 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+
+(kern-mk-map
+ 'm_old_absalot 31 31 pal_expanded
+ (list
+               "rn rn rn rn rn rn rn rn rn xx xx xx xx xx xx rn rn rn rn rn rn r8 r8 r8 rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn xx xx ,T ,E ,M ,P ,L ,E xx xx rn rn rr ,, ,, ,, r2 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rr xx !! cc cc cc cc cc cc !! xx xx rn rr ,, ,, ,, r2 rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rr rr !! !! cc aa cc cc aa cc !! !! xx xx rr ,, ,, ,, r2 rn rn rn rn rn rn "
+               "rn rn rn rn r8 rn xx !! !! !! cc cc cc cc cc cc !! !! !! xx rr ,, ,, ,, r2 rn rn rn rn rn rn "
+               "rn rn rn r4 ,, r2 xx ,, ,, pp ,, ,, ,, ,, ,, ,, pp ,, ,, xx rr ,, ,, ,, r2 rn rn rn rn rn rn "
+               "rn rn rn rc ,, xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr rr ,, rr rr rr rn rn rn rn rn rn "
+               "rn rn r4 ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb rr ,, rr ,M ,E ,A ,T rn rn rn rn "
+               "rn rn r4 ,, ,, ,, ,, ,, ,, pp ,, ,, ,, ,, ,, ,, pp ,, ,, ,, ,, ,, rr ,, ,, ,, ,, r2 rn rn rn "
+               "rn rn xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr ,, ,, ,, ,, r2 rn rn rn "
+               "xx xx xx r1 xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rn r4 ,, ,, ,, ,, ,, ,, r2 rn rn rn "
+               "rn ,S ,L ,A ,V ,E ,S xx rr xx ,, pp ,, ,, pp ,, r3 xx xx rn r4 ,, xx xx xx xx xx xx xx xx xx "
+               "xx ,, ,, ,, ,, ,, ,, xx rn xx ,, ,, ,, ,, ,, ,, xx rn rn rn r4 ,, xx ,F ,L ,E ,S ,H ,L ,Y xx "
+               "xx ,, ,, ,, ,, ,, ,, xx rn xx ,, ,, ,, ,, ,, ,, xx rn rn rn r4 ,, re ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, ,, xx rn xx ,, pp ,, ,, pp ,, xx rn rn rn r4 ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx xx rd ,, ,, xx xx xx rn xx ,, ,, ,, ,, ,, ,, xx rn rn rn rn r1 xx ,, ,, ,, aa ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, ,, rr rn xx xx xx ,, ,, xx xx xx rn rn rn rn rn xx ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx xx xx ,, ,, xx rr rr rn rn rn xx ,, ,, rr rn rn rn rn xx xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, ,, xx rn rn rn xx ,, ,, xx rn rn rn xx ,, ,, ,, xx ,, ,, [[ @@ ]] ,, ,, xx "
+               "xx xx xx ,, ,, xx xx xx xx xx xx rr ,, ,, xx xx rr xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx ,F ,E ,A ,S ,T xx xx "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx rr xx xx xx xx rr rr xx "
+               "xx xx xx ,, xx xx xx xx xx xx ,, ,, ,, xx xx ,, ,, ,, xx xx xx xx xx xx rr cc cc cc cc cc r2 "
+               "xx xx xx ,, xx xx xx xx rn xx ,, ,, ,, xx xx ,, ,, ,, xx ,B ,L ,O ,O ,D xx cc cc ~~ ~~ cc r2 "
+               "xx ,, xx ,, xx xx xx xx rr xx ,, ,, ,, rr xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, cc ~~ ~~ ~~ cc r2 "
+               "xx xx xx ,, xx xx xx xx rr ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, cc ~~ aa cc cc r2 "
+               "xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, cc ~~ ~~ ~~ cc xx "
+               "xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx xx rr rr xx ,B ,A ,T ,H ,S xx cc cc ~~ ~~ cc xx "
+               "xx ,, ,, ,, ,, ,, xx xx xx xx ,, ,, ,, xx rr rn rn rn xx xx xx xx xx xx xx cc cc cc cc cc xx "
+               "xx xx xx r1 r1 r1 xx xx rn rn xx xx xx xx rn rn rn rn rn rn rn rn rn rn rr xx xx xx xx xx xx "
+))
+
+;;----------------------------------------------------------------------------
+;; NPC's
+;;----------------------------------------------------------------------------
+(kern-load "silas.scm")
+(kern-load "dennis.scm")
+(kern-load "selene.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_old_absalot     ; tag
+ "Old Absalot"      ; name
+ nil          ; sprite
+ m_old_absalot      ; map
+ #f              ; wraps
+ #t              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+  (put (mk-ladder-up 'p_absalot 2 2) 11 27)
+
+  ;; npc's
+  (put (mk-silas) 9 9)
+  (put (mk-dennis) 9 9)
+  (put (mk-selene) 9 9)
+
+  ;; slave prison
+  (put (kern-tag 'oa-cp1 (mk-portcullis)) 2 16)
+  (put (kern-tag 'oa-cp2 (mk-portcullis)) 2 18)
+  (put (kern-tag 'oa-cp3 (mk-portcullis)) 5 16)
+  (put (kern-tag 'oa-cp4 (mk-portcullis)) 5 18)
+  (put (mk-corpse) 1 16)
+  (put (kern-tag 'oa-ps1 (mk-portcullis)) 3 19)
+  (put (kern-tag 'oa-ps2
+                 (mk-connected-portcullis 'oa-ps1)) 4 19)
+  (put (mk-lever 'oa-ps2) 2 20)
+  (put (mk-lever 'oa-cp1) 1 14)
+  (put (mk-lever 'oa-cp2) 2 14)
+  (put (mk-lever 'oa-cp3) 5 14)
+  (put (mk-lever 'oa-cp4) 6 14)
+
+  ;; treasure room
+  (put (mk-magic-locked-door) 3 23)
+  (put (kern-mk-obj F_poison_perm 1) 3 24)
+  (put (kern-mk-obj F_sleep_perm 1) 3 25)
+  (put (kern-mk-obj F_energy_perm 1) 3 26)
+  (put (kern-mk-obj F_fire_perm 1) 3 27)
+  (put (kern-mk-obj F_poison_perm 1) 3 28)
+  (put (kern-mk-obj F_poison_perm 1) 2 27)
+  (put (kern-mk-obj F_poison_perm 1) 4 27)
+  (put (kern-mk-obj F_sleep_perm 1) 1 27)
+  (put (kern-mk-obj F_sleep_perm 1) 2 28)
+  (put (kern-mk-obj F_sleep_perm 1) 3 29)
+  (put (kern-mk-obj F_sleep_perm 1) 4 28)
+  (put (kern-mk-obj F_sleep_perm 1) 5 27)
+  (put (kern-mk-obj F_energy_perm 1) 1 28)
+  (put (kern-mk-obj F_energy_perm 1) 2 29)
+  (put (kern-mk-obj F_energy_perm 1) 4 29)
+  (put (kern-mk-obj F_energy_perm 1) 5 28)
+  (put (kern-mk-obj F_fire_perm 1) 1 29)
+  (put (kern-mk-obj F_fire_perm 1) 5 29)
+  
+  (put (mk-hidden 't_rune_s 1) 4 29)
+
+  ;; meat locker
+  (put (mk-locked-door) 22 14)
+  (put (mk-corpse) 26 8)
+  (put (mk-corpse) 26 9)
+  (put (mk-corpse) 26 10)
+  (put (mk-corpse) 25 8)
+  (put (mk-corpse) 25 9)
+  (put (mk-corpse) 24 8)
+
+  ;; Silas's room
+  (put (mk-bed) 4 8)
+  (put (mk-locked-door) 6 8)
+  (put (mk-magic-locked-door) 4 6)
+  (put (mk-chest 'bomb-trap
+                 '((1 t_demon_gate_book)
+                  (1 t_spell_book_gate_magick)
+                  (1 t_spell_book_summoning)
+                  (1 t_spell_book_enchantment_curses)
+                  ))
+       4 5)
+
+  ;; Bunkroom
+  (put (mk-door) 19 8)
+  (put (mk-door) 21 6)
+  (put (mk-bed) 21 1)
+  (put (mk-bed) 23 1)
+  (put (mk-bed) 23 3)
+  (put (mk-bed) 23 5)
+
+  )
+
+ nil ; hooks
+ nil ; edge entrances
+ )
+
+(mk-place-music p_old_absalot 'ml-dungeon-town)
diff --git a/worlds/haxima-1.002/old-mine.scm b/worlds/haxima-1.002/old-mine.scm
new file mode 100644 (file)
index 0000000..137f47f
--- /dev/null
@@ -0,0 +1,65 @@
+;;;;
+;;;; old-mine.scm -- an abandoned mine littered with gems
+;;;;
+
+(mk-dungeon-room
+ 'p_old_mine "Old Mine"
+ (list
+               "rn rn r8 r8 rn rn rn rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 rn "
+               "rn rc bb bb ra rn rn rn rc bb bb bb .. .. .. .. bb bb r2 "
+               "r4 bb .. .. bb ra r8 rc bb .. .. .. .. .. .. .. .. bb r2 "
+               "r4 bb .. .. .. .. .. .. .. .. .. .. r3 r5 .. .. .. bb r2 "
+               "rn r5 .. .. .. .. .. .. .. .. .. bb r2 rn r5 .. .. r3 rn "
+               "rn r4 .. .. rb r1 r1 r5 .. .. .. rb r8 rn r4 .. .. r2 rn "
+               "rn r4 .. .. bb ra r8 r8 rd .. .. bb bb ra rc .. .. r2 rn "
+               "rn r4 .. .. .. bb bb bb bb .. .. .. bb .. bb .. .. r2 rn "
+               "rn r4 .. .. .. bb bb .. .. .. .. .. .. .. .. .. .. r2 rn "
+               "rn r4 .. .. bb rf .. .. .. .. .. .. .. .. .. .. .. ra rn "
+               "rn r4 .. .. r7 bb .. .. .. .. .. r3 r5 .. .. .. .. bb r2 "
+               "rn r4 .. .. ra rd .. .. .. .. bb r2 rn r1 r5 .. .. r3 rn "
+               "rn r4 .. .. .. bb .. .. r7 bb r3 r8 r8 rn rc .. .. r2 rn "
+               "rn rc .. .. .. .. .. r3 r8 r9 rc .. .. re .. .. .. r2 rn "
+               "r4 bb .. .. .. .. .. re .. .. .. .. .. .. .. .. .. r2 rn "
+               "r4 bb .. .. .. .. .. .. .. .. .. .. .. .. .. r7 .. ra rn "
+               "rn r5 bb .. .. .. .. .. .. r3 r5 .. .. r3 r1 r4 .. .. r2 "
+               "rn rn r1 r5 bb r3 r1 r1 r1 rn rn r1 r1 rn rn r4 .. .. r2 "
+               "rn rn rn rn r1 rn rn rn rn rn rn rn rn rn rn rn r1 r1 rn "
+  )
+ (put (mk-ladder-down 'p_trolls_den 3 15) 17 17)
+
+ ;; put some wandering ghasts in
+ (put (guard-pt 'skeletal-warrior) 4 15)
+ (put (guard-pt 'skeletal-warrior) 15 2)
+ (put (guard-pt 'skeletal-spear-thrower) 9 9)
+ (put (spawn-pt 'ghast) 15  9)
+ (put (spawn-pt 'ghast) 11 14)
+ (put (spawn-pt 'ghast)  9  4)
+ (put (spawn-pt 'giant-spider) 3 3)
+ (put (spawn-pt 'giant-spider) 4 4)
+ (put (mk-step-trig 'wind-trap nil) 15 14)
+ (put (mk-step-trig 'wind-trap nil) 16 12)
+ (put (mk-step-trig 'wind-trap nil)  2  8)
+ (put (mk-step-trig 'wind-trap nil) 10  3)
+ )
+
+;; drop gems
+(put-random-stuff p_old_mine
+                  (mk-rect 0 0 19 19)
+                  (lambda (loc)
+                    (eqv? (kern-place-get-terrain loc)
+                          t_boulder))
+                  (lambda (loc)
+                    (kern-obj-put-at (kern-mk-obj t_gem 
+                                                  (modulo (random-next) 
+                                                          10))
+                                     loc))
+                  10)
+
+;; drop some corpses
+(drop-random-corpses p_old_mine 5)
+
+;; fill upper left corner with cobwebs
+(webify p_old_mine 0 0 6 7)
+
+(mk-place-music p_old_mine 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/oparine.scm b/worlds/haxima-1.002/oparine.scm
new file mode 100644 (file)
index 0000000..0c2e602
--- /dev/null
@@ -0,0 +1,166 @@
+;;----------------------------------------------------------------------------
+;; Oparine
+;;
+;; Main trade port for the peninsula.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_oparine 31 55 pal_expanded
+       (list
+               ".. .. .. .. .. .. .. .. .. .. .. .. cc cc cc cc cc cc .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. xx xx xx xx xx xx xx xx xx xx cc cc cc cc cc cc xx xx xx xx xx xx xx xx xx xx xx xx .. "
+               ".. .. xx .C .H .E .E .R .F .U .L xx cc cc cc cc cc cc xx ,, xx .B .I .L .G .E xx ,, ,, xx .. "
+               ".. .. xx .B .U .N .K .M .A .T .E xx cc cc cc cc cc cc xx ,, xx .W .A .T .E .R xx ,, ,, xx .. "
+               ".. .. ,, ,, ,, ,, ,, ,, ,, ,, ,, xx cc cc cc cc cc cc xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. "
+               ".. .. xx [[ @@ @@ @@ @@ @@ @@ ]] xx cc cc cc cc cc cc xx ,, xx [[ @@ @@ @@ ]] xx xx xx xx .. "
+               ".. .. xx ,, ,, ,, ,, ,, ,, ,, ,, ws cc cc cc cc cc cc xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+               ".. .. xx ,, ,, ,, ,, ,, ,, ,, ,, ,, cc cc cc cc cc cc ws ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+               ".. .. xx xx xx xx ,, ,, xx xx xx sI cc cc cc cc cc xx xx [[ @@ ]] ,, ,, ,, [[ @@ ]] xx xx .. "
+               ".. .. xx ,, ,, xx ,, ,, ,, ,, ,, xx cc cc cc cc cc xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx .. "
+               ".. .. xx ,, ,, ,, ,, ,, xx ,, ,, ws cc cc cc cc cc xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, && xx .. "
+               ".. .. xx xx xx xx ,, ,, xx xx xx xx cc cc cc cc cc xx xx [[ @@ ]] ,, ,, ,, [[ @@ ]] xx xx .. "
+               ".. .. xx ,, ,, xx ,, ,, ,, ,, ,, xx cc cc cc cc cc cc ws ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+               ".. .. xx ,, ,, ,, ,, ,, xx ,, ,, ws cc cc cc cc cc cc xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx .. .. "
+               ".. .. xx xx xx xx xx ,, xx xx xx xx cc cc cc cc cc cc xx xx xx xx sT ,, xx xx xx xx xx .. .. "
+               ".. .. xx ,, ,, xx ,, ,, xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc .. .. "
+               ".. .. xx ,, ,, xx ,, ,, xx cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc .. .. "
+               ".. .. xx ,, ws xx xx xx xx cc cc cc cc cc cc ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## "
+               "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ## _3 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 _1 __ "
+               "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc oo __ __ __ __ __ oo __ __ __ __ __ oo __ __ "
+               "cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee "
+               ".. .. .. .. xx xx xx xx xx cc cc cc cc cc cc cc ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee "
+               ".. .. .. .. xx ,, ,, ,, xx cc cc cc cc cc cc cc ee ee ee ee ee ee ee ee ee ee ee ee ee ee ee "
+               ".. .. .. .. xx ,, ,, ,, ,, cc cc cc cc cc cc cc oo __ __ ee ee ee oo __ __ __ __ __ oo __ __ "
+               ".. .. .. .. xx ,, ,, ,, xx cc cc cc ## ## ## ## __ __ __ ee ee ee __ __ __ __ __ __ __ __ __ "
+               ".. xx xx xx xx xx xx xx xx cc cc cc ## _3 _1 __ __ __ __ ee ee ee __ __ #e #a #a ee #f __ __ "
+               ".. xx ,A ,L ,K ,E ,M ,Y xx cc cc cc ## _2 __ __ __ __ __ ee ee ee __ #e #E ee ee ee #F #f __ "
+               ".. xx ,, ,, ,, ,, ,, ,, ws cc cc cc ## _2 xx xx xx xx oo ee ee ee oo #b ee ee ee ee ee #c __ "
+               ".. xx ,, ,, ,, ,, ,, ,, sP cc cc cc ## _2 xx ee ee xx ~~ ee ee ee __ #b <n #= #= #= <n #c __ "
+               ".. xx ,, ,, aa && ,, ,, ,, cc cc cc ## _2 xx ee ee ee ee ee ee ee __ #b ee ee ee ee ee #c __ "
+               ".. xx ,, ,, ,, ,, ,, ,, xx cc cc cc ## _2 xx ee ee xx __ ee ee ee ee ee ee ee ee vv vv ee __ "
+               ".. xx ,, ,, ,, ,, ,, ,, ws cc cc cc ## _2 xx xx xx xx __ ee ee ee __ #b vv ee ee ee ee ee __ "
+               ".. xx [[ @@ @@ @@ @@ ]] xx cc cc cc ## _2 __ __ __ __ __ ee ee ee __ #b ee ee ee ee ee ee __ "
+               ".. xx xx xx xx xx xx xx xx cc cc cc ## ~a ~~ ~~ __ __ oo ee ee ee oo #b ee ee ee vv vv #c __ "
+               ".. .. .. .. .. .. .. .. bb .. .. .. bb .. ~% ~~ -- __ __ ee ee ee __ ee ee ee ee vv vv ee __ "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ~a ~~ -- __ __ __ __ __ #b vv vv ee ee ee #c __ "
+               ".. .. .. .. .. .. .. .. bb .. .. .. bb .. .. ~% ~~ ~~ -- __ __ __ __ #b ee ee ee vv vv #c __ "
+               ".. xx xx xx xx xx xx xx .. .. .. .. .. .. .. .. ~a ~~ -- -- __ __ __ #g #G vv ee vv vv #h __ "
+               ".. xx [[ .S .E .A ]] xx bb .. .. .. bb .. .. .. ~% ~~ ~~ -- __ __ __ __ #g #G ee #H #h __ __ "
+               ".. xx .W .I .T .C .H sR .. .. .. .. .. .. .. .. ~C ~~ ~~ -- -- __ __ __ __ #g #d #h __ __ __ "
+               ".. xx ,, ,, ,, ,, ,, ws bb .. .. .. bb .. .. .. ~3 ~~ ~~ -- -- __ __ __ __ __ __ __ __ __ __ "
+               ".. xx ,, ,, ,, ,, ,, ,, .. .. .. .. .. .. .. ~C ~~ ~~ ~~ -- -- __ __ __ __ __ __ __ __ __ __ "
+               ".. xx ,, [[ @@ ]] ,, ws bb .. .. .. bb .. .. ~3 ~~ ~~ -- -- -- -- __ __ __ __ __ __ __ __ __ "
+               ".. xx xx ,, ,, ,, xx xx .. .. .. .. .. .. .. ~2 ~~ ~~ ~~ ~~ -- -- -- __ __ __ __ __ __ __ __ "
+               ".. .. xx xx ,, xx xx .. bb .. .. .. oo .. oo ~8 ~8 ~~ ~~ ~~ -- -- -- __ __ __ __ __ __ __ __ "
+               ".. .. xx ,, ,, ,, xx .. .. .. .. .. ee ee ee .. .. bb ~~ ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+               ".. .. xx ,, ,, ,, ws .. bb .. .. .. ee ee ee .. .. .. ~a ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+               ".. .. xx xx ,, xx xx .. .. .. .. .. ee ee ee .. .. .. bb ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+               ".. .. .. bb .. bb .. .. .. .. bb .. oo ~~ oo .. .. .. ~3 ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. ~6 .. .. .. .. ~~ ~~ ~~ -- -- __ __ __ __ __ __ __ __ "
+               ".. .. bb ~3 ~1 ~5 bb .. .. .. .. ~C ~3 ~~ oo ee ee ee oo ~~ ~~ -- -- -- __ __ __ __ __ __ __ "
+               "~C ~3 ~~ ~~ ~~ ~~ ~~ ~5 ~A .. ~C ~3 ~~ ~~ ~~ ee ee ee ~~ ~~ ~~ -- -- -- -- __ __ __ __ __ __ "
+               "~~ ~~ -- -- -- -- -- ~~ ~~ ~1 ~~ ~~ ~~ ~c oo ee ee ee oo ~a ~~ ~~ -- -- -- __ __ __ __ __ __ "
+               "-- -- -- __ __ __ -- -- -- -- -- ~~ ~c ~# .. .. .. .. .. ~% ~a ~~ ~~ -- -- __ __ __ __ __ __ "
+               "-- -- -- __ __ __ -- -- -- -- -- ~~ ~# .. .. .. .. .. .. .. ~% ~~ ~~ -- -- -- __ __ __ __ __ "
+       )
+)
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "alchemist.scm")
+(kern-load "oscar.scm")
+(kern-load "henry.scm")
+(kern-load "bart.scm")
+(kern-load "lia.scm")
+(kern-load "fing.scm")
+(kern-load "ghertie.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_oparine     ; tag
+ "Oparine"      ; name
+ s_town          ; sprite
+ m_oparine      ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ (list ;; objects
+
+  ;; npc's
+  (put (mk-alchemist) 0 0)
+  (put (mk-oscar) 0 0)
+  (put (mk-henry) 0 0)
+  (put (mk-bart) 0 0)
+  (put (mk-lia) 0 0)
+  (put (mk-fing) 0 0)
+  (put (mk-ghertie) 0 0)
+  (put (mk-kalcifax) 0 0)
+
+  ;; inn
+  (put (mk-locked-door) 2 4)
+  (put (mk-windowed-door) 11  7)
+  (put (mk-bed)  3  9)
+  (put (mk-bed)  3 12)
+  (put (mk-bed)  6 15)
+  (put (mk-bed) 10 12)
+  (put (mk-bed) 10  9)
+  (put (kern-tag 'oparine-inn-room-1-door (mk-locked-door))  5 10)
+  (put (kern-tag 'oparine-inn-room-2-door (mk-locked-door))  5 13)
+  (put (kern-tag 'oparine-inn-room-3-door (mk-magic-locked-door))  7 14)
+  (put (kern-tag 'oparine-inn-room-4-door (mk-locked-door))  8 12)
+  (put (kern-tag 'oparine-inn-room-5-door (mk-locked-door))  8  9)
+
+  ;; innkeepers room
+  (put (mk-door) 3 17)
+  (put (mk-bed) 4 15)
+
+  ;; bart's
+  (put (mk-door) 17 29)
+
+  ;; sea witch
+  (put (mk-windowed-door) 7 41)
+  (put (mk-locked-door) 4 47)  
+  (put (mk-door) 4 44)
+  (put (mk-bed) (zone-x sea-witch-bed) (zone-y sea-witch-bed))
+  
+  ;; Alkemysts
+  (put (mk-door) 8 29)
+  (put (mk-magic-locked-door) 8 23)
+  (put (mk-bed) 5 22)
+
+  ;; tavern
+  (put (mk-locked-door) 19 5)
+  (put (mk-windowed-door) 23 14)
+  (put (mk-clock) 27 13)
+  (put (mk-door) 20 4)
+  (put (mk-door) 26 4)
+  (put (mk-bed) 27 2)
+
+  )
+ (list 'lock-inn-room-doors)  ;; On-entry hook
+ (list  ;; edge entrances
+  (list east 0 19)
+  (list north 16 54)
+  (list west 30 21)
+  (list northeast 0 50)
+  (list northwest 19 54)
+  )
+)
+
+  (let* ((kmir (kern-tag 'sea-witch-mirror (mk-mirror 's_mirror_bg_flagstones)))
+         (ksen (mk-char-sensor 'sea-witch-mirror)))
+       (kern-obj-put-at kmir (list p_oparine 5 45))
+       (kern-obj-put-at ksen (list p_oparine 5 46)))
+
+(mk-place-music p_oparine 'ml-large-town)
+
+
diff --git a/worlds/haxima-1.002/oscar.scm b/worlds/haxima-1.002/oscar.scm
new file mode 100644 (file)
index 0000000..76ab9f2
--- /dev/null
@@ -0,0 +1,207 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; In Oparine
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_oscar
+               (list 0  0  oparine-innkeepers-bed "sleeping")
+               (list 8  0  bilge-water-seat-3     "eating")
+               (list 9  0  cheerful-counter       "working")
+               (list 12 0  bilge-water-seat-3     "eating")
+               (list 13 0  cheerful-counter       "working")
+               (list 21 0  bilge-water-seat-3     "eating")
+               (list 22 0  bilge-water-hall       "idle")
+               (list 23 0  oparine-innkeepers-bed "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (oscar-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Oscar is the innkeeper in Oparine.  He is a glum fellow, with a wooden leg.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (oscar-hail knpc kpc)
+  (say knpc "[You meet a glum man with a wooden leg] Hello."))
+
+(define (oscar-default knpc kpc)
+  (say knpc "I don't know."))
+
+(define (oscar-name knpc kpc)
+  (say knpc "I'm Oscar the Innkeeper."))
+
+(define (oscar-join knpc kpc)
+  (say knpc "I would just get in the way."))
+
+(define (oscar-job knpc kpc)
+  (say knpc "I'm the Innkeeper. "
+       "I doubt you want to rent a room, "
+       "but if you do let me know."))
+
+(define (oscar-bye knpc kpc)
+  (say knpc "Bye"))
+
+;; Trade...
+(define (oscar-trade knpc kpc)
+  (if (not (string=? "working" (kern-obj-get-activity knpc)))
+      (say knpc "The inn is open from 9 to 9, and I do have to eat sometime, "
+           "so try me later.")
+      (let ((door (eval 'oparine-inn-room-1-door)))
+        ;; is the room still open?
+        (if (not (door-locked? (kobj-gob door)))
+            ;; yes - remind player
+            (say knpc "Your room is still open.")
+            ;; no - ask if player needs a room
+            (begin
+              (say knpc "Do you need a room?")
+              (if (kern-conv-get-yes-no? kpc)
+                  ;; yes - player wants a room
+                  (begin
+                    (say knpc 
+                         "That will be " oparine-inn-room-price " gold. "
+                         "You can have the room as long as you're in town. "
+                         "Do you still want it?")
+                    (if (kern-conv-get-yes-no? kpc)
+                        ;; yes - player agrees to the price
+                        (let ((gold (kern-player-get-gold)))
+                          ;; does player have enough gold?
+                          (if (>= gold oparine-inn-room-price)
+                              ;; yes - player has enough gold
+                              (begin
+                                (say knpc "Ok, you're in room 1, "
+                                     "but you won't like it. "
+                                     "Don't complain to me because I told you "
+                                     "so.")
+                                (kern-player-set-gold 
+                                 (- gold 
+                                    oparine-inn-room-price))
+                                (send-signal knpc door 'unlock)
+                                (kern-conv-end)
+                                )
+                              ;; no - player does not have enouvh gold)
+                              (say knpc "Sorry, but you don't have the gold. "
+                                   "This isn't a poorhouse, you know." )))
+                        ;; no - player does not agree to the price
+                        (say knpc 
+                             "I knew you wouldn't.")))
+                  ;; no - player does not want a room
+                  (say knpc "I didn't think so. "
+                       "I was just being polite.")))))))
+
+;; Inn...
+(define (oscar-inn knpc kpc)
+  (say knpc "The former owner gave it the name. "
+       "I didn't feel like changing it. Besides, that would be bad luck."))
+
+(define (oscar-luck knpc kpc)
+  (say knpc "The ghost in room 3 likes the name. I don't want the ghost of "
+       "a wicked pirate mad at me.")
+       (quest-data-assign-once 'questentry-ghertie)
+       (quest-data-update 'questentry-ghertie 'ghertieloc 1))
+
+(define (oscar-ghost knpc kpc)
+  (say knpc "Ghastly Ghertie was murdered by her crew in room 3. "
+       "She still haunts it so I don't rent it out. "
+       "I wish she would pay her bill.")
+       (quest-data-update 'questentry-ghertie 'ghertieid 1)
+       (quest-data-update 'questentry-ghertie 'ghertieloc 1)
+       (quest-data-assign-once 'questentry-ghertie))
+
+;; Leg...
+(define (oscar-leg knpc kpc)
+  (say knpc "I tried to be a sailor but nobody would take me. "
+       "So I cut off my leg to make myself look like a sailor. "
+       "They still wouldn't take me. I miss that leg."))
+
+;; Townspeople...
+(define (oscar-opar knpc kpc)
+  (say knpc "This is a port city. Most of my customers are travelers who "
+       "disembark here before traveling north."))
+
+(define (oscar-gher knpc kpc)
+  (say knpc "Ghertie was a wicked pirate back before my time. "
+       "Her own crew murdered her and left with her ship and her treasure.")
+       (quest-data-assign-once 'questentry-ghertie))
+
+(define (oscar-alch knpc kpc)
+  (say knpc "His shop is next to the tavern. He's always looking for weird "
+       "stuff to use in his experiments."))
+
+(define (oscar-bart knpc kpc)
+  (say knpc "Bart the shipwright has a shop just across the way. "
+       "He usually gets pretty drunk at night. I can't keep up with him."))
+
+(define (oscar-seaw knpc kpc)
+  (say knpc "The sea witch is very beautiful but keeps to herself. "
+       "She ignores me, of course."))
+
+(define (oscar-henr knpc kpc)
+  (say knpc "There's a real sailor. I'll never be like him."))
+
+(define oscar-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default oscar-default)
+       (method 'hail oscar-hail)
+       (method 'bye  oscar-bye)
+       (method 'job  oscar-job)
+       (method 'name oscar-name)
+       (method 'join oscar-join)
+       
+       ;; trade
+       (method 'trad oscar-trade)
+       (method 'room oscar-trade)
+       (method 'buy  oscar-trade)
+       (method 'sell oscar-trade)
+
+       ;; inn
+       (method 'inn  oscar-inn)
+       (method 'luck oscar-luck)
+       (method 'ghos oscar-ghost)
+       (method 'pira oscar-ghost)
+       (method 'leg  oscar-leg)
+
+       ;; town & people
+       (method 'opar oscar-opar)
+       (method 'alch oscar-alch)
+       (method 'gher oscar-gher)
+       (method 'ghas oscar-gher)
+       (method 'henr oscar-henr)
+       (method 'bart oscar-bart)
+       (method 'sea  oscar-seaw)
+       (method 'witc oscar-seaw)
+
+       ))
+
+(define (mk-oscar)
+  (bind 
+   (kern-mk-char 'ch_oscar           ; tag
+                 "Oscar"             ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_townsman          ; sprite
+                 faction-men         ; starting alignment
+                 1 1 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 1  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'oscar-conv         ; conv
+                 sch_oscar           ; sched
+                 'townsman-ai        ; special ai
+                 nil                 ; container
+                 (list t_dagger)     ; readied
+                 )
+   (oscar-mk)))
diff --git a/worlds/haxima-1.002/palette.scm b/worlds/haxima-1.002/palette.scm
new file mode 100644 (file)
index 0000000..01a7537
--- /dev/null
@@ -0,0 +1,488 @@
+(kern-mk-palette 'pal_expanded
+  (list
+    ;; There are 110 entries in this palette
+    ;; The widest glyph is 2 characters
+    ;; 
+    ;; Note: 
+    ;; It is best if all glyphs in a palette are of the same width,
+    ;; so all glyphs in this palette should be 2 characters wide, 
+    ;; like "xx" rather than "x".
+    ;; 
+    ;; This constraint makes it easier to edit maps via search & replace,
+    ;; and makes it easier to change the palette.
+    ;; 
+    ;; NOTE: "x#" is reserved for blocking mechanisms, see block-teleporting in
+    ;; naz.scm
+    (list  "xx"   t_wall)               ;; "wall"
+    (list  "__"   t_deep)               ;; "deep water"
+    (list  "_!"   t_sunlit_deep)               ;; "deep water"
+    (list  "~*"   t_blendable_shoals)            ;; "shallow water"
+    (list  "_s"   t_sludge)
+    (list  "~s"   t_shallow_sludge)
+    (list  "dd"   t_dirt)
+    (list  "gg"   t_gravel)
+       
+    (list  "%%"   t_bog)                ;; "bog"
+    (list  ".."   t_grass)              ;; "grass"
+    (list  ".!"   t_sunlit_grass)              ;; "grass"
+    (list  "t."   t_trees_v)            ;; "trees (transparent)"
+    (list  "tt"   t_trees)              ;; "trees"
+    (list  "t|"   t_trees_d)            ;; "trees denser"
+
+    (list  "||"   t_forest)             ;; "forest"
+    (list  "|X"   t_forest_d)           ;; "forest (denser)"
+    (list  "|t"   t_forest_l)           ;; "forest (lighter)"
+    (list  "|."   t_forest_v)           ;; "forest (non-LOS-blocking)"
+    (list  "|v"   t_forest_b)           ;; "forest (totally LOS-blocking)"
+
+    (list  "{{"   t_hills)              ;; "hills"
+
+    (list  "^^"   t_mountains)          ;; "mountains"
+    (list  "^."   t_mountains_v)        ;; "mountains" (non-LOS-blocking)
+    (list  "^v"   t_mountains_b)        ;; "mountains" (below player)
+    (list  "^~"   t_fake_mountains)
+
+    (list  ",,"   t_flagstones)         ;; "flagstones"
+    (list  "~,"   t_inv_wall)
+    (list  "d,"   t_doorway)
+    (list  "cc"   t_cobblestone)        ;; "cobblestone"
+    (list  "cx"   t_impassable_cobblestone)        ;; "cobblestone"
+
+    (list  "cg"   t_gold_cobble)
+    (list  "cy"   t_cyan_cobble)
+    (list  "cG"   t_gray_cobble)
+    (list  "cb"   t_blue_cobble)
+    (list  "co"   t_olive_cobble)
+    (list  "cw"   t_white_cobble)
+    (list  "Tb"   t_black_tile)
+    (list  "Tg"   t_gold_spiral_tile)
+    (list  "Tb"   t_blue_spiral_tile)
+
+    (list  "ee"   t_deck)               ;; "deck"
+    (list  "oo"   t_mast)               ;; "mast"
+    (list  "ff"   t_fire_terrain)       ;; "fire"
+    (list  "!!"   t_lava)               ;; "lava"
+    (list  "~!"   t_fake_lava)
+    (list  "!_"   t_deep_lava)
+    (list  "&&"   t_fireplace)          ;; "fireplace"
+
+    (list  "x."   t_wall_v)             ;; "wall"  (non-LOS-blocking)
+    (list  "~x"   t_fake_wall)
+
+    (list  "**"   t_stars)              ;; "stars"
+       (list  "*."   t_void)
+    (list  "??"   t_secret_door)        ;; "secret door"
+    (list  "pp"   t_pillar)             ;; "pillar"
+    (list  "~p"   t_false_pillar)
+    (list  "bb"   t_boulder)            ;; "boulder"
+    (list  "b~"   t_water_rocks)        ;; "boulder" in water
+    (list  "bt"   t_tombstone)
+    (list  "bT"   t_tombstone2)
+       
+    (list  "rr"   t_wall_rock)          ;; "rock wall"
+    (list  "r."   t_wall_rock_v)        ;; "rock wall"  (non-LOS-blocking)
+    (list  "~r"   t_fake_wall_rock)     ;; "rock wall"  (fake)
+
+    (list  "WW"   t_ships_wheel)        ;; "ship's wheel"
+    (list  "x!"   t_wall_torch)         ;; "wall torch"
+    (list  "##"   t_ship_hull)          ;; "ship's hull"
+    (list  "#>"   t_ship_hull2)          ;; "ship's hull (LOS-blocking)"
+
+    (list  ".A"   t_a)                  ;; "an A"
+    (list  ".B"   t_b)                  ;; "a B"
+    (list  "?B"   t_fake_b)                  ;; "a B"
+    (list  ".C"   t_c)                  ;; "a C"
+    (list  ".D"   t_d)                  ;; "a D"
+    (list  ".E"   t_e)                  ;; "an E"
+    (list  ".F"   t_f)                  ;; "an F"
+    (list  ".G"   t_g)                  ;; "a G"
+    (list  ".H"   t_h)                  ;; "an H"
+    (list  ".I"   t_i)                  ;; "an I"
+    (list  ".J"   t_j)                  ;; "a J"
+    (list  ".K"   t_k)                  ;; "a K"
+    (list  ".L"   t_l)                  ;; "an L"
+    (list  ".M"   t_m)                  ;; "an M"
+    (list  ".N"   t_n)                  ;; "an N"
+    (list  ".O"   t_o)                  ;; "an O"
+    (list  "~O"   t_fake_o)
+    (list  ".P"   t_p)                  ;; "a P"
+    (list  ".Q"   t_q)                  ;; "a Q"
+    (list  ".R"   t_r)                  ;; "an R"
+    (list  ".S"   t_s)                  ;; "an S"
+    (list  ".T"   t_t)                  ;; "a T"
+    (list  ".U"   t_u)                  ;; "a U"
+    (list  ".V"   t_v)                  ;; "a V"
+    (list  ".W"   t_w)                  ;; "a W"
+    (list  ".X"   t_x)                  ;; "an X"
+    (list  ".Y"   t_y)                  ;; "a Y"
+    (list  ".Z"   t_z)                  ;; "a Z"
+
+    (list  ",A"   t_rune_a)             ;; "a rune"
+    (list  ",B"   t_rune_b)             ;; "a rune"
+    (list  ",C"   t_rune_c)             ;; "a rune"
+    (list  ",D"   t_rune_d)             ;; "a rune"
+    (list  ",E"   t_rune_e)             ;; "a rune"
+    (list  ",F"   t_rune_f)             ;; "a rune"
+    (list  ",G"   t_rune_g)             ;; "a rune"
+    (list  ",H"   t_rune_h)             ;; "a rune"
+    (list  ",I"   t_rune_i)             ;; "a rune"
+    (list  ",J"   t_rune_j)             ;; "a rune"
+    (list  ",K"   t_rune_k)             ;; "a rune"
+    (list  ",L"   t_rune_l)             ;; "a rune"
+    (list  ",M"   t_rune_m)             ;; "a rune"
+    (list  ",N"   t_rune_n)             ;; "a rune"
+    (list  ",O"   t_rune_o)             ;; "a rune"
+    (list  ",P"   t_rune_p)             ;; "a rune"
+    (list  ",Q"   t_rune_q)             ;; "a rune"
+    (list  ",R"   t_rune_r)             ;; "a rune"
+    (list  ",S"   t_rune_s)             ;; "a rune"
+    (list  ",T"   t_rune_t)             ;; "a rune"
+    (list  ",U"   t_rune_u)             ;; "a rune"
+    (list  ",V"   t_rune_v)             ;; "a rune"
+    (list  ",W"   t_rune_w)             ;; "a rune"
+    (list  ",X"   t_rune_x)             ;; "a rune"
+    (list  ",Y"   t_rune_y)             ;; "a rune"
+    (list  ",Z"   t_rune_z)             ;; "a rune"
+    (list  ";T"   t_rune_th)            ;; "a rune"
+    (list  ";E"   t_rune_ee)            ;; "a rune"
+    (list  ";N"   t_rune_ng)            ;; "a rune"
+    (list  ";A"   t_rune_ea)            ;; "a rune"
+    (list  ";S"   t_rune_st)            ;; "a rune"
+    (list  ";D"   t_rune_dot)           ;; "a rune"
+
+    (list  "@@"   t_counter_2x1_c)      ;; "counter"
+    (list  "[["   t_counter_2x1_w)      ;; "counter"
+    (list  "]]"   t_counter_2x1_e)      ;; "counter"
+    (list  "00"   t_counter_1x1)        ;; "counter"
+
+    (list  "++"   t_ankh)               ;; "ankh"
+    (list  "+s"   t_statue)               ;; "ankh"
+    (list  "aa"   t_altar)              ;; "altar"
+    (list  "ar"   t_rune_altar)              ;; "altar"
+    (list  "a!"   t_active_altar)              ;; "altar"
+    (list  "<<"   t_leftwing)           ;; "castle wall"
+    (list  ">>"   t_rightwing)          ;; "castle wall"
+    (list  "w+"   t_arrow_slit)         ;; "arrow slit"
+    (list  "ws"   t_window_in_stone)    ;; "window"
+    (list  "wr"   t_window_in_rock)     ;; "window"
+    
+    (list  "=="   t_bridge_WE)          ;; "east-west bridge"
+    (list  "=|"   t_bridge_NS)          ;; "east-west bridge"
+    (list  "=!"   t_lava_bridge_NS)
+    (list  "vv"   t_chasm)              ;; "chasm"
+
+    (list "sE" t_equip_sign)
+    (list "sA" t_weapon_sign)
+    (list "sH" t_healer_sign)
+    (list "sT" t_tavern_sign)
+    (list "sI" t_inn_sign)
+    (list "sP" t_alchemy_sign)
+    (list "sR" t_magic_sign)
+    (list "sS" t_str_sign)
+    (list "sD" t_dex_sign)
+    (list "sW" t_wis_sign)
+       
+       ;; blended terrains (mostly terrain + corner of something else)
+       
+       (list  "/0"   t_trail_0)            ;; "trail"
+    (list  "/1"   t_trail_1)            ;; "trail"
+    (list  "/2"   t_trail_2)            ;; "trail"
+    (list  "/3"   t_trail_3)            ;; "trail"
+    (list  "/4"   t_trail_4)            ;; "trail"
+    (list  "/5"   t_trail_5)            ;; "trail"
+    (list  "/6"   t_trail_6)            ;; "trail"
+    (list  "/7"   t_trail_7)            ;; "trail"
+    (list  "/8"   t_trail_8)            ;; "trail"
+    (list  "/9"   t_trail_9)            ;; "trail"
+    (list  "/a"   t_trail_a)            ;; "trail"
+    (list  "/b"   t_trail_b)            ;; "trail"
+    (list  "/c"   t_trail_c)            ;; "trail"
+    (list  "/d"   t_trail_d)            ;; "trail"
+    (list  "/e"   t_trail_e)            ;; "trail"
+    (list  "/f"   t_trail_f)            ;; "trail"
+       
+       (list  "~~" t_shoals)     ;; shallow + land
+    (list  "~1" t_shore_n)
+    (list  "~2" t_shore_w)
+    (list  "~3" t_shore_nw)
+    (list  "~4" t_shore_e)
+    (list  "~5" t_shore_ne)
+    (list  "~6" t_shore_we)
+    (list  "~7" t_shore_nwe)
+    (list  "~8" t_shore_s)
+    (list  "~9" t_shore_ns)
+    (list  "~a" t_shore_ws)
+    (list  "~b" t_shore_nws)
+    (list  "~c" t_shore_es)
+    (list  "~d" t_shore_nes)
+    (list  "~e" t_shore_wes)
+    (list  "~f" t_shore_c)
+       
+    (list  "--" t_shallow)            ;; water + land
+    (list  "-1" t_wshore_n)
+    (list  "-2" t_wshore_w)
+    (list  "-3" t_wshore_nw)
+    (list  "-4" t_wshore_e)
+    (list  "-5" t_wshore_ne)
+    (list  "-6" t_wshore_we)
+    (list  "-7" t_wshore_nwe)
+    (list  "-8" t_wshore_s)
+    (list  "-9" t_wshore_ns)
+    (list  "-a" t_wshore_ws)
+    (list  "-b" t_wshore_nws)
+    (list  "-c" t_wshore_es)
+    (list  "-d" t_wshore_nes)
+    (list  "-e" t_wshore_wes)
+    (list  "-f" t_wshore_c)
+       
+       (list  "_1" t_dshore_n)        ;; deep water + land
+    (list  "_2" t_dshore_w)
+    (list  "_3" t_dshore_nw)
+    (list  "_4" t_dshore_e)
+    (list  "_5" t_dshore_ne)
+    (list  "_6" t_dshore_we)
+    (list  "_7" t_dshore_nwe)
+    (list  "_8" t_dshore_s)
+    (list  "_9" t_dshore_ns)
+    (list  "_a" t_dshore_ws)
+    (list  "_b" t_dshore_nws)
+    (list  "_c" t_dshore_es)
+    (list  "_d" t_dshore_nes)
+    (list  "_e" t_dshore_wes)
+    (list  "_f" t_dshore_c)
+       
+       (list  "*1" t_voids_n)             ;; void + land
+    (list  "*2" t_voids_w)
+    (list  "*3" t_voids_nw)
+    (list  "*4" t_voids_e)
+    (list  "*5" t_voids_ne)
+    (list  "*6" t_voids_we)
+    (list  "*7" t_voids_nwe)
+    (list  "*8" t_voids_s)
+    (list  "*9" t_voids_ns)
+    (list  "*a" t_voids_ws)
+    (list  "*b" t_voids_nws)
+    (list  "*c" t_voids_es)
+    (list  "*d" t_voids_nes)
+    (list  "*e" t_voids_wes)
+    (list  "*f" t_voids_c)
+       
+       (list  "{1" t_hilledge_n)          ;; grass + hills
+    (list  "{2" t_hilledge_w)
+    (list  "{3" t_hilledge_nw)
+    (list  "{4" t_hilledge_e)
+    (list  "{5" t_hilledge_ne)
+    (list  "{6" t_hilledge_we)
+    (list  "{7" t_hilledge_nwe)
+    (list  "{8" t_hilledge_s)
+    (list  "{9" t_hilledge_ns)
+    (list  "{a" t_hilledge_ws)
+    (list  "{b" t_hilledge_nws)
+    (list  "{c" t_hilledge_es)
+    (list  "{d" t_hilledge_nes)
+    (list  "{e" t_hilledge_wes)
+    (list  "{f" t_hilledge_c)
+       
+    (list  "%3" t_bog_nw)              ;; bog + land
+    (list  "%5" t_bog_ne)
+    (list  "%7" t_bog_nwe)
+    (list  "%a" t_bog_ws)
+    (list  "%b" t_bog_nws)
+    (list  "%c" t_bog_es)
+    (list  "%d" t_bog_nes)
+    (list  "%e" t_bog_wes)
+    (list  "%f" t_bog_c)
+
+    (list  "t3" t_trees_nw)               ;; trees + grass
+    (list  "t5" t_trees_ne)
+    (list  "t7" t_trees_nwe)
+    (list  "ta" t_trees_ws)
+    (list  "tb" t_trees_nws)
+    (list  "tc" t_trees_es)
+    (list  "td" t_trees_nes)
+    (list  "te" t_trees_wes)
+    (list  "tf" t_trees_c)
+
+       (list  "t#" t_grasst_nw)             ;; grass + trees
+    (list  "t%" t_grasst_ne)
+    (list  "t&" t_grasst_nwe)
+    (list  "tA" t_grasst_ws)
+    (list  "tB" t_grasst_nws)
+    (list  "tC" t_grasst_es)
+    (list  "tD" t_grasst_nes)
+    (list  "tE" t_grasst_wes)
+    (list  "tF" t_grasst_c)
+       
+       (list  "~#" t_grassw_nw)           ;; grass + water
+    (list  "~%" t_grassw_ne)
+    (list  "~&" t_grassw_nwe)
+    (list  "~A" t_grassw_ws)
+    (list  "~B" t_grassw_nws)
+    (list  "~C" t_grassw_es)
+    (list  "~D" t_grassw_nes)
+    (list  "~E" t_grassw_wes)
+    (list  "~F" t_grassw_c)
+       
+       (list  "{#" t_hilli_nw)             ;; hills + grass
+    (list  "{%" t_hilli_ne)
+    (list  "{&" t_hilli_nwe)
+    (list  "{A" t_hilli_ws)
+    (list  "{B" t_hilli_nws)
+    (list  "{C" t_hilli_es)
+    (list  "{D" t_hilli_nes)
+    (list  "{E" t_hilli_wes)
+    (list  "{F" t_hilli_c)
+       
+       (list  "|#" t_forestg_nw)          ;; forest + grass
+    (list  "|%" t_forestg_ne)
+    (list  "|&" t_forestg_nwe)
+    (list  "|A" t_forestg_ws)
+    (list  "|B" t_forestg_nws)
+    (list  "|C" t_forestg_es)
+    (list  "|D" t_forestg_nes)
+    (list  "|E" t_forestg_wes)
+
+       (list  "tG" t_treew_nw)            ;; trees + water
+    (list  "tH" t_treew_ne)
+    (list  "tI" t_treew_nwe)
+    (list  "tJ" t_treew_ws)
+    (list  "tK" t_treew_nws)
+    (list  "tL" t_treew_es)
+    (list  "tM" t_treew_nes)
+    (list  "tN" t_treew_wes)
+    (list  "tO" t_treew_c)
+       
+       (list  "{G" t_hillw_nw)            ;; hills + water
+    (list  "{H" t_hillw_ne)
+    (list  "{I" t_hillw_nwe)
+    (list  "{J" t_hillw_ws)
+    (list  "{K" t_hillw_nws)
+    (list  "{L" t_hillw_es)
+    (list  "{M" t_hillw_nes)
+    (list  "{N" t_hillw_wes)
+    (list  "{O" t_hillw_c)     
+       
+       (list  "{g" t_hillv_nw)           ;; hills + void
+    (list  "{h" t_hillv_ne)
+    (list  "{i" t_hillv_nwe)
+    (list  "{j" t_hillv_ws)
+    (list  "{k" t_hillv_nws)
+    (list  "{l" t_hillv_es)
+    (list  "{m" t_hillv_nes)
+    (list  "{n" t_hillv_wes)   
+       
+       (list  ".g" t_grassv_nw)          ;; grass + void
+    (list  ".h" t_grassv_ne)
+    (list  ".i" t_grassv_nwe)
+    (list  ".j" t_grassv_ws)
+    (list  ".k" t_grassv_nws)
+    (list  ".l" t_grassv_es)
+    (list  ".m" t_grassv_nes)
+    (list  ".n" t_grassv_wes)
+       
+       (list  "^g" t_mountv_nw)        ;; mounts + void
+    (list  "^h" t_mountv_ne)
+    (list  "^i" t_mountv_nwe)
+    (list  "^j" t_mountv_ws)
+    (list  "^k" t_mountv_nws)
+    (list  "^l" t_mountv_es)
+    (list  "^m" t_mountv_nes)
+    (list  "^n" t_mountv_wes)  
+       
+       (list  "^3" t_mountg_nw)     ;; mounts + grass
+    (list  "^5" t_mountg_ne)
+    (list  "^7" t_mountg_nwe)
+    (list  "^a" t_mountg_ws)
+    (list  "^b" t_mountg_nws)
+    (list  "^c" t_mountg_es)
+    (list  "^d" t_mountg_nes)
+    (list  "^e" t_mountg_wes)
+    (list  "^f" t_mountg_c)    
+       
+       (list  "^G" t_mountw_nw)        ;; mounts + water
+    (list  "^H" t_mountw_ne) 
+    (list  "^I" t_mountw_nwe)
+    (list  "^J" t_mountw_ws)
+    (list  "^K" t_mountw_nws)
+    (list  "^L" t_mountw_es)
+    (list  "^M" t_mountw_nes)
+    (list  "^N" t_mountw_wes)
+    (list  "^O" t_mountw_c)    
+       
+    (list  "!3" t_lava_nw)        ;; lava + land
+    (list  "!5" t_lava_ne)
+    (list  "!6" t_lava_we)
+    (list  "!7" t_lava_nwe)
+    (list  "!a" t_lava_ws)
+    (list  "!b" t_lava_nws)
+    (list  "!c" t_lava_es)
+    (list  "!d" t_lava_nes)
+    (list  "!e" t_lava_wes)
+    (list  "!f" t_lava_c)
+    
+    (list      "#=" t_rail_ew)
+    (list      "#|" t_rail_ns)
+    (list      "#a" t_bulwark_n)
+    (list      "#b" t_bulwark_w)
+    (list      "#c" t_bulwark_e)
+    (list      "#d" t_bulwark_s)
+    (list      "#A" t_bulwark_v_n)
+    (list      "#B" t_bulwark_v_w)
+    (list      "#C" t_bulwark_v_e)
+    (list      "#D" t_bulwark_v_s)
+    (list      "#e" t_bulwark_w_nw)
+    (list      "#f" t_bulwark_w_ne)
+    (list      "#g" t_bulwark_w_sw)
+    (list      "#h" t_bulwark_w_se)
+    (list      "#E" t_bulwark_d_nw)
+    (list      "#F" t_bulwark_d_ne)
+    (list      "#G" t_bulwark_d_sw)
+    (list      "#H" t_bulwark_d_se)  
+    (list      "#i" t_bulwark_v_nw)
+    (list      "#j" t_bulwark_v_ne)
+    (list      "#k" t_bulwark_v_sw)
+    (list      "#l" t_bulwark_v_se)
+    (list      "#I" t_bulwark_x_nw)
+    (list      "#J" t_bulwark_x_ne)
+    (list      "#K" t_bulwark_x_sw)
+    (list      "#L" t_bulwark_x_se)
+    (list      "#s" t_bulwark_x_ns)
+    (list      "#r" t_bulwark_x_ew)    
+  
+    (list      "#m" t_tank_l)
+    (list      "#M" t_tank_d)
+    (list      "#n" t_tank_nw)
+    (list      "#o" t_tank_ne)
+    (list      "#p" t_tank_sw)
+    (list      "#q" t_tank_se)  
+    (list      "#N" t_tank_d_nw)
+    (list      "#O" t_tank_d_ne)
+    (list      "#P" t_tank_d_sw)
+    (list      "#Q" t_tank_d_se) 
+      
+    (list      "<n" t_stair_un)
+    (list      "<s" t_stair_us)
+    (list      "<w" t_stair_uw)
+    (list      "<e" t_stair_ue)
+    
+    (list      "rn" t_nat_rock)
+    (list      "r1" t_nat_rock_n)
+    (list      "r2" t_nat_rock_w)
+    (list      "r3" t_nat_rock_nw)
+    (list      "r4" t_nat_rock_e)
+    (list      "r5" t_nat_rock_ne)
+    (list      "r6" t_nat_rock_we)
+    (list      "r7" t_nat_rock_nwe)
+    (list      "r8" t_nat_rock_s)
+    (list      "r9" t_nat_rock_ns)
+    (list      "ra" t_nat_rock_ws)
+    (list      "rb" t_nat_rock_nws)
+    (list      "rc" t_nat_rock_es)
+    (list      "rd" t_nat_rock_nes)
+    (list      "re" t_nat_rock_wes)
+    (list      "rf" t_nat_rock_nwes)
+     (list     "r~" t_fake_wall_nrock)   
+
+  )
+) ;; palette pal_expanded
+
diff --git a/worlds/haxima-1.002/parties.scm b/worlds/haxima-1.002/parties.scm
new file mode 100644 (file)
index 0000000..0210a62
--- /dev/null
@@ -0,0 +1,361 @@
+;;----------------------------------------------------------------------------
+;; pgroup -- one type of npc within an npc party type
+(define (pgroup-mk npct dice)
+  (list 'pgroup npct dice))
+(define (pgroup-npct pgrp) (cadr pgrp))
+(define (pgroup-dice pgrp) (caddr pgrp))
+(define (pgroup-size pgrp)
+  (define (loop n sum)
+    ;;(println "  pgroup-size loop n=" n "sum=" sum)
+    (if (= n 0)
+        sum
+        (loop (- n 1)
+              (+ sum (max 0 (kern-dice-roll (pgroup-dice pgrp))))
+              )))
+  (loop (min 3
+             (max 1 
+                  (length (filter is-alive? 
+                                  (kern-party-get-members (kern-get-player))))))
+        0)
+  )
+(define (pgroup-generate pgrp)
+  ;;(println " pgroup-generate")
+  (define (loop n)
+    ;;(println "  n=" n)
+    (if (<= n 0)
+        nil
+        (cons (mk-npc (pgroup-npct pgrp) (calc-level))
+              (loop (- n 1)))))
+  (loop (pgroup-size pgrp)))
+
+;;----------------------------------------------------------------------------
+;; ptype -- npc party type
+(define (ptype-mk name sprite faction dc scarce . groups)
+  (list 'ptype sprite faction groups name dc scarce nil))
+(define (ptype-sprite ptype) (cadr ptype))
+(define (ptype-faction ptype) (caddr ptype))
+(define (ptype-groups ptype) (cadddr ptype))
+(define (ptype-name ptype) (list-ref ptype 4))
+(define (ptype-dc ptype) (list-ref ptype 5))
+(define (ptype-scarcity ptype) (list-ref ptype 6))
+(define (ptype-vehicle-type-tag ptype) (list-ref ptype 7))
+(define (ptype-set-vehicle-type-tag! ptype vtag)
+  (set-car! (list-tail ptype 7) vtag))
+(define (ptype-generate ptype)
+  ;;(println "ptype-generate")
+  (let ((kparty (kern-mk-party)))
+    (kern-being-set-name kparty (ptype-name ptype))
+    (kern-obj-set-sprite kparty (ptype-sprite ptype))
+    (kern-being-set-base-faction kparty (ptype-faction ptype))
+    (map (lambda (pgroup)
+           (map (lambda (kchar)
+                  (kern-party-add-member kparty kchar))
+                (pgroup-generate pgroup)))
+         (ptype-groups ptype))
+    (let ((vtag (ptype-vehicle-type-tag ptype)))
+      ;;(println "vtag=" vtag)
+      (if (not (null? vtag))
+          (kern-party-set-vehicle kparty 
+                                  (mk-vehicle (eval vtag)))))
+    kparty
+    ))
+
+;;----------------------------------------------------------------------------
+;; mk-npc-party
+(define (mk-npc-party ptype-tag) 
+  (ptype-generate (eval ptype-tag)))
+
+;;----------------------------------------------------------------------------
+;; NPC PARTY TYPES
+(define forest-goblin-party-l1
+  (ptype-mk "goblin stalker" s_fgob_stalker faction-forest-goblin 1 2
+            (pgroup-mk 'forest-goblin-stalker "1")
+            ))            
+(define forest-goblin-party-l2
+  (ptype-mk "goblin scouting party" s_fgob_archer faction-forest-goblin 2 2
+            (pgroup-mk 'forest-goblin-stalker "1")
+            (pgroup-mk 'forest-goblin-hunter  "1")
+            ))
+            
+(define forest-goblin-party-l3 
+  (ptype-mk "goblin hunting party" s_fgob_archer faction-forest-goblin 3 2
+            (pgroup-mk 'forest-goblin-stalker "1d2")
+            (pgroup-mk 'forest-goblin-hunter  "1d2")
+            (pgroup-mk 'wolf "1d2")
+            ))
+(define forest-goblin-party-l4 
+  (ptype-mk "goblin tribe"  s_fgob_civilian faction-forest-goblin 4 2
+            (pgroup-mk 'forest-goblin-stalker "1d2")
+            (pgroup-mk 'forest-goblin-hunter  "1d2")
+            (pgroup-mk 'wolf "1d2")
+            (pgroup-mk 'forest-goblin-shaman "1")
+            ))
+(define bandit-party-l1
+  (ptype-mk "gang of footpads" s_brigand faction-outlaw 1 4
+            (pgroup-mk 'footpad "1d2")
+            ))
+(define bandit-party-l2
+  (ptype-mk "gang of bandits" s_brigand faction-outlaw 2 4
+            (pgroup-mk 'bandit "1d2")
+            ))
+(define bandit-party-l3
+  (ptype-mk "a gang of highwaymen" s_brigand faction-outlaw 3 4
+            (pgroup-mk 'highwayman "1d2")
+            ))
+(define bandit-party-l4
+  (ptype-mk "a gang of blackguards" s_brigand faction-outlaw 4 4
+            (pgroup-mk 'blackguard "1d2")
+            ))
+(define bandit-party-l5
+  (ptype-mk "a gang of sinister blackguards" s_brigand faction-outlaw 5 4
+            (pgroup-mk 'blackguard "1d2")
+            (pgroup-mk 'bomber "1d2")
+            ))
+(define pirate-party-l3
+  (ptype-mk "crew of pirates" s_brigand faction-outlaw 3 5
+            (pgroup-mk 'highwayman "1d2")
+            ))
+(ptype-set-vehicle-type-tag! pirate-party-l3 't_ship)
+(define pirate-party-l4
+  (ptype-mk "crew of pirates" s_brigand faction-outlaw 3 5
+            (pgroup-mk 'blackguard "1d2")
+            ))
+(ptype-set-vehicle-type-tag! pirate-party-l4 't_ship)
+(define troll-party-l3
+  (ptype-mk "band of trolls" s_troll faction-troll 3 5
+            (pgroup-mk 'troll "1")
+            ))
+(define troll-party-l4
+  (ptype-mk "band of trolls with goblin slaves" s_troll faction-troll 4 5
+            (pgroup-mk 'troll "1")
+            (pgroup-mk 'forest-goblin-stalker "1d3-1")
+            ))
+(define green-slime-party-l2
+  (ptype-mk "ooze of slimes" s_slime faction-monster 2 3
+            (pgroup-mk 'green-slime "1d3")
+            ))
+(define yellow-slime-party-l3
+  (ptype-mk "yellow slime colony" s_yellow_slime faction-monster 3 3
+            (pgroup-mk 'green-slime "1d3")
+            (pgroup-mk 'yellow-slime "1")
+            ))
+(define fire-slime-party-l4
+  (ptype-mk "fire slime colony" s_red_slime faction-monster 4 3
+            (pgroup-mk 'fire-slime "1d2")
+            ))
+(define hydra-party-l5
+  (ptype-mk "hydra with slimes" s_hydra faction-monster 5 3
+            (pgroup-mk 'green-slime "1d3")
+            (pgroup-mk 'yellow-slime "1d2")
+            (pgroup-mk 'hydra "1")
+            ))
+
+(define dryad-party-l3
+  (ptype-mk "dryad grove" s_reaper faction-monster 3 5
+            (pgroup-mk 'dryad "1")
+            ))
+
+(define dryad-party-l4
+  (ptype-mk "dryad grove with wolves" s_reaper faction-monster 4 5
+            (pgroup-mk 'dryad "1")
+            (pgroup-mk 'wolf "1d3")
+            ))
+
+(define dryad-party-l5
+  (ptype-mk "dryad grove with shamans" s_reaper faction-monster 5 5
+            (pgroup-mk 'dryad "1")
+            (pgroup-mk 'forest-goblin-shaman "1d3")
+            ))
+
+(define wolf-party-l1 
+  (ptype-mk "wolf pack" s_wolf faction-monster 2 5
+            (pgroup-mk 'wolf "1")
+            ))
+
+(define wolf-party-l2 
+  (ptype-mk "wolf pack" s_wolf faction-monster 2 5
+            (pgroup-mk 'wolf "1d3")
+            ))
+
+(define skeleton-party-l2
+  (ptype-mk "skeleton brigade" s_skeleton faction-monster 2 5
+            (pgroup-mk 'skeletal-warrior "1")
+            ))
+
+(define skeleton-party-l3
+  (ptype-mk "skeleton brigade" s_skeleton faction-monster 3 5
+            (pgroup-mk 'skeletal-warrior "1")
+            (pgroup-mk 'skeletal-spear-thrower "1")
+            ))
+(define skeleton-party-l4 
+  (ptype-mk "skeleton brigade" s_skeleton faction-monster 4 5
+            (pgroup-mk 'skeletal-warrior "1d2")
+            (pgroup-mk 'skeletal-spear-thrower "1d3")
+            ))
+(define skeleton-pirates-l4 
+  (ptype-mk "crew of cursed pirates" s_skeleton faction-monster 4 5
+            (pgroup-mk 'skeletal-warrior "1d2")
+            (pgroup-mk 'skeletal-spear-thrower "1d3")
+            ))
+(ptype-set-vehicle-type-tag! skeleton-pirates-l4 't_ship)
+
+(define lich-party-l5
+  (ptype-mk "lich with undead servants" s_lich faction-monster 5 5
+            (pgroup-mk 'lich "1")
+            (pgroup-mk 'skeletal-warrior "1d2")
+            (pgroup-mk 'skeletal-spear-thrower "1d3")
+            ))
+
+(define wisp-party-l5
+  (ptype-mk "swarm of wisps" s_wisp faction-none 5 5
+            (pgroup-mk 'wisp "1d3")
+            ))
+
+(define ghast-party 
+  (ptype-mk "haunt of ghasts" s_ghost faction-monster 1 2
+            (pgroup-mk 'ghast "1d3")
+            ))
+
+(define dragon-party-l6
+  (ptype-mk "lone dragon" s_dragon_party faction-monster 6 1
+            (pgroup-mk 'dragon "1")
+            ))
+
+(define dragon-party-l7
+  (ptype-mk "dragon with cave goblins" s_dragon_party faction-monster 7 1
+            (pgroup-mk 'dragon "1")
+            (pgroup-mk 'cave-goblin-berserker "1d2")
+            (pgroup-mk 'cave-goblin-slinger "1d2")
+            (pgroup-mk 'cave-goblin-priest "1")
+            ))
+
+(define dragon-party-l8
+  (ptype-mk "flock of dragons" s_dragon_party faction-monster 8 1
+            (pgroup-mk 'dragon "1d3")
+            ))
+
+(define gint-party-l4
+  (ptype-mk "gint scouting party" s_gint_party faction-gint 4 5
+            (pgroup-mk 'gint-warrior "1")
+            ))
+
+(define gint-party-l5
+  (ptype-mk "gint hunting party" s_gint_party faction-gint 5 5
+            (pgroup-mk 'gint-warrior "1")
+            (pgroup-mk 'cave-goblin-slinger "1d2")
+            (pgroup-mk 'wolf "1d2")
+            ))
+
+(define gint-party-l6
+  (ptype-mk "gint war party" s_gint_party faction-gint 6 3
+            (pgroup-mk 'gint-warrior "1d2")
+            (pgroup-mk 'troll "1d2")
+            (pgroup-mk 'cave-goblin-slinger "1d3")
+            (pgroup-mk 'wolf "1d2")
+            ))
+
+(define kraken-party-l3
+  (ptype-mk "school of kraken" s_kraken faction-monster 3 5
+            (pgroup-mk 'kraken "1d2")
+            ))
+
+(define sea-serpent-party-l3
+  (ptype-mk "school of sea serpents" s_sea_serpent faction-monster 3 5
+            (pgroup-mk 'sea-serpent "1d2")
+            ))
+
+(define nixie-party-l2
+  (ptype-mk "school of nixies" s_nixie_spear faction-monster 2 3
+            (pgroup-mk 'nixie-swordsman "1d2")
+            (pgroup-mk 'nixie-spearman "1d2-1")
+            ))
+
+(define nixie-party-l3
+  (ptype-mk "school of nixies with kraken" s_kraken faction-monster 3 5
+            (pgroup-mk 'nixie-swordsman "1d2")
+            (pgroup-mk 'nixie-spearman "1d2")
+            (pgroup-mk 'kraken "1")
+            ))
+
+(define nixie-party-l4
+  (ptype-mk "school of nixies with kraken" s_kraken faction-monster 3 5
+            (pgroup-mk 'nixie-swordsman "1d2")
+            (pgroup-mk 'nixie-spearman "1d2")
+            (pgroup-mk 'kraken "1")
+            ))
+
+(define nixie-party-l5
+  (ptype-mk "school of nixies with sea serpent" s_sea_serpent faction-monster 4 5
+            (pgroup-mk 'nixie-swordsman "1d2")
+            (pgroup-mk 'nixie-spearman "1d2")
+            (pgroup-mk 'sea-serpent "1")
+            ))
+
+(define spider-party-l3
+  (ptype-mk "clutch of spiders" s_spider faction-spider 3 5
+            (pgroup-mk 'giant-spider "1d2")
+            ))
+
+(define spider-party-l4
+  (ptype-mk "clutch of spiders" s_spider faction-spider 4 5
+            (pgroup-mk 'giant-spider "1d2")
+            (pgroup-mk 'queen-spider "1")
+            ))
+(define headless-party-l1
+  (ptype-mk "headless horror" s_headless faction-monster 1 4
+            (pgroup-mk 'headless "1")))
+(define headless-party-l3
+  (ptype-mk "mob of headless horrors" s_headless faction-monster 3 4
+            (pgroup-mk 'headless "1d2")))
+(define headless-party-l5
+  (ptype-mk "warlock with headless horrors" s_wizard faction-monster 5 4
+            (pgroup-mk 'headless "1d2")
+            (pgroup-mk 'warlock "1")
+            ))
+
+(define accursed-party-l4
+  (ptype-mk "accursed master" s_wizard faction-accursed 4 2
+            (pgroup-mk 'accursed-master "1")
+            (pgroup-mk 'accursed-apprentice "1d2-1")
+            (pgroup-mk 'accursed-guardian "1d2")
+            ))
+(define accursed-party-l5
+  (ptype-mk "accursed master" s_wizard faction-accursed 5 2
+            (pgroup-mk 'accursed-master "1")
+            (pgroup-mk 'accursed-defender "1d2")
+            ))
+(define accursed-party-l6
+  (ptype-mk "accursed adept" s_wizard faction-accursed 6 2
+            (pgroup-mk 'accursed-master "1")
+            (pgroup-mk 'accursed-defender "1d2")
+            (pgroup-mk 'accursed-templar "1d2")
+            ))
+(define militia-party-l4
+  (ptype-mk "squad of deserters" s_guard faction-outlaw  4 4
+            (pgroup-mk 'halberdier "1d2")
+            (pgroup-mk 'crossbowman "1d2-1")
+            ))
+
+(define snake-party-l1
+  (ptype-mk "rave of snakes" s_snake faction-monster 1 5
+            (pgroup-mk 'snake "1d2")
+            ))
+(define bat-party-l1
+  (ptype-mk "cloud of bats" s_bat faction-monster 1 1
+            (pgroup-mk 'bat "1d2")
+            ))
+
+(define rat-party-l1
+  (ptype-mk "pack of rats" s_rat faction-monster 5 5
+            (pgroup-mk 'rat "1d2")
+            ))
+
+(define griffin-party-l3
+  (ptype-mk "pride of griffins" s_griffin faction-monster 3 5
+            (pgroup-mk 'griffin "1d2")
+            ))
+
+(define insect-party-l1
+  (ptype-mk "cloud of insects" s_insects faction-monster 1 5
+            (pgroup-mk 'insect "1d3")
+            ))
\ No newline at end of file
diff --git a/worlds/haxima-1.002/patch.scm b/worlds/haxima-1.002/patch.scm
new file mode 100644 (file)
index 0000000..a3acfe5
--- /dev/null
@@ -0,0 +1,171 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Glasdrin
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_patch
+               (list 0  0  gdp-bed "sleeping")
+               (list 7  0  ghg-s1  "eating")
+               (list 8  0  gh-ward "working")
+               (list 11 0  ghg-s1  "eating")
+               (list 12 0  gh-ward "working")
+               (list 17 0  ghg-s1  "eating")
+               (list 18 0  gc-hall "idle")
+               (list 21 0  gdp-hut "idle")
+               (list 22 0  gdp-bed "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (patch-mk) (list 'townsman))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; An old wizard living in Glasdrin, who works as a healer.
+;; He wears an eyepatch, and is known as "Doc Patch".
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (patch-hail knpc kpc)
+  (say knpc "[You meet a sprightly old wizard with an eyepatch] "
+       "Hail, traveler."))
+
+(define (patch-default knpc kpc)
+  (say knpc "I can't help you with that."))
+
+(define (patch-name knpc kpc)
+  (say knpc "People call me Doc Patch."))
+
+(define (patch-join knpc kpc)
+  (say knpc "No, my duty is here, Wanderer."))
+
+(define (patch-job knpc kpc)
+  (say knpc "I run the hospital. Do you need healing?")
+  (if (kern-conv-get-yes-no? kpc)
+      (patch-trade knpc kpc)
+      (say knpc "Well if you ever do, I can fix you up.")))
+
+(define (patch-bye knpc kpc)
+  (say knpc "Keep well!"))
+
+;; Trade...
+(define (patch-trade knpc kpc)
+  (if (trade-services knpc kpc
+                      (list
+                       (svc-mk "Heal" 30 heal-service)
+                       (svc-mk "Cure" 30 cure-service)
+                       (svc-mk "Resurrect" 100 resurrect-service)))
+      (begin
+        (say knpc "What else can I do for you?")
+        (patch-trade knpc kpc))
+      (begin
+        (say knpc "Will there be anything else?")
+        (if (kern-conv-get-yes-no? kpc)
+            (patch-trade knpc kpc)
+            (say knpc "Very well.")))))
+  
+;; Patch...
+(define (patch-patc knpc kpc)
+  (say knpc "I lost my eye in Kurpolis. It's so dark there I didn't really "
+       "need it. [He winks. With his good eye.]"))
+
+(define (patch-kurp knpc kpc)
+  (say knpc "The paladins keep an outpost in the dungeon, and "
+       "I did a tour of duty down there in my youth."))
+
+(define (patch-tour knpc kpc)
+  (say knpc "All citizens of Glasdrin are required to serve a tour of duty. "
+       "I was a medik."))
+
+(define (patch-medi knpc kpc)
+  (say knpc "A medik is a mage that specializes in healing arts. Paladin "
+       "squads are all assigned a medik to support them in battle. "
+       "We get some basic combat training, but I only had to use my dagger "
+       "once."))
+
+(define (patch-dagg knpc kpc)
+  (say knpc "Yep, I carried that dagger for six months and finally got to use "
+       "it... peeling potatoes for kitchen duty."))
+
+(define (patch-dung knpc kpc)
+  (say knpc "Monsters breed in the deeps, and it's better to stop them there "
+       "before they can get to the surface. Don't you agree?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "You're damned tootin'! So the paladins keep a company there "
+           "to patrol the middle levels. If you ever find yourself in need "
+           "of help down there, seek them out. They'll have a medik.")
+      (say knpc "Harumph! I suppose you'd rather let them run amok over "
+           "the countryside!")))
+
+(define (patch-doc knpc kpc)
+  (say knpc "I'm a medik. Are you in need of healing?")
+  (if (kern-conv-get-yes-no? kpc)
+      (patch-trade knpc kpc)
+      (say knpc "Ok. Come by the hospital if you ever need assistance. "
+           "I know how you adventurers get torn up in fights!")))
+
+(define (patch-hosp knpc kpc)
+  (say knpc "Yep. The paladins of Glasdrin are always getting in scraps. "
+       "I get the odd adventurer and sick villager in, too."))
+
+;; Townspeople...
+
+(define patch-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default patch-default)
+       (method 'hail patch-hail)
+       (method 'bye  patch-bye)
+       (method 'job  patch-job)
+       (method 'name patch-name)
+       (method 'join patch-join)
+       
+       ;; trade
+       (method 'trad patch-trade)
+       (method 'heal patch-trade)
+       (method 'cure patch-trade)
+       (method 'resu patch-trade)
+       (method 'help patch-trade)
+
+       ;; patch
+       (method 'patc patch-patc)
+       (method 'kurp patch-kurp)
+       (method 'tour patch-tour)
+       (method 'medi patch-medi)
+       (method 'dagg patch-dagg)
+       (method 'dung patch-dung)
+       (method 'doc  patch-doc)
+       (method 'hosp patch-hosp)
+       (method 'outp patch-dung)
+
+       ;; town & people
+
+       ))
+
+(define (mk-patch)
+  (bind 
+   (kern-mk-char 'ch_patch           ; tag
+                 "Patch"             ; name
+                 sp_human            ; species
+                 oc_wizard           ; occ
+                 s_companion_wizard  ; sprite
+                 faction-glasdrin         ; starting alignment
+                 1 3 0               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 6            ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'patch-conv         ; conv
+                 sch_patch           ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_staff)))                 ; container
+                 (list t_dagger)                 ; readied
+                 )
+   (patch-mk)))
diff --git a/worlds/haxima-1.002/pitfalls.png b/worlds/haxima-1.002/pitfalls.png
new file mode 100644 (file)
index 0000000..5bfccfd
Binary files /dev/null and b/worlds/haxima-1.002/pitfalls.png differ
diff --git a/worlds/haxima-1.002/pitfalls.scm b/worlds/haxima-1.002/pitfalls.scm
new file mode 100644 (file)
index 0000000..62b13b6
--- /dev/null
@@ -0,0 +1,138 @@
+;;----------------------------------------------------------------------------
+;; pitfall - "A source of danger or difficulty not easily foreseen and avoided"
+;;
+;; Traps may be attached to doors (see doors.scm) or containers (see
+;; container.scm), but I also want some objects that are _just_ traps. They
+;; start out invisible, but when detected they become visible. When a character
+;; steps on one that is still hidden, the 'step' signal handler rolls and uses
+;; the character's thiefly skill to determine if the character detects and
+;; avoids the trap before it trips.
+;;----------------------------------------------------------------------------
+(define (mk-pitfall name ddc dmg usedc) (list 'pitfall name ddc dmg #f #t usedc))
+(define (pitfall-name pfall) (cadr pfall))
+(define (pitfall-detect-dc pfall) (caddr pfall))
+(define (pitfall-damage pfall) (cadddr pfall))
+(define (pitfall-detected? pfall) (list-ref pfall 4))
+(define (pitfall-set-detected! pfall val) (list-set-ref! pfall 4 val))
+(define (pitfall-known-to-npc? pfall) (list-ref pfall 5))
+(define (pitfall-set-known-to-npc! pfall val) (list-set-ref! pfall 5 val))
+(define (pitfall-use-dc pfall) (list-ref pfall 6))
+
+;; The step handler runs whenever a character (kchar) steps on the pitfall
+;; object (kobj). If the pitfall has already been detected then no harm
+;; done. If the character is an NPC, and the pitfall was not put there by the
+;; player, then the NPC avoids it automatically. Otherwise the character gets a
+;; roll to avoid the pitfall. Whether avoided or not, the pitfall will be
+;; detected and made visible.
+(define (kpitfall-step-handler kobj kchar)
+  (let ((pfall (kobj-gob-data kobj)))
+    (if (and (not (pitfall-detected? pfall))
+             (or (is-player-party-member? kchar)
+                 (not (pitfall-known-to-npc? pfall))
+                 ))
+        (let ((roll (kern-dice-roll "1d20"))
+              (bonus (occ-thief-dice-roll kchar)))
+          (kern-obj-remove-effect kobj ef_permanent_invisibility)
+          (pitfall-set-detected! pfall #t)
+          (cond ((or (= roll 20)
+                     (> (+ roll bonus)
+                        (pitfall-detect-dc pfall)))
+                 (kern-log-msg (kern-obj-get-name kchar) 
+                               " ^c+gavoids^c- " 
+                               (pitfall-name pfall) 
+                               "!")
+                 )
+                (else
+                 (kern-log-msg (kern-obj-get-name kchar) " ^c+rtrips^c- "
+                               (pitfall-name pfall)
+                               "!")
+                 (kern-obj-apply-damage 
+                  kchar
+                  "ouch" 
+                  (kern-dice-roll (pitfall-damage pfall)))))))))
+
+;; This is a helper for kpitfall-use-handler. It checks if the location in the
+;; current place has the right passability class for a pitfall to be concealed
+;; on it.
+(define (terrain-ok-for-pitfall? loc)
+  (let ((pclass (kern-terrain-get-pclass (kern-place-get-terrain loc))))
+    (foldr (lambda (a b) (or a (= pclass b)))
+           #f
+           (list pclass-grass pclass-trees pclass-forest))))
+
+(define (mk-pitfall-from-ktype ktype)
+  (cond ((eqv? ktype t_caltrops) (mk-caltrops))
+        ((eqv? ktype t_beartrap) (mk-beartrap))))
+
+;; The use handler runs when the player directs a character (kchar) to use a
+;; pitfall type (ktype) from inventory. This prompts the player to select a
+;; tile. If the tile has the right passability and is unoccupied, this creates
+;; a new instance and conceals it on the tile.
+;;
+;; Update: this is dangerous. Roll against the kchar's thiefly skill to
+;; determine if they succeed or just manage to hurt themselves.
+(define (kpitfall-use-handler ktype kchar)
+  (if (not (has-skill? kchar sk_arm_trap))
+      result-lacks-skill
+      (let ((loc (kern-ui-target (kern-obj-get-location kchar) 1)))
+        (cond ((null? loc) 
+               (kern-log-msg "Abort!")
+               result-no-target
+               )
+              ((not (terrain-ok-for-pitfall? loc)) 
+               (kern-log-msg "Wrong terrain type!")
+               result-not-here
+               )
+              ((occupied? loc) 
+               (kern-log-msg "Somebody is there!")
+               result-not-here
+               )
+              (else
+               (let* ((kobj (mk-pitfall-from-ktype ktype))
+                      (pfall (kobj-gob-data kobj))
+                      )
+                 (cond ((null? kobj) 
+                        (kern-log-msg "Script error: unknown type")
+                        #f)
+                       ((not (check-roll (pitfall-use-dc pfall)
+                                         (occ-thief-dice-roll kchar)))
+                        (kern-log-msg "^c+rOOPS...^c- " 
+                                      (kern-obj-get-name kchar) 
+                                      " fumbles "
+                                      (pitfall-name pfall) "!")
+                        (kpitfall-step-handler kobj kchar)
+                        result-failed
+                        )
+                       (else
+                        (kern-log-msg (kern-obj-get-name kchar)
+                                      " plants "
+                                      (pitfall-name pfall)
+                                      "!")
+                        (kern-obj-put-at kobj loc)
+                        (kern-obj-remove-from-inventory kchar ktype 1)
+                        (pitfall-set-known-to-npc! pfall #f)
+                        result-ok
+                        ))))))))
+
+(define ktrap-ifc
+  (ifc obj-ifc
+       (method 'step kpitfall-step-handler)
+       (method 'use kpitfall-use-handler)
+       ))
+
+(kern-mk-sprite-set 'ss_pitfalls 32 32 8 8 0 0 "pitfalls.png")
+(kern-mk-sprite 's_caltrops ss_pitfalls 1 0 #f 0)
+(kern-mk-sprite 's_beartrap ss_pitfalls 1 1 #f 0)
+
+(mk-obj-type 't_caltrops "caltrops" s_caltrops layer-mechanism ktrap-ifc)
+(mk-obj-type 't_beartrap "beartrap" s_beartrap layer-mechanism ktrap-ifc)
+
+(define (mk-caltrops)
+  (let ((kobj (kern-mk-obj t_caltrops 1)))
+    (kern-obj-add-effect kobj ef_permanent_invisibility nil)
+    (bind kobj (mk-pitfall "a caltrops" 18 "1d10" dc-easy))))
+
+(define (mk-beartrap)
+  (let ((kobj (kern-mk-obj t_beartrap 1)))
+    (kern-obj-add-effect kobj ef_permanent_invisibility nil)
+    (bind kobj (mk-pitfall "a beartrap" 16 "2d10" dc-challenging))))
diff --git a/worlds/haxima-1.002/player.scm b/worlds/haxima-1.002/player.scm
new file mode 100644 (file)
index 0000000..b121a1a
--- /dev/null
@@ -0,0 +1,10 @@
+;; This defines the gob for the player party in haxima.
+;; This sort of thing would probably be best stored in quest flags.
+(define (player-gob) (gob (kern-get-player)))
+(define (mk-player-gob) (list 
+                         #f ;; found warritix
+                         #f ;; trial of stewardess done
+                         ))
+(define (player-found-warritrix?) (not (null? (quest-data-getvalue 'questentry-warritrix 'found))))
+(define (player-stewardess-trial-done?) (not (null? (quest-data-getvalue 'questentry-warritrix 'avenged))))
+
diff --git a/worlds/haxima-1.002/poor-house.scm b/worlds/haxima-1.002/poor-house.scm
new file mode 100644 (file)
index 0000000..ef52917
--- /dev/null
@@ -0,0 +1,89 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_poor_house 19 19 pal_expanded
+       (list
+               ".. .. .. .. .. .. .. .. .. /7 .. bb bb bb bb bb bb bb ta "
+               ".. /0 /d /d /d /d /d /d /d /a bb .. .. .. .. t3 tt t5 bb "
+               ".. /7 .. .. .. .. .. .. .. .. bb .. .. .. .. te bb tt bb "
+               ".. /7 .. rr rr rr rr rr rr bb rr .. .. .. .. t% tb tc bb "
+               ".. /7 .. rr .P .O .O .R ]] rr .. .. .. .. .. .. .. .. bb "
+               ".. /7 .. rr .H .O .U .S .E rr .. .. .. .. .. .. .. .. bb "
+               ".. /7 .. ,, ,, ,, ,, ,, ,, rr rr rr ,, rr bb rr .. .. bb "
+               ".. /7 .. bb ,, ,, ,, ,, ,, rr ,, ,, ,, ,, .. rr .. .. bb "
+               ".. /7 .. rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr bb bb .. "
+               "/d /6 .. rr rr rr ,, rr rr bb ,, ,, 00 ,, ,, wr .. /0 /d "
+               ".. /7 .. rr ,, ,, ,, ,, ,, rr ,, ,, 00 ,, ,, rr .. /7 .. "
+               ".. /7 .. rr ,, ,, ,, ,, ,, rr ,, ,, 00 ,, ,, rr .. /7 .. "
+               ".. /7 .. wr ,, ,, ,, ,, ,, rr ,, ,, ,, ,, ,, rr .. /7 .. "
+               ".. /7 .. rr ,, .. ,, ,, ,, rr ,, ,, ,, ,, ,, wr .. /7 .. "
+               ".. /7 .. rr ,, ,, .. ,, ,, rr ,, bb && bb ,, rr .. /7 .. "
+               ".. /7 .. rr rr rr bb rr rr rr rr rr rr rr rr rr .. /7 .. "
+               ".. /7 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. /7 .. "
+               ".. /8 /d /d /d /d /d /d /d /1 /d /d /d /d /d /d /d /a .. "
+               ".. .. .. .. .. .. .. .. .. /7 .. .. .. .. .. .. .. .. .. "
+       ))
+
+;;----------------------------------------------------------------------------
+;; NPC's
+;;----------------------------------------------------------------------------
+(kern-load "meaney.scm")
+(kern-load "amy.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_poor_house     ; tag
+ "The Poor House"      ; name
+ s_hamlet      ; sprite
+ m_poor_house      ; map
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+
+  ;; npcs
+  (put (mk-npc 'bull 6) 14 3)
+  (put (mk-meaney) 9 9)
+  (put (mk-amy) 9 9)
+
+  ;; beds
+  (put (mk-bed) 4 10)
+  (put (mk-bed)  4 12)
+  (put (mk-bed)  4 14)
+  (put (mk-bed)  8 10)
+  (put (mk-bed)  8 12)
+  (put (mk-bed)  8 14)
+
+  ;; doors
+  (put (mk-door-in-rock) 3 6)
+  (put (mk-door-in-rock) 12 6)
+  
+  ;empty doorways
+  (put (mk-archway-rock) 6 9)
+  (put (mk-archway-rock) 9 8)
+  
+  ;; chests
+  (put (mk-chest
+        nil
+        '((1 t_food))) 10 14)
+  (put (mk-chest
+        nil
+        '((1 t_gold_coins))) 14 14)
+
+  )
+
+ nil ; hooks
+ (list  ; edge entrances
+       (list southwest 10 0)
+ )
+ )
+
+
+(mk-place-music p_poor_house 'ml-small-town)
diff --git a/worlds/haxima-1.002/portals.scm b/worlds/haxima-1.002/portals.scm
new file mode 100644 (file)
index 0000000..cae40da
--- /dev/null
@@ -0,0 +1,232 @@
+;; portals.scm
+
+
+;; A portal destination is simply a Scheme list of (place x y).
+;; 
+;; Here are some convenience functions for:
+;; - creating a destination:  portal-mk
+;; - inquiring the place:     portal-place
+;; - inquiring the (x y):     portal-coords
+(define (portal-mk     place x y) (list place x y))
+(define (portal-place  portal)    (safe-eval (car portal)))
+(define (portal-coords portal)    (cons (portal-place portal) (cdr portal)))
+
+;; portal-step:
+;;     Function called when a portal is activated.
+;;     Causes the stepper to be relocated to the portal destination.
+(define (portal-step kportal kstepper)
+  (let ((portal (kobj-gob-data kportal)))
+    (kern-obj-relocate kstepper
+                       (portal-coords portal)
+                       nil)))
+
+;; prompt-portal-step:
+;;     Function called when a portal is activated.
+;;     Prints two UI confirmation prompts, and on double-confirmation, 
+;;     relocates the stepper.
+(define (prompt-portal-step kportal kstepper)
+  (kern-print "\n")
+  (kern-print "Are you SURE you want to step there?\n")
+  (if (kern-conv-get-yes-no? kstepper)
+      (begin
+        (kern-print "\n")
+        (kern-print "\n")
+        (kern-print "Are you REALLY REALLY SURE?\n")
+        (if (kern-conv-get-yes-no? kstepper)
+            (begin
+              (kern-print "\n")
+              (kern-print "\n")
+              (kern-print "\n")
+              (kern-print "Ok... you asked for it!\n")
+              (portal-step kportal kstepper))
+            (kern-print "Wise move.\n")))
+        (kern-print "Make up your mind.\n")))
+            
+
+(define portal-ifc
+  ;; This is the interface for a "use (E)nter command" portal, 
+  ;; which acts when the (E)nter command is invoked while standing upon the portal.
+  ;; 
+  ;; By convention, small-scale places accessible from a large-scale wilderness
+  ;; place are generally of this type.  It is thus possible to enter the 
+  ;; (smaller, contained) place from any direction, or to walk through that
+  ;; tile in the wilderness without entering.
+  (ifc '()
+       (method 'enter portal-step)))
+       
+(define bump-portal-ifc
+  ;; This is the interface for a pseudo-edge tile
+  ;; Marked impassable, but teleports you to the next area if yu bump into it
+  (ifc '()
+       (method 'init
+               (lambda (kobj)
+                 (kern-obj-set-pclass kobj pclass-wall)
+                 ))
+       (method 'bump portal-step)))
+
+(define auto-portal-ifc
+  ;; This is the interface for an "automatic enter" portal, 
+  ;; which acts immediately when stepped upon.
+  ;; 
+  ;; By convention, this interface is used for most small-scale portals,
+  ;; magical gates, and for trapdoors and other "surprise" portals.
+  (ifc '()
+       (method 'step portal-step)))
+
+(define prompting-auto-portal-ifc
+  ;; This is the interface for a "prompting" portal,
+  ;; which prints a UI prompt for the user to confirm their intention to enter.
+  ;; 
+  ;; By convention, this interface is used for non-surprise portals
+  ;; which present the appearance of not being able to readily return,
+  ;; such as holes in the floor (without a ladder or rope attched),
+  ;; or portals whose destination is (or appears to be) potentially hazardous,
+  ;; such as certain magical gates to unknown destinations.
+  (ifc '()
+       (method 'step prompt-portal-step)))
+
+
+;; Portal objects for some common portal types: 
+;;     Instances of such objects are placed on the appropriate map on the
+;;     "mechanisms" layer.  These object "types" specify a name/label, sprite,
+;;     and a portal "interface" behavior.  Instances are created by "portal
+;;     constructor" functions such as those below.
+(mk-obj-type 't_ladder_down "ladder leading down" s_ladder_down   layer-mechanism portal-ifc)
+(mk-obj-type 't_ladder_up   "ladder leading up"   s_ladder_up     layer-mechanism portal-ifc)
+(mk-obj-type 't_trap_door   "trap door"           '()             layer-mechanism auto-portal-ifc)
+(mk-obj-type 't_bump_door   nil           '()             layer-mechanism bump-portal-ifc)
+(mk-obj-type 't_teleporter  "teleporter"          s_floor_plate   layer-mechanism prompting-auto-portal-ifc)
+(mk-obj-type 't_dungeon "dungeon" s_dungeon layer-mechanism       auto-portal-ifc)
+(mk-obj-type 't_ship_relic "ship relic" s_ship layer-mechanism auto-portal-ifc)
+
+;; mk-portal -- generic helper constructor
+(define (mk-portal type place-tag x y)
+  (bind (kern-mk-obj type 1)
+        (portal-mk place-tag x y)))
+;; Portal constructor functions for some common portal types:
+;;     These functions create an instance of a portal type,
+;;     binding a destination (place-tag x y) to one of the "types" defined above.
+(define (mk-ladder-down place-tag x y) (mk-portal t_ladder_down place-tag x y))
+(define (mk-ladder-up   place-tag x y) (mk-portal t_ladder_up   place-tag x y))
+(define (mk-trap-door   place-tag x y) (mk-portal t_trap_door   place-tag x y))
+(define (mk-bump-door   place-tag x y) (mk-portal t_bump_door   place-tag x y))
+(define (mk-teleporter  place-tag x y) (mk-portal t_teleporter  place-tag x y))
+(define (mk-dungeon place-tag x y) (mk-portal t_dungeon place-tag x y))
+(define (mk-ship-relic place-tag x y) (mk-portal t_ship_relic place-tag x y))
+
+;;----------------------------------------------------------------------------
+;; Special portal -- entrance to thief's cave near Bole. Invisible, but under
+;; reveal it shows the letter 'O'. When stepped on at midnight the player is
+;; transported to the Traps I dungeon.
+;;----------------------------------------------------------------------------
+(define (thief-door-step kportal kchar)
+  (let ((time (kern-get-time)))
+    (if (and (>= (time-hour time) 0)
+             (< (time-hour time) 3))
+        (portal-step kportal kchar))))
+
+(define thief-door-ifc
+  (ifc '()
+       (method 'step thief-door-step)))
+
+(mk-obj-type 't_thief_door "strange mark" s_O layer-mechanism thief-door-ifc)
+
+(define (mk-thief-door place-tag x y)
+  (make-invisible (mk-portal t_thief_door place-tag x y)))
+
+;;----------------------------------------------------------------------------
+;; Secret Path -- visible only when Reveal is in effect
+;;----------------------------------------------------------------------------
+(mk-obj-type 't_secret_path "secret path" s_cobblestone layer-none nil)
+(define (mk-secret-path)
+  (make-invisible (kern-mk-obj t_secret_path 1)))
+
+;;----------------------------------------------------------------------------
+;; Clue Trigger -- make a mechanism which will provide a clue when stepped
+;; on. Technically not a portal, but it doesn't really fit anywhere else,
+;; either.
+;;----------------------------------------------------------------------------
+(define (clue-mk msg) msg)
+(define (clue-msg clue) clue)
+(define (clue-trigger clue)
+  (apply kern-log-msg (clue-msg clue)))
+
+(define (clue-step kmech kchar)
+  (clue-trigger (kobj-gob-data kmech)))
+
+(define clue-step-ifc
+  (ifc '()
+       (method 'step clue-step)))
+
+(mk-obj-type 't_step_clue nil nil layer-mechanism clue-step-ifc)
+
+(define (mk-step-clue . msg)
+  (bind (kern-mk-obj t_step_clue 1)
+        (clue-mk msg)))
+
+;;----------------------------------------------------------------------------
+;; The riddle machine -- fills region with given terrain when answered
+;; incorrectly
+;;----------------------------------------------------------------------------
+(define (riddle-mk ans ter-tag x y w h pos? msg)
+  (list ans ter-tag x y w h pos? msg 
+        #t  ;; rm-on-correct
+        #t  ;; rm-on-wrong
+        ))
+(define (riddle-ans riddle) (car riddle))
+(define (riddle-terrain riddle) (eval (cadr riddle)))
+(define (riddle-x riddle) (caddr riddle))
+(define (riddle-y riddle) (list-ref riddle 3))
+(define (riddle-w riddle) (list-ref riddle 4))
+(define (riddle-h riddle) (list-ref riddle 5))
+(define (riddle-pos? riddle) (list-ref riddle 6))
+(define (riddle-msg riddle) (list-ref riddle 7))
+(define (riddle-rm-on-correct? riddle) (list-ref riddle 8))
+(define (riddle-rm-on-wrong? riddle) (list-ref riddle 9))
+(define (riddle-set-rm-on-correct! riddle val) (list-set-ref! riddle 8 val))
+(define (riddle-set-rm-on-wrong! riddle val) (list-set-ref! riddle 9 val))
+
+(define (riddle-trigger riddle kmech)
+  (shake-map 10)
+  (fill-terrain (riddle-terrain riddle)
+                (loc-place (kern-obj-get-location kmech))
+                (riddle-x riddle)
+                (riddle-y riddle)
+                (riddle-w riddle)
+                (riddle-h riddle))
+  )
+
+(define (riddle-step kmech kchar)
+  (if (is-player-party-member? kchar)
+      (let ((riddle (kobj-gob-data kmech)))
+        (kern-log-msg "*** STENTORIAN VOICE ***")
+        (apply kern-log-msg (riddle-msg riddle))
+        (let ((guess (kern-conv-get-reply kchar)))
+          (cond ((eq? guess (riddle-ans riddle))
+                 (kern-log-msg "YOU MAY PASS")
+                 (if (riddle-pos? riddle)
+                     (riddle-trigger riddle kmech))
+                 (if (riddle-rm-on-correct? riddle)
+                     (kern-obj-remove kmech))
+                 )
+                (else
+                 (kern-log-msg "WRONG!")
+                 (if (not (riddle-pos? riddle))
+                     (riddle-trigger riddle kmech))
+                 (if (riddle-rm-on-wrong? riddle)
+                     (kern-obj-remove kmech))
+                 )
+                )))))
+                
+
+(define riddle-step-ifc
+  (ifc '()
+       (method 'step riddle-step)))
+
+(mk-obj-type 't_step_riddle nil nil layer-mechanism riddle-step-ifc)
+
+(define (mk-riddle ans ter-tag x y w h  pos? . msg)
+  (bind (kern-mk-obj t_step_riddle 1)
+        (riddle-mk ans ter-tag x y w h pos? msg)))
+
diff --git a/worlds/haxima-1.002/portcullis.scm b/worlds/haxima-1.002/portcullis.scm
new file mode 100644 (file)
index 0000000..c4eb610
--- /dev/null
@@ -0,0 +1,36 @@
+;; A portcullis is a trivial extension of the binary mechanism. It responds to
+;; a generic 'signal by toggling its state.
+
+;; Extend the bim interface to support the 'signal message
+(define (portcullis-state on?)
+  (if on?
+      (state-mk 's_portcullis_up #f pclass-none 0)
+      (state-mk 's_portcullis_down #f pclass-bars 0)))
+
+(define (kportcullis-manual kobj khandler)
+  (kern-log-msg "Portcullis won't budge!"))
+
+(define portcullis-ifc
+  (ifc bim-ifc
+       (method 'open kportcullis-manual)
+       (method 'close kportcullis-manual)
+       (method 'open-remote bim-on)
+       (method 'close-remote bim-off)     
+       (method 'signal bim-toggle)
+       (method 'state portcullis-state)
+       ))
+
+;; Make a kernel portcullis type
+(mk-obj-type 't_portcullis "portcullis" nil layer-mechanism portcullis-ifc)
+
+;; Define a constructor
+(define (mk-connected-portcullis dest-tag)
+  (bind (kern-mk-obj t_portcullis 1) 
+        (bim-mk #f dest-tag nil)))
+  
+(define (mk-portcullis) 
+  (mk-connected-portcullis nil))
+
+(define (mk-open-portcullis)
+  (bind (kern-mk-obj t_portcullis 1) 
+        (bim-mk #t nil nil)))
diff --git a/worlds/haxima-1.002/potions.png b/worlds/haxima-1.002/potions.png
new file mode 100644 (file)
index 0000000..7765677
Binary files /dev/null and b/worlds/haxima-1.002/potions.png differ
diff --git a/worlds/haxima-1.002/potions.scm b/worlds/haxima-1.002/potions.scm
new file mode 100644 (file)
index 0000000..c0be383
--- /dev/null
@@ -0,0 +1,140 @@
+;; ----------------------------------------------------------------------------
+;; potions.scm -- potion object types. Potions work on the drinker.
+;; ----------------------------------------------------------------------------
+
+(kern-mk-sprite-set 'ss_potions 32 32 2 5 0 0 "potions.png")
+
+(kern-mk-sprite 's_healing_potion       ss_potions 1 0 #f 0)
+(kern-mk-sprite 's_mana_potion          ss_potions 1 1 #f 0)
+(kern-mk-sprite 's_immunity_potion      ss_potions 1 2 #f 0)
+(kern-mk-sprite 's_cure_potion          ss_potions 1 3 #f 0)
+(kern-mk-sprite 's_invisibility_potion  ss_potions 1 4 #f 0)
+(kern-mk-sprite 's_red_bubbly_potion    ss_potions 1 5 #f 0)
+(kern-mk-sprite 's_green_bubbly_potion  ss_potions 1 6 #f 0)
+(kern-mk-sprite 's_yellow_bubbly_potion ss_potions 1 7 #f 0)
+(kern-mk-sprite 's_round_bubbly_purple  ss_potions 1 10 #f 0)
+(kern-mk-sprite 's_round_bubbly_lblue   ss_potions 1 11 #f 0)
+(kern-mk-sprite 's_round_bubbly_yellow  ss_potions 1 12 #f 0)
+
+;; mk-potion -- utility for making potion types. 'drink-proc' should return one
+;; of the result-* codes.
+(define (mk-potion tag name sprite drink-proc)
+  (mk-usable-item tag name sprite norm drink-proc
+                  (lambda (kpotion kuser) 
+                    (drink-proc kpotion kuser))))
+
+;; mk-clingy-potion -- utility for making potion types that automatically cause
+;; npc's that want them to get them. 'drink-proc' should return one of the
+;; result-* codes.
+(define (mk-clingy-potion tag name sprite drink-proc wants-it?)
+  (mk-usable-clingy-item tag name sprite norm drink-proc wants-it?))
+
+;; healing (red) potion     
+(mk-clingy-potion 't_heal_potion "healing potion" s_healing_potion 
+                  (lambda (kpotion kuser)
+                    (kern-obj-heal kuser (kern-dice-roll "2d10"))
+                    result-ok)
+                  wants-healing?)
+
+;; mana (blue) potion
+(mk-clingy-potion 't_mana_potion "mana potion" s_mana_potion 
+                  (lambda (kpotion kuser)
+                    (kern-char-dec-mana kuser (- 0 (kern-dice-roll "1d8+2")))
+                    result-ok)
+                  wants-mana?)
+
+;; cure (green) potion
+(mk-potion 't_cure_potion "cure potion" s_cure_potion
+           (lambda (kpotion kuser) 
+             (kern-obj-remove-effect kuser ef_poison)
+             result-ok))
+                        
+(mk-potion 't_xp_potion "potion of gain level" s_cure_potion
+           (lambda (kpotion kuser) 
+             (kern-char-add-experience kuser 500)
+             result-ok))
+
+(define (potion-gain-stats kuser current-stat stat-name stat-setter)
+  (println "cur:" current-stat)
+  (cond ((< current-stat 20)
+         (kern-log-msg (kern-obj-get-name kuser) " gains " stat-name "!")
+         (stat-setter kuser (+ current-stat (kern-dice-roll "1d3+1")))
+         result-ok)
+        ((< current-stat 25)
+         (kern-log-msg (kern-obj-get-name kuser) " gains a little " stat-name "!")
+         (stat-setter kuser (+ current-stat (kern-dice-roll "1d3")))
+         result-ok)
+        ((< current-stat 35)
+         (let ((droll (kern-dice-roll "1d2-1")))
+           (println "droll:" droll)
+           (cond ((> droll 0)
+                  (kern-log-msg (kern-obj-get-name kuser) " already has a lot of " stat-name ", but gets a wee bit more.")
+                  (stat-setter kuser (+ current-stat 1))
+                  result-ok)
+                 (else
+                  (kern-log-msg (kern-obj-get-name kuser) " already has a lot of " stat-name " and now just feels a little sick.")
+                  result-no-effect))))
+        (else
+         (kern-log-msg (kern-obj-get-name kuser) " has too much " stat-name " and has become such an arrogant bore that potions have no more effect.")
+         result-no-effect)))
+
+(mk-potion 't_str_potion "potion of strength" s_round_bubbly_yellow
+               (lambda (kpotion kuser)
+                       (potion-gain-stats kuser (kern-char-get-base-strength kuser)
+                                           "strength" kern-char-set-strength)))
+                        
+(mk-potion 't_dex_potion "potion of dexterity" s_round_bubbly_purple
+               (lambda (kpotion kuser)
+                       (potion-gain-stats kuser (kern-char-get-base-dexterity kuser)
+                                           "dexterity" kern-char-set-dexterity)))
+                        
+(mk-potion 't_int_potion "potion of intelligence" s_round_bubbly_lblue
+               (lambda (kpotion kuser)
+                       (potion-gain-stats kuser (kern-char-get-base-intelligence kuser)
+                               "intelligence" kern-char-set-intelligence)))
+
+(mk-potion 't_info_potion "potion of enlightenment" s_mana_potion
+           (lambda (kpotion kuser) 
+            (kern-log-msg "Information about " (kern-obj-get-name kuser))
+                       (kern-log-msg "Thief skill: " (number->string (occ-ability-thief kuser)))
+                       (kern-log-msg "Offensive magic: " (number->string (occ-ability-blackmagic kuser)))
+                       (kern-log-msg "Utility magic: " (number->string (occ-ability-whitemagic kuser)))
+                       (kern-log-msg "Magic resistance: " (number->string (occ-ability-magicdef kuser)))
+                       (kern-log-msg "Combat strength: " (number->string (occ-ability-strattack kuser)))
+                       (kern-log-msg "Combat dexterity: " (number->string (occ-ability-dexattack kuser)))
+                       (kern-log-msg "Avoidance: " (number->string (occ-ability-dexdefend kuser)))
+                       result-ok))
+
+
+;; posion immunity (bubbly yellow) potion
+(mk-potion 't_poison_immunity_potion "immunity potion" s_immunity_potion
+           (lambda (kpotion kuser) 
+             (kern-obj-add-effect kuser ef_temporary_poison_immunity nil)
+             result-ok))
+
+;; invisibility (black) potion
+(mk-potion 't_invisibility_potion "invisibility potion" s_invisibility_potion
+           (lambda (kpotion kuser)
+             (kern-obj-add-effect kuser ef_invisibility nil)
+             result-ok))
+
+;; FIXME: the following "blood" potions need to do stuff
+(mk-potion 't_dragons_blood "dragon's blood"  s_red_bubbly_potion
+           (lambda (kpotion kuser)
+             (kern-obj-add-effect kuser ef_temporary_fire_immunity nil)
+             result-ok))
+
+;; hydra's blood -- turn arrows into poisoned arrows?
+(mk-potion 't_hydras_blood "hydra's blood" s_green_bubbly_potion
+           (lambda (kpotion kuser)
+             (kern-obj-add-effect kuser ef_temporary_grow_head nil)
+             result-ok))
+
+;; lich's blood -- turn arrows into diseased arrows?
+(mk-potion 't_lichs_blood "lich's blood" s_yellow_bubbly_potion
+           (lambda (kpotion kuser)
+               (kern-obj-add-effect kuser ef_temporary_disease_immunity nil)
+               (kern-obj-add-effect kuser ef_temporary_poison_immunity nil)
+               result-ok))
+
+
diff --git a/worlds/haxima-1.002/powers.scm b/worlds/haxima-1.002/powers.scm
new file mode 100644 (file)
index 0000000..eb5c860
--- /dev/null
@@ -0,0 +1,1532 @@
+;;--------------------------------------------------------------
+;; This stuff needs to be somewhere more generic
+;;--------------------------------------------------------------
+
+(define pi (* 2 (acos 0)))
+                  
+(define (xy->angle x y)
+       (if (equal? x 0)
+               (cond ((> y 0) (atan 999999))
+                       ((< y 0) (atan -999999))
+                       (else 0))
+               (if (< x 0)
+                       (+ (atan (/ y x)) pi)
+                       (atan (/ y x)))))
+
+(define (cone-in-range x y range)
+       (< (+ (* x x) (* y y)) (* range range)))
+               
+(define (angle-wrap angle)
+       (cond ((< angle 0) (angle-wrap (+ angle (* 2 pi))))
+               ((> angle (* 2 pi)) (angle-wrap (- angle (* 2 pi))))
+               (else angle)))
+               
+(define (angle-diff baseangle testangle)
+       (- (angle-wrap (- testangle baseangle pi)) pi))
+
+(define (cone-in-angle x y minangle maxangle)
+       (let ((tangle (xy->angle x y)))
+               (if (< (angle-diff minangle maxangle) 0)
+                       (or (>= (angle-diff minangle tangle) 0)
+                               (<= (angle-diff maxangle tangle) 0))
+                       (and (>= (angle-diff minangle tangle) 0)
+                               (<= (angle-diff maxangle tangle) 0))
+                       )))
+       
+(define (cone-get-edge x y inlist)
+       (cons (list y x) 
+       (cons (list x y) inlist)))
+       
+(define (cone-get-initial n inlist)
+       (cone-get-edge (- 0 n) 0
+       (cone-get-edge n 0 inlist)))
+       
+(define (cone-get-sides n m inlist)
+       (if (< m n)
+               (cone-get-sides n (+ m 1)
+                       (cone-get-edge n m
+                       (cone-get-edge (- 0 n) m
+                       (cone-get-edge n (- 0 m)
+                       (cone-get-edge (- 0 n) (- 0 m) inlist))))
+               )
+               inlist))
+
+(define (cone-get-corners n inlist)
+       (cons (list n n)
+       (cons (list (- 0 n) (- 0 n) )
+       (cone-get-edge (- 0 n) n inlist))))
+       
+(define (cone-get-box n)
+       (cone-get-sides n 1
+       (cone-get-corners n
+       (cone-get-initial n nil))))
+                       
+(define (cone-check-cell origin minangle maxangle range proc cell)
+       (let* ((x (car cell))
+                       (y (cadr cell))
+                       (loc (list (car origin) (+ (cadr origin) x) (+ y (caddr origin)))))
+               (if (and (cone-in-range x y range)
+                                       (cone-in-angle x y minangle maxangle)
+                                       (kern-is-valid-location? loc)
+                                       )
+                               (proc loc)
+                               )))
+                       
+                       
+(define (cone-handle-box origin minangle maxangle range proc list)
+       (if (not (null? list))
+               (begin          
+                       (cone-check-cell origin minangle maxangle range proc (car list))
+                       (cone-handle-box origin minangle maxangle range proc (cdr list))
+               )))
+
+                       
+(define (cone-area-slice n origin minangle maxangle range proc)
+       (if (< n range)
+               (begin
+                       (cone-handle-box origin minangle maxangle range proc
+                               (cone-get-box n))
+                       (cone-area-slice (+ n 1) origin minangle maxangle range proc)
+               )))
+                       
+(define (cone-area-effect origin angle range width proc)
+       (let ((minangle (angle-wrap (- angle (/ width 2))))
+               (maxangle (angle-wrap (+ angle (/ width 2)))))
+       (cone-area-slice 1 origin minangle maxangle range proc)
+    ))
+       
+(define (cone-do-simple caster target range proc)
+       (let* ((origin (kern-obj-get-location caster))
+                       (x (- (cadr target) (cadr origin))) 
+                       (y (- (caddr target) (caddr origin))))
+               (cone-area-effect origin (xy->angle x y) range (/ pi 2) proc)
+               ))
+               
+(define (cone-simple caster range proc)
+       (let ((origin (kern-obj-get-location caster))
+               (target (get-target-loc caster range)))
+               (if (null? target)
+                       #f
+                       (let ((x (- (cadr target) (cadr origin))) 
+                               (y (- (caddr target) (caddr origin)))) 
+                       (cone-area-effect origin (xy->angle x y) range (/ pi 2) proc))
+               )))     
+
+(define (powers-field-generic loc f_type duration proc)
+       (let* ((finduration (if (< duration 1) 1 duration))
+                       (afield (kern-mk-field f_type finduration)))
+               (if (can-be-dropped? afield loc cant)
+                       (begin
+                               (kern-obj-put-at afield loc)
+                               (kern-map-repaint)
+                               (if (not (null? proc))
+                                       (for-each proc (kern-get-objects-at loc))
+                               )
+                               ;; remove fields on semi-bad locations
+                               (if (or (< duration 1)
+                                               (not (can-be-dropped? afield loc no-drop)))
+                                       (kern-obj-remove afield)
+                               )
+                               (kern-map-repaint)
+                       ))
+       ))
+               
+(define (mk-basic-cone-proc origin objfx field-type leaveproc)
+       (define (dropfield loc)
+               (if (kern-obj-put-at (kern-mk-obj field-type 1) loc)))
+       (define (is-my-field? kobj) (eqv? field-type (kern-obj-get-type kobj)))
+       (define (cleanfields loc)
+               (let ((fields (filter is-my-field? (kern-get-objects-at loc)))
+                               (duration (leaveproc)))
+                       (cond ((null? fields) nil)
+                               (else
+                                       (kern-obj-remove (car fields))))
+                       (if     (and (terrain-ok-for-field? loc)
+                                       (> duration 0))
+                               (kern-obj-put-at (kern-mk-field field-type duration) loc))
+                               ))
+       (lambda (loc)
+               (if (kern-in-los? origin loc)
+                       (if (null? field-type)
+                               (if (not (null? objfx))
+                                       (map objfx (kern-get-objects-at loc))
+                               )
+                               (powers-field-generic loc field-type (leaveproc) objfx)
+                       ))
+       ))
+       
+(define (mk-cone-proc-sfx origin objfx sfx field-type leaveproc)
+       (define (dropfield loc)
+               (if (kern-obj-put-at (kern-mk-obj field-type 1) loc)))
+       (define (is-my-field? kobj) (eqv? field-type (kern-obj-get-type kobj)))
+       (define (cleanfields loc)
+               (let ((fields (filter is-my-field? (kern-get-objects-at loc)))
+                               (duration (leaveproc)))
+                       (cond ((null? fields) nil)
+                               (else
+                                       (kern-obj-remove (car fields))))
+                       (if     (and (terrain-ok-for-field? loc)
+                                       (> duration 0))
+                               (kern-obj-put-at (kern-mk-field field-type duration) loc))
+                               ))
+       (lambda (loc)
+               (kern-sound-play-at sfx origin)
+               (if (kern-in-los? origin loc)
+                       (if (null? field-type)
+                               (if (not (null? objfx))
+                                       (map objfx (kern-get-objects-at loc))
+                               )
+                               (powers-field-generic loc field-type (leaveproc) objfx)
+                       ))
+       ))
+                               
+;; todo- inc these in line-cell to simplify?
+(define (line-do-proc proc location)
+       (if (kern-is-valid-location? location)
+               (proc location 1)
+               #f
+       ))
+               
+(define (line-diag place x y dx dy proc)
+       (let* ((curx (floor x))
+                       (cury (floor y))
+                       (newx (floor (+ x (/ dx 2))))
+                       (newy (floor (+ y (/ dy 2))))
+                       (location (loc-mk place newx newy)))
+               (if (or (not (equal? newx curx))
+                                       (not (equal? newy cury)))
+                       (if (kern-is-valid-location? location)
+                               (proc location 0.5)
+                               #f
+                       )
+                       #t
+               )
+       ))
+               
+(define (line-cell place x y dx dy endx endy proc)
+       (let ((curx (floor x))
+                       (cury (floor y)))
+               (if (and 
+                               (if (equal? (abs dx) 1) (line-diag place x y 0 (* dy 1.0000001) proc) (line-diag place x y (* dx 1.0000001) 0 proc))
+                               (line-do-proc proc (loc-mk place curx cury))
+                               (not (and (equal? curx endx) (equal? cury endy)))
+                               (if (equal? (abs dx) 1) (line-diag place (+ x dx) (+ y dy) 0 (* dy -0.9999999) proc) (line-diag place (+ x dx) (+ y dy) (* dx -0.9999999) 0 proc))
+                               )
+                       (line-cell place (+ x dx) (+ y dy) dx dy endx endy proc))
+       ))
+                               
+;; todo will fail on looping maps
+(define (line-draw place startx starty stopx stopy proc)
+       (if (and (equal? startx stopx)
+                               (equal? starty stopy))
+               (line-do-proc proc (loc-mk place startx starty))
+               (let* ((xdif (- stopx startx))
+                               (ydif (- stopy starty))
+                               (div (if (> (abs xdif) (abs ydif)) (abs xdif) (abs ydif)))
+                               (dx (/ xdif div))
+                               (dy (/ ydif div)))
+                       (line-cell place (+ startx 0.5) (+ starty 0.5) dx dy stopx stopy proc)
+               )))
+                       
+(define (cast-missile-proc kchar ktarg ktype)
+  (kern-fire-missile ktype
+                     (kern-obj-get-location kchar)
+                     (kern-obj-get-location ktarg)))
+
+;;--------------------------------------------------------------
+;; Shared utilities
+;;--------------------------------------------------------------
+
+(define (contest-of-skill offense defense)
+  (let ((oprob (+ offense 1))
+        (tprob (number->string (+ offense defense 2))))
+    (println "oprob=" oprob " tprob=" tprob " offense=" offense " defense=" defense)
+    (if (< (kern-dice-roll (string-append "1d" tprob))
+           oprob)
+          #t
+          #f
+        )))
+
+
+;;--------------------------------------------------------------
+;; Spells
+;;--------------------------------------------------------------
+
+
+;todo add area effect for high powered users?
+(define (powers-awaken caster ktarg power)
+       (kern-obj-remove-effect ktarg ef_sleep)
+       (kern-char-set-sleep ktarg #f)
+       result-ok)
+       
+(define (powers-blink-range power)
+       (+ 3 power))
+       
+(define (powers-blink caster ktarg power)
+       (if (kern-place-is-passable ktarg caster)
+               (kern-obj-relocate caster ktarg nil)
+               (kern-log-msg "Blink Failed: Impassable terrain")
+       )
+       result-ok)
+       
+(define (powers-blink-party-range power)
+       (cond ((< power 20) (* power 0.75))
+               (else 15)))
+       
+(define (powers-blink-party caster ktarg power)
+       (if (kern-place-is-passable ktarg (kern-char-get-party caster))
+               (kern-obj-relocate (kern-char-get-party caster) ktarg nil)
+               (kern-log-msg "Blink Failed: Impassable terrain")
+       )
+       result-ok)
+
+(define (powers-charm-range power)
+       (+ 3 (/ power 3)))
+       
+; (Only) failed charm pisses off target
+(define (powers-charm caster target power)
+       (cond
+         ((has-charm-immunity? target)
+          (msg-log-visible (kern-obj-get-location target) (kern-obj-get-name target) " immune to charm")
+          )
+         ((contest-of-skill
+           (+ power 1)
+           (occ-ability-magicdef target))
+          (let ((tloc (kern-obj-get-location target)))
+            (kern-obj-add-effect target 
+                                 ef_charm 
+                                 (charm-mk (kern-being-get-current-faction caster)))
+            (kern-map-flash-sprite s_heart (loc-x tloc) (loc-y tloc))
+                                       (msg-log-visible tloc (kern-obj-get-name target) " is charmed")
+                                        )
+          )
+         (else 
+          (msg-log-visible (kern-obj-get-location target) (kern-obj-get-name target) " resists charm")
+          (kern-harm-relations target caster)
+          )
+         )
+       result-ok
+        )
+
+;; Weaker than charm, this turns the target's alignment to be that of
+;; monsters. The monster faction is hostile to most others, so the player can
+;; use it against outlaws, cave goblins, etc.
+(define (powers-beastly-illusion caster target power)
+  (cond ((has-charm-immunity? target)
+         (msg-log-visible (kern-obj-get-location target) (kern-obj-get-name target) " resists illusion")
+         )
+        ((contest-of-skill (+ power 1) (occ-ability-magicdef target))
+         (let ((tloc (kern-obj-get-location target)))
+           (kern-obj-add-effect target ef_charm (charm-mk faction-monster))
+           (kern-map-flash-sprite s_heart (loc-x tloc) (loc-y tloc))
+           (msg-log-visible tloc (kern-obj-get-name target) " is deluded")
+           ))
+        (else (msg-log-visible (kern-obj-get-location target) (kern-obj-get-name target) " resists illusion"))
+        )
+  (kern-harm-relations target caster)
+  result-ok
+  )
+
+(define (powers-clone-range power)
+       (+ 1 (/ power 7)))
+
+(define (powers-clone caster target power)
+       (let* ((clone (kern-obj-clone target))
+                               (loc (pick-loc (kern-obj-get-location target) clone)))
+               (kern-being-set-base-faction clone (kern-being-get-current-faction caster))
+               ;; clone has equipment of original
+               (map (lambda (ktype)
+                       (kern-obj-add-to-inventory clone ktype 1))
+                       (kern-char-get-arms target)
+               )
+               (kern-char-arm-self clone)
+               ;; clone level based on of weaker of caster or original
+               (if (> (kern-char-get-level target) (kern-char-get-level caster))
+                       (kern-char-set-level clone (+ 1 (* (kern-char-get-level caster) 0.75)))
+                       (kern-char-set-level clone (+ 1 (* (kern-char-get-level target) 0.75)))
+               )
+               ;; clone may not have more hp/mana than original
+               (if (> (kern-char-get-hp clone) (kern-char-get-hp target))
+                       (kern-char-set-hp clone (kern-char-get-hp target)))
+               (if (> (kern-char-get-mana clone) (kern-char-get-mana target))
+                       (kern-char-set-mana clone (kern-char-get-mana target)))
+               ;;(kern-char-set-ai clone 'spell-sword-ai)
+               (kern-obj-put-at clone loc)
+       )
+       result-ok)
+       
+(define (powers-cone-flamespray caster ktarg power)
+       (let ((damage (mkdice 2 (min (floor (+ 2 (/ power 2))) 10))))
+               (define (flambe-all kobj)
+                       (if (and (is-being? kobj)
+                                       (not (has-fire-immunity? kobj)))
+                               (kern-obj-inflict-damage kobj "burning" (kern-dice-roll damage) caster)
+                               ))
+               (cone-do-simple caster ktarg 3.3
+                       (mk-basic-cone-proc (kern-obj-get-location caster) flambe-all F_fire (lambda () 0))
+                       ))
+                       result-ok)
+
+(define (powers-cone-basic-leaveproc balance width)
+       (lambda ()
+               (- (kern-dice-roll (mkdice 1 width)) balance)))
+       
+;; this may need to be limited...
+(define (powers-cone-basic-range power)
+       (+ 3 (/ power 3)))
+       
+(define (powers-cone-fire-range power)
+       (+ 5 (/ power 3)))
+       
+(define (powers-cone-energy caster ktarg power)
+       (let ((damage (mkdice (floor (/ power 2)) 3)))
+               (define (energize-all kobj)
+                       (if (is-being? kobj)
+                               (kern-obj-inflict-damage kobj "shocked" (kern-dice-roll damage) caster)
+                               ))
+               (cone-do-simple caster ktarg (powers-cone-basic-range power)
+                       (mk-basic-cone-proc (kern-obj-get-location caster) energize-all F_energy 
+                               (powers-cone-basic-leaveproc 40 (+ 30 (* 4 power)))
+                       )))
+                       result-ok)
+
+;; check for: no unintended victims
+;;    at least 2 fire vulnerable targets
+(define (powers-cone-fire-test caster targloc power)
+       ;;(println "test cone fire")
+       (let ((viable-targets (list 0))
+                       (shot-ok (list #t)))
+               (define (checktarg kobj)
+                       (if (is-being? kobj)
+                               ;; test for hostility and known (ie permanent) fire resistance
+                               (if (is-hostile? kobj caster)
+                                       (if (not (has-effect? kobj ef_fire_immunity))
+                                               (set-car! viable-targets (+ (car viable-targets) 1))
+                                       )
+                                       (set-car! shot-ok #f)
+                               )
+                       )
+               )                       
+               (cone-do-simple caster targloc (powers-cone-fire-range power)
+                       (mk-basic-cone-proc (kern-obj-get-location caster) checktarg nil nil)
+                       )
+               ;;(println "tested cone fire " (car shot-ok) " " (car viable-targets))
+               (and (car shot-ok)
+                       (> (car viable-targets )1))
+       ))
+                       
+(define (powers-cone-fire caster targloc power)
+       (let ((damage (mkdice (floor (/ power 2)) 3)))
+               (define (burn-all kobj)
+                       (if (and (is-being? kobj)
+                                       (not (has-fire-immunity? kobj)))
+                               (begin
+                                       (kern-obj-inflict-damage kobj "burning" (kern-dice-roll damage) caster)
+                                       (kern-harm-relations kobj caster)
+                               )
+                       ))
+               (cone-do-simple caster targloc (powers-cone-fire-range power)
+                       (mk-cone-proc-sfx (kern-obj-get-location caster) burn-all sound-fireblast F_fire 
+                               (powers-cone-basic-leaveproc 30 (+ 20 (* 5 power)))
+                       )
+               ))
+       result-ok
+)
+
+(define (powers-cone-poison caster ktarg power)
+       (let ((damage (mkdice 1 (floor (/ power 4)))))
+               (define (poison-all kobj)
+                       (if (is-being? kobj)
+                               (begin
+                                       (apply-poison kobj)
+                                       (if (is-poisoned? kobj)
+                                               (begin
+                                                       (kern-harm-relations kobj caster)
+                                                       (kern-harm-relations kobj caster)
+                                                       (kern-harm-relations kobj caster)
+                                                       (kern-harm-relations kobj caster)
+                                                       (kern-obj-inflict-damage kobj "poison" (kern-dice-roll damage) caster)
+                                               )
+                               ))))
+               (cone-do-simple caster ktarg (powers-cone-basic-range power)
+                       (mk-basic-cone-proc (kern-obj-get-location caster) poison-all F_poison 
+                               (powers-cone-basic-leaveproc 60 (+ 40 (* 3 power)))
+                       )))
+                       result-ok)
+
+(define (powers-cone-sleep caster ktarg power)
+       (let ((damage (mkdice 1 (floor (/ power 4)))))
+               (define (sleep-all kobj)
+                       (if (is-being? kobj)
+                               (begin
+                                       (kern-harm-relations kobj caster)
+                                       (if (contest-of-skill
+                                                       (+ power 8)
+                                                       (occ-ability-magicdef kobj))
+                                               (apply-sleep kobj))
+                               )))
+               (cone-do-simple caster ktarg (powers-cone-basic-range power)
+                       (mk-basic-cone-proc (kern-obj-get-location caster) sleep-all F_sleep 
+                               (powers-cone-basic-leaveproc 40 (+ 30 (* 4 power)))
+                       )))
+                       result-ok)
+
+;todo limit to some range?
+(define (powers-confuse caster unused power)
+       (define (confuse kchar)
+               (if (contest-of-skill
+                               power
+                               (+ (occ-ability-magicdef kchar) 2))
+                       (kern-being-set-base-faction kchar (random-faction))
+                       ))
+       (map confuse (all-hostiles caster))
+       result-ok)
+       
+(define (powers-cure-poison caster ktarg power)
+       (kern-obj-remove-effect ktarg ef_poison)
+       (if (< (kern-dice-roll "1d25") power)
+            (kern-obj-remove-effect ktarg ef_disease))
+       result-ok)
+       
+;todo currently only checks topmost item
+(define (powers-detect-traps caster ktarg power)
+  (let ((traps (ifccall ktarg 'get-traps)))
+    (cond ((null? traps)
+           (kern-log-msg (kern-obj-get-name caster)
+                         " does not detect any traps")
+           )
+          (else
+           (map (lambda (trap)
+                  (trap-set-detected! trap #t)
+                  (kern-log-msg (kern-obj-get-name caster)
+                                " detects a " (trap-name trap) " trap!")
+                  )
+                traps)
+           )))
+  result-ok)
+
+;again, a bit of range for powerful users?
+(define (powers-dispel-field caster ktarg power)
+   (kern-print "Dispelled field!\n")
+   (kern-obj-remove ktarg)
+   (kern-map-repaint)
+   result-ok)
+   
+;; todo saving throw vs caster power for different effects?
+(define (powers-dispel-magic caster ktarg power)
+       (effects-dispel-magic ktarg)
+       result-ok)
+
+(define (powers-disarm-traps kchar ktarg power)
+  (let (
+        (traps (filter (lambda (trap) 
+                          (and (trap-detected? trap) 
+                               (not (trap-tripped? trap))))
+                        (ifccall ktarg 'get-traps)))
+        )
+    ;; Check if any unprocessed traps remaining
+    (cond ((null? traps) 
+           result-no-effect
+           )
+          ((not (handles? ktarg 'rm-traps)) 
+           (kern-log-msg "Traps can't be removed!")
+           result-no-effect
+           )
+          (else
+           ;; Roll to succeed
+           (let* (
+                  (trap (car traps))
+                  (dc (trap-avoid-dc trap))
+                  (roll (kern-dice-roll "1d20"))
+                  (bonus (kern-dice-roll (string-append "1d" (number->string power))))
+                  )
+             (cond ((or 
+                     (= roll 20) 
+                     (> (+ roll bonus) dc)
+                     )
+                    ;; Success - disarm the trap
+                    (kern-log-msg (kern-obj-get-name kchar) " ^c+gdisarms^c- a " (trap-name trap) " trap!")
+                    (trap-set-tripped! trap #t)
+                    result-ok
+                    )
+                   (else
+                    ;; Failure - trip the trap (kchar will get another roll
+                    ;; to avoid the damage)
+                    (trap-trigger trap ktarg kchar)
+                    result-failed
+                    )))))))
+
+
+;todo limit range?
+(define (powers-fear caster unused power)                      
+       (define (repel kchar)
+               (msg-log-visible (kern-obj-get-location kchar) (kern-obj-get-name kchar) " flees in terror!")
+               (kern-map-flash-sprite s_magicflash (loc-x tloc) (loc-y tloc))
+               (kern-char-set-fleeing kchar #t)
+               )
+       (define (try-repel kchar)
+               (if (contest-of-skill
+                               (+ power 8)
+                               (occ-ability-magicdef kchar))
+                       (repel kchar)))
+       (map try-repel (all-hostiles caster))
+       result-ok)
+
+;todo
+; fields would be a lot more useful if a wall was created instead of one square
+;   (length based on caster strength of course)
+; I need a 'line' utility anyway, perhaps a ui along the lines of (select center point) (select end point)
+;   -> draw line from centre to end and opposite side
+(define (powers-field-range power)
+       (if (> power 30)
+               7
+               (+ 1 (/ power 5))
+       ))
+
+(define (powers-field-length power)
+       (+ 1 (/ power 4)))
+       
+(define (powers-field-wall start stop f_type duration leng proc)
+       (let ((lengremaining (list leng)))
+               (define (put-field location delta)
+                       (powers-field-generic location f_type duration proc)
+                       (set-car! lengremaining (- (car lengremaining) delta))
+                       (> (car lengremaining) 0)
+                       )
+               (line-draw (loc-place start) (loc-x start) (loc-y start) (loc-x stop) (loc-y stop) put-field)
+       ))
+       
+(define (powers-field-fire-wall caster start stop power)
+       (define (do-burn kobj)
+               (if (and (kern-obj-is-char? kobj)
+                               (not (has-fire-immunity? kobj)))
+                       (kern-obj-inflict-damage kobj "burning" (kern-dice-roll "2d3+2") caster)
+               ))
+       (powers-field-wall start stop F_fire (+ 20 (kern-dice-roll (mkdice 1 power))) (powers-field-length power) do-burn)
+       result-ok)
+       
+(define (powers-field-energy-wall caster start stop power)
+       (define (do-burn kobj)
+               (if (kern-obj-is-char? kobj)
+                       (kern-obj-inflict-damage kobj "shocked" (kern-dice-roll "2d8") caster)
+               ))
+       (powers-field-wall start stop F_energy (+ 20 (kern-dice-roll (mkdice 2 power))) (powers-field-length power) do-burn)
+       result-ok)
+
+(define (powers-field-poison-wall caster start stop power)
+       (define (do-burn kobj)
+               (if (and (kern-obj-is-char? kobj)
+                               (not (has-poison-immunity? kobj)))
+                       (begin
+                               (apply-poison kobj)
+                               (kern-harm-relations kobj caster)
+                               (kern-harm-relations kobj caster)
+                       )
+               ))
+       (powers-field-wall start stop F_poison (+ 10 (kern-dice-roll (mkdice 1 power))) (powers-field-length power) do-burn)
+       result-ok)
+
+(define (powers-field-sleep-wall caster start stop power)
+       (define (do-burn kobj)
+               (if (and (kern-obj-is-char? kobj)
+                               (not (has-sleep-immunity? kobj)))
+                       (begin
+                               (kern-harm-relations kobj caster)                       
+                               (apply-sleep kobj)
+                       )
+               ))
+       (powers-field-wall start stop F_sleep (+ 15 (kern-dice-roll (mkdice 1 power))) (powers-field-length power) do-burn)
+       result-ok)
+       
+(define (powers-field-energy caster ktarg power)
+       (kern-obj-put-at (kern-mk-field F_energy (+ 20 (kern-dice-roll (mkdice 2 power)))) ktarg)
+       result-ok)
+
+(define (powers-field-fire caster ktarg power)
+       (kern-obj-put-at (kern-mk-field F_fire (+ 20 (kern-dice-roll (mkdice 1 power)))) ktarg)
+       result-ok)
+       
+(define (powers-field-poison caster ktarg power)
+       (kern-obj-put-at (kern-mk-field F_poison (+ 10 (kern-dice-roll (mkdice 1 power)))) ktarg)
+       result-ok)
+
+(define (powers-field-sleep caster ktarg power)
+       (kern-obj-put-at (kern-mk-field F_sleep (+ 15 (kern-dice-roll (mkdice 1 power)))) ktarg)
+       result-ok)
+       
+(define (powers-field-energy-weak caster ktarg power)
+       (powers-field-generic ktarg F_energy (+ 5 (kern-dice-roll (mkdice 1 (ceiling (/ power 2))))) apply-lightning)
+       result-ok)
+
+(define (powers-field-fire-weak caster ktarg power)
+       (powers-field-generic ktarg F_fire (+ 5 (kern-dice-roll (mkdice 1 (ceiling (/ power 3))))) burn)
+       result-ok)
+       
+(define (powers-field-poison-weak caster ktarg power)
+       (powers-field-generic ktarg F_poison (+ 3 (kern-dice-roll (mkdice 1 (ceiling (/ power 3))))) apply-poison)
+       result-ok)
+
+(define (powers-field-sleep-weak caster ktarg power)
+       (powers-field-generic ktarg F_sleep (+ 4 (kern-dice-roll (mkdice 1 (ceiling (/ power 3))))) apply-sleep)
+       result-ok)
+
+(define (powers-fireball-range power)
+       (+ 3 (/ power 3)))
+       
+;; returns true if the location is ok
+(define (powers-fireball-collateral-check caster targloc apower)
+       ;;(println "fireball check")
+       (let ((place (loc-place targloc))
+                       (x (loc-x targloc))
+                       (y (loc-y targloc)))
+               (define (checkloc kloc)
+                       (null? 
+                               (filter
+                                       (lambda (kobj)
+                                               (and (kern-obj-is-char? kobj)
+                                                       (not (is-hostile? kobj caster))
+                                                       )
+                                       )
+                                       (kern-get-objects-at kloc)
+                               )
+                       ))
+               (define (checkoff xoff yoff)
+                       (let ((kloc (mk-loc place (+ x xoff) (+ y yoff))))
+                               (if (kern-is-valid-location? kloc)
+                                       (checkloc kloc)
+                                       #t
+                               )
+                       ))
+               (and (checkoff 0 0)
+                       (or (<= apower 10)
+                               (and (checkoff 1 0)
+                                       (checkoff -1 0)
+                                       (checkoff 0 1)
+                                       (checkoff 0 -1)
+                               ))
+                       (or (<= apower 15)
+                               (and (checkoff 1 1)
+                                       (checkoff 1 -1)
+                                       (checkoff -1 1)
+                                       (checkoff -1 -1)
+                               ))
+                       )
+       ))
+       
+(define (powers-fireball caster ktarg apower)
+       ;;(println "fireball")
+       (define (fireball-damage-dice power)
+               (if (> power 3) (string-append (number->string  (floor (/ power 2))) "d3")
+                               "1d3"))
+       (define (is-my-field? kobj) (eqv? F_fire (kern-obj-get-type kobj)))
+       (define (cleanfields kplace x y)
+               (let ((kloc (mk-loc kplace x y)))
+                       (if (kern-is-valid-location? kloc)
+                               (let ((fields (filter is-my-field? (kern-get-objects-at kloc))))
+                                       (cond ((null? fields) nil)
+                                               (else
+                                                       (kern-obj-remove (car fields))))))))
+       (define (do-fireball-hit kplace x y damdf damdi)
+          (define (fire-damage kobj)
+            (if (kern-obj-is-char? kobj)
+                (begin
+                  (kern-log-msg "Burning!")
+                  (if (not (has-fire-immunity? kobj))
+                      (kern-obj-inflict-damage kobj "burning" (kern-dice-roll damdf) caster)
+                                (if (not (null? damdi))
+                       (kern-obj-inflict-damage kobj "impact" (kern-dice-roll damdi) caster))
+                       ))
+                ;;(kern-obj-apply-damage kobj "burning" (kern-dice-roll damdf))
+                ))
+          (let ((kloc (mk-loc kplace x y)))
+            (if (kern-is-valid-location? kloc)
+                (begin
+                  (kern-obj-put-at (kern-mk-obj F_fire 1) kloc)
+                  (kern-map-repaint)
+                  (for-each fire-damage
+                            (kern-get-objects-at kloc))
+                  ))))
+       (let* ((targchar (get-being-at ktarg))
+               (damf (fireball-damage-dice apower))
+               (dami (if (> apower 5) (fireball-damage-dice (/ apower 3)) nil)))
+               (define (do-fireball-effect kplace x y)
+                       (kern-sound-play-at sound-explode (mk-loc kplace x y))
+                       (do-fireball-hit kplace x y damf dami)
+                       (if (> apower 10) (let ((apower (- apower 5))
+                                       (damf (fireball-damage-dice apower))
+                                       (dami (if (> apower 5) (fireball-damage-dice (/ apower 3)) nil)))
+                               (do-fireball-hit kplace (+ x 1) y damf dami)
+                               (do-fireball-hit kplace (- x 1) y damf dami)
+                               (do-fireball-hit kplace x (+ y 1) damf dami)
+                               (do-fireball-hit kplace x (- y 1) damf dami)
+                       (if (> apower 10) (let ((apower (- apower 5))
+                                       (damf (fireball-damage-dice apower))
+                                       (dami (if (> apower 5) (fireball-damage-dice (/ apower 3)) nil)))
+                               (do-fireball-hit kplace (+ x 1) (+ y 1) damf dami)
+                               (do-fireball-hit kplace (- x 1) (+ y 1) damf dami)
+                               (do-fireball-hit kplace (+ x 1) (- y 1) damf dami)
+                               (do-fireball-hit kplace (- x 1) (- y 1) damf dami)
+                               (cleanfields kplace (+ x 1) (+ y 1))                            
+                               (cleanfields kplace (- x 1) (+ y 1))                            
+                               (cleanfields kplace (+ x 1) (- y 1))                            
+                               (cleanfields kplace (- x 1) (- y 1))                            
+                       ))
+                       (cleanfields kplace (+ x 1) y)                          
+                       (cleanfields kplace (- x 1) y)                          
+                       (cleanfields kplace x (+ y 1))                          
+                       (cleanfields kplace x (- y 1))                          
+                       ))
+                       (cleanfields kplace x y)
+               )
+               (if (null? targchar)
+                       (kern-log-msg (kern-obj-get-name caster)
+                                                       " hurls a fireball")
+                       (kern-log-msg (kern-obj-get-name caster)
+                                                       " hurls a fireball at "
+                                               (kern-obj-get-name targchar)))
+               (temp-ifc-set 
+                       (lambda (kmissile kuser ktarget kplace x y)
+                               (do-fireball-effect kplace x y)
+                       )
+               )
+               (kern-sound-play-at sound-missile (kern-obj-get-location caster))
+               (kern-sound-play-at sound-missile ktarg)
+               (kern-fire-missile t_mfireball
+                     (kern-obj-get-location caster)
+                     ktarg))
+       result-ok)
+
+;todo high power should go to user specified gate
+(define (powers-gate-travel caster ktarg power)
+  ;; Fix for bug 1738251, which involved summoning gates over magically locked
+  ;; doors: check passability. Use the passability of the caster as a
+  ;; reasonable estimate for the passability of the gate.
+  (if (not (kern-place-is-passable ktarg caster))
+      result-not-here
+      (let ((gate (summon-moongate 'ord)))
+        (kern-obj-put-at gate ktarg)
+        (moongate-open gate)
+        result-ok)))
+                 
+(define (powers-great-light caster ktarg power)
+       (let ((lightadd 
+                       (kern-dice-roll
+                               (mkdice 5 power))))
+               (light-apply-new ktarg (+ 6000 (* 50 power))))
+               result-ok)
+
+;todo should the messages be in the ui part?
+(define (powers-great-heal kchar ktarg power)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts a great healing spell on "
+                (if (eqv? kchar ktarg)
+                    "self"
+                    (kern-obj-get-name ktarg)))
+  (kern-obj-heal ktarg 
+                 (+ 10 power (kern-dice-roll "2d20")
+                    (kern-dice-roll (mkdice 4 power))))
+  result-ok)
+
+;todo should the messages be in the ui part?
+(define (powers-heal kchar ktarg power)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts a healing spell on "
+                (if (eqv? kchar ktarg)
+                    "self"
+                    (kern-obj-get-name ktarg)))
+  (kern-obj-heal ktarg 
+                 (+ 2 (kern-dice-roll "1d10")
+                    (kern-dice-roll (mkdice 2 power))))
+  result-ok)
+       
+;todo vary duration with power
+(define (powers-invisibility kchar ktarg power)
+       (kern-obj-add-effect ktarg ef_invisibility nil)
+       result-ok)
+
+;todo hack in something for xp & hostility
+(define (powers-kill kchar ktarg)
+  (kern-log-msg (kern-obj-get-name kchar)
+                " casts kill at "
+                (kern-obj-get-name ktarg))
+       (kern-sound-play-at sound-missile (kern-obj-get-location kchar))
+       (kern-sound-play-at sound-missile (kern-obj-get-location ktarg))
+  (cast-missile-proc kchar ktarg t_deathball)
+  result-ok)
+       
+(define (powers-light caster ktarg power)
+       (let ((lightadd 
+                       (kern-dice-roll
+                               (mkdice 5 power))))
+               (light-apply-new ktarg (+ 400 (* 5 power))))
+               result-ok)
+                 
+(define (powers-lightning-range power)
+       (+ 3 (/ power 2.5)))
+       
+;; todo will fail on looping maps
+(define (powers-lightning-collateral-check caster targloc apower)
+       ;;(println "checkzap")
+       (let* ((range (powers-lightning-range apower))
+                       (casterloc (kern-obj-get-location caster))
+                       (targrange (+ 1 (kern-get-distance targloc casterloc)))
+                       (rangemult (if (> targrange 0) (ceiling (/ range targrange)) 0))
+                       (dx (* rangemult (- (loc-x targloc) (loc-x casterloc))))
+                       (dy (* rangemult (- (loc-y targloc) (loc-y casterloc))))
+                       (endx (+ (loc-x casterloc) dx))
+                       (endy (+ (loc-y casterloc) dy))
+                       (shot-ok (list #t))
+                       (range-ok (> range targrange))
+                       )
+               (define (check-loc location delta)
+                       (cond ((equal? location casterloc) #t)
+                               ((> (kern-get-distance location casterloc) range) #f)
+                               ((null? (filter
+                                                       (lambda (kobj)
+                                                               (and (kern-obj-is-char? kobj)
+                                                                       (not (is-hostile? kobj caster))
+                                                                       )
+                                                       )
+                                                       (kern-get-objects-at location)
+                                               ))
+                                       #t
+                                       )
+                               (else (set-car! shot-ok #f) #f)
+                       ))
+               (if (and range-ok (> rangemult 0))
+                       (begin
+                               (line-draw (loc-place targloc) (loc-x casterloc) (loc-y casterloc) endx endy check-loc)
+                               (car shot-ok)
+                       )
+                       #f
+               )
+       ))
+       
+(define (powers-lightning caster targloc apower)
+       ;;(println "zap")
+  (let ((targets (list nil))
+        (dam (mkdice (floor (+ 1 (/ apower 3))) 4))
+        )
+    (temp-ifc-set 
+     (lambda (kmissile kuser ktarget kplace x y unused)
+       (let (
+             (targchar (get-being-at (mk-loc kplace x y)))
+             )
+         (if (not (null? targchar))
+             (set-car! targets (cons targchar (car targets)))
+             ))
+       #t      
+       ))
+    (kern-sound-play sound-lightning)
+    (kern-fire-missile-to-max t_lightning_bolt (powers-lightning-range apower)
+                              (kern-obj-get-location caster)
+                              targloc
+                              )    
+    (if (not (null? (car targets)))
+        (map
+         (lambda (zappee)
+           (kern-log-msg (kern-obj-get-name zappee) " shocked!")
+           (kern-obj-inflict-damage zappee "shocked" (kern-dice-roll dam) caster)                                              
+           )
+         (car targets)
+         ))
+    )
+  result-ok)
+               
+(define (powers-lock caster ktarg power)
+       ((kobj-ifc ktarg) 'lock ktarg caster)
+       result-ok)
+
+(define (powers-lock-magic caster ktarg power)
+       ((kobj-ifc ktarg) 'magic-lock ktarg caster)
+       result-ok)
+       
+(define (powers-locate caster ktarg power)
+       (let ((loc (kern-obj-get-location caster)))
+               (kern-log-msg "You are in " (kern-place-get-name (car loc)) 
+                              " at [x=" (cadr loc) " y=" (caddr loc) "]"))
+       result-ok)
+
+(define (powers-magic-missile-range power)
+       (+ 4 (/ power 3)))
+                 
+;todo messages out?
+(define (powers-magic-missile kchar ktarg power)
+       (kern-sound-play-at sound-missile (kern-obj-get-location kchar))
+       (kern-sound-play-at sound-missile (kern-obj-get-location ktarg))
+       (kern-log-msg (kern-obj-get-name kchar)
+                       " fires magic missile at "
+                       (kern-obj-get-name ktarg))
+       (if (cast-missile-proc kchar ktarg t_magicarrow_p)
+               (let* (
+                       (apower 
+                               (ceiling (- 
+                                       (/ power 2)
+                                       (/ (occ-ability-magicdef ktarg) 10)
+                                       )))
+                       (damagedice (string-append 
+                               (number->string (if (> apower 0) apower 1))
+                               "d3")))
+               (kern-obj-inflict-damage ktarg
+                                                        "magic" (kern-dice-roll damagedice) kchar)))
+       result-ok)
+
+(define (powers-negate-magic caster ktarg power)
+       (kern-add-magic-negated (kern-dice-roll
+               (mkdice 3 (floor (+ (/ power 3) 1)))))
+       result-ok)
+
+(define (powers-paralyse caster ktarg power)
+       (if (and (can-paralyze? ktarg)
+                               (contest-of-skill
+                                               (+ power 5)
+                                               (occ-ability-magicdef ktarg)))
+        (kern-obj-add-effect ktarg ef_paralyze nil))
+       result-ok)
+               
+(define (powers-poison-range power)
+       (+ 3 (/ power 3)))
+       
+;todo contest to resist? to-hit roll required? power based initial damage?
+;note instant hostility - you cant just cause someone to slowly die and say
+;sorry afterwards
+(define (powers-poison-effect caster ktarg power)
+       (if (and (kern-obj-is-char? ktarg)
+                       (not (null? ktarg)))
+               (begin
+                  (if (contest-of-skill
+                       power
+                       (occ-ability-dexdefend ktarg))
+                      (apply-poison ktarg)
+                      (kern-log-msg (kern-obj-get-name ktarg) " avoids poison!")
+               )))
+       )
+
+(define (powers-poison caster ktarg power)
+       (define (do-poison-effect kmissile kuser ktarget kplace x y dam)
+               (on-hit-target ktarget dam 
+                                       (lambda (obj) (powers-poison-effect kuser obj (+ power 10))))
+               (on-hit-nontarget ktarget (loc-mk kplace x y) dam 
+                                       (lambda (obj) (powers-poison-effect kuser obj power)))
+                               )
+       (temp-ifc-set do-poison-effect)
+       (kern-log-msg (kern-obj-get-name caster)
+                               " hurls poison missile at "
+                               (kern-obj-get-name ktarg))
+       (kern-harm-relations ktarg caster)
+       (kern-harm-relations ktarg caster)
+       (kern-harm-relations ktarg caster)
+       (kern-harm-relations ktarg caster)
+       (kern-sound-play-at sound-missile (kern-obj-get-location caster))
+       (kern-sound-play-at sound-missile (kern-obj-get-location ktarg))
+       (cast-missile-proc caster ktarg t_mpoison_bolt)
+       result-ok)
+
+;todo duration based on power?
+(define (powers-protect caster ktarg power)
+  (let ((party (kern-char-get-party caster)))
+    (if (null? party) 
+        (kern-obj-add-effect caster ef_protection nil)
+        (kern-obj-add-effect party ef_protection nil)
+        )
+    )
+       result-ok)
+
+;todo duration based on power?
+(define (powers-protect-vs-fire caster ktarg power)
+       (kern-obj-add-effect ktarg ef_temporary_fire_immunity nil)
+       result-ok)
+
+;todo duration based on power?
+(define (powers-protect-vs-poison caster ktarg power)
+       (kern-obj-add-effect ktarg ef_temporary_poison_immunity nil)
+       result-ok)
+
+;todo duration based on power?
+(define (powers-protect-vs-poison-all caster ktarg power)
+  (let ((party (kern-char-get-party caster)))
+    (if (null? party) 
+        (kern-obj-add-effect caster ef_temporary_poison_immunity nil)
+        (kern-obj-add-effect party ef_temporary_poison_immunity nil)
+        )
+    )
+       result-ok)
+
+(define (powers-quickness caster dir power)
+       (kern-add-quicken (kern-dice-roll
+               (mkdice 3 (floor (+ (/ power 3) 1)))))
+       result-ok)
+
+;note is different scenarios, could have other uses
+(define (powers-raise-lost-area caster loc power)
+       (let ((kobjs (filter can-raise-vessel? 
+                                       (kern-get-objects-at loc))))
+               (if (not (null? kobjs))
+                       (let ((kgen (car kobjs)))                
+                               (signal-kobj kgen 'raise kgen caster)
+                       )))
+       result-ok)
+
+;resurrect should have side effects, diminishing with power
+(define (powers-resurrect caster ktarg power)
+  (cond ((is-dead? ktarg)
+         (kern-char-resurrect ktarg)
+         (apply-sleep ktarg)
+         result-ok)
+        (else
+         result-no-effect))
+       result-ok)
+                               
+(define (powers-reveal caster ktarg power)
+       (kern-add-reveal (* power 4))
+       result-ok)
+
+
+(define (powers-sleep-target-range power)
+       (+ (/ power 3) 3))
+
+(define (powers-sleep-apply target power)
+       (if (contest-of-skill power (occ-ability-magicdef target))
+                       (begin
+                               (msg-log-visible (kern-obj-get-location target) (kern-obj-get-name target) " slept")
+                               (apply-sleep target))
+                       (begin 
+                               (msg-log-visible (kern-obj-get-location target) (kern-obj-get-name target) " resists sleep"))
+       ))
+       
+(define (powers-sleep-target caster ktarg power)
+       (powers-sleep-apply ktarg (+ power 6))
+       (kern-harm-relations ktarg caster)
+  result-ok)
+
+;todo limit to some range?
+(define (powers-sleep-area caster ktarg power)
+       (let ((hostiles (all-hostiles caster)))
+               (define (trysleep target)
+                       (powers-sleep-apply target (+ power 3))
+                       )
+       (cond ((null? hostiles) result-ok)
+             (else
+              (map trysleep hostiles)
+              result-ok))))
+                       
+(define (powers-smoke-range power)
+       (+ 3 (/ power 3)))
+                   
+(define (powers-smoke-field caster ktarg apower)
+       (fields-smoke-apply (loc-place ktarg) (loc-x ktarg) (loc-y ktarg) apower)
+       result-ok
+       )
+                       
+;todo duration based on power?
+(define (powers-spider-calm caster ktarg power)
+       (kern-obj-add-effect ktarg ef_spider_calm nil)
+       result-ok)
+
+(define (powers-summon targetloc quantity typegen levelgen faction)
+       (define (run-loop count done)
+               (if (<= count 0) done
+                       (let* ((knpc (spawn-npc (typegen) (levelgen)))
+                                       (loc (pick-loc targetloc knpc)))
+                               (if (null? loc) 
+                                       (begin
+                                               (kern-obj-dec-ref knpc)
+                                               done)
+                                       (begin
+                                               (kern-being-set-base-faction knpc faction)
+                                               (kern-obj-set-temporary knpc #t)
+                                               (kern-obj-put-at knpc loc)
+                                               (run-loop (- count 1) 1)
+                                       )))))
+       (run-loop quantity 0))
+       
+(define (powers-summon-simple-levelgen power)
+       (lambda ()
+               (+ (floor (+ (* power 0.2) 1
+                       (kern-dice-roll
+                               (mkdice 3 (floor (+ (* power 0.2) 1))))
+                       )))))
+
+(define (powers-summon-single-type type)
+       (lambda ()
+               type
+       ))
+
+;todo enable remote summoning for high power?
+(define (powers-summon-medium-size caster ktarg power type-tag)
+  (let ((spower (floor (+ (/ power 4) 1))))
+       (powers-summon (kern-obj-get-location caster)
+                       (kern-dice-roll (mkdice 1 spower))
+                       (powers-summon-single-type type-tag)
+                       (powers-summon-simple-levelgen power)
+                       (kern-being-get-base-faction caster))
+       ))
+
+;todo enable remote summoning for high power?
+(define (powers-summon-snake caster ktarg power)
+  (powers-summon-medium-size caster ktarg power 'snake)
+       result-ok)
+
+;todo enable remote summoning for high power?
+(define (powers-summon-spider caster ktarg power)
+  (powers-summon-medium-size caster ktarg power 'giant-spider)
+       result-ok)
+
+;todo enable remote summoning for high power?
+(define (powers-summon-wolf caster ktarg power)
+  (powers-summon-medium-size caster ktarg power 'wolf)
+       result-ok)
+
+;todo enable remote summoning for high power?
+(define (powers-summon-small caster ktarg power type-tag)
+  (let ((spower (floor (+ (/ power 4) 1))))
+       (powers-summon (kern-obj-get-location caster)
+                       (kern-dice-roll (mkdice 2 spower))
+                       (powers-summon-single-type type-tag)
+                       (powers-summon-simple-levelgen power)
+                       (kern-being-get-base-faction caster))
+       ))
+
+;todo enable remote summoning for high power?
+(define (powers-summon-insect caster ktarg power)
+  (powers-summon-small caster ktarg power 'insect)
+       result-ok)
+
+;todo enable remote summoning for high power?
+(define (powers-summon-rat caster ktarg power)
+  (powers-summon-small caster ktarg power 'rat)
+       result-ok)
+
+;todo enable remote summoning for high power?
+(define (powers-summon-bat caster ktarg power)
+  (powers-summon-small caster ktarg power 'bat)
+       result-ok)
+
+;todo enable remote summoning for high power?
+(define (powers-summon-undead caster ktarg power)
+  (let ((spower (floor (+ (/ power 4) 1))))
+       (powers-summon (kern-obj-get-location caster)
+                       (kern-dice-roll (mkdice 1 spower))
+                       (lambda () 
+                (random-select (list 'skeletal-warrior 'skeletal-spear-thrower 'ghast)))
+                       (powers-summon-simple-levelgen power)
+                       (kern-being-get-base-faction caster))
+       )
+       result-ok)
+       
+(define (powers-summon-slime caster ktarg power)
+  (let ((spower (floor (+ (/ power 4) 1))))
+       (powers-summon (kern-obj-get-location caster)
+                       (kern-dice-roll (mkdice 1 spower))
+                       (powers-summon-single-type 'green-slime)
+                       (powers-summon-simple-levelgen power)
+                       (kern-being-get-base-faction caster))
+       )
+       result-ok)
+                
+       
+(define (powers-telekinesis-range power)
+       (+ (/ power 3) 1))
+       
+;todo damage/knock away critters?
+;should fail on no handler squares rather than aborting?
+(define (powers-telekinesis caster ktarg power)
+  ((kobj-ifc ktarg) 'handle ktarg caster)
+  result-ok)
+       
+(define (powers-timestop caster dir power)
+       (kern-add-time-stop (kern-dice-roll
+               (mkdice 3 (floor (+ (/ power 3) 1)))))
+       result-ok)
+       
+; a few things needed here:
+;      check for visibility before messages
+;      no player specific messages
+;      only hits hostiles
+;   area of effect based on power
+;      'turned' as an effect? [so it shows on description] or maybe fleeing should show...
+(define (powers-turn-undead caster unused power)
+       (define (is-undead-char? kobj)
+               (and (obj-is-char? kobj)
+               (species-is-undead? (kern-char-get-species kobj)))
+               )
+       (define (repel kchar)
+               (if (contest-of-skill
+                               (+ power 3)
+                               (occ-ability-magicdef kchar))
+                       (let ((tloc (kern-obj-get-location kchar)))
+                               (kern-map-flash-sprite s_magicflash (loc-x tloc) (loc-y tloc))
+                               (msg-log-visible tloc (kern-obj-get-name kchar) " turned")
+                               (kern-char-set-fleeing kchar #t)
+                       )
+                       (begin
+                               (msg-log-visible (kern-obj-get-location kchar) (kern-obj-get-name kchar) " resists")
+                       )
+               )
+       )
+       (let* ((all-kobjs (all-hostiles caster))
+               (all-undead-combatants (filter is-undead-char? all-kobjs)))
+                       (map repel all-undead-combatants)
+       )
+       result-ok)
+       
+;todo limit to some (large) range?
+(define (powers-tremor caster unused power)
+       (let ((damdice (mkdice 1 power))
+               (foes (all-hostiles caster)))
+       (define (tremor kchar)
+               (cond ((kern-char-is-asleep? kchar) (kern-char-set-sleep kchar #f))
+                       ((> (kern-dice-roll "1d4") 1)
+                               (kern-map-set-jitter #t)
+                               (kern-map-repaint)
+                               (kern-char-set-sleep kchar #t)
+                               (kern-obj-inflict-damage kchar "knocked down" (kern-dice-roll damdice) caster))
+                               (else nil)))
+       (define (loop n kchar)
+               (if (not (= n 0))
+                       (begin
+                       (map tremor kchar)
+                       (loop (- n 1) kchar))))
+       (define (wakeup kchar) (kern-char-set-sleep kchar #f))
+    (kern-log-enable #f)
+    (map kern-obj-inc-ref foes)
+    (shake-map 20)
+    (loop (+ 1 (floor (/ power 4))) foes)
+    (kern-map-repaint)
+    (map wakeup foes)
+    (map kern-obj-dec-ref foes)
+    (map wakeup (kern-place-get-beings (loc-place (kern-obj-get-location caster))))
+       (kern-log-enable #t)
+       )
+       result-ok)
+
+(define (powers-unlock caster ktarg power)
+  (println "power:" power)
+  (let ((dc ((kobj-ifc ktarg) 'get-unlock-dc ktarg caster)))
+    (println "dc:" dc)
+    (if (= 0 dc) 
+        result-no-effect
+        (let ((roll (kern-dice-roll "1d20"))
+              (bonus (kern-dice-roll (string-append "1d" (number->string power)))))
+          (println "roll:" roll)
+          (println "bonus:" bonus)
+          (cond ((or (= roll 20) 
+                     (> (+ roll bonus ) dc))
+                 (if ((kobj-ifc ktarg) 'unlock ktarg caster)
+                     result-ok
+                     result-no-effect))
+                (else result-failed))))))
+
+(define (powers-unlock-magic caster ktarg power)
+  (if ((kobj-ifc ktarg) 'magic-unlock ktarg caster)
+      result-ok
+      result-no-effect))
+       
+(define (powers-view caster ktarg power)
+       (kern-map-center-camera (kern-obj-get-location caster))
+       (kern-map-set-peering #t)
+       (kern-map-repaint)
+       (kern-print "Hit a key when done gazing...\n")
+       (ui-waitkey)
+       (kern-map-set-peering #f)
+       (kern-map-repaint)
+       result-ok)
+
+(define (powers-web-range power)
+       (+ 3 (/ power 3)))
+       
+;note defense is dodge, not magicdef
+(define (powers-web caster target power)
+       (define (do-web-effect kplace x y)
+               (let* ((loc (mk-loc kplace x y))
+                               (targchar (get-being-at loc)))
+                       (if (not (null? targchar))
+                               (begin
+                                       (if (contest-of-skill
+                                                       power
+                                                       (occ-ability-dexdefend targchar))
+                                               (ensnare targchar))
+                                               (kern-harm-relations kobj caster)))
+                       (if (and (< (kern-dice-roll "1d20") power)
+                                       (terrain-ok-for-field? loc))
+                               (kern-obj-put-at (kern-mk-obj web-type 1) loc))
+               ))
+       (let ((targchar (get-being-at target))) 
+               (if (null? targchar)
+                       (kern-log-msg (kern-obj-get-name caster)
+                                                       " hurls a web")
+                       (kern-log-msg (kern-obj-get-name caster)
+                                                       " hurls a web at "
+                                               (kern-obj-get-name targchar)))
+               (temp-ifc-set 
+                       (lambda (kmissile kplace x y)
+                               (do-web-effect kplace x y)
+                       ))
+               (kern-sound-play-at sound-missile (kern-obj-get-location caster))
+               (kern-sound-play-at sound-missile target)
+               (kern-fire-missile t_mweb
+                     (kern-obj-get-location caster)
+                     target)
+       )
+       result-ok)
+
+(define (powers-wind-change caster dir power)
+       (kern-set-wind dir (+ 10 (kern-dice-roll (mkdice (* 2 power) 6))))
+       result-ok)
+       
+(define (powers-xray caster dir power)
+       (kern-add-xray-vision (kern-dice-roll
+               (mkdice 10 (floor (+ (/ power 3) 1)))))
+       result-ok)
+               
+;; vttjo - "Vectors to tiles jumped over"
+(define (powers-jump-vttjo dx dy)
+    (cond ((= dx 2)
+           (cond ((= dy -1) (list (cons 1 0) (cons 1 -1)))
+                 ((= dy 0)  (list (cons 1 0)))
+                 ((= dy 1)  (list (cons 1 0) (cons 1 1)))
+                 (else nil)))
+          ((= dx 1)
+           (cond ((= dy -2) (list (cons 0 -1) (cons 1 -1)))
+                 ((= dy 2)  (list (cons 0 1) (cons 1 1)))
+                 (else nil)))
+          ((= dx 0)
+           (cond ((= dy -2) (list (cons 0 -1)))
+                 ((= dy 2) (list (cons 0 1)))
+                 (else nil)))
+          ((= dx -1)
+           (cond ((= dy -2) (list (cons 0 -1) (cons -1 -1)))
+                 ((= dy 2) (list (cons 0 1) (cons -1 1)))
+                 (else nil)))
+          ((= dx -2)
+           (cond ((= dy -1) (list (cons -1 0) (cons -1 -1)))
+                 ((= dy 0)  (list (cons -1 0)))
+                 ((= dy 1)  (list (cons -1 0) (cons -1 1)))
+                 (else nil)))
+          (else nil)))
+
+(define (powers-jump caster ktarg power)
+  (let ((cloc (kern-obj-get-location caster)))
+
+    ;; special case: when jumping 1 (or fewer tiles) use normal movement mode
+    (define (jump-one)
+      (cond ((not (kern-place-move-is-passable? cloc ktarg caster))
+             (kern-log-msg "Jump failed: blocked!")
+             result-no-effect)
+            (else
+             (kern-obj-relocate caster ktarg nil)
+             result-ok)))
+
+    (cond ((not (kern-place-is-passable ktarg caster))
+           (kern-log-msg "Jump Failed: Impassable terrain")
+           result-no-effect)
+          (else
+           (let* ((vect (loc-diff cloc ktarg))
+                  (dx (loc-x vect))
+                  (dy (loc-y vect))
+                  (kplace (loc-place (kern-obj-get-location caster))))
+             (cond ((and (<= (abs dx) 1) (<= (abs dy) 1))
+                    (jump-one))
+                   (else
+                    ;; normal case: jump of more than 1 tile
+                    (kern-obj-set-mmode caster mmode-jump)
+                    (let* ((vttjo (powers-jump-vttjo dx dy))
+                          (result
+                           (cond ((foldr (lambda (val vtt)
+                                           (or val
+                                               (not (kern-place-is-passable 
+                                                     (mk-loc kplace 
+                                                             (+ (car vtt) (loc-x cloc))
+                                                             (+ (cdr vtt) (loc-y cloc)))
+                                                     caster))))
+                                         #f vttjo)
+                                  (kern-log-msg "Jump failed: blocked!")
+                                  result-no-effect)
+                                 (else
+                                  (kern-obj-relocate caster ktarg nil)
+                                  (kern-obj-add-effect caster ef_fatigue nil)
+                                  result-ok))))
+                      (kern-obj-set-mmode caster nil)
+                      result))))))))
+
+(define (powers-sprint caster ktarg power)
+  ;; hokay... first let's get the path from here to there
+  (let* ((origin (kern-obj-get-location caster))
+         (kplace (loc-place origin))
+         (path (line (loc-x origin) (loc-y origin) 
+                     (loc-x ktarg) (loc-y ktarg)))
+         )
+    ;; and now, for each point on the path, let's move the dude there and apply
+    ;; any terrain/field effects. The way should be passable (unless we do
+    ;; something weird like along the way trigger a mech which throws up a
+    ;; wall, in which case I guess that's an advantage of having the sprint
+    ;; skill ;) Note that the dude may die along the way due to tile effects,
+    ;; so keep a ref count just to be safe and check for death in the move-dude
+    ;; function.
+    (define (move-dude ok xy)
+      (and ok
+           (let ((loc (loc-mk kplace (car xy) (cdr xy))))
+             (cond ((or (not (passable? loc caster))
+                        (occupied? loc))
+                    (println loc " impassable")
+                    #f
+                    )
+                   ((not (kern-char-is-dead? caster))
+                    (kern-obj-relocate caster loc nil)
+                    (kern-map-repaint)
+                    (kern-place-apply-tile-effects kplace caster)
+                    #t
+                    )
+                   ))))
+    (kern-obj-inc-ref caster)
+    (foldr move-dude #t (cdr path))
+    (kern-obj-dec-ref caster)
+    )
+  (kern-obj-add-effect caster ef_fatigue nil)
+  result-ok)
+
+;; Roll to even make the attempt, then roll to see if you get stuck.
+(define (powers-wriggle caster ktarg power)
+  (kern-obj-set-mmode caster mmode-wriggle)
+  (cond ((not (kern-place-move-is-passable? (kern-obj-get-location caster)
+                                            ktarg caster))
+         (kern-log-msg "Wriggle failed: blocked!")
+         (kern-obj-set-mmode caster nil)
+         result-not-here)
+        (else
+         (kern-obj-relocate caster ktarg nil)
+         (kern-obj-set-mmode caster nil)
+         (cond ((passable? (kern-obj-get-location caster) caster)
+                (kern-log-msg "(Was that really necessary?)")
+                result-ok
+                )
+               ((not (check-roll dc-avoid-stuck (occ-thief-dice-roll caster)))
+                (kern-obj-add-effect caster ef_stuck nil)
+                result-failed
+                )
+               (else
+                result-ok
+                )))))
+
+(define (powers-butcher caster ktarg power)
+  (if ((kobj-ifc ktarg) 'butcher ktarg caster)
+      result-ok
+      result-no-effect))
+
+(define (powers-pickpocket kactor ktarg power)
+  (cond ((contest-of-skill power (occ-ability-thief ktarg))
+         (let ((ktype (kern-ui-select-item ktarg)))
+           (cond ((null? ktype) result-no-effect)
+                 (else
+                  (kern-obj-remove-from-inventory ktarg ktype 1)
+                 (if (ktype-can? ktype 'receive)
+                       ((kern-type-get-gifc ktype) 'receive ktype kactor)
+                 )
+                  (kern-obj-add-to-inventory kactor ktype 1)
+                  result-ok
+                  ))))
+        (else
+         (harm-relations kactor ktarg)
+         result-failed
+         )))
+  
\ No newline at end of file
diff --git a/worlds/haxima-1.002/pre-entry-hooks.scm b/worlds/haxima-1.002/pre-entry-hooks.scm
new file mode 100644 (file)
index 0000000..656ab37
--- /dev/null
@@ -0,0 +1,16 @@
+
+;; Note: this procedure cannot be defined in the session.scm file or it will
+;; not be saved and therefore will not be available when reloading the game. In
+;; general, nothing should be defined (using Scheme 'define') in the session
+;; file, only kernel calls should be made. The exception is things that are
+;; truly only needed once on initial startup (for example, I currently define
+;; some time constants there that fit this category). Since in general
+;; procedures do not have modifiable state they can be kept in files (like this
+;; one) which are loaded by the session file.
+(define (green-tower-pre-entry-hook kplace kpp)
+  (kern-print "Enter GreenTower?\n")
+  (kern-conv-get-yes-no? kpp))
+
+(define (pit-of-death-pre-entry-hook kplace kpp)
+  (kern-print "BWA-HA-HA-HA-HA!")
+  #t)
diff --git a/worlds/haxima-1.002/prices.scm b/worlds/haxima-1.002/prices.scm
new file mode 100644 (file)
index 0000000..50c9679
--- /dev/null
@@ -0,0 +1,8 @@
+;; inn prices
+(define trigrave-inn-room-price 20)
+(define oparine-inn-room-price  25)
+(define glasdrin-inn-room-price 40)
+
+;; ship prices
+(define oparine-ship-price      1000)
+(define oparine-ship-tradein-price 300)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/prison.scm b/worlds/haxima-1.002/prison.scm
new file mode 100644 (file)
index 0000000..7e003e3
--- /dev/null
@@ -0,0 +1,128 @@
+
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_prison 32 9 pal_expanded
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn rn "
+  "xx ,, ,, ,, xx xx xx xx xx ,, xx ,, xx rn xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx rn rn rn rn rn "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx xx xx "
+  "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx ee xx xx ,, xx xx xx ,, xx xx xx ,, xx xx xx ,, ,, ,, xx "
+  "xx ,, ,, ,, xx xx ,, ,, ,, x! ,, ,, ,, ee ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, xx ee xx xx ,, xx xx xx ,, xx xx xx ,, xx xx xx ,, ,, ,, xx "
+  "xx ,, ,, ,, xx rn xx ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx xx xx xx xx xx "
+  "xx ,, ,, ,, xx rn xx xx xx ,, xx ,, xx rn xx ,, ,, ,, xx ,, ,, ,, xx ,, ,, ,, xx rn rn rn rn rn "
+  "xx xx xx xx xx rn xx xx xx xx xx xx xx rn xx xx xx xx xx xx xx xx xx xx xx xx xx rn rn rn rn rn "
+  ))
+
+;;----------------------------------------------------------------------------
+;; NPC's
+;;----------------------------------------------------------------------------
+(kern-load "gholet.scm")
+(kern-load "valus.scm")
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place
+ 'p_prison     ; tag
+ "Prison"      ; name
+ s_hamlet      ; sprite
+ m_prison      ; map
+ #f              ; wraps
+ #t              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+
+ (list ; objects
+
+  (put (mk-monman) 0 0)
+
+  (put (mk-ladder-up 'p_glasdrin 2 2) 6 4)
+  
+  ;; store room
+  (put (mk-locked-door) 6 2)
+  (put (mk-chest
+        'burn-trap
+        '(( 10 t_food)
+          )) 1 1)
+  (put (mk-chest
+        'burn-trap
+        '((1 t_cure_potion)
+          (1 t_heal_potion)
+          )) 2 1)
+  (put (mk-chest
+        'burn-trap
+        '((10 t_arrow)
+          )) 1 2)
+  (put (mk-chest
+        'burn-trap
+        '((10 t_bolt)
+          )) 2 7)
+  (put (mk-chest
+        'burn-trap
+        '((1 t_vas_mani_scroll)
+          )) 3 7)
+  (put (mk-chest
+        'burn-trap
+        '((10 sulphorous_ash)
+          (5 garlic)
+          (5 ginseng)
+          )) 3 6)
+
+  ;; rats in store room
+  (put (spawn-pt 'rat) 1 1)
+  (put (spawn-pt 'rat) 1 3)
+  (put (spawn-pt 'rat) 2 4)
+  (put (spawn-pt 'rat) 3 7)
+  (put (spawn-pt 'rat) 1 6)
+  (put (spawn-pt 'rat) 4 2)
+
+  ;; portcullises
+  (put (kern-tag 'pp1 (mk-portcullis)) 12 4)
+  (put (kern-tag 'pp2 (mk-portcullis)) 14 4)
+
+  ;; energy fields for zorn
+  (put (kern-mk-obj F_energy_perm 1) 26 4)
+  (put (kern-mk-obj F_energy_perm 1) 28 3)
+  (put (kern-mk-obj F_energy_perm 1) 28 4)
+  (put (kern-mk-obj F_energy_perm 1) 28 5)
+  (put (kern-mk-obj F_energy_perm 1) 29 3)
+  (put (kern-mk-obj F_energy_perm 1) 29 5)
+  (put (kern-mk-obj F_energy_perm 1) 30 3)
+  (put (kern-mk-obj F_energy_perm 1) 30 4)
+  (put (kern-mk-obj F_energy_perm 1) 30 5)
+
+  ;; cell doors
+  (put (mk-locked-windowed-door) 16 3)
+  (put (mk-locked-windowed-door) 20 3)
+  (put (mk-locked-windowed-door) 24 3)
+  (put (mk-locked-windowed-door) 16 5)
+  (put (mk-locked-windowed-door) 20 5)
+  (put (mk-locked-windowed-door) 24 5)
+  (put (mk-locked-door)  27 4)
+
+  ;; levers
+  (put (mk-lever 'pp1) 11 1)
+  (put (mk-lever 'pp2) 11 7)
+
+  ;; prisoners
+  (put (mk-gholet) 24 1)
+  (put (mk-npc 'zorn 8) 29 4)
+  (put (mk-npc 'footpad 8) 16 7)
+  (put (mk-valus) 24 6)
+
+  ;; guards
+  (put (guard-pt 'halberdier) 9 1)
+  (put (guard-pt 'halberdier) 9 7)
+
+  )
+
+ (list 'on-entry-to-dungeon-room) ; on-entry hook(s)
+ nil ; edge entrances
+ )
+
+(mk-place-music p_prison 'ml-dungeon-town)
diff --git a/worlds/haxima-1.002/progress_bar_image.png b/worlds/haxima-1.002/progress_bar_image.png
new file mode 100644 (file)
index 0000000..2826253
Binary files /dev/null and b/worlds/haxima-1.002/progress_bar_image.png differ
diff --git a/worlds/haxima-1.002/pseudorandom-map.scm b/worlds/haxima-1.002/pseudorandom-map.scm
new file mode 100644 (file)
index 0000000..5af864e
--- /dev/null
@@ -0,0 +1,948 @@
+;utility for searching {sum-of-probability, object} lists
+(define (get-numbered-elem alist value)
+       (if (>= (car (car alist)) value)
+               (cdar alist)
+               (get-numbered-elem (cdr alist) value)
+               )
+       )
+       
+;list utilities
+;return list with given element swapped
+(define (list-swap alist entry index)
+       (if (null? alist)
+               nil
+               (if (zero? index)
+                       (cons entry (cdr alist))
+                       (cons (car alist)
+                               (list-swap (cdr alist) entry (- index 1)))
+                       )))
+                       
+;return list with nulls defaulting to another list
+(define (list-merge newlist defaultlist)
+       (if (null? newlist)
+               nil
+               (cons (if (null? (car newlist))
+                                       (car defaultlist)
+                                       (car newlist))
+                               (list-merge (cdr newlist) (cdr defaultlist))
+               )))
+               
+;;vector-merge: return copy of a vector with nulls defaulting to another vector
+(define (vector-merge-visitor instance index newvec defvec)
+       (if (<= 0 index)
+               (let ((element (vector-ref newvec index))) 
+                       (if (null? element)
+                               (vector-set! instance index (vector-ref defvec index))
+                               (vector-set! instance index element)
+                       )
+                       (vector-merge-visitor instance (- index 1) newvec defvec)
+               )
+               instance
+       ))
+
+(define (vector-merge newvec defaultvec)
+       (vector-merge-visitor
+               (make-vector (vector-length newvec) nil)
+                       (- (vector-length newvec) 1)
+                       newvec defaultvec)
+               )
+               
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; mutable list support
+;; workarounds for list building commands dying on empty lists
+
+(define (mk-mutable-list alist)
+       (if (null? alist)
+               (list 'mutable-list-placeholder)
+               alist))
+
+(define (mutable-list-insert alist index entry)
+       (cond
+               ((equal? (car alist) 'mutable-list-placeholder)
+                       (if (zero? index)
+                               (set-car! alist entry)
+                               (begin
+                                       (set-car! alist nil)
+                                       (set-cdr! alist (list 'mutable-list-placeholder))
+                                       (mutable-list-insert (cdr alist) (- index 1) entry)
+                               ))
+               )
+               ((zero? index)
+                       (set-cdr! alist (cons (car alist) (cdr alist)))
+                       (set-car! alist entry)
+                       )
+               ((null? (cdr alist))
+                       (set-cdr! alist (list 'mutable-list-placeholder))
+                       (mutable-list-insert (cdr alist) (- index 1) entry)
+                       )
+               (#t
+                       (mutable-list-insert (cdr alist) (- index 1) entry))
+       ))
+                       
+               
+
+(define (mutable-list-set alist index entry)
+       (cond
+               ((equal? (car alist) 'mutable-list-placeholder)
+                       (if (zero? index)
+                               (set-car! alist entry)
+                               (begin
+                                       (set-car! alist nil)
+                                       (set-cdr! alist (list 'mutable-list-placeholder))
+                                       (mutable-list-set (cdr alist) (- index 1) entry)
+                               ))
+               )
+               ((zero? index)
+                       (set-car! alist entry)
+                       )
+               ((null? (cdr alist))
+                       (set-cdr! alist (list 'mutable-list-placeholder))
+                       (mutable-list-set (cdr alist) (- index 1) entry)
+                       )
+               (#t
+                       (mutable-list-set (cdr alist) (- index 1) entry))
+       ))
+
+;; exercise for the reader: reimplement as balanced tree
+
+(define (mutable-pairlist-get! alist index)
+       (cond
+               ((equal? (car alist) 'mutable-list-placeholder)
+                       (set-car! alist (list index 'mutable-list-placeholder))
+                       (cdar alist)
+               )
+               ((< (caar alist) index)
+                       (if (null? (cdr alist))
+                               (begin
+                                       (set-cdr! alist (list (list index 'mutable-list-placeholder)))
+                                       (cdadr alist)
+                               )
+                               (mutable-pairlist-get! (cdr alist) index)
+                       ))
+               ((equal? (caar alist) index)
+                       (cdar alist)
+                       )
+               ((> (caar alist) index)
+                       (set-cdr! alist (cons (car alist) (cdr alist)))
+                       (set-car! alist (list index 'mutable-list-placeholder))
+                       (cdar alist)
+                       )
+       ))
+       
+(define (mutable-pairlist-get alist index)
+       (cond
+               ((null? alist)
+                       nil
+                       )
+               ((equal? (car alist) 'mutable-list-placeholder)
+                       nil
+                       )               
+               ((< (caar alist) index)
+                       (mutable-pairlist-get (cdr alist) index)
+                       )
+               ((> (caar alist) index)
+                       nil
+                       )
+               (#t ;;(equal? (caar alist) index)
+                       (cdar alist)
+                       )
+       ))
+       
+(define (mutable-pairlist-expand-placeholder alist)
+       (if (equal? (car alist) 'mutable-list-placeholder)
+               (set-car! alist (list 'mutable-list-placeholder))
+                       )
+       alist)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; blit stats
+
+; areamargin: from edge of room to area
+; edgemargin: from corner of room to each side of edge tile
+; edgewidth: from edge of room to inner side of edge tile
+
+(define (prmap-mk-blitstats roomwidth roomheight areamargin edgemargin edgewidth)
+       (list
+               (list edgemargin 0 (- roomwidth edgemargin edgemargin) edgewidth)
+               (list 0 edgemargin edgewidth (- roomheight edgemargin edgemargin))
+               (list (- roomwidth edgewidth) edgemargin edgewidth (- roomheight edgemargin edgemargin))
+               (list edgemargin (- roomheight edgewidth) (- roomwidth edgemargin edgemargin) edgewidth)
+               (list areamargin areamargin (- roomwidth areamargin areamargin) (- roomheight areamargin areamargin))
+       ))
+       
+(define (prmap-blitstats-north data)
+       (list-ref data 0))
+(define (prmap-blitstats-west data)
+       (list-ref data 1))
+(define (prmap-blitstats-east data)
+       (list-ref data 2))
+(define (prmap-blitstats-south data)
+       (list-ref data 3))
+(define (prmap-blitstats-area data)
+       (list-ref data 4))
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Directions   
+
+(define prmap-room-offsets
+       (vector 
+               (list 0 1)
+               (list -1 0)
+               (list 1 0)
+               (list 0 -1)
+       )
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Generic room data
+
+(mk-obj-type 't_roomdata nil nil layer-none nil)
+
+; returns roomdata object or nil if none
+(define (get-roomdata kplace)
+       (let ((dataslist (kplace-get-objects-of-type kplace t_roomdata)))
+               (if (equal? (length dataslist) 0)
+                       nil
+                       (gob (car dataslist)))))
+                       
+
+; replaces any roomdatas in place with given data
+(define (set-roomdata kplace data)
+       (begin
+               ; remove any/all previous data
+               (map (lambda (rdataobj)
+                               (kern-obj-remove rdataobj))
+                       (kplace-get-objects-of-type kplace t_roomdata))
+               ;add new t_roomdata
+               (kern-obj-put-at
+                       (bind (kern-obj-set-visible (kern-mk-obj t_roomdata 1) #f) data)
+                       (list kplace 0 0))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Random map roomdata
+
+(define (prmap-roomdata-tag data)
+       (list-ref data 0))
+(define (prmap-roomdata-x data)
+       (list-ref data 1))
+(define (prmap-roomdata-y data)
+       (list-ref data 2))
+(define (prmap-roomdata-z data)
+       (list-ref data 3))
+(define (prmap-roomdata-rooms data)
+       (list-ref data 4))
+
+(define (prmap-roomdata-setxyz data x y z)
+       (set-car! (cdr data) x)
+       (set-car! (cddr data) y)
+       (set-car! (cdddr data) z))
+
+(define (prmap-mk-roomdata room-tag x y z rooms)
+       (set-roomdata (eval room-tag) (list room-tag x y z rooms))
+       )
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Room linking
+
+; 2 dimensional map - 5 rooms
+
+;  2   5   4   1   3                   
+; 513 324 132 245 451                          
+;  4   1   5   3   2 
+
+(define (prmap-linkrooms-2d room1-tag room2-tag room3-tag room4-tag room5-tag)
+       (prmap-mk-roomdata room1-tag 0 0 0 (list room2-tag room5-tag room3-tag room4-tag))
+       (prmap-mk-roomdata room2-tag 0 0 0 (list room5-tag room3-tag room4-tag room1-tag))
+       (prmap-mk-roomdata room3-tag 0 0 0 (list room4-tag room1-tag room2-tag room5-tag))
+       (prmap-mk-roomdata room4-tag 0 0 0 (list room1-tag room2-tag room5-tag room3-tag))
+       (prmap-mk-roomdata room5-tag 0 0 0 (list room3-tag room4-tag room1-tag room2-tag))
+       )
+
+; 3 dimensional map - 7 rooms
+
+;   2 6     3 7     5 4     1 5     6 2     7 3     4 1
+; 5 1 3   6 2 4   1 3 7   2 4 6   7 5 1   4 6 2   3 7 5
+; 7 4     5 1     6 2     3 7     4 3     1 5     2 6
+
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Map paramater storage
+
+(mk-obj-type 't_mapdata nil nil layer-none nil)
+
+; returns roomdata object or nil if none
+(define (prmap-get-mapdata kplace)
+       (let ((dataslist (kplace-get-objects-of-type kplace t_mapdata)))
+               (if (equal? (length dataslist) 0)
+                       nil
+                       (gob (car dataslist)))))
+                       
+
+; replaces any roomdatas in place with given data
+(define (prmap-set-mapdata kplace data)
+       (begin
+               ; remove any/all previous data
+               (map (lambda (rdataobj)
+                               (kern-obj-remove rdataobj))
+                       (kplace-get-objects-of-type kplace t_mapdata))
+               ;add new t_mapdata
+               (kern-obj-put-at
+                       (bind (kern-obj-set-visible (kern-mk-obj t_mapdata 1) #f) data)
+                       (list kplace 0 0))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Map random seed values
+
+(define (prmap-mk-prng-params xscale yscale zscale offset modulus)
+       (list xscale yscale zscale offset modulus))
+
+(define (prmap-prng-param-xscale data)
+       (list-ref data 0))
+(define (prmap-prng-param-yscale data)
+       (list-ref data 1))
+(define (prmap-prng-param-zscale data)
+       (list-ref data 2))
+(define (prmap-prng-param-offset data)
+       (list-ref data 3))
+(define (prmap-prng-param-modulus data)
+       (list-ref data 4))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Random map parameter data
+
+(define (prmap-mk-mapdata mapname nsparams ewparams areaparams edgemaps areamaps blitstats hardlinkfunction) 
+       (list mapname nsparams ewparams areaparams edgemaps areamaps blitstats nil hardlinkfunction (mk-mutable-list nil)))
+
+(define (prmap-params-mapname params)
+       (list-ref params 0))
+(define (prmap-params-nsparams params)
+       (list-ref params 1))
+(define (prmap-params-ewparams params)
+       (list-ref params 2))
+(define (prmap-params-areaparams params)
+       (list-ref params 3))
+(define (prmap-params-edgemaps params)
+       (list-ref params 4))
+(define (prmap-params-areamaps params)
+       (list-ref params 5))
+(define (prmap-params-blitstats params)
+       (eval (list-ref params 6)))
+       
+(define (prmap-params-current params)
+       (let ((data (list-ref params 7)))
+               (if (null? data)
+                       nil
+                       (eval data)
+               )))
+               
+(define (prmap-params-set-current params room)
+       (let ((curdat (list-tail params 7)))
+               (set-car! curdat room)))
+       
+(define (prmap-params-hardlinkfunction params)
+       (let ((candidatefn (list-ref params 8)))
+               (eval
+                       (if (null? candidatefn)
+                               'prmap-room-hardlinkentry-get
+                               candidatefn
+               ))))
+(define (prmap-params-hardlinks params)
+       (list-ref params 9)
+       )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Random template handling
+
+(define (prmap-get-template rxloc ryloc rzloc maptype maplistref)
+       (let* (
+                       (xmult (prmap-prng-param-xscale maptype)) 
+                       (ymult (prmap-prng-param-yscale maptype)) 
+                       (zmult (prmap-prng-param-zscale maptype)) 
+                       (addfactor (prmap-prng-param-offset maptype)) 
+                       (modfactor (prmap-prng-param-modulus maptype)) 
+                       (maplist (eval maplistref))
+                       (mapnumber (modulo (+ (* rxloc xmult) (* ryloc ymult) (* rzloc zmult) addfactor) modfactor))
+               )
+               ;get the map from the first entry with value greater than mapnumber             
+               (cdr 
+                       (car (filter (lambda (listentry)
+                               (> (car listentry) mapnumber))
+                                       maplist))
+                       )
+       ))
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; hardlinks- fixed rooms enabling
+
+(define (prmap-room-hardlinkentry-get! xloc yloc zloc linksdata)
+       (let ((linkentry 
+                       (mutable-pairlist-get!
+                       (mutable-pairlist-get!
+                       (mutable-pairlist-get! linksdata zloc) yloc ) xloc )
+                       ))
+               (if (equal? (car linkentry) 'mutable-list-placeholder)
+                       (set-car! linkentry (vector nil nil nil nil)))
+               (car linkentry)
+       ))
+
+(define (prmap-room-hardlink-set! xloc yloc zloc linksdata dir target maptemplate passable hooklist)
+       (vector-set! (prmap-room-hardlinkentry-get! xloc yloc zloc linksdata)
+               (cardinal-dir-num dir)
+               (cons target (cons maptemplate (cons passable hooklist)))
+       ))
+       
+(define (prmap-room-hardlinkentry-get xloc yloc zloc linksdata)
+       (let ((linkentry 
+                       (mutable-pairlist-get
+                       (mutable-pairlist-get
+                       (mutable-pairlist-get linksdata zloc) yloc ) xloc )
+                       ))
+               (if (null? linkentry)
+                       (vector nil nil nil nil)
+                       (car linkentry))
+       ))
+
+(define (prmap-room-getmaphardlink xloc yloc zloc mapdata)
+       (apply (prmap-params-hardlinkfunction mapdata) (list xloc yloc zloc (prmap-params-hardlinks mapdata)))
+       )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; x y location tracking
+
+;sets x and y location of new rooms based on current location and direction to new room
+(define (prmap-room-setxyz roomslist dir rxloc ryloc rzloc)
+       (let* (
+                       (kplace (eval (get-cardinal-lref roomslist dir)))
+                       (roomdata (get-roomdata kplace))
+                       (offsets (get-cardinal-ref prmap-room-offsets dir))
+                       (rxoff (+ rxloc (car offsets)))
+                       (ryoff (+ ryloc (cadr offsets)))
+               )
+               (prmap-roomdata-setxyz roomdata rxoff ryoff rzloc)
+               ))
+
+;set xy stuff for all neighboring rooms
+(define (prmap-room-init-neighbors kplace roomdata)
+       (let* (
+                       (rooms (prmap-roomdata-rooms roomdata))
+                       (rxloc (prmap-roomdata-x roomdata))
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (rzloc (prmap-roomdata-z roomdata))
+               )
+               (map (lambda (dir)
+                       (prmap-room-setxyz rooms dir rxloc ryloc rzloc))
+                       (list north west east south))
+               ;debugging map
+               (if #f
+                       (begin
+                               (kern-log-msg (string-append 
+                                       (number->string rxloc) " "
+                                       (number->string ryloc) " "
+                                       (number->string rzloc) " "))
+                               (println "loc : " rxloc " " ryloc " " rzloc)
+                               )
+               )
+       ))
+       
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Room linking
+
+; links in neighbors, or rooms from hardlink list, as appropriate
+(define (prmap-room-init-links kplace roomdata mapdata)
+       (let* (
+                       (rooms (prmap-roomdata-rooms roomdata))
+                       (rxloc (prmap-roomdata-x roomdata))
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (rzloc (prmap-roomdata-z roomdata))
+                       (linkinfo (prmap-room-getmaphardlink rxloc ryloc rzloc mapdata))
+               )
+               (map (lambda (dir)
+                       ;roomlinktarget is hardlink target if it exists, else regular neighbor
+                       (let* (
+                               (thishardlink (get-cardinal-ref linkinfo dir))
+                               (hardlinktarget (if (null? thishardlink)
+                                                                       nil
+                                                                       (car thishardlink)))
+                               (roomlinktarget (if (null? hardlinktarget)
+                                                                       (get-cardinal-lref rooms dir)
+                                                                       hardlinktarget))
+                               )
+                               (kern-place-set-neighbor dir kplace (eval roomlinktarget))
+                       ))
+                       (list north west east south))
+       ))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; map construction    
+       
+; do a single map blit
+(define (prmap-do-map-blit destmap srcmap blitstats)
+       (let (
+                       (xloc (list-ref blitstats 0))
+                       (yloc (list-ref blitstats 1))
+                       (wid (list-ref blitstats 2))  
+                       (hgt (list-ref blitstats 3))
+               )       
+               (kern-blit-map destmap xloc yloc
+                               (eval srcmap)
+                               xloc yloc wid hgt)
+       ))
+       
+; blit map for area and all sides. uses hard linked sides if given
+(define (prmap-room-blit-map kplace roomdata mapdata)
+       (let* (
+                       (rxloc (prmap-roomdata-x roomdata))
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (rzloc (prmap-roomdata-z roomdata))
+                       (linkinfo (prmap-room-getmaphardlink rxloc ryloc rzloc mapdata))
+                       (blitstats (prmap-params-blitstats mapdata))
+                       (destmap (kern-place-map kplace))
+                       (rmapdata (vector
+                               (list 0 1 (prmap-params-nsparams mapdata))
+                               (list 0 0 (prmap-params-ewparams mapdata))
+                               (list 1 0 (prmap-params-ewparams mapdata))
+                               (list 0 0 (prmap-params-nsparams mapdata))
+                               ))
+                       (areamap-choice (prmap-get-template rxloc ryloc rzloc (prmap-params-areaparams mapdata) (prmap-params-areamaps mapdata)))
+               )
+               (prmap-do-map-blit destmap
+                       (car areamap-choice)
+                       (prmap-blitstats-area blitstats))
+               (if (> (length areamap-choice) 1)
+                       (apply (eval (cadr areamap-choice)) (list kplace))
+                       )
+               (map (lambda (dir)
+                       ;roomlinktarget is hardlink target if it exists, else regular neighbor
+                       (let* (
+                                       (thishardlink (get-cardinal-ref linkinfo dir))
+                                       (thisrmapdata (get-cardinal-ref rmapdata dir))
+                                       (thisx (+ rxloc (car thisrmapdata)))
+                                       (thisy (+ ryloc (cadr thisrmapdata)))
+                                       (thisrtype (caddr thisrmapdata))
+                                       (linkmap (if (or (null? thishardlink) (null? (car (cdr thishardlink))))
+                                                               (prmap-get-template thisx thisy rzloc thisrtype (prmap-params-edgemaps mapdata))
+                                                               (cdr thishardlink)))
+                               )
+                               (prmap-do-map-blit destmap (car linkmap)
+                                       (get-cardinal-lref blitstats dir))
+                               (if (> (length linkmap) 2)
+                                       (map (eval (get-cardinal-lref (cddr linkmap) dir)) (list kplace))
+                                       )
+                       ))
+                       (list north west east south))
+       ))
+       
+; blit map for all sides. uses hard linked sides if given
+;; todo refactor duplicate code!
+(define (prmap-room-blit-map-edges kplace roomdata mapdata)
+       (let* (
+                       (rxloc (prmap-roomdata-x roomdata))
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (rzloc (prmap-roomdata-z roomdata))
+                       (linkinfo (prmap-room-getmaphardlink rxloc ryloc rzloc mapdata))
+                       (blitstats (prmap-params-blitstats mapdata))
+                       (destmap (kern-place-map kplace))
+                       (rmapdata (vector
+                               (list 0 1 (prmap-params-nsparams mapdata))
+                               (list 0 0 (prmap-params-ewparams mapdata))
+                               (list 1 0 (prmap-params-ewparams mapdata))
+                               (list 0 0 (prmap-params-nsparams mapdata))
+                               ))
+               )
+               (map (lambda (dir)
+                       ;roomlinktarget is hardlink target if it exists, else regular neighbor
+                       (let* (
+                                       (thishardlink (get-cardinal-ref linkinfo dir))
+                                       (thisrmapdata (get-cardinal-ref rmapdata dir))
+                                       (thisx (+ rxloc (car thisrmapdata)))
+                                       (thisy (+ ryloc (cadr thisrmapdata)))
+                                       (thisrtype (caddr thisrmapdata))
+                                       ;;(temp (println "thl " thishardlink))
+                                       (linkmap (if (or (null? thishardlink) (null? (car (cdr thishardlink))))
+                                                               (prmap-get-template thisx thisy rzloc thisrtype (prmap-params-edgemaps mapdata))
+                                                               (cdr thishardlink)))
+                               )
+                          ;;(println "lm " linkmap)
+                               (prmap-do-map-blit destmap (car linkmap)
+                                       (get-cardinal-lref blitstats dir))
+                               (if (> (length linkmap) 2)
+                                       (map (eval (get-cardinal-lref (cddr linkmap) dir)) (list kplace))
+                                       )
+                       ))
+                       (list north west east south))
+       )
+       ;;(println "done")
+       )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Monster handling
+
+(define (prmap-reduce-level level remaining)
+       (max 1
+               (- level (/ (* level (kern-dice-roll "1d100")) 50 (max remaining 2)))
+               )
+       )
+       
+(define (prmap-get-monster-group quantity grouptype level typelev)
+       (cons (mk-npc (car (get-numbered-elem grouptype typelev)) (ceiling (/ level 100)))
+               (if (> quantity 0)
+                       (prmap-get-monster-group (- quantity 1) grouptype
+                               (prmap-reduce-level level quantity)
+                               (prmap-reduce-level typelev quantity))
+                       nil)
+       ))
+       
+(define (prmap-mk-monster-group group-types monster-types dice level)
+       (let* (
+                       (grouptype (get-numbered-elem group-types (kern-dice-roll dice)))
+                       (grouplist (list-ref monster-types (car grouptype)))
+               )
+               (prmap-get-monster-group (kern-dice-roll (caddr grouptype))
+                       grouplist level (cadr grouptype))
+       ))
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Object handling
+
+(define (prmap-room-roomkey target mapname)
+       (let* ((roomdata (get-roomdata target))
+                               (x (prmap-roomdata-x roomdata))
+                               (y (prmap-roomdata-y roomdata))
+                               (z (prmap-roomdata-z roomdata)))
+               (string-append mapname "|" 
+                       (number->string x) "|" 
+                       (number->string y) "|"
+                       (number->string z))
+       ))
+
+;; TODO this should be done by layer, not type! (add kern method?)
+
+(define (prmap-room-freezable-type obj)
+       (let ((objtype (kern-obj-get-type obj)))
+       (not (in-text-list? objtype (list t_roomdata t_mapdata t_sounddata))
+       ))
+       )
+
+(define (prmap-room-freeze-current mapdata)
+       (let ((current (prmap-params-current mapdata)))
+               (if (not (null? current))
+                       (let* ((roomkey (prmap-room-roomkey current (prmap-params-mapname mapdata))))
+                          ;;(println "freeze: " roomkey)
+                               (map (lambda (obj)
+                                       (if (prmap-room-freezable-type obj)
+                                               (let*
+                                                       ((loc (kern-obj-get-location obj))
+                                                               (x (car (cdr loc)))
+                                                               (y (car (cddr loc))))
+                                                       (kern-obj-freeze obj roomkey x y)
+                                                       (kern-obj-remove obj)
+                                               )
+                                               nil
+                                       ))
+                                       (kern-place-get-objects current))
+                               (prmap-params-set-current mapdata nil)
+                       )
+               )
+               ))
+
+(define (prmap-room-thaw kplace mapdata)
+       (let ((roomkey (prmap-room-roomkey kplace (prmap-params-mapname mapdata))))
+          ;;(println " thaw: " roomkey)
+               (do 
+                       ((obj (kern-obj-thaw roomkey kplace) (kern-obj-thaw roomkey kplace)))
+                       ((null? obj))
+                  ;;(println "obj " (kern-obj-get-name obj))
+               )       
+               (prmap-params-set-current mapdata (prmap-roomdata-tag (get-roomdata kplace)))
+       ))
+
+(define (prmap-room-cleanout kplace)
+       (map (lambda (obj)
+               (if (prmap-room-freezable-type obj)
+                       (begin 
+                               (kern-obj-remove obj))
+                       nil
+               ))
+               (kern-place-get-objects kplace))
+       )
+               
+(define (prmap-room-addmonster kplace kchar)
+       (kern-obj-put-at kchar 
+               (random-loc-place-iter kplace 
+                       (lambda (loc)
+                               (and (passable? loc kchar)
+                                       (not (is-bad-terrain-at? loc))
+                                       (not (any-object-types-at? loc all-field-types))
+                                       (not (occupied? loc))
+                               ))
+               15))
+       )
+
+; creates new objects for a room
+;    this one is rather specific to the endless deeps. need generic version
+(define (prmap-room-init-contents kplace roomdata)
+       (let* (
+                       (rxloc (prmap-roomdata-x roomdata))
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (distance (sqrt (+ (* rxloc rxloc) (* ryloc ryloc))))
+               )
+               (if (and (null? (kern-place-get-beings kplace))
+                               (< (kern-dice-roll "1d100") 
+                                       (min 75 (+ 25 (* 15 (sqrt distance))))))
+                       (begin 
+                       (map (lambda (monster)
+                               (begin 
+
+                                       (prmap-room-addmonster kplace monster)))
+                               (prmap-mk-monster-group deep-group-types deep-monster-types 
+                                       (string-append "1d" (number->string (min 300 (ceiling (* 120 (sqrt distance))))))
+                                       (+ 400 (* 100 (sqrt distance)))))
+                                       )
+               )
+       ))
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Map cohesion checking
+
+(define (vector-2d-make width height fill)
+    (let ((2dvec (make-vector height nil)))
+        (do ((index (- height 1) (- index 1)))
+            ((< index 0) 2dvec)
+          (vector-set! 2dvec index (make-vector width fill)))
+       ))
+       
+(define (vector-2d-get table cursor)
+       (vector-ref (vector-ref table (vector-ref cursor 1)) (vector-ref cursor 0))
+       )
+
+(define (vector-2d-get-off table xmin ymin cursor)
+       (vector-ref (vector-ref table (- (vector-ref cursor 1) ymin)) (- (vector-ref cursor 0) xmin))
+       )
+       
+(define (vector-2d-set-off table xmin ymin cursor entry)
+       (vector-set! (vector-ref table (- (vector-ref cursor 1) ymin)) (- (vector-ref cursor 0) xmin) entry)
+       )
+
+;; ensures that an area of man is completely connected adding new links as necessary
+;; (linkfactory x y z mapdata dir) should return an appropriate hardlink (list template hooks)
+(define (prmap-ensure-cohesion mapdata xmin xmax ymin ymax zloc linkfactory)
+       (let* ((width (- xmax xmin -1))
+                       (height (- ymax ymin -1))
+                       (table (vector-2d-make width height 'unk))
+                       (checking-cursor (vector 0 0))
+                       (checking-end (vector 0 0))
+                       (working-cursor (vector xmin ymin))
+                       ;; flags are: (most southwesterly exploration dir), 
+                       ;; (have finished checking loop),
+                       ;; (have finished checking whole maze)
+                       (flags (vector #f #f #f))
+                       (rmapdata (vector
+                                       (list 0 1 (prmap-params-nsparams mapdata))
+                                       (list 0 0 (prmap-params-ewparams mapdata))
+                                       (list 1 0 (prmap-params-ewparams mapdata))
+                                       (list 0 0 (prmap-params-nsparams mapdata))
+                                       ))
+                       )
+                       
+               (define (prmap-cohesion-check-neighbor linkinfo xloc yloc zloc dir)
+                       (let* (
+                               (thishardlink (get-cardinal-ref linkinfo dir))
+                               (thisrmapdata (get-cardinal-ref rmapdata dir))
+                               (thisx (+ xloc (car thisrmapdata)))
+                               (thisy (+ yloc (cadr thisrmapdata)))
+                               (thisrtype (caddr thisrmapdata))
+                               (linkmap (if (or (null? thishardlink) (null? (car (cdr thishardlink))))
+                                               (prmap-get-template thisx thisy zloc thisrtype (prmap-params-edgemaps mapdata))
+                                               (cdr thishardlink))
+                                               ))
+                                       (cadr linkmap)
+                               ))
+                               
+               (define (link-neighbor linkinfo xloc yloc zloc dir)
+                       (let* ((posoff (get-cardinal-ref prmap-room-offsets dir))
+                                       (xoff (- xmin (car posoff)))
+                                       (yoff (- ymin (cadr posoff)))
+                                       )
+                               (if (and (equal? (vector-2d-get-off table xoff yoff working-cursor) 'unk)
+                                               (prmap-cohesion-check-neighbor linkinfo xloc yloc zloc dir)
+                                               )
+                                       (begin
+                                               (vector-2d-set-off table xoff yoff working-cursor 'lin)
+                                               (vector-set! flags 0 dir)
+                                               ))
+                               ))
+                               
+               (define (check-hardlink xoff yoff dir)
+                       (null? (get-cardinal-ref
+                               (prmap-room-getmaphardlink 
+                                       (+ (vector-ref checking-cursor 0) xoff xmin) 
+                                       (+ (vector-ref checking-cursor 1) yoff ymin) 
+                                               zloc mapdata)
+                                       dir)
+                               ))
+                               
+               (define (mk-linkpair xoff yoff dir1 dir2)
+                       (let ((linkhere (apply linkfactory 
+                                       (list
+                                               (+ (vector-ref checking-cursor 0) xmin)
+                                               (+ (vector-ref checking-cursor 1) ymin)
+                                               zloc mapdata dir1)
+                                       ))
+                               (linkthere (apply linkfactory 
+                                       (list
+                                               (+ (vector-ref checking-cursor 0) xoff xmin)
+                                               (+ (vector-ref checking-cursor 1) yoff ymin) 
+                                               zloc mapdata dir2))
+                                       ))
+                               (prmap-room-hardlink-set! 
+                                       (+ (vector-ref checking-cursor 0) xmin)
+                                       (+ (vector-ref checking-cursor 1) ymin)
+                                       zloc (prmap-params-hardlinks mapdata) dir1
+                                       nil (car linkhere) #t (cadr linkhere))
+                               (prmap-room-hardlink-set! 
+                                       (+ (vector-ref checking-cursor 0) xoff xmin)
+                                       (+ (vector-ref checking-cursor 1) yoff ymin) 
+                                       zloc (prmap-params-hardlinks mapdata) dir2
+                                       nil (car linkthere) #t (cadr linkthere))
+                               )
+                       (vector-2d-set-off table 0 0 checking-cursor 'lin)
+                       (vector-set! working-cursor 0 (+ (vector-ref checking-cursor 0) xmin))
+                       (vector-set! working-cursor 1 (+ (vector-ref checking-cursor 1) ymin))
+                       (vector-set! flags 1 #t)
+                       )       
+                       
+               (vector-set! (vector-ref table 0) 0 'lin)
+                               
+               ;; loop on fixing links till all checked
+               (do 
+                       ()
+                       ((vector-ref flags 2))
+                       
+;; single continuity working pass
+;;
+;; start from northwest corner (or continue from where a new area was linked in)
+;;
+;; we are at the west end of the south row of the potentially linked part of the maze
+;; if we are at a linked cell:
+;;    mark any accessible neighbors as linked
+;;    mark the current cell explored
+;; if we added any linked cells to the south or west, backtrack to those cells
+;;    (so we are always looking at the west end of the southmost unknown row)
+;; otherwise continue east or to the start of the next row
+               
+                       (do
+                               ()
+                               ((> (vector-ref working-cursor 1) ymax))
+                               (vector-set! flags 0 east)
+                               (if (equal? (vector-2d-get-off table xmin ymin working-cursor) 'lin)
+                                       (begin
+                                               (vector-2d-set-off table xmin ymin working-cursor 'exp)
+                                               (let* ((xloc (vector-ref working-cursor 0))
+                                                               (yloc (vector-ref working-cursor 1))
+                                                               (linkinfo (prmap-room-getmaphardlink xloc yloc zloc mapdata)))
+                                                       (if (< (vector-ref working-cursor 1) ymax)
+                                                               (link-neighbor linkinfo xloc yloc zloc north))
+                                                       (if (< (vector-ref working-cursor 0) xmax)
+                                                               (link-neighbor linkinfo xloc yloc zloc east))
+                                                       (if (> (vector-ref working-cursor 0) xmin)
+                                                               (link-neighbor linkinfo xloc yloc zloc west))
+                                                       (if (> (vector-ref working-cursor 1) ymin)
+                                                               (link-neighbor linkinfo xloc yloc zloc south))
+                                               )))
+                               (cond ((equal? (vector-ref flags 0) south)
+                                               (vector-set! working-cursor 1 (- (vector-ref working-cursor 1) 1)))
+                                       ((equal? (vector-ref flags 0) west)
+                                               (vector-set! working-cursor 0 (- (vector-ref working-cursor 0) 1)))
+                                       ((< (vector-ref working-cursor 0) xmax)
+                                               (vector-set! working-cursor 0 (+ (vector-ref working-cursor 0) 1)))
+                                       (#t
+                                               (vector-set! working-cursor 0 xmin)
+                                               (vector-set! working-cursor 1 (+ 1 (vector-ref working-cursor 1))))
+                               )
+                       )
+               
+;; single checking working pass
+;;
+;; start from an initially random point in the maze
+;;
+;; from here iterate through each cell in each row of the maze.
+;; when the current cells status is not the same as that of the cell to the north or east,
+;;    then we are on a boundary between explored and unexplored, so
+;;    create a hardlink joining the cells and stop the current pass
+;; mark any explored cell with explored neighbors so it can be ignored on later passes
+;; when the cursor reaches the northeast point, continue from the southwest
+;; the entire maze is linked when the cursor reaches where it started from 
+       
+                       (vector-set! flags 1 #f)
+                       ;; checking end is tile before current checking cursor
+                       ;;   looping if need be
+                       (vector-set! checking-cursor 0 (- (kern-dice-roll (mkdice 1 width)) 1))
+                       (vector-set! checking-cursor 1 (- (kern-dice-roll (mkdice 1 height)) 1))
+                       (cond ((> (vector-ref checking-cursor 0) 0)
+                               (vector-set! checking-end 0 (- (vector-ref checking-cursor 0) 1))
+                               (vector-set! checking-end 1 (vector-ref checking-cursor 1))
+                               )
+                               ((> (vector-ref checking-cursor 1) 0)
+                                       (vector-set! checking-end 0 (- width 1))
+                                       (vector-set! checking-end 1 (- (vector-ref checking-cursor 1) 1))
+                                       )
+                               (#t
+                                       (vector-set! checking-end 0 (- width 1))
+                                       (vector-set! checking-end 1 (- height 1))
+                                       ))
+       
+                       (do
+                               ()
+                               ((vector-ref flags 1))
+                               (let ((currentstatus (vector-2d-get-off table 0 0 checking-cursor))     )
+                               ;;(println "checking " checking-cursor)
+                               (cond
+                                       ((equal? (vector-2d-get-off table 0 0 checking-cursor) 'chk))
+                                       ;; check east
+                                       ((and (< (vector-ref checking-cursor 0) (- width 1))
+                                                       (not (equal? (vector-2d-get-off table -1 0 checking-cursor) currentstatus))
+                                                       (not (equal? (vector-2d-get-off table -1 0 checking-cursor) 'chk))
+                                                       (check-hardlink 0 0 east)
+                                                       (check-hardlink 1 0 west)
+                                                       )
+                                               (mk-linkpair 1 0 east west)
+                                               ;;(println "mklink east " working-cursor)
+                                               )
+                                       ;; check north
+                                       ((and (< (vector-ref checking-cursor 1) (- height 1))
+                                                       (not (equal? (vector-2d-get-off table 0 -1 checking-cursor) currentstatus))
+                                                       (not (equal? (vector-2d-get-off table 0 -1 checking-cursor) 'chk))
+                                                       (check-hardlink 0 0 north)
+                                                       (check-hardlink 0 1 south)
+                                                       )
+                                               (mk-linkpair 0 1 north south)
+                                               ;;(println "mklink north " working-cursor)
+                                               )
+                                       ((equal? (vector-2d-get-off table 0 0 checking-cursor) 'exp)
+                                               (vector-2d-set-off table 0 0 checking-cursor 'chk))
+                               )
+                               (cond
+                                       ;; done
+                                       ((and (equal? (vector-ref checking-cursor 0) (vector-ref checking-end 0))
+                                               (equal? (vector-ref checking-cursor 1) (vector-ref checking-end 1)))
+                                               (vector-set! flags 1 #t)
+                                               (vector-set! flags 2 #t)
+                                               )
+                                       ;; next cell east
+                                       ((< (vector-ref checking-cursor 0) (- width 1))
+                                               (vector-set! checking-cursor 0 (+ (vector-ref checking-cursor 0) 1)))
+                                       ;; next row
+                                       ((< (vector-ref checking-cursor 1) (- height 1))
+                                               (vector-set! checking-cursor 0 0)
+                                               (vector-set! checking-cursor 1 (+ 1 (vector-ref checking-cursor 1))))
+                                       ;; loop to sw
+                                       (#t
+                                               (vector-set! checking-cursor 0 0)
+                                               (vector-set! checking-cursor 1 0))
+                               )
+                       ))
+                       ;;(println "tab " table)
+               )
+       ))
diff --git a/worlds/haxima-1.002/quest-sys.scm b/worlds/haxima-1.002/quest-sys.scm
new file mode 100644 (file)
index 0000000..bd55b7f
--- /dev/null
@@ -0,0 +1,284 @@
+;; Defines the basic stuff for the haxima quest system
+
+;; Create a new quest.
+;;
+;; title - a string that will be shown in the quest log listing and at the top
+;; of the quest pane
+;;
+;; tag - an optional tag (preferably unique) that can be used to retrieve the quest.
+;;
+;; descr - a list of strings (ie paragraph) that will be shown in the quest pane
+;;
+;; assign - an optional symbol[1] for a proc that will run when the quest is assigned;
+;; of the form (assign quest target), where 'quest' is the thing being created right
+;; here and 'target' is the (scheme) object the quest is being assigned to. Iff
+;; 'assign' returns #t then the quest will be added to the target's list of
+;; quests.
+;;
+;; status - an optional symbol [1] for a proc that will be called by the ztats pane, of
+;; the form (status quest), when the quest details are shown in the quest log.
+;; It is called before the description is written, so it may alter that if required.
+;; The method should return a list of strings to be appended to the description, or nil
+;; Note that this should not be used to update the icon or inprog/done/failed status, as
+;; they are used in the preceeding panel.
+;;
+;; icon - symbol [1] for sprite to use for the quest UI
+;;
+;; payload - whatever you want for your particular quest (this is an optional
+;; number of parms)
+;;
+;; (* optional = use nil to ignore)
+;;
+;; Example:
+;;
+;;   (qst-mk "Find 6 Foozles" 
+;;           '( 
+;;              "If you find 6 Foozles, Mr. Squeejie will give you an enchanted toothpick."
+;;                             "" 
+;;              "Seek them out in distant Foozleburg"
+;;            )
+;;           'find-foozle-assign
+;;           'find-foozle-status
+;;                      's_quest_foozles
+;;           0 ; payload tracks num foozles found so far
+;;           )
+;;
+;; Notes:
+;;
+;; [1] The symbol of a proc named foo is 'foo. You must use a symbol because
+;; the name of the procedure must be saved as part of an object's gob. It would
+;; be nice if you could just pass in a lambda, but saving and reloading lambda
+;; closures is left as an exercise for the advanced reader. BTW, this rule
+;; applies within the payload lists as well.
+;;
+(define (qst-mk title tag descr assign status icon . payload)
+  (if (or (not (symbol? assign))
+          (not (symbol? status)))
+      (error "qst-mk: 'assign' and 'status' must be the symbols for procedures (ie, not the procedures themselves)"))
+  (list 'quest title tag descr assign status 'inprogress icon payload))
+  
+(define (qst-title qst) (list-ref qst 1))
+
+(define (qst-tag qst) (list-ref qst 2))
+
+(define (qst-descr qst) (list-ref qst 3))
+
+(define (qst-assign qst target) 
+  (println "qst-assign")
+  (apply (eval (list-ref qst 4)) 
+         (list qst target)))
+         
+(define (qst-status qst)
+       (let ((statfn (list-ref qst 5)))
+               (if (not (null? statfn))
+                       (apply (eval statfn) (list qst))
+               ))
+)
+
+(define (qst-done? qst)
+  ;;(println "qst-done? qst=" qst)
+  (list-ref qst 6))
+  
+(define (qst-done! qst result)
+       ;;(kern-log-msg "^c+gYou have completed the quest ^c+w" (qst-title qst) "^c-!^c-")
+       (if (not (equal? (list-ref qst 6) result))
+               (begin
+                       (list-set-ref! qst 6 result)
+                       (qst-bump! qst)
+               )
+       ))
+
+(define (qst-complete? qst)
+       (equal? (list-ref qst 6) 'complete))
+       
+(define (qst-complete! qst)
+  (qst-done! qst 'complete))
+  
+(define (qst-failed? qst)
+       (equal? (list-ref qst 6) 'failed))
+
+(define (qst-failed! qst)
+  (qst-done! qst 'failed))
+       
+(define (qst-icon qst) (list-ref qst 7))
+  
+(define (qst-payload qst) (list-ref qst 8))
+
+(define (quest-assign qst)
+  (println "quest-assign")
+  (let ((target (gob (kern-get-player))))
+    (if (and (notnull? qst)
+             (notnull? target)
+             (qst-assign qst target))
+        (begin
+               (quest-insert qst)
+          ;;(tbl-append! target 'quests qst)
+          ;;(println "quest-assign: " target)
+          ;;(kern-log-msg "^c+gYou have a new quest: " (qst-title qst) "^c-")
+          ))))
+          
+(define (quest-assigned? qst)
+       (println "quest-assigned?")
+       (let* ((target (gob (kern-get-player)))
+                       (qstlist (tbl-get target 'quests))
+                       )
+               (if (or (null? qst)
+                               (null? qstlist)
+                               )
+                       #f
+                       (in-list? qst qstlist)
+       )
+       ))
+      
+;; first item, if any, else nil 
+(define (safe-car alist)
+       (cond ((null? alist)
+               nil)
+               ((pair? alist)
+               (car alist))
+               (#t alist))) 
+          
+(define (quest-get tag)
+       (safe-car
+               (filter 
+                       (lambda (quest) (eq? (qst-tag quest) tag))
+                       (tbl-get (gob (kern-get-player)) 'quests)
+               )
+       ))
+
+(define (quest-remove qst)
+       ;; (cons a nil) = a; (cons nil b) != b;
+       (define (quest-remove-helper qstlist)
+               (if (null? qstlist) nil
+                       (let ((qhead (safe-car qstlist)))
+                               (println "rem? " (eq? qhead qst) " " )
+                               (if (eq? qhead qst)
+                                       (cdr qstlist)
+                                       (cons
+                                               qhead
+                                               (quest-remove-helper (cdr qstlist))
+                                       )
+                               )
+                       )
+               ))
+       (let* ((target (gob (kern-get-player)))
+                       (trimmed  (quest-remove-helper (tbl-get target 'quests) qst))
+                       )
+               (if (null? trimmed)
+                       (tbl-rm! target 'quests)
+                       (tbl-set! target 'quests trimmed)
+                       )
+       ))
+       
+(define (qst-set-title! qst title) (list-set-ref! qst 1 title))
+(define (qst-set-descr! qst descr) (list-set-ref! qst 3 descr))
+(define (qst-set-icon! qst icon) (list-set-ref! qst 7 icon))
+
+;; bump the quest to the top of its appropriate list
+(define (qst-bump! quest)
+       (define (qst-bump-base! qst)
+               (if (quest-assigned? qst)
+                       (begin
+                               (quest-remove qst)
+                               (quest-insert qst)
+                       )
+               ))
+       ;; if we have a parent quest, bump that first
+       (let ((parent (quest-tbl-get quest 'qparent)))
+               (if (not (null? parent))
+                       (let ((pqst (quest-get parent)))
+                               (if (not (null? pqst))
+                                       (qst-bump! pqst)
+                               ))
+               ))
+       (qst-bump-base! quest)
+       ;; if we have children, bump them
+       (let ((childlist (quest-tbl-get quest 'qchildren)))
+               (println childlist)
+               (map (lambda (entry)
+                               (let ((cqst (quest-get entry)))
+                                       (if (not (null? cqst))
+                                               (qst-bump-base! cqst)
+                                               )
+                                       ))
+                        childlist)
+               )
+       )
+       
+(define (quest-insert qst)
+       (let* ((target (gob (kern-get-player)))
+                       (targlist (tbl-get target 'quests))
+                       (inserttype (qst-done? qst))
+                       (parent (quest-tbl-get qst 'qparent))
+                       )
+               (define (insert-here? testee)
+                       (cond ((eq? inserttype 'inprogress) #t)
+                               ((eq? inserttype (qst-done? testee)) #t)
+                               ((eq? 'failed (qst-done? testee)) #t)
+                               (#t #f))
+                       )
+               (define (quest-insert-helper qstlist)
+                       (if (null? qstlist) (list qst)
+                               (let ((qhead (safe-car qstlist)))
+                                       (if (insert-here? qhead)
+                                               (cons qst qstlist)
+                                               (cons
+                                                       qhead
+                                                       (quest-insert-helper (cdr qstlist))
+                                               )
+                                       )
+                               )
+                       ))
+               (define (quest-insertchild-helper qstlist)
+                       (if (null? qstlist) (list qst)
+                               (let ((qhead (safe-car qstlist)))
+                                       (if (or (not (equal? parent (quest-tbl-get qhead 'qparent)))
+                                                       (insert-here? qhead))
+                                               (cons qst qstlist)
+                                               (cons
+                                                       qhead
+                                                       (quest-insertchild-helper (cdr qstlist))
+                                               )
+                                       )
+                               )
+                       ))
+               (define (quest-insert-findparent qstlist)
+                       (if (null? qstlist) (nil)
+                               (let ((qhead (safe-car qstlist)))
+                                       (if (equal? parent (qst-tag qhead))
+                                               (cons
+                                                       qhead 
+                                                       (quest-insertchild-helper (cdr qstlist))
+                                               )
+                                               (cons
+                                                       qhead
+                                                       (quest-insert-findparent (cdr qstlist))
+                                               )
+                                       )
+                               )
+                       ))
+               (cond ((null? targlist) (tbl-append! target 'quests qst))
+                       ((null? parent) (tbl-set! target 'quests (quest-insert-helper targlist)))
+                       (#t (tbl-set! target 'quests (quest-insert-findparent targlist)))
+                       )
+       ))
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Some special handling for quests with tbl payloads
+
+(define (quest-tbl? quest)
+       (let ((qpayload (qst-payload quest)))
+               (cond ((not (pair? qpayload)) #f)
+                        ((not (pair? (car qpayload))) #f)
+                       (#t (is-tbl? (car qpayload)))
+               )
+       ))
+       
+(define (quest-tbl-get quest tag)
+       (let ((qpayload (qst-payload quest)))
+               (cond ((not (pair? qpayload)) nil)
+                        ((not (pair? (car qpayload))) nil)
+                       ((not (is-tbl? (car qpayload))) nil)
+                       (#t (tbl-get (car qpayload) tag))
+               )
+       ))
diff --git a/worlds/haxima-1.002/quests-data-static.scm b/worlds/haxima-1.002/quests-data-static.scm
new file mode 100644 (file)
index 0000000..6f8bd47
--- /dev/null
@@ -0,0 +1,804 @@
+;;----------------------------------------------------
+;; this is a collection place for updates to quests
+;;
+;; the function is an arbitary method call, but the ones here tend to
+;; basically boil down to retreiving a bunch of flags from the quest payload
+;; and updating the quest via (qst-set-descr! text)
+;;
+;; the boilerplate at the front of the methods just makes the quest data easily accessible
+;; via a tbl-flag? method without needing to go through several level of redirection each time
+;;
+
+;;---------------
+;; bandits
+(define (quest-bandits-update)
+  (println "quest-bandits-update")
+  (let* ((quest (quest-data-get 'questentry-bandits))
+         (quest-tbl (car (qst-payload quest)))
+         (header (kern-ui-paginate-text
+                  "Gregor, an old charcoal burner, has asked for your help in dealing with some troublesome bandits that have been plaguing the great forest."
+                  "")))
+    (println "quest-tbl:" quest-tbl)
+    (define (tbl-flag? tag) 
+      (not (null? (tbl-get quest-tbl tag)))
+      )
+    (qst-set-descr! quest
+                    (cond ((tbl-flag? 'done)
+                           (kern-ui-paginate-text
+                            "You have delivered Nate to the Rangers of Green Tower and he is now their problem."
+                            ))
+                          ((tbl-flag? 'nate-given-to-jailor)
+                           (append header
+                                   (kern-ui-paginate-text
+                                    "Take the jailor's receipt back to Deric, the commander of the Green Tower rangers, to collect the reward."
+                                    )))
+                          ((tbl-flag? 'captured-nate-and-talked-to-deric)
+                           (append header
+                                   (kern-ui-paginate-text
+                                    "Deliver Nate to the jailor in Green Tower and he will give you a receipt."
+                                    )))
+                          ((tbl-flag? 'captured-nate)
+                           (append header
+                                   (kern-ui-paginate-text 
+                                    "Take Nate back to Green Tower and talk to the Ranger commander."
+                                    )))
+                          ((tbl-flag? 'talked-to-deric)
+                           (append header
+                                   (kern-ui-paginate-text 
+                                    "Deric, commander of the rangers, was not much help. But he did give you signed orders to enlist one of his men."
+                                    )))
+                          (else
+                           (append header
+                                   (kern-ui-paginate-text
+                                    "Gregor said to ask about the bandits in Green Tower."
+                                    )))
+                          )
+
+               )
+       ))
+
+;;---------------
+;; whereami
+
+    (define (quest-whereami-update)
+      (let* ((quest (quest-data-get 'questentry-whereami))
+             (quest-tbl (car (qst-payload quest)))
+             (qp-shard (tbl-get quest-tbl 'shard))
+             (qp-wanderer (tbl-get quest-tbl 'wanderer)))
+
+        (qst-set-descr! quest
+                        
+                        (if (not (null? (tbl-get quest-tbl 'nossifer)))
+
+                            (kern-ui-paginate-text
+                             "You have found yourself on the Shard, a small fragment of a world, that floats surrounded by a great void."
+                             ""
+                             "The demon lord Nossifer arranged for your arrival, to set in motion events that would allow his own passage to the Shard."
+                             ""
+                             "Now the Demon Gate is open, and the only thing left in Nossifer's way is you..."
+                             )
+                            
+                            (append
+                             ;;1 where
+                             (cond ((null? qp-shard)
+                                    (kern-ui-paginate-text
+                                     "You have found yourself in a world you have no knowledge of, with barest impressions of what might have gone before."
+                                     ""
+                                     ))
+                                   ((equal? 1 qp-shard)
+                                    (kern-ui-paginate-text
+                                     "You have found yourself in a world you have no knowledge of. The inhabitants refer to it as the Shard."
+                                     ""
+                                     ))
+                                   (#t (kern-ui-paginate-text
+                                        "You have found yourself on the Shard, a small fragment of a world, that floats surrounded by a great void."
+                                        ""
+                                        ))
+                                   )
+
+
+                             ;; how
+                             (if (and (null? qp-wanderer) (null? qp-shard))
+                                 (kern-ui-paginate-text "Where are you?")
+                                 nil
+                                 )
+                             
+                             (cond ((null? qp-wanderer)
+                                    (kern-ui-paginate-text
+                                     "How and why are you here?"
+                                     "And what are you going to do now?"
+                                     ))
+                                   ((equal? 1 qp-wanderer)
+                                    (kern-ui-paginate-text
+                                     "Others like you have in the past been found stumbling into this world. The inhabitants know you as 'Wanderers'."
+                                     ""
+                                     "Now you are here, what are you going to do?"
+                                     ))
+                                   (#t (kern-ui-paginate-text
+                                        "Wanderers like yourself, who have occasionally stumbled upon this world, have in the past been responsible for great deeds."
+                                        ""
+                                        "How will you make your place?"
+                                        ))
+                                   )
+
+                             )
+                            )
+                        )
+       ))
+
+;;-----------------------
+;; calltoarms
+
+(define (quest-calltoarms-update)
+       (let* ((quest (quest-data-get 'questentry-calltoarms))
+                       (quest-tbl (car (qst-payload quest)))
+                       (header (kern-ui-paginate-text
+                                       "You have recieved an urgent message to contact someone called the Enchanter as soon as possible."
+                                       "")))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "You have allied yourself with the Enchanter, one of the Wise who watch over the shard."
+               ))
+       ((tbl-flag? 'talked)
+               (append header
+               (kern-ui-paginate-text
+                       "You have met with the Enchanter, but you and he did not come to any agreement."
+               )))
+       ((tbl-flag? 'tower)
+               (append header
+               (kern-ui-paginate-text
+                       "You have found the Enchanter's Tower in the Fens. However, getting inside could be more difficult than reaching it."
+               )))
+       ((tbl-flag? 'directions)
+               (append header
+               (kern-ui-paginate-text
+                       "The Enchanter's Tower may be found in the Fens, a swampland north of the town of Trigrave, in the western part of the Shard."
+               )))
+       (#t
+               (append header
+               (kern-ui-paginate-text
+                       "The message suggests that you ask the caretaker of the clearing that you arrived in for directions."
+               )))
+)
+
+               )
+       ))
+
+;; give some xp for reaching the tower
+(define (quest-calltoarms-tower kplace kplayer)
+       (quest-data-update-with 'questentry-calltoarms 'tower 1 (quest-notify (grant-xp-fn 5)))
+       )
+
+;;-----------------------
+;; thiefrune
+
+;; TODO: make the theft appear not to happen until the player is on the scene, by altering convs based on quest status
+
+(define (quest-thiefrune-update)
+       (let* ((quest (quest-data-get 'questentry-thiefrune))
+                       (quest-tbl (car (qst-payload quest)))
+                       (header (kern-ui-paginate-text
+                                       "The Enchanter has asked you to investigate a theft from his tower."
+                                       "")))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond ((tbl-flag? 'recovered) 
+               (append header
+               (kern-ui-paginate-text
+                       "You have tracked down the thief and retrieved a rune belonging to the Enchanter."
+               )))
+       ((tbl-flag? 'talked)
+               (append header
+               (kern-ui-paginate-text
+                       "The culprit, Mouse, seems to be willing to negotiate."
+               )))
+       ((tbl-flag? 'den5)
+               (append header
+               (kern-ui-paginate-text
+                       "You have found the thief's hideout in Bole, and breached the defensive upper levels."
+               )))
+       ((tbl-flag? 'den4)
+               (append header
+               (kern-ui-paginate-text
+                       "You have found the thief's hideout in Bole, and have passed three levels of traps."
+               )))
+       ((tbl-flag? 'den3)
+               (append header
+               (kern-ui-paginate-text
+                       "You have found the thief's hideout in Bole, and have passed two levels of traps."
+               )))
+       ((tbl-flag? 'den2)
+               (append header
+               (kern-ui-paginate-text
+                       "You have found the thief's hideout in Bole, but have only passed the first level."
+               )))
+       ((tbl-flag? 'den1)
+               (append header
+               (kern-ui-paginate-text
+                       "You have found the thief's hideout in Bole, but have yet to breach its defenses."
+               )))
+       ((tbl-flag? 'bole)
+               (append header
+               (kern-ui-paginate-text
+                       "The ^c+mthief^c- has been seen heading northeast through the Great Forest. Bole would be the most likely place to look."
+               )))
+       ((tbl-flag? 'tower)
+               (append header
+               (kern-ui-paginate-text
+                       "The ^c+mthief^c- has been seen heading east through the mountain passes. The Green Tower would be the best place to start looking."
+               )))
+       (#t
+               (append header
+               (kern-ui-paginate-text
+                       "The ^c+mthief^c- has been tracked as far as Trigrave. The townsfolk there may be able to give you further information."
+               )))
+)
+
+               )
+       ))
+
+;; give some xp for getting through the dungeon
+(define (quest-thiefrune-den1 kplace kplayer)
+       (quest-data-update 'questentry-thiefrune 'tower 1)
+       (quest-data-update 'questentry-thiefrune 'bole 1)
+       (quest-data-update-with 'questentry-thiefrune 'den1 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+(define (quest-thiefrune-den2 kplace kplayer)
+       (quest-data-update-with 'questentry-thiefrune 'den2 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+(define (quest-thiefrune-den3 kplace kplayer)
+       (quest-data-update-with 'questentry-thiefrune 'den3 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+(define (quest-thiefrune-den4 kplace kplayer)
+       (quest-data-update-with 'questentry-thiefrune 'den4 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+(define (quest-thiefrune-den5 kplace kplayer)
+       (quest-data-update-with 'questentry-thiefrune 'den5 1 (quest-notify (grant-party-xp-fn 10)))
+       )
+
+
+;;-----------------------
+;; runeinfo
+
+;; TODO: runes are unidentified until you check in with abe?
+
+(define (quest-runeinfo-update)
+       (let* ((quest (quest-data-get 'questentry-runeinfo))
+                       (quest-tbl (car (qst-payload quest)))
+                       (header (kern-ui-paginate-text
+                               "The stolen rune that you recovered must have great significance to prompt it's theft. The Enchanter has given you the task of seeking out this reason."
+                               ""
+                               )))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "The rune you carry is one of the Keys to the Demon Gate. The gate itself lies somewhere in the north. It was sealed by the wise in ages past, and the Keys were scattered and hidden."
+               ))
+       ((tbl-flag? 'gate)
+               (append header
+               (kern-ui-paginate-text
+                       "The runes are also known as the Keys to the Demon Gate. The gate itself lies somewhere in the north. It was sealed by the wise in ages past, and the Keys were scattered and hidden."
+               )))
+       ((tbl-flag? 'keys)
+               (append header
+               (kern-ui-paginate-text
+                       "The runes are also known as the Keys to the Demon Gate. What that means remains unknown."
+               )))
+       ((tbl-flag? 'abe)
+               (append header
+               (kern-ui-paginate-text
+                       "The Alchemist has advised you that ^c+mAbe^c-, at the Green Tower, has studied the nature of the runes."
+               )))
+       (#t
+               (append header
+               (kern-ui-paginate-text
+                       "He suggests that you start with the ^c+mAlchemist^c-, who may be found at Oparine."
+               )))
+)
+
+               )
+       ))
+
+
+;;-----------------------
+;; dragon blood
+
+(define (quest-dragon-update quest)
+       (let* ((quest-tbl (car (qst-payload quest)))
+                       (header (kern-ui-paginate-text
+                               "The Alchemist has offered to trade you information on the wherabouts of a Rune, in exchange for the blood of a dragon."
+                               )))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "The Alchemist has traded you information on the wherabouts of a Rune, in exchange for the blood of a dragon."
+               ))
+       ((in-inventory? (car (kern-party-get-members (kern-get-player))) t_dragons_blood 1)
+               (append header
+               (kern-ui-paginate-text
+                       ""
+                       "You have a vial of dragon's blood in your possession."
+               )))
+       ((tbl-flag? 'sea)
+               (append header
+               (kern-ui-paginate-text
+                       ""
+                       "He suggests that the Fire Sea may be the best place to seek them out."
+               )))
+       (#t
+               header
+               )
+)
+
+               )
+       ))
+
+;;-----------------------
+;; deeps rune
+
+(define (quest-rune-p-update)
+       (let* ((quest (quest-data-get 'questentry-rune-p))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "A rune was found in the depths of Kurpolis."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "The Alchemist provided you with information on a rune buried in the deeps of Kurpolis:"
+                       ""
+                  "\"The paladins have built several fortifications in the deeps of Kurpolis. One of the runes was buried in the foundations of the deepest fort.\""
+                  ""
+                       "\"A pick and shovel may be enough to get it out again, but it might be difficult with a dozen paladins breathing down your neck.\""
+               ))
+)
+
+               )
+       ))
+       
+       
+;;-----------------------
+;; spider rune
+
+(define (quest-rune-f-update)
+       (let* ((quest (quest-data-get 'questentry-rune-f))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "The lost rune of King Clovis was retrieved from the Spider Queen Angriss."
+               ))
+       ((and (tbl-flag? 'angrisslair) (tbl-flag? 'angriss))
+               (kern-ui-paginate-text
+                       "King Clovis once possessed a rune, but he fell during the Goblin Wars."
+                       ""
+                       "Information from the goblins has lead you to Angriss' lair, which may be where the rune lies now."
+               ))      
+       ((tbl-flag? 'angriss)
+               (kern-ui-paginate-text
+                       "King Clovis once possessed a rune, but he fell during the Goblin Wars."
+                       ""
+                  "The goblin Kama has given you a clue to its location- Something (maybe a spider?) can be found where the southern edge of the Great Forest meets the mountains in the east."
+               ))              
+       ((tbl-flag? 'kama)
+               (kern-ui-paginate-text
+                       "King Clovis once possessed a rune, but he fell during the Goblin Wars."
+                       ""
+                  "The goblins may know what became of it. The goblin Kama may be able to help you, if you can find him."
+               ))              
+       ((tbl-flag? 'gen)
+               (kern-ui-paginate-text
+                       "King Clovis once possessed a rune, but he fell during the Goblin Wars."
+                       ""
+                  "The goblins may know what became of it. Amongst humans, the ranger Gen has the greatest knowledge of their kind."
+               ))              
+       (#t
+               (kern-ui-paginate-text
+                       "King Clovis once possessed a rune, but he fell during the Goblin Wars."
+                       ""
+                  "The goblins may know what became of it, but would they tell you?"
+               ))
+)
+
+               )
+       ))
+       
+(define (quest-rune-f-lair kplace kplayer)
+       (if (not (null? (quest-data-getvalue 'questentry-rune-f 'angriss)))
+               (quest-data-update-with 'questentry-rune-f 'angrisslair 1 (quest-notify nil))
+       ))
+
+;;-----------------------
+;; void rune
+
+;; todo add more sections? info on voidships, etc?
+
+(define (quest-rune-d-update)
+       (let* ((quest (quest-data-get 'questentry-rune-d))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "A rune was recovered from the Temple of the Void."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "Legends tell of a temple in the void, which housed a rune."
+               ))
+)
+
+               )
+       ))
+
+;;-----------------------
+;; pirate rune
+
+(define (quest-rune-c-update)
+       (let* ((quest (quest-data-get 'questentry-rune-c))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "A rune was recovered from the wreck of the Merciful Death."
+               ))
+       ((tbl-flag? 'shiploc)
+               (append
+                       (kern-ui-paginate-text
+                       "The pirate captain Ghertie once held a rune aboard her ship, the Merciful Death."
+                       ""
+                       )
+                       (kern-ui-paginate-text (string-append "Her ghost has revealed the location of the ship: [" (number->string merciful-death-x) ", " (number->string merciful-death-y) "]."))
+                       (if (tbl-flag? 'shipraise)
+                               (kern-ui-paginate-text
+                               ""
+                               "The ship may be raised with the Vas Uus Ylem spell, mixed using mandrake, blood moss and spider silk."
+                               )
+                               nil
+                       )
+               ))
+       ((tbl-flag? 'info)
+               (kern-ui-paginate-text
+                       "The pirate captain Ghertie once held a rune aboard her ship, the Merciful Death."
+                       ""
+                       "Her ghost now haunts Oparine, seeking ^c+mrevenge^c- upon her crew."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "The pirate captain Ghertie once held a rune."
+               ))
+)
+
+               )
+       ))
+
+;;-----------------------
+;; pirate quest
+
+(define (quest-ghertie-update)
+       (let* ((quest (quest-data-get 'questentry-ghertie))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       (string-append "The ghost of Ghertie the pirate once haunted the inn at Oparine. In exchange for her revenge, she revealed the location of her sunken ship: [" (number->string merciful-death-x) ", " (number->string merciful-death-y) "].")
+               ))
+       ((tbl-flag? 'questinfo)
+               (append
+                       (kern-ui-paginate-text
+                               "The ghost of Ghertie the pirate haunts the inn at Oparine. She seeks revenge on the survivors of the crew that betrayed her."
+                               ""
+                               "Gholet, Jorn and Meaney each wear a ring marking them as Ghertie's crew. Ghertie will accept the rings as proof that you have hunted them down, in exchange for the location of her sunken treasure."
+                       )
+                       (if (and (tbl-flag? 'ring-jorn)
+                                               (tbl-flag? 'ring-meaney)
+                                               (tbl-flag? 'ring-gholet))
+                               (kern-ui-paginate-text
+                                       ""
+                                       "You have retrieved all three skull rings."
+                               )
+                               (append
+                                       (cond 
+                                               ((tbl-flag? 'ring-gholet)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "You have retrieved a skull ring from Gholet."
+                                                       ))
+                                               ((tbl-flag? 'gholet-price)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "Gholet is held in the dungeons beneath Glasdrin, and will exchange the ring for a dozen lockpicks."
+                                                       ))
+                                               ((tbl-flag? 'gholet-dungeon)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "Gholet is held in the dungeons beneath Glasdrin."
+                                                       ))
+                                               ((tbl-flag? 'gholet-prison)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "If Gholet can be found anywhere it will be in some prison or another."
+                                                       ))
+                                               (#t nil)
+                                       )
+                                       (cond 
+                                               ((tbl-flag? 'ring-jorn)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "You have retrieved a skull ring from Jorn."
+                                                       ))
+                                               ((tbl-flag? 'jorn-loc)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "Jorn can be found at the Green Tower's White Stag Inn."
+                                                       ))
+                                               ((tbl-flag? 'jorn-forest)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "Jorn is a bandit somewhere in the Great Forest."
+                                                       ))
+                                               (#t nil)
+                                       )
+                                       (cond 
+                                               ((tbl-flag? 'ring-meaney)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "You have retrieved a skull ring from Meaney."
+                                                       ))
+                                               ((tbl-flag? 'meaney-loc)
+                                                       (kern-ui-paginate-text
+                                                               ""
+                                                               "Meaney runs the Poor House, north of Oparine."
+                                                       ))
+                                               (#t nil)
+                                       )
+                               )
+                       )
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       (string-append
+                               (if (tbl-flag? 'ghertieid)
+                                       "The ghost of Ghertie the pirate" 
+                                       "A ghost")
+                               (if (tbl-flag? 'ghertieloc)
+                                       "haunts the inn at Oparine. "
+                                       "may be found in Oparine. ")
+                               (if (tbl-flag? 'revenge)
+                                       "She seeks ^c+mrevenge^c-, and may aid you if you take care of her unfinished business."
+                                       (string-append "Why does "
+                                               (if (tbl-flag? 'ghertieid) "she" "it")
+                                               "linger in undeath?"
+                                       )
+                               ))
+               ))
+)
+
+               )
+       ))
+
+
+;;------------------------------------------------------------------------ 
+;; Warritrix rune
+;; 
+
+(define (quest-rune-l-update)
+       (let* ((quest (quest-data-get 'questentry-rune-l))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "A rune was recovered from the fallen Warritrix."
+               ))
+       ((and (tbl-flag? 'located) (tbl-flag? 'know-hall))
+               (kern-ui-paginate-text
+                       (string-append
+                       "One of the runes is carried by the Warritrix. "
+                       "She may be found in the Lost Halls, at [" 
+                       (number->string (loc-x lost-halls-loc)) "," (number->string (loc-y lost-halls-loc))
+                       "]."
+                       )
+               ))
+       ((and (tbl-flag? 'located) (tbl-flag? 'approx-hall))
+               (kern-ui-paginate-text
+                       (string-append
+                       "One of the runes is carried by the Warritrix. "
+                       "She may be found in the Lost Halls, on the Shard's south coast."
+                       )
+               ))
+       ((tbl-flag? 'located)
+               (kern-ui-paginate-text
+                       "One of the Runes is carried by the Warritrix, who may be found at the Lost Halls."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "One of the Runes is carried by the Warritrix."
+               ))
+)              
+
+               )
+       ))
+
+;;-----------------------
+;; absalot rune
+
+(define (quest-rune-s-update)
+       (let* ((quest (quest-data-get 'questentry-rune-s))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'done)
+               (kern-ui-paginate-text
+                       "A rune was recovered from the Absalot ruins."
+               ))
+       ((tbl-flag? 'silasinfo)
+               (kern-ui-paginate-text
+                       "Silas has a rune hidden in the Absalot ruins."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "A rune may be found somewhere in Absalot."
+               ))
+)
+
+               )
+       ))
+
+;;-----------------------
+;; enchanter rune
+;; tracks if the player has gotten the rune back from the enchanter
+
+(define (quest-rune-k-update)
+       (let* ((quest (quest-data-get 'questentry-rune-k))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond 
+       ((tbl-flag? 'entrusted-with-rune)
+               (kern-ui-paginate-text
+                       "The Enchanter has entrusted the Rune of Knowledge into your care."
+               ))
+       ((tbl-flag? 'player-got-rune)
+               (kern-ui-paginate-text
+                       "The Rune of Knowledge belonged to the Enchanter, but has since fallen into your hands."
+               ))
+       ((tbl-flag? 'ench-should-have-rune)
+               (kern-ui-paginate-text
+                       "The Rune of Knowledge belongs to the Enchanter. You may be able to convince him to turn it over to you."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "The Rune of Knowledge belonged to the Enchanter."
+               ))
+)
+
+               )
+       ))
+
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Search for the Wise quest group
+
+(define (quest-wise-init)
+       (quest-data-assign-once 'questentry-wise)
+       (map (lambda (tag)
+                (if (not (null? (quest-data-getvalue tag 'name)))
+                       (quest-data-assign-once tag)
+               ))
+               (list 'questentry-enchanter 'questentry-warritrix  'questentry-alchemist
+                                               'questentry-the-man 'questentry-engineer  'questentry-necromancer)
+       ))
+
+(define (quest-wise-subinit tag)
+       (quest-data-update tag 'name 1)
+       (if (quest-data-assigned? 'questentry-wise)
+               (quest-data-assign-once tag)
+       )
+       )
+
+;; TODO- merge lost hall location info with rune quest 
+(define (quest-warritrix-update)
+       (let* ((quest (quest-data-get 'questentry-warritrix))
+                       (quest-tbl (car (qst-payload quest))))
+               (define (tbl-flag? tag) (not (null? (tbl-get quest-tbl tag))))
+               (qst-set-descr! quest
+               
+(cond
+       ((tbl-flag? 'avenged)
+               (kern-ui-paginate-text
+                       "The Warritrix was the most cunning warrior of the age, but was slain in an ambush in the Lost Halls."
+                       ""
+                       "You have since brought her betrayers to justice."
+               ))
+       ((tbl-flag? 'found)
+               (kern-ui-paginate-text
+                       "The Warritrix was the most cunning warrior of the age, but was slain in an ambush in the Lost Halls."
+               ))
+       ((tbl-flag? 'slain)
+               (cond
+                       ((tbl-flag? 'lost-hall-loc)
+                               (kern-ui-paginate-text
+                                       (string-append
+                                       "The Warritrix was the most cunning warrior of the age, but her spirit has been seen in the Void."
+                                       ""
+                                       "Her mortal remains may still lie in the Lost Halls, at ["
+                                       (number->string (loc-x lost-halls-loc)) "," (number->string (loc-y lost-halls-loc))
+                                       "]."
+                                       )
+                               ))
+                       ((tbl-flag? 'lost-hall)
+                               (kern-ui-paginate-text
+                                       "The Warritrix was the most cunning warrior of the age, but her spirit has been seen in the Void."
+                                       ""
+                                       "Her mortal remains may still lie in the Lost Halls."
+                               ))
+                       (#t
+                               (kern-ui-paginate-text
+                                       "The Warritrix was the most cunning warrior of the age, but her spirit has been seen in the Void."
+                                       ""
+                                       "When alive, she served the city of Glasdrin."
+                               ))
+               ))
+       ((tbl-flag? 'lost-hall-loc)
+               (kern-ui-paginate-text
+                       (string-append
+                       "The Warritrix is the most cunning warrior of the age. She is overdue from her mission the the Lost Halls, which can be found at ["
+                       (number->string (loc-x lost-halls-loc)) "," (number->string (loc-y lost-halls-loc))
+                       "]."
+                       )
+               ))
+       ((tbl-flag? 'lost-hall)
+               (kern-ui-paginate-text
+                       "The Warritrix is the most cunning warrior of the age. A mission has taken her to the Lost Halls."
+               ))
+       ((tbl-flag? 'assignment)
+               (kern-ui-paginate-text
+                       "The Warritrix is the most cunning warrior of the age. She is currently away from Glasdrin on a mission."
+               ))
+       ((tbl-flag? 'general-loc)
+               (kern-ui-paginate-text
+                       "The Warritrix is the most cunning warrior of the age. She can normally be found around Glasdrin."
+               ))
+       ((tbl-flag? 'common)
+               (kern-ui-paginate-text
+                       "The Warritrix is the most cunning warrior of the age."
+               ))
+       (#t
+               (kern-ui-paginate-text
+                       "The Warritrix is one of the wise."
+               ))
+)
+
+               )
+       ))
diff --git a/worlds/haxima-1.002/quests-data.scm b/worlds/haxima-1.002/quests-data.scm
new file mode 100644 (file)
index 0000000..185dc7a
--- /dev/null
@@ -0,0 +1,478 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Quest Data Table
+;;
+;; The basic quest data mechanism is based on a tbl of quest information. This allows quests
+;; to be created once, then tracked and updated from a central repository.
+;; While not suitable for quests generated on the fly, this is a lot more convenient for
+;; complex plot based quests. On the fly quests can still interface directly with the
+;; quest-sys module.
+;;
+;; The questadd function here handles creation of quests (it also makes sure the quest is
+;; created iff it is needed, so savegames have some chance of updating right)
+;;
+;; It is inside a let definition, and hence wont work elsewhere. The quest to be added is
+;; a quest using qst-mk from the quest-sys module
+;;
+;; (questadd (qst-mk
+;;    "Name of Quest"
+;;    'tag-to-refer-to-quest
+;;    "Text description of quest, probably using kern-ui-paginate-text"
+;;    'function-called-on-quest-assignment  ;; probably 'quest-assign-notify, or nil
+;;    'function-called-before-quest-is-displayed  ;; probably nil
+;;    'sprite-for-quest
+;;    quest-payload
+;;     )
+;;
+;; The various quest-data-* methods assume that quest-payload is a tbl, containing various
+;; info possibly including:
+;;
+;;             'on-update  a method name that will be called in response to a quest-data-update call
+;;             'bonus-xp   a storage space for experience rewards that are accrued before the player
+;;                                     knows about the quest (the xp will increase the rewards given once the
+;;                                     the player knows why they are being given xp)
+;;
+;;
+;; Using quests basically boils down to:
+;;      defining the quest here
+;;      adding a (quest-data-assign-once 'tag-to-refer-to-quest) at the relevent place in the game code
+;;      adding a (quest-data-complete 'tag-to-refer-to-quest)
+;;                                   at the relevent place in the game code
+;;             
+;;             for nicely updating quest information, add the on-update method as described above, and sprinkle
+;;      the plot with
+;;          (quest-data-update 'tag-to-refer-to-quest 'name-of-quest-flag value-to-set-tag-to)
+;;             and
+;;          (quest-data-update-with 'tag-to-refer-to-quest 'name-of-quest-flag value-to-set-tag-to
+;;                  function-to-perform-if-the-tag-wasnt-already-set-that-way)
+;;      a common example of the latter would be giving the party an xp reward:
+;;          (quest-data-update-with 'tag-to-refer-to-quest 'name-of-quest-flag value-to-set-tag-to
+;;                  (grant-party-xp-fn amount-of-xp-to-share-out))
+;;
+;;
+
+(let*
+       (
+               (newtbl (tbl-mk))
+               (oldtbl (tbl-get (gob (kern-get-player)) 'questdata))
+               (questdata (if (null? oldtbl)
+                                               (begin 
+                                                       (tbl-set! (gob (kern-get-player)) 'questdata newtbl)
+                                                       newtbl
+                                               )
+                                               oldtbl))
+               (questadd (lambda (quest)
+                       (if (null? (tbl-get questdata (qst-tag quest)))
+                               (tbl-set! questdata (qst-tag quest) quest)
+                       )))
+       )
+       
+(questadd (qst-mk 
+       "Character Creation"
+       'questentry-charcreate
+       (kern-ui-paginate-text
+               "Move to the moongate at the north side of the room to begin the game."
+               ""
+               "Along the way you will be prompted for your characters name. You may also customize your attributes by talking to the statues in the room."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_quest_start
+       0
+))
+
+(questadd (qst-mk "Where am I?"
+       'questentry-whereami
+       (kern-ui-paginate-text
+               "You have found yourself in a world you have no knowledge of, with barest impressions of what might have gone before."
+               ""
+               "Where are you?"
+               "How and why are you here?"
+               "And what are you going to do now?"
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_quest_start
+       (tbl-build
+               'on-update 'quest-whereami-update
+               )
+       ;; 'shard- pc knows about shard(1), cosmology(2)
+       ;; 'wanderer- pc knows about wanderers(1), potential(2)
+       ;; 'nossifer- pc knows about N's summoning(3)
+))
+
+(questadd (qst-mk "A Call to Arms"
+       'questentry-calltoarms
+       (kern-ui-paginate-text
+               "You have recieved an urgent message to contact someone called the Enchanter as soon as possible."
+               ""
+               "The message suggests that you ask the caretaker of the clearing that you arrived in for directions."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_enchanter
+       (tbl-build
+               'on-update 'quest-calltoarms-update
+               'bonus-xp 0
+               )
+       ;; 'directions- pc has directions to tower
+       ;; 'tower- pc has reached tower
+       ;; 'talked- pc has talked to the enchanter
+       ;; 'done- pc has been enlisted
+))
+       
+(questadd (qst-mk "To Catch a Thief"
+       'questentry-thiefrune
+       (kern-ui-paginate-text
+               "The Enchanter has asked you to investigate a theft from his tower."
+               ""
+               "The ^c+mthief^c- has been tracked as far as Trigrave. The townsfolk there may be able to give you further information."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_brigand
+       (tbl-build
+               'on-update 'quest-thiefrune-update
+               'bonus-xp 0
+               )
+       ;; '
+       ;; 'tower- pc has reached tower
+       ;; 'talked- pc has talked to the enchanter
+       ;; 'done- pc has been enlisted
+))
+
+(questadd (qst-mk "The Secret of the Runes"
+       'questentry-runeinfo
+       (kern-ui-paginate-text
+               "The stolen rune that you recovered must have great significance to prompt it's theft. The Enchanter has given you the task of seeking out this reason."
+               ""
+               "He suggests that you start with the ^c+mAlchemist^c-, who may be found at Oparine."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_k
+       (tbl-build
+               'on-update 'quest-runeinfo-update
+               'bonus-xp 0
+               )
+))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; runes questgroup
+
+(questadd (qst-mk "The Search for the Runes"
+       'questentry-allrunes
+       (kern-ui-paginate-text
+               "The Enchanter believes that the Accursed are seeking the runes for nefarious purposes. It is up to you to collect them first."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_group
+       (tbl-build
+               ;;'on-update 'quest-allrunes-update
+               'bonus-xp 0
+               )
+))
+
+;; TODO- alternate path in which the rune is lost?
+(questadd (qst-mk "A Rune in Hand"
+       'questentry-rune-k
+       (kern-ui-paginate-text
+               "The Rune of Knowledge belongs to the Enchanter. You may be able to convince him to turn it over to you."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_k
+       (tbl-build
+               'on-update 'quest-rune-k-update
+               'entrusted-with-rune 0
+               'player-got-rune 0
+               'ench-should-have-rune 0
+               'bonus-xp 0
+               )
+))
+
+(questadd (qst-mk "A Rune in the Deeps"
+       'questentry-rune-p
+       (kern-ui-paginate-text
+               "The Alchemist provided you with information on a rune buried in the deeps of Kurpolis."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               'on-update 'quest-rune-p-update
+               'bonus-xp 0
+               )
+))
+
+(questadd (qst-mk "A Soldier's Rune"
+       'questentry-rune-l
+       (kern-ui-paginate-text
+               "One of the Runes is carried by the Warritrix."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               'on-update 'quest-rune-l-update
+               'bonus-xp 0
+               'located 0
+               'know-hall 0
+               'approx-hall 0
+               )
+))
+
+(questadd (qst-mk "A Lost Rune"
+       'questentry-rune-f
+       (kern-ui-paginate-text
+               "King Clovis once possessed a rune, but he fell during the Goblin Wars."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               'on-update 'quest-rune-f-update
+               'bonus-xp 0
+               )
+))
+
+(questadd (qst-mk "A Rune in the Void"
+       'questentry-rune-d
+       (kern-ui-paginate-text
+               "Legends tell of a temple in the void, which housed a rune."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               'on-update 'quest-rune-d-update
+               'bonus-xp 0
+               )
+))
+
+(questadd (qst-mk "A Rune in Fire"
+       'questentry-rune-w
+       (kern-ui-paginate-text
+               "A rune was found amongst the hoard of a dragon lairing in the Fire Sea."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               'bonus-xp 0
+               )
+))
+
+(questadd (qst-mk "A Rune in the Ruins"
+       'questentry-rune-s
+       (kern-ui-paginate-text
+               "A rune can be found in Old Absalot, beneath the ruins."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               ;;'on-update 'quest-allrunes-update
+               'bonus-xp 0
+               )
+))
+
+(questadd (qst-mk "A Rune in the Sea"
+       'questentry-rune-c
+       (kern-ui-paginate-text
+               "A rune once belonged to the pirate Ghertie."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_runestone_r
+       (tbl-build
+               'on-update 'quest-rune-c-update
+               'bonus-xp 0
+               )
+))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; wise questgroup
+
+(questadd (qst-mk "The Wise"
+       'questentry-wise
+       (kern-ui-paginate-text
+               "The Wise have great influence over affairs in the Shard. Seeking them out may be critical to your success."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_quest_wise
+       (tbl-build
+               ;;'on-update 'quest-wise-update
+               )
+))
+
+(questadd (qst-mk "The Enchanter"
+       'questentry-enchanter
+       (kern-ui-paginate-text
+               "The Enchanter is a great and knowledgable Wizard, one of the Wise of the present age."
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_enchanter
+       (tbl-build
+               ;;'on-update 'quest-enchanter-update
+               'qparent 'questentry-wise
+               )
+))
+
+(questadd (qst-mk "The Alchemist"
+       'questentry-alchemist
+       (kern-ui-paginate-text
+               "The Alchemist is one of the wise."
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_companion_tinker
+       (tbl-build
+               ;;'on-update 'quest-alchemist-update
+               'qparent 'questentry-wise
+               )
+))
+
+(questadd (qst-mk "The MAN"
+       'questentry-the-man
+       (kern-ui-paginate-text
+               "The MAN is one of the wise."
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_companion_bard
+       (tbl-build
+               ;;'on-update 'quest-the-man-update
+               'qparent 'questentry-wise
+               )
+))
+
+(questadd (qst-mk "The Engineer"
+       'questentry-engineer
+       (kern-ui-paginate-text
+               "The Alchemist is one of the wise."
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_companion_tinker
+       (tbl-build
+               ;;'on-update 'quest-engineer-update
+               'qparent 'questentry-wise
+               )
+))
+
+(questadd (qst-mk "The Necromancer"
+       'questentry-necromancer
+       (kern-ui-paginate-text
+               "The Necromancer is one of the wise."
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_black_mage
+       (tbl-build
+               ;;'on-update 'quest-necromancer-update
+               'qparent 'questentry-wise
+               )
+))
+
+(questadd (qst-mk "The Warritrix"
+       'questentry-warritrix
+       (kern-ui-paginate-text
+               "The Warritrix is one of the wise."
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_avatar
+       (tbl-build
+               'on-update 'quest-warritrix-update
+               'qparent 'questentry-wise
+               )
+               ;;'name - knows existance, but no info
+               ;;'common - basic info
+               ;;'general-loc - common knowledge info
+               ;;'assignment - failed to find her
+               ;;'lost-hall - where she has been sent
+               ;;'lost-hall-loc - additionally, knows location of hall
+               ;;'slain - indirect evidence of her fall
+               ;;'reached - reached location of corpse - used by losthalls mechs
+               ;;'found - located corpse
+               ;;'avenged - completed justice quest TODO- pull from that quest info instead
+))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(questadd (qst-mk "A Haunted Inn"
+       'questentry-ghertie
+       (kern-ui-paginate-text
+               "A ghost haunts the inn at Oparine. Why does it linger in undeath?"
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_ghost
+       (tbl-build
+               'on-update 'quest-ghertie-update
+               ;; ghertieloc  - gherties loc
+               ;; ghertieid - ghertie info
+               ;; revenge      - gherties trigger
+               ;; questinfo - quest info revealed
+               ;; meaney-loc - location of meaney
+               ;; ring-meaney - got ring from meaney
+               ;; jorn-forest - rough info on jorn
+               ;; jorn-loc - jorn found
+               ;; ring-jorn - got ring from jorn
+               ;; gholet-prison - rough info on gholet
+               ;; gholet-glasdrin - found gholet
+               ;; gholet-price - gholets offer for ring
+               ;; ring-gholet - got ring from gholet
+               )
+))
+
+(questadd (qst-mk "Blood Price: Dragon"
+       'questentry-dragon
+       (kern-ui-paginate-text
+               "The Alchemist has offered to trade you information on the wherabouts of a Rune, in exchange for the blood of a dragon."
+       )
+       'quest-assign-notify
+       'quest-dragon-update
+       's_dragon_party
+       (tbl-build
+               )
+))
+
+(questadd (qst-mk "A Soldiers Justice"
+       'questentry-warrjustice
+       (kern-ui-paginate-text
+               "The Warritrix has been slain by treachery. Will this crime go unpunished?"
+       )
+       'quest-assign-subquest
+       'quest-status-inprogress
+       's_ghost
+       (tbl-build
+               'on-update 'quest-warrjustice-update
+               )
+               ;;'statue - info about statue
+               ;;'book - info about journal
+               ;;'havejournal - found journal
+               ;;'avenged - completed justice quest
+))
+
+(questadd (qst-mk "Bandit Troubles"
+       'questentry-bandits
+       (kern-ui-paginate-text
+               "Gregor, an old charcoal burner, has asked for your help in dealing with some troublesome bandits that have been plaguing the great forest."
+               ""
+               "He suggests that the Rangers at Green Tower will be able to assist in this task."
+       )
+       'quest-assign-notify
+       'quest-status-inprogress
+       's_brigand
+       (tbl-build
+         'on-update 'quest-bandits-update
+         )
+))
+
+)
+
diff --git a/worlds/haxima-1.002/quests-mech.scm b/worlds/haxima-1.002/quests-mech.scm
new file mode 100644 (file)
index 0000000..2268536
--- /dev/null
@@ -0,0 +1,267 @@
+;; Sets a quest to be complete, with notification if it is in progress
+;; Note that if you set the quest to be complete before you assign it,
+;; then the assignment notification will say that it has been immediately
+;; completed, avoiding spamming the player with multiple notifications
+
+(define (quest-complete quest)
+       (if (and (quest-assigned? quest) use-quest-pane)
+               (kern-log-msg "^c+mQuest completed:^c-\n^c+m" (qst-title quest) "^c-")
+               )
+       (qst-complete! quest)
+       )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; internal utility methods
+
+(define (quest-data-add-child parent quest)
+       (let ((childlist (quest-data-getvalue parent 'qchildren)))
+               (if (not (in-list? quest childlist))
+                       (quest-data-update parent 'qchildren
+                               (cons
+                                       quest
+                                       childlist
+                               )
+                       ))
+       ))
+               
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; quest assignment callbacks for use in quest definition
+
+;; causes a notification on assignment
+(define (quest-assign-notify quest target)
+       (let ((notifytext (if (qst-complete? quest)
+                                               "^c+mQuest completed:^c-\n^c+m"
+                                               "^c+mNew quest:^c-\n^c+m"
+                                               )))
+               (if use-quest-pane
+                       (kern-log-msg notifytext (qst-title quest) "^c-")
+               )
+               #t
+       ))
+       
+;; ensures parent/subquest relation once quest is assigned
+(define (quest-assign-subquest quest target)
+       (let ((parent (quest-tbl-get quest 'qparent)))
+               (if (not (null? parent))
+                       (quest-data-add-child parent (qst-tag quest))
+                       )
+               #t
+       ))
+       
+;; allows quest to proceed without any other action
+(define (quest-assign-silent quest target)
+               #t
+       )
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; quest display callbacks for use in quest definition
+       
+;; doesnt actually do anything
+(define (quest-status-from-payload quest)
+       "In progress"
+       )
+
+;; doesnt actually do anything
+(define (quest-status-inprogress quest)
+       "In progress"
+       )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Interacting with the Quest Data Table
+;;
+;; The quest data table is a global storage location for fixed, plot
+;; based quests that are created once and then activated at the
+;; appropriate time
+;;
+;; Anything procedurally generated on the fly would need
+;; to interface directly with the quest-sys module.
+;;
+       
+;; retrieves a quest from the quest data table
+(define (quest-data-get tag)
+  (println "quest-data-get:" tag)
+       (let* ((questdata (tbl-get (gob (kern-get-player)) 'questdata))
+                       )
+                       (tbl-get questdata tag)
+               )
+       )
+       
+;; retrieves a value from a quest payload tbl, given the key for the quest
+;; and for the value
+(define (quest-data-getvalue quest tag)
+       (let* ((qpayload (car (qst-payload (quest-data-get quest)))))
+               (tbl-get qpayload tag)
+               )
+       )
+
+;; assigns a quest from the quest data table, while ensuring it is not
+;;      given out repeatedly
+(define (quest-data-assign-once tag)
+       (let ((questentry (quest-data-get tag)))
+               (if (not (quest-assigned? questentry))
+                       (quest-assign questentry)
+               )
+       ))
+       
+;; checks if a quest from the quest data table has been assigned
+(define (quest-data-assigned? tag)
+       (quest-assigned? (quest-data-get tag))
+       )
+       
+;; assuming quest in the QDT uses a tbl for payload, updates a key/value pair
+(define (quest-data-update tag key value)
+       (let* ((qpayload (car (qst-payload (quest-data-get tag))))
+                       (updatehook (tbl-get qpayload 'on-update))
+                       )
+               (if (not (equal? (tbl-get qpayload key) value))
+                       (begin
+                               (tbl-set! qpayload key value)
+                               (if (not (null? updatehook))
+                                       ((eval updatehook))
+                               )
+                               (qst-bump! (quest-data-get tag))
+                       ))
+       ))
+       
+;; updates as per quest-data-update, but additionally triggers a passed in function
+(define (quest-data-update-with tag key value callback)
+  (println "quest-data-update-with")
+  (let* (      
+         (quest (quest-data-get tag))
+         (qpayload (car (qst-payload quest)))
+         )
+    (println "quest:" quest)
+    (println "qpayload:" qpayload)
+    (if (is-tbl? qpayload)
+        (let (
+              (updatehook (tbl-get qpayload 'on-update))
+              )
+          (println "updatehook" updatehook)
+          (if (not (equal? (tbl-get qpayload key) value))
+              (begin                   
+                (tbl-set! qpayload key value)
+                (callback quest)
+                (if (not (null? updatehook))
+                    ((eval updatehook))
+                    )          
+                (qst-bump! (quest-data-get tag))
+                )
+              )
+          )
+        )
+    )
+  )
+
+;; sets the description for a quest in the QDT
+(define (quest-data-descr! tag descr)
+       (qst-set-descr! (quest-data-get tag) descr)
+       )
+
+;; sets the icon for a quest in the QDT
+(define (quest-data-icon! tag icon)
+       (qst-set-icon! (quest-data-get tag) icon)
+       )       
+
+;; sets a quest in the QDT to be complete, giving a notification if appropriate
+;;    see the notes for quest-complete, above
+(define (quest-data-complete tag)
+       (quest-complete (quest-data-get tag))
+       )
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;    
+;; callbacks for quest-data-update-with
+
+;; if appropriate, notifies the player about a change in quest state
+;; can be chained to further functions
+(define (quest-notify subfunction)
+  (println "quest-notify")
+       (lambda (quest) 
+               (if (and (quest-assigned? quest) use-quest-pane)
+                       (kern-log-msg "^c+mQuest updated:^c-\n^c+m" (qst-title quest) "^c-")
+                       )
+               (if (not (null? subfunction))
+                       (subfunction quest))
+       ))
+       
+;; grants the player a given amount of experience, using or adding to the bonus xp
+;;          as appropriate
+(define (grant-xp-fn amount)
+       (lambda (quest) 
+               (let* ((qpayload (car (qst-payload quest)))
+                               (bonusxp (tbl-get qpayload 'bonus-xp))
+                               (bonusxp (if (null? bonusxp)
+                                                       0 bonusxp))
+                               (totalxp (+ bonusxp amount))
+                               )
+                       (if (quest-assigned? quest)
+                               (begin
+                                       (kern-char-add-experience (car (kern-party-get-members (kern-get-player))) totalxp)
+                                       (tbl-set! qpayload 'bonus-xp 0)
+                               )
+                               (tbl-set! qpayload 'bonus-xp totalxp)
+                       )
+               )
+       ))
+       
+;; shares amongst the players party a given amount of experience,
+;;       using or adding to the bonus xp as appropriate
+(define (grant-party-xp-fn amount)
+       (lambda (quest) 
+               (let* ((qpayload (car (qst-payload quest)))
+                               (bonusxp (tbl-get qpayload 'bonus-xp))
+                               (bonusxp (if (null? bonusxp)
+                                                       0 bonusxp))
+                               (totalxp (+ bonusxp amount))
+                               (party (kern-party-get-members (kern-get-player)))
+                               (xp-each (ceiling (/ totalxp (length party))))
+                               )
+                       (if (quest-assigned? quest)
+                               (begin
+                                       (map (lambda (kchar) (kern-char-add-experience kchar xp-each)) party)
+                                       (tbl-set! qpayload 'bonus-xp 0)
+                               )
+                               (tbl-set! qpayload 'bonus-xp totalxp)
+                       )
+               )
+       ))
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Reconcile active and pregenned quests at game load to simplify
+;; ingame tracking
+;;
+;; internal methods- will run automatically
+       
+(kern-add-hook 'new_game_start_hook 'reconcile-quests)
+(kern-add-hook 'new_game_start_hook 'refresh-quests)
+
+(define (reconcile-quests kplayer)
+       (let ((questlist
+                                       (tbl-get (gob
+                                               (kern-get-player)) 'quests))
+                               (questdata
+                                       (tbl-get (gob 
+                                               (kern-get-player)) 'questdata))
+                       )
+               (map 
+                       (lambda (quest)
+                               (let ((tag (qst-tag quest)))
+                                       (if (and (not (null? tag))
+                                                       (not (null? (tbl-get questdata tag))))
+                                               (tbl-set! questdata tag quest))
+                               ))
+               questlist)
+       ))
+
+(define (refresh-quests)
+       (load "quests-data.scm")
+       )
+       
+       
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; utilities
+       
+;; links a quest and subquest after they are already in-play
+(define (quest-data-convert-subquest quest parent)
+       (quest-data-update quest 'qparent parent)
+       (quest-data-add-child parent quest)
+       )       
\ No newline at end of file
diff --git a/worlds/haxima-1.002/quests.png b/worlds/haxima-1.002/quests.png
new file mode 100644 (file)
index 0000000..d7bbfc4
Binary files /dev/null and b/worlds/haxima-1.002/quests.png differ
diff --git a/worlds/haxima-1.002/r2a_mech.scm b/worlds/haxima-1.002/r2a_mech.scm
new file mode 100644 (file)
index 0000000..59971a5
--- /dev/null
@@ -0,0 +1,29 @@
+(kern-mk-map
+ 'm_lava_flow 1 5 pal_expanded
+ (list "!!" "!_" "!!" "!_" "!!")
+)
+
+(kern-mk-map
+ 'm_lava_bridge 1 5 pal_expanded
+ (list ".." "~!" ".." "~!" "..")
+) 
+
+(define (r2a-statue-hail knpc kpc)
+        (begin
+          (let ((resp (kern-conv-get-reply kpc)))
+            (if (eq? resp 'onus) 
+                (begin
+                                       (shake-map 15)
+                                       (blit-map p_absalot_passage 5 15 1 5 m_lava_bridge)
+                  ))
+            (kern-conv-end))))
+        
+
+(define r2a-statue-conv
+  (ifc basic-conv
+       (method 'hail r2a-statue-hail)
+       ))
+(define (fix-lava kplace kplayer)
+       (blit-map p_absalot_passage 5 15 1 5 m_lava_flow)
+)
diff --git a/worlds/haxima-1.002/raise-merciful-death.scm b/worlds/haxima-1.002/raise-merciful-death.scm
new file mode 100644 (file)
index 0000000..bbd760b
--- /dev/null
@@ -0,0 +1,13 @@
+(define merciful-death-x 121)
+(define merciful-death-y 87)
+
+(define (raise-merciful-death)
+  (let ((loc (mk-loc p_shard 
+                     merciful-death-x 
+                     merciful-death-y)))
+  (kern-log-msg "From her watery grave...")
+  (kern-log-msg "...THE MERCIFUL DEATH ARISES!")
+  (shake-map 10)
+  (kern-place-set-subplace p_merciful_death loc)
+  (kern-map-set-dirty)
+  ))
diff --git a/worlds/haxima-1.002/reagents.png b/worlds/haxima-1.002/reagents.png
new file mode 100644 (file)
index 0000000..b5cbd37
Binary files /dev/null and b/worlds/haxima-1.002/reagents.png differ
diff --git a/worlds/haxima-1.002/reagents.scm b/worlds/haxima-1.002/reagents.scm
new file mode 100644 (file)
index 0000000..b7d1674
--- /dev/null
@@ -0,0 +1,37 @@
+(kern-mk-sprite-set 'ss_reagents 32 32 1 9 0 0 "reagents.png")
+
+(kern-mk-sprite 's_spider_silk ss_reagents    1 0 #f 0)
+(kern-mk-sprite 's_sulphorous_ash ss_reagents 1 1 #f 0)
+(kern-mk-sprite 's_ginseng ss_reagents        1 2 #f 0)
+(kern-mk-sprite 's_blood_moss ss_reagents     1 3 #f 0)
+(kern-mk-sprite 's_garlic ss_reagents         1 4 #f 0)
+(kern-mk-sprite 's_black_pearl ss_reagents    1 5 #f 0)
+(kern-mk-sprite 's_nightshade ss_reagents     1 6 #f 0)
+(kern-mk-sprite 's_mandrake ss_reagents       1 7 #f 0)
+(kern-mk-sprite 's_royal_cape ss_reagents 1 8 #f 0)
+
+
+;; Extend the basic object interface to support mixing. Currently mix does
+;; nothing in the script, but it's important to let the kernel know that this
+;; type of object can be used with the M)ix command.
+(define reagent-ifc
+  (ifc obj-ifc
+       (method 'mix (lambda () '()))))
+
+(define (mk-reagent-type tag name sprite)
+  (mk-obj-type tag name sprite layer-item reagent-ifc))
+
+(define reagent-types
+  (list
+   (list 'sulphorous_ash "sulphurous ash" s_sulphorous_ash)
+   (list 'ginseng        "ginseng"        s_ginseng)
+   (list 'garlic         "garlic"         s_garlic)
+   (list 'spider_silk    "spider silk"    s_spider_silk)
+   (list 'blood_moss     "blood moss"     s_blood_moss)
+   (list 'black_pearl    "black pearl"    s_black_pearl)
+   (list 'nightshade     "nightshade"     s_nightshade)
+   (list 'mandrake       "mandrake"       s_mandrake)
+   (list 't_royal_cape   "royal cape mushroom" s_royal_cape)
+   ))
+
+(map (lambda (type) (apply mk-reagent-type type)) reagent-types)
diff --git a/worlds/haxima-1.002/river.wav b/worlds/haxima-1.002/river.wav
new file mode 100644 (file)
index 0000000..4005259
Binary files /dev/null and b/worlds/haxima-1.002/river.wav differ
diff --git a/worlds/haxima-1.002/road_to_absalot.scm b/worlds/haxima-1.002/road_to_absalot.scm
new file mode 100644 (file)
index 0000000..8f08309
--- /dev/null
@@ -0,0 +1,298 @@
+(kern-load "joel.scm")
+(kern-load "r2a_mech.scm")
+
+(mk-dungeon-room
+ 'p_road_to_absalot_1 "Passage to Absalot"
+       (list
+               "rn rn rn r4 !! r2 rn rc ,, ,, ,, ra r8 r8 r4 !! r2 rn rn "
+               "rn rn rn rc !! ra rc {{ ,, .. ,, {{ {{ {{ re !! ra rn rn "
+               "rn r8 rc {{ !! {A {{ {C ,, ,, ,, {{ !3 !! !! !! {{ r2 rn "
+               "r4 {{ {{ {C !! !! !! !5 ,, ,, ,, {{ !! bb {F !! {{ r2 rn "
+               "r4 {{ !3 !! !! {& bb !! ,, ,, {4 {{ !! {# bb !! {{ r2 rn "
+               "r4 {{ !! bb !! {{ {% !! ,, ,, ,, {{ !e {{ {% !! {{ ra rn "
+               "r4 {{ !e {& !! {{ {{ !e .. ,, ,, {A {{ {{ {{ !! {{ {{ r~ "
+               "r4 {{ {{ {{ !! {{ {{ pp ,, ,, ,, pp {{ {{ {C !! {A {{ r2 "
+               "rn r5 {{ {C !! {A {C ,, ,, ,, ,, ,, {{ !3 !! !! !5 {{ r2 "
+               "rn r4 {{ !3 !! !! !5 ,, ,, ,, ,, ,, {{ !! bb bb !! {{ r2 "
+               "rn r4 {{ !! bb bb !! ,, ,, ,, ,, ,, {{ !! bb {& !e {{ r2 "
+               "rn rc {{ !! {& bb !! pp {8 ,, ,, bb {{ !! {# {{ {{ {{ r2 "
+               "r4 {{ {{ !! {{ {% !! {# {{ {{ {{ {{ {{ !! {{ {{ {{ {{ r2 "
+               "r4 {{ {{ !! {{ {{ !e {{ {{ r7 {{ {{ {{ !! {{ {{ {{ {{ r2 "
+               "r4 {{ {{ !e {{ {{ {{ {{ r3 r4 {{ {{ {{ !! {{ {{ {{ {{ r2 "
+               "rn r5 {{ {{ {{ r7 {{ {{ r2 rn r5 {{ {{ !e {{ {{ r7 bb r2 "
+               "rn rn r5 {{ r3 r4 {{ r3 rn rn rn r5 {{ {{ {{ r3 rn r1 rn "
+               "rn rn r4 {{ r2 rn r1 rn rn rn rn rn r5 {{ r3 rn rn rn rn "
+               "rn rn rn r1 rn rn rn rn rn rn rn rn rn r1 rn rn rn rn rn "
+       )
+  (put (mk-ladder-up 'p_gate_to_absalot 9 1) 9 9)
+  (put (mk-bump-door 'p_absalot_passage 1 38) 18 6)
+ (put (spawn-pt 'troll-m) 4 12)
+ (put (spawn-pt 'troll-m) 13 4)
+ (put (spawn-pt 'headless) 9 4)
+ (put (spawn-pt 'headless) 5 4)
+ (put (spawn-pt 'gazer) 3 17)
+ )
+(mk-place-music p_road_to_absalot_1 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_fire_bridge "Fire Bridge"
+       (list
+               "xx xx xx rr rr xx xx xx ,, ,, ,, xx xx xx xx xx xx xx xx "
+               "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr "
+               "xx ,, .. ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, bb rr "
+               "rr ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, rr "
+               "rr ,, ,, ,, ,, xx rr xx ,, w+ ,, xx xx xx ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, xx !_ !_ ,, ,, !! !_ !_ xx ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, w+ !! !_ !_ !_ !_ !_ !! w+ ,, ,, ,, ,, xx "
+               "rr ,, ,, ,, ,, xx !! !! !_ !_ !_ !! !! rr ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, xx xx !! !! !! !! !! xx xx ,, .. ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, w+ !! ,, ,, !! !! w+ ,, ,, ,, ,, ,, rr "
+               "xx ,, ,, ,, ,, ,, w+ !! ,, ,, bb !! w+ ,, ,, ,, ,, ,, xx "
+               "xx ,, ,, ,, ,, ,, w+ !! ,, ,, ,, !! w+ ,, ,, ,, ,, ,, xx "
+               "xx xx ,, ,, ,, xx rr !! !! ,, ,, !! xx xx ,, ,, ,, xx xx "
+               "!_ xx bb w+ w+ xx !! !! ,, ,, ,, !! !! xx w+ w+ w+ xx !_ "
+               "!_ !! !! !! !! !! !! !! ,, ,, !! !! !! !! !! !! !! !! !_ "
+               "!_ !! !! !! !! !! !c {& ,, ,, {4 {% !a !! !! !! !! !! !_ "
+               "r5 {{ {% !a !! !c {# {{ ,, ,, ,, {{ {% !a !! !c {# {{ r3 "
+               "r4 {{ {{ {{ {{ {{ {{ {{ {2 ,, ,, {{ {{ {{ {{ {{ {{ r3 rn "
+               "rn r1 r1 r1 r1 r1 r1 r5 ,, ,, ,, r3 r1 r1 r1 r1 r1 rn rn "
+       )
+  (put (kern-tag 'fb-p2 (mk-portcullis)) 8 4)
+  (put (kern-tag 'fb-p1
+                 (mk-connected-portcullis 'fb-p2)) 10 4)
+  (put (kern-tag 'fb-b1 (mk-tblitter 'p_fire_bridge
+                                     8 6 3 3
+                                     'm_deck_section)) 1 1)
+  (put (mk-lever 'fb-p1) 3 10)
+  (put (mk-lever 'fb-b1) 15 10)
+  ;(put (mk-magic-locked-door) 9 0)
+  (put (guard-pt 'craven-archer) 5 10)
+  (put (guard-pt 'ghast) 3 11)
+  (put (guard-pt 'skeletal-spear-thrower) 5 9)
+
+  (put (guard-pt 'craven-archer) 13 11)
+  (put (guard-pt 'ghast) 14 9)
+  (put (guard-pt 'craven-archer) 13 9)
+
+  (put (guard-pt 'death-knight) 8 3)
+  (put (guard-pt 'death-knight) 10 3)
+  (put (spawn-pt 'demon) 16 2)
+
+  (put (kern-mk-obj t_spell_book_force_magick_matter 1) 17 9)
+ )
+
+(mk-place-music p_fire_bridge 'ml-dungeon-adventure)
+
+(mk-dungeon-room
+ 'p_road_to_absalot_3 "Passage to Absalot"
+       (list
+               "rn rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn rn "
+               "rn rn rc {C !! !! !c {{ {{ {{ {{ {{ !a !! !! {A ra rn rn "
+               "rn rc {C !3 !! !c {# {{ {{ {{ {{ {{ {{ {% !! !5 {A ra rn "
+               "r4 {C !3 !! !c {# {{ {{ bb xx xx {{ {{ {{ !a !! !5 {A r2 "
+               "r4 !! !! !c {# {{ {{ xx rr rr xx xx {{ {{ {% !a !! !! r2 "
+               "r4 !! !! {# {{ {{ xx xx xx xx xx xx xx {{ {{ {% !! !! r2 "
+               "r4 !! !! {{ {{ xx xx xx ,, ,, ,, bb rr xx {{ {{ !! !! r2 "
+               "r4 !! !! {{ {{ rr xx xx ,, ,, ,, rr xx xx {{ {{ !! !! r2 "
+               "r4 !! !! {{ {{ bb rr xx ,, ,, ,, xx xx xx {{ {{ !! !! r2 "
+               "r4 !! !! {A {{ {{ xx xx xx ,, xx xx xx {{ {{ {C !! !! r2 "
+               "r4 !! !! !5 {A {{ {{ xx xx ,, xx xx {{ {{ {C !3 !! !! r2 "
+               "r4 !! !! !! !5 {A {{ {{ xx ,, xx {{ {{ {C !3 !! !! !! r2 "
+               "r4 {% !! !! !! !5 {A {{ ,, ,, ,, {{ !3 !! !! !! !! {# r~ "
+               "r4 {{ !a !! !! !! !5 {{ {2 ,, ,, {{ !! !! !! !! !c {{ r2 "
+               "r4 {{ {% !a !! !! !! {{ ,, ,, ,, {{ !! !! !! !c {# {{ r2 "
+               "r4 {{ {{ {% !a !! xx rr ,, ,, .. xx xx !! !c {# {{ {{ r2 "
+               "rn r5 {{ {{ {% !a xx ,, ,, ,, ,, ,, xx !c {# {{ {{ {{ r2 "
+               "rn rn r5 {{ {{ {{ rr bb ,, ,, ,, ,, ?? {{ {{ {{ {{ r3 rn "
+               "rn rn rn r1 r1 xx xx xx ,, ,, ,, xx xx xx r1 r1 r1 rn rn "
+       )
+ (put (mk-magic-locked-door) 9 10)
+ (put (mk-ladder-up 'p_tower_of_absalot 9 9) 9 7)
+ (put (mk-bump-door 'p_absalot_passage 1 2) 18 12)
+ (put (guard-pt 'ghast) 10 8)
+ (put (guard-pt 'death-knight) 8 8)
+ (put (spawn-pt 'craven-archer) 10 6)
+ (put (spawn-pt 'zorn) 8 6)
+ (put (spawn-pt 'zorn) 7 6)
+ (put (spawn-pt 'zorn) 9 6)
+ )
+
+(mk-place-music p_road_to_absalot_3 'ml-dungeon-adventure)
+
+(define (mk-r2a-statue)
+  (bind 
+   (kern-mk-char 
+    'ch_r2a_statue           ; tag
+    "Statue"             ; name
+    sp_statue         ; species
+    nil              ; occ
+    s_statue     ; sprite
+    faction-men      ; starting alignment
+    0 0 0            ; str/int/dex
+    999 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    0                   ; xp
+    max-health ; mp
+    0
+    9
+    #f               ; dead
+    'r2a-statue-conv         ; conv
+    nil           ; sched
+    'ankh-ai              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   nil))
+
+(kern-mk-place 
+ 'p_absalot_passage     ; tag
+ "Secret Passage"      ; name
+  nil          ; sprite
+       (kern-mk-map nil 19 40 pal_expanded
+               (list
+               "rn rn rn r8 rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "r8 r8 rc .. ra r8 rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               ".. {8 .. .. {c {{ r2 rn rn rn rn rn rn rn rn rn rn rn rn "
+               "r5 {{ {2 r7 {{ {3 ra rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn r1 r1 rn r5 .. bb ra rn rn rn rn rn rn rn rn r8 rn rn "
+               "rn rn rn rn r4 .. {c {{ r2 rn rn r8 rn rn rn rc *7 ra rn "
+               "rn rn rn rn rn r5 {{ {3 r2 rn r4 *7 ra rn r4 *3 vv *5 r2 "
+               "rn rn rn rn rn rn r5 .. r2 rn rc vv *5 ra rc vv vv vv ra "
+               "rn rn rn rn rn rn rc .. r2 r4 *3 vv vv vv vv vv vv vv vv "
+               "rn rn rn rn rn r4 {{ {2 r2 r4 *2 vv vv vv vv vv vv vv vv "
+               "rn rn rn rn rn r4 {1 bb r2 rc vv vv vv vv vv vv vv vv vv "
+               "rn rn rn rn rn rc .. r3 rc *3 vv vv vv vv vv *c r7 vv vv "
+               "rn rn rn rn r4 {{ .. re *3 vv vv vv vv vv *c r3 r4 *2 vv "
+               "rn r8 r8 r8 r4 .. *3 vv vv vv vv vv vv vv r3 rn rc *2 vv "
+               "rc !! !! !! re .. *2 vv vv vv vv vv vv vv ra r4 bb vv vv "
+               "!! !! !! !! !! !! *2 vv vv vv vv vv vv vv *5 re *3 vv vv "
+               "!! !_ !_ !_ !_ !_ *2 vv vv vv vv vv vv vv vv vv vv vv vv "
+               "!_ !_ !_ !_ +s !! *2 vv vv vv vv vv vv vv vv vv vv vv vv "
+               "!_ !_ !! !_ !_ !_ *2 vv vv vv vv vv vv vv vv vv vv vv vv "
+               "!! !! !! !! !! !! *a vv vv vv vv vv vv vv vv vv vv vv vv "
+               "!! !! r3 r1 r5 {c {h vv vv vv vv vv vv vv vv vv vv vv vv "
+               "r1 r1 rn rn r4 {{ .. *2 vv vv vv vv vv vv vv vv vv vv vv "
+               "rn rn rn rn rn rd .. *2 vv vv vv vv vv *c r7 vv vv vv vv "
+               "rn rn rn rn r4 {{ .l vv vv vv vv vv vv bb r6 *a vv vv vv "
+               "rn rn rn rn r4 .. *3 vv vv vv vv vv vv rb rn rd vv vv vv "
+               "rn rn rn rn r4 .. *2 vv vv vv vv vv vv *5 re *3 vv vv vv "
+               "rn rn rn rn rc {{ *2 vv vv vv vv vv vv vv vv vv vv vv vv "
+               "rn rn rn r4 {{ .. *a vv vv vv vv vv vv vv vv vv vv vv vv "
+               "rn rn rn rc {1 {8 r3 r5 *a vv vv vv vv vv vv vv vv vv vv "
+               "rn rn r4 {{ {6 {{ r2 rn r5 *a vv vv vv vv vv vv vv vv vv "
+               "rn rn r4 {{ {2 r3 rn rn rn r5 vv vv vv vv vv vv *c r3 r1 "
+               "rn rn r4 {1 {8 r2 rn rn rn r4 *2 vv *c r7 vv *c r3 rn rn "
+               "rn rn r4 {4 {{ r2 rn rn rn r4 *e r3 r1 r4 *e r3 rn rn rn "
+               "rn rn r4 bb {1 r2 rn rn rn rn r1 rn rn rn r1 rn rn rn rn "
+               "rn rn rn rd .. r2 rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn r4 {{ {2 r2 rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn r8 rc {{ {2 r2 rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rc {4 {{ {3 r3 rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               ".. .. r3 r1 rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "r1 r1 rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               )
+       )
+
+ #f              ; wraps
+ #t              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ (list (put (mk-monman) 0 0) ; objects
+ (put (mk-bump-door 'p_road_to_absalot_3 17 12) 0 2)
+ (put (mk-bump-door 'p_road_to_absalot_1 17 6) 0 38)
+ (put (make-invisible (mk-r2a-statue)) 4 17)
+ (put (spawn-pt 'bat) 15 22)
+ (put (spawn-pt 'bat) 10 10)
+ (put (spawn-pt 'bat) 10 30)
+ (put (spawn-pt 'bat) 16 30)
+ (put (spawn-pt 'bat) 16 15)
+ )
+ (list
+       'fix-lava
+       'on-entry-to-dungeon-room
+       ) ;; hooks
+       nil
+ )
+
+(mk-place-music p_absalot_passage 'ml-dungeon-adventure)
+(mk-dungeon-level 
+ (list p_road_to_absalot_3)
+ (list p_fire_bridge)
+ (list p_road_to_absalot_1)
+ )
+
+(mk-tower
+ 'p_gate_to_absalot "Gate To Absalot"
+       (list
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ xx xx xx xx xx ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx xx xx xx xx ,, ,, ,, xx xx xx xx rr ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx ,, ,, ,, xx .. ,, ,, xx ,, ,, ,, bb ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx bb ,, ,, ,, ,, ,, ,, ,, ,, .. ,, rr ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx ,, .. ,, xx ,, ,, ,, xx ,, ,, ,, xx ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx ,, ,, ,, xx xx bb xx rr ,, ,, bb xx ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx ,, ,, bb xx bb bb bb xx ,, ,, ,, xx ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx ,, ,, ,, w+ .. bb .. w+ ,, ,, ,, xx ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx ,, ,, ,, xx .. .. .. xx bb ,, ,, xx ^^ ^^ ^^ "
+               "^^ ^^ ^^ xx xx w+ xx rr .. .. .. xx xx w+ xx xx ^^ ^^ ^^ "
+               "^^ ^^ ^^ {{ {a .. .. .. .. .. .. .. .. .. {c {{ ^^ ^^ ^^ "
+               "^^ ^^ ^^ {{ {{ {2 .. .. .. .. .. .. .. {4 {{ {{ ^^ ^^ ^^ "
+               "^^ ^^ ^^ {{ {{ {2 .. .. .. && .. .. .. {4 {{ {{ ^^ ^^ ^^ "
+               "^^ ^^ ^^ {{ {{ {a .. .. .. .. .. .. .. {c {{ {{ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ {{ {{ {a .. .. .. .. .. {c {{ {{ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ {{ {{ {3 .. .. .. .. .. {5 {{ {{ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ {{ {{ {3 .. .. .. .. .. .. .. {5 {{ {{ ^^ ^^ ^^ "
+       )
+       (list
+               (list northwest 14 18)
+               (list northeast 4 18)
+       )
+ (put (mk-ladder-down 'p_road_to_absalot_1 9 9) 9 1)
+ (put (mk-joel) 9 10)
+ (put (mk-npc 'bull 4) 12 12)
+ (put (mk-npc 'bull 4) 10 15)
+ )
+
+(mk-place-music p_gate_to_absalot 'ml-small-town)
+
+(mk-tower
+ 'p_tower_of_absalot "Tower of Absalot"
+       (list
+               "^^ tt tt tc %% te bb %% .. .. ta tc bb ta tc %% %% %c ^^ "
+               "^^ ta tt %b ~f %% %% %% %% =| %d bb %b %% %% %% ~f ^3 ^^ "
+               "^^ ^5 tt t5 %e t7 bb %e .. .. .. %f bb t7 %a ~f ^b ^^ ^^ "
+               "^^ ^^ tt tt tt tt td bb .. .. .. bb tb tt t5 %a ~f ^a ^^ "
+               "^^ ^^ tt tt tc xx w+ xx rr .. xx xx bb xx ta tt tt t5 ^^ "
+               "^^ ^^ tt tt xx xx ,, ,, w+ .. w+ ,, ,, xx xx tt tt tt ^^ "
+               "^^ ^^ tt tt w+ ,, ,, ,, rr d, xx ,, ,, ,, w+ tt tt tt ^^ "
+               "^^ ^^ ta tt xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx tt tt tc ^^ "
+               "^^ ^^ ^5 tt xx ,, ,, ,, ,, ,, ,, ,, ,, ,, xx tt tt ^3 ^^ "
+               "^^ ^^ ^^ tt bb .. ,, ,, ,, /c ,, ,, ,, ,, w+ tt tt ^^ ^^ "
+               "^^ ^^ ^^ tt t5 .. ,, ,, ,, ,, ,, ,, ,, ,, rr tt tt ^^ ^^ "
+               "^^ ^^ ^c tt tc .. .. ,, ,, ,, ,, ,, ,, ,, rr tt tt ^^ ^^ "
+               "^^ ^^ t3 tt bb .. ,, ,, ,, ,, ,, ,, ,, ,, w+ tt tt ^^ ^^ "
+               "^^ ^^ ta tt rr rr ,, ,, ,, ,, ,, ,, ,, xx xx tt tc ^^ ^^ "
+               "^^ ^^ ^5 tt t5 rr w+ xx xx w+ xx xx w+ xx t3 tt ^3 ^^ ^^ "
+               "^^ ^^ ^^ ta tt tt tt tt tt tt tt tt tt tt tt tc ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^5 ta tt tt tt tt tt tt tt tt tc ^3 ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+       )
+       (list
+               (list southwest 11 0)
+               (list southeast 2 0)
+       )
+ (put (mk-ladder-down 'p_road_to_absalot_3 9 7) 9 9)
+ (put (spawn-pt 'death-knight) 6 7)
+ (put (spawn-pt 'ghast) 12 11)
+ )
+
+(mk-place-music p_tower_of_absalot 'ml-outdoor-adventure)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/roland.scm b/worlds/haxima-1.002/roland.scm
new file mode 100644 (file)
index 0000000..907bc88
--- /dev/null
@@ -0,0 +1,181 @@
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (roland-mk free? joined? greeted?) (list free? joined? greeted?))
+(define (roland-is-free? knpc) (car (kobj-gob-data knpc)))
+(define (roland-joined? knpc) (cadr (kobj-gob-data knpc)))
+(define (roland-greeted? knpc) (caddr (kobj-gob-data knpc)))
+(define (roland-set-free! knpc) (set-car! (kobj-gob-data knpc) #t))
+(define (roland-set-joined! knpc) (set-car! (cdr (kobj-gob-data knpc)) #t))
+(define (roland-set-greeted! knpc) (set-car! (cddr (kobj-gob-data knpc)) #t))
+
+(define roland-greetings
+  (list
+   "Well met!"
+   "Hail, Wanderer!"
+   ))
+
+;;----------------------------------------------------------------------------
+;; Custom AI
+;; 
+;; This AI controls Roland until he is freed. It constantly tries to pathfind
+;; to the prison exit. Once it gets outside the cell it sets the "freed" flag
+;; and resorts to the default kernel AI.
+;;----------------------------------------------------------------------------
+(define (roland-exit-point knpc)
+  (mk-loc (kobj-place knpc)
+          (rect-x slimey-cavern-prison-cell-exit)
+          (rect-y slimey-cavern-prison-cell-exit)))
+
+(define (roland-ai knpc)
+  (define (out-of-cell?)
+    (not (loc-in-rect? (kern-obj-get-location knpc)
+                       slimey-cavern-prison-cell)))
+  (define (try-to-escape)
+    (kern-log-enable #f)
+    (pathfind knpc (roland-exit-point knpc))
+    (kern-log-enable #t))
+  (define (set-free)
+    (roland-set-free! knpc)
+    (kern-char-set-ai knpc nil)
+    (kern-being-set-base-faction knpc faction-men)
+    )
+  (or (roland-greeted? knpc)
+      (and (any-player-party-member-visible? knpc)
+           (begin
+             (taunt knpc nil roland-greetings)
+             (roland-set-greeted! knpc))))
+  (if (out-of-cell?)
+      (set-free knpc)
+      (try-to-escape)))
+
+;; Note: (can-pathfind? ...) will pathfind through the locked door nowadays, so
+;; it cannot be relied on. Let's just let Roland try to get out and he'll know
+;; he's free.
+(define (roland-is-or-can-be-free? knpc)
+  (roland-is-free? knpc))
+
+(define (roland-join-player knpc)
+  (or (roland-joined? knpc)
+      (begin
+        (join-player knpc)
+        (roland-set-joined! knpc #t))))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Roland is a knight errant, serving Lord Froederick.
+;; He is currently imprisoned by bandits in a cell in the slimy cave.
+;; Roland is a potential party member.
+;;----------------------------------------------------------------------------
+(define (roland-join knpc kpc)
+  (if (is-player-party-member? knpc)
+      (say knpc "Yes, I am still with you. Lead on!")
+      (if (roland-joined? knpc)
+          (begin
+            (say knpc "I am honored to rejoin you.")
+            (join-player knpc)
+            (kern-conv-end)
+            )
+          (if (roland-is-or-can-be-free? knpc)
+              ;; yes - will the player accept his continued allegiance to
+              ;; Froederick?
+              (begin
+                (say knpc "I thank you for freeing me! I owe you my life, and will gladly join you. What say you?")
+                (if (yes? kpc)
+                    (begin
+                      (say knpc "I am honored! Those vile rogues took my "
+                           "iron chest which contains my equipment. It should be "
+                           "around here somewhere.")
+                      (roland-join-player knpc))
+                    (say knpc "[sadly] As you will.")))
+              (say knpc "I am locked in this cell! Free me from this dishonour, "
+                   "and you will gain an ally.")
+              ))))
+  
+(define roland-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default 
+               (lambda (knpc kpc) 
+                 (say knpc "I'm afraid I can't help you with that.")))
+       (method 'hail 
+               (lambda (knpc kpc) 
+                 (if (roland-joined? knpc)
+                     (say knpc "I will aid thee any way I can.")
+                     (roland-join knpc kpc))))
+
+       (method 'bye (lambda (knpc kpc) (say knpc "Farewell.")))
+       (method 'job 
+               (lambda (knpc kpc) 
+                 (say knpc "I am a knight errant.")))
+       (method 'name (lambda (knpc kpc) (say knpc "I am Roland.")))
+       (method 'join roland-join)
+
+       (method 'cell
+               (lambda (knpc kpc)
+                 (say knpc "Use picklocks on a locked door to open it. Or, cast "
+                      "an unlock spell.")))
+       (method 'clov
+               (lambda (knpc kpc)
+                 (say knpc "I was with him the day he fell in battle. "
+                      "The enemy ambushed us, and I was knocked senseless. "
+                      "I dreamt that a hideous beast dragged the King down into Tartos. "
+                      "When I awoke I was in a camp hospital.")))
+       (method 'free
+               (lambda (knpc kpc)
+                 (say knpc "I was waylaid and kidnapped by the bandits in this "
+                      "cave. They've locked me in this cell to hold me for "
+                      "ransom.")))
+       (method 'pick
+               (lambda (knpc kpc)
+                 (say knpc "Bandits and thieves usually carry picklocks.")))
+       (method 'spel
+               (lambda (knpc kpc)
+                 (say knpc "You should ask a Wizard about spells.")))
+       (method 'trig 
+               (lambda (knpc kpc) 
+                 (say knpc "I know Trigave is a small town, a crossroad of "
+                      "the north, with much history.")))
+       (method 'knig 
+               (lambda (knpc kpc)
+                 (say knpc "I was a squire of King Clovis in the Goblin Wars. "
+                      "When the wars ended, I took to wandering.")
+                 ))
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-roland)
+  (bind 
+    (kern-mk-char 
+     'ch_roland          ; tag
+     "Roland"            ; name
+     sp_human            ; species
+     oc_warrior          ; occ
+     s_knight            ; sprite
+     faction-prisoner    ; starting alignment
+     6 0 6               ; str/int/dex
+     pc-hp-off           ; hp bonus
+     pc-hp-gain          ; hp per-level bonus
+     0                   ; mp off
+     0                   ; mp gain
+     max-health          ; hp
+     -1                  ; xp
+     max-health          ; mp
+     0                   ; ap
+     3                   ; lvl
+     #f                  ; dead
+     'roland-conv        ; conv
+     nil                 ; sched
+     'roland-ai          ; special ai
+     nil                 ; container
+     nil                 ; readied
+     )
+    (roland-mk #f #f #f)))
diff --git a/worlds/haxima-1.002/rowing.wav b/worlds/haxima-1.002/rowing.wav
new file mode 100644 (file)
index 0000000..95f0fa9
Binary files /dev/null and b/worlds/haxima-1.002/rowing.wav differ
diff --git a/worlds/haxima-1.002/rune.png b/worlds/haxima-1.002/rune.png
new file mode 100644 (file)
index 0000000..2a0dbf3
Binary files /dev/null and b/worlds/haxima-1.002/rune.png differ
diff --git a/worlds/haxima-1.002/runes.scm b/worlds/haxima-1.002/runes.scm
new file mode 100644 (file)
index 0000000..569828f
--- /dev/null
@@ -0,0 +1,149 @@
+;; rune sprites
+
+;; also used where external events trigger quest
+(define (rune-basic-quest questtag questicon)
+       (quest-data-complete questtag)
+       (quest-data-assign-once questtag)
+       (quest-data-update-with questtag 'done 1 (grant-party-xp-fn 50))
+       (qst-set-icon! (quest-get questtag) questicon)
+       )
+           
+(define (rune-basic-get kobj kchar questtag)
+  ;; Get the sprite before picking up the object, because picking it up will
+  ;; deallocate it.
+  (let ((sprite (kern-obj-get-sprite kobj)))
+    (kobj-get kobj kchar)
+    (rune-basic-quest questtag sprite)))
+
+;; rune interface: when a rune is used on a special altar, it transforms the
+;; alter and signals the demon gate mechanism
+(define (rune-use ktype kuser)
+  (let ((loc (get-target-loc kuser 1)))
+    (cond ((null? loc) 
+           result-no-target)
+          ((eqv? (kern-place-get-terrain loc) t_rune_altar)
+           (shake-map 5)
+           (kern-log-msg "A LOCK IS RELEASED!")
+           (kern-obj-remove-from-inventory kuser ktype 1)
+           (kern-place-set-terrain loc t_active_altar)
+           (send-signal kuser demon-gate 'on)
+           result-ok)
+          (else 
+           result-not-here))))
+
+(define rune-ifc
+  (ifc obj-ifc
+       (method 'use rune-use)
+       ))
+
+;; special extended interface for rune of leadership: summon the ghost of the
+;; warritrix when the player picks it up
+(define (rune-li-get kobj kchar)
+  (kern-log-msg "An apparition appears!")
+  (kern-obj-put-at (mk-warritrix)
+                   (kern-obj-get-location kobj))
+  (let ((sprite (kern-obj-get-sprite kobj)))
+    (kern-obj-remove kobj)
+    (kobj-get (kern-mk-obj t_rune_l 1) kchar)
+    (rune-basic-quest 'questentry-rune-l sprite))
+  )
+(define rune-li-ifc
+  (ifc rune-ifc
+       (method 'get rune-li-get)))
+
+;; trigger quest update
+(define (rune-l-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-p)
+       )
+(define rune-l-ifc
+  (ifc rune-ifc
+       (method 'get rune-l-get)))
+
+;; trigger quest update
+(define (rune-k-receive ktype kchar)
+       (quest-data-update-with 'questentry-thiefrune 'recovered 1 (quest-notify (grant-party-xp-fn 50)))
+       (quest-data-update 'questentry-rune-k 'player-got-rune 1)
+       )
+(define (rune-k-get kobj kchar)
+       (rune-k-receive kobj kchar)
+       (kobj-get kobj kchar)
+       )
+(define rune-k-ifc
+  (ifc rune-ifc
+       (method 'get rune-k-get)
+       (method 'receive rune-k-receive)
+       ))
+       
+;; trigger quest update
+(define (rune-p-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-p)
+       )
+(define rune-p-ifc
+  (ifc rune-ifc
+       (method 'get rune-p-get)))
+
+;; trigger quest update
+(define (rune-w-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-w)
+       )
+(define rune-w-ifc
+  (ifc rune-ifc
+       (method 'get rune-w-get)))
+
+;; trigger quest update
+(define (rune-f-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-f)
+       )
+(define rune-f-ifc
+  (ifc rune-ifc
+       (method 'get rune-f-get)))
+       
+;; trigger quest update
+(define (rune-d-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-d)
+       )
+(define rune-d-ifc
+  (ifc rune-ifc
+       (method 'get rune-d-get)))
+
+;; trigger quest update
+(define (rune-c-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-c)
+       )
+(define rune-c-ifc
+  (ifc rune-ifc
+       (method 'get rune-c-get)))
+
+;; trigger quest update
+(define (rune-s-get kobj kchar)
+       (rune-basic-get kobj kchar 'questentry-rune-s)
+       )
+(define rune-s-ifc
+  (ifc rune-ifc
+       (method 'get rune-s-get)))
+
+;; rune types
+(mk-quest-obj-type 't_rune_k "Rune of Knowledge" s_runestone_k layer-item rune-k-ifc)
+(mk-quest-obj-type 't_rune_p "Rune of Power" s_runestone_p layer-item rune-p-ifc)
+(mk-quest-obj-type 't_rune_s "Rune of Skill" s_runestone_s layer-item rune-s-ifc)
+(mk-quest-obj-type 't_rune_c "Rune of Curiosity" s_runestone_c layer-item rune-c-ifc)
+(mk-quest-obj-type 't_rune_f "Rune of Freedom" s_runestone_f layer-item rune-f-ifc)
+(mk-quest-obj-type 't_rune_w "Rune of Wisdom" s_runestone_w layer-item rune-w-ifc)
+(mk-quest-obj-type 't_rune_d "Rune of Discretion" s_runestone_d layer-item rune-d-ifc)
+(mk-quest-obj-type 't_rune_l "Rune of Leadership" s_runestone_l layer-item rune-l-ifc)
+(mk-quest-obj-type 't_rune_l_init "Rune of Leadership" s_runestone_l layer-item rune-li-ifc)
+
+;; list of all rune types
+(define rune-types 
+  (list t_rune_k
+        t_rune_p
+        t_rune_s
+        t_rune_c
+        t_rune_l
+        t_rune_f
+        t_rune_w
+        t_rune_d))
+
+;; check if kpc has all the runes in inventory
+(define (has-all-runes? kpc)
+  (all-in-inventory? kpc rune-types))
diff --git a/worlds/haxima-1.002/runestones.png b/worlds/haxima-1.002/runestones.png
new file mode 100644 (file)
index 0000000..0124508
Binary files /dev/null and b/worlds/haxima-1.002/runestones.png differ
diff --git a/worlds/haxima-1.002/scrolls.png b/worlds/haxima-1.002/scrolls.png
new file mode 100644 (file)
index 0000000..c5a7b78
Binary files /dev/null and b/worlds/haxima-1.002/scrolls.png differ
diff --git a/worlds/haxima-1.002/scrolls.scm b/worlds/haxima-1.002/scrolls.scm
new file mode 100644 (file)
index 0000000..9e23320
--- /dev/null
@@ -0,0 +1,106 @@
+;; ============================================================================
+;; scrolls.scm -- useable scrolls
+;; ============================================================================
+
+(kern-mk-sprite-set 'ss_scrolls 32 32 3 4 0 0 "scrolls.png")
+
+(kern-mk-sprite 's_an_tym_scroll          ss_scrolls 1 0 #f 0) ;; stop time
+(kern-mk-sprite 's_in_mani_corp_scroll    ss_scrolls 1 1 #f 0) ;; resurrect
+(kern-mk-sprite 's_vas_rel_por_scroll     ss_scrolls 1 2 #f 0) ;; gate travel
+(kern-mk-sprite 's_xen_corp_scroll        ss_scrolls 1 3 #f 0) ;; kill
+
+(kern-mk-sprite 's_sanct_lor_scroll       ss_scrolls 1 4 #f 0) ;; invisibility
+(kern-mk-sprite 's_in_quas_xen_scroll     ss_scrolls 1 5 #f 0) ;; clone
+(kern-mk-sprite 's_in_vas_por_ylem_scroll ss_scrolls 1 6 #f 0) ;; tremor
+(kern-mk-sprite 's_an_xen_ex_scroll       ss_scrolls 1 7 #f 0) ;; charm
+
+(kern-mk-sprite 's_in_an_scroll           ss_scrolls 1 8 #f 0) ;; negate
+(kern-mk-sprite 's_in_ex_por_scroll       ss_scrolls 1 9 #f 0) ;; unlock magic
+(kern-mk-sprite 's_vas_mani_scroll        ss_scrolls 1 10 #f 0) ;; great heal
+(kern-mk-sprite 's_wis_quas_scroll        ss_scrolls 1 11 #f 0) ;; reveal
+
+(kern-mk-sprite 's_wis_an_ylem_scroll     ss_scrolls 1 13 #f 0) ;; xray
+
+(kern-mk-sprite 's_rel_xen_quas_scroll    ss_scrolls 1 14 #f 0) ;; monster alignment
+
+(define (mk-scroll tag name sprite spell)
+  (mk-usable-item tag name sprite norm 
+                  (lambda (kscrolltype kuser)
+                    (apply spell (list kuser)))))
+
+(define (in-wilderness? caster)
+       (let ((place (loc-place (kern-obj-get-location caster))))
+       (and 
+               (kern-place-is-wilderness? place)
+               (not (kern-place-is-combat-map? place))
+       )))
+
+;;-----------------------------------------------------------------------------------------
+;; Scroll Functions
+;;-----------------------------------------------------------------------------------------
+
+(define (scroll-xen-corp caster)
+       (if (in-wilderness? caster)
+               result-not-here
+               (user-cast-ranged-targeted-spell caster 4 cast-kill-proc)
+       ))
+               
+(define (scroll-in-quas-xen caster)
+       (if (in-wilderness? caster)
+               result-not-here
+               (cast-ui-basic-ranged-spell powers-clone
+                       caster 
+                       (powers-clone-range 12)
+                       12)
+       ))
+
+(define (scroll-in-vas-por-ylem caster)
+       (if (in-wilderness? caster)
+               result-not-here
+               (powers-tremor caster caster 12)
+       ))
+
+(define (scroll-an-xen-ex caster)
+       (if (in-wilderness? caster)
+               result-not-here
+               (cast-ui-basic-ranged-spell powers-charm
+                       caster 
+                       (powers-charm-range 12)
+                       12)
+       ))
+               
+(define (scroll-rel-xen-quas caster)
+  (if (in-wilderness? caster)
+      result-not-here
+      (rel-xen-quas caster))
+  )
+
+(define (scroll-rel-xen-quas caster)
+  (if (in-wilderness? caster)
+      result-not-here
+      (rel-xen-quas caster))
+  )
+
+(define (scroll-paralyze caster)
+  (paralyze caster)
+  )
+
+;;-----------------------------------------------------------------------------------------
+;; Scroll List
+;;-----------------------------------------------------------------------------------------
+
+(mk-scroll 't_an_tym_scroll "An Tym (Time Stop) scroll" s_an_tym_scroll an-tym) ;; context-any
+(mk-scroll 't_in_mani_corp_scroll "In Mani Corp (Resurrection) scroll" s_in_mani_corp_scroll in-mani-corp)  ;; context-any
+(mk-scroll 't_vas_rel_por_scroll "Vas Rel Por (Gate) scroll" s_vas_rel_por_scroll vas-rel-por)  ;; context-any
+(mk-scroll 't_xen_corp_scroll "Xen Corp (Death Bolt) scroll" s_xen_corp_scroll scroll-xen-corp) 
+(mk-scroll 't_sanct_lor_scroll "Sanct Lor (Invisibility) scroll" s_sanct_lor_scroll sanct-lor) ;; context-any
+(mk-scroll 't_in_quas_xen_scroll "In Quas Xen (Clone) scroll" s_in_quas_xen_scroll scroll-in-quas-xen)
+(mk-scroll 't_in_vas_por_ylem_scroll "In Vas Por Ylem (Tremor) scroll" s_in_vas_por_ylem_scroll scroll-in-vas-por-ylem) 
+(mk-scroll 't_an_xen_ex_scroll "An Xen Ex (Charm) scroll" s_an_xen_ex_scroll scroll-an-xen-ex)
+(mk-scroll 't_in_an_scroll "In An (Negate Magic) scroll" s_in_an_scroll in-an) ;; context-any
+(mk-scroll 't_in_ex_por_scroll "In Ex Por (Magic Unlock) scroll" s_in_ex_por_scroll in-ex-por)  ;; context-any??
+(mk-scroll 't_vas_mani_scroll "Vas Mani (Great Heal) scroll" s_vas_mani_scroll vas-mani) ;; context-any
+(mk-scroll 't_wis_quas_scroll "Wis Quas (Reveal) scroll" s_wis_quas_scroll wis-quas) ;; context-any
+(mk-scroll 't_wis_an_ylem_scroll "Wis An Ylem (X-Ray Vision) scroll" s_wis_an_ylem_scroll wis-an-ylem) ;; context-any
+(mk-scroll 't_rel_xen_quas_scroll "Rel Xen Quas (Illusion of Beastliness) scroll" s_rel_xen_quas_scroll rel-xen-quas)
+(mk-scroll 't_test_paralyze_scroll "Paralyze Me!" s_an_tym_scroll scroll-paralyze)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/selene.scm b/worlds/haxima-1.002/selene.scm
new file mode 100644 (file)
index 0000000..956e83b
--- /dev/null
@@ -0,0 +1,132 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define selene-lvl 5)
+(define selene-species sp_human)
+(define selene-occ nil)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Old Absalot.
+;;----------------------------------------------------------------------------
+(define selene-bed oa-bed3)
+(define selene-mealplace oa-tbl2)
+(define selene-workplace oa-baths)
+(define selene-leisureplace oa-temple)
+(kern-mk-sched 'sch_selene
+               (list 0  0 selene-bed          "sleeping")
+               (list 7  0 selene-mealplace    "eating")
+               (list 8  0 selene-workplace    "working")
+               (list 12 0 selene-mealplace    "eating")
+               (list 13 0 selene-workplace    "working")
+               (list 18 0 selene-mealplace    "eating")
+               (list 19 0 selene-leisureplace "idle")
+               (list 22 0 selene-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (selene-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Selene is a female cult member of the Accursed.
+;; She is unstable, wicked, and depraved.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (selene-hail knpc kpc)
+  (say knpc "[This wild-eyed young woman stares at you impishly]"))
+
+(define (selene-default knpc kpc)
+  (say knpc "[She giggles. It is an evil sound]"))
+
+(define (selene-name knpc kpc)
+  (say knpc "Selene."))
+
+(define (selene-join knpc kpc)
+  (say knpc "[She shakes here head emphatically]"))
+
+(define (selene-job knpc kpc)
+  (say knpc "[She shrugs] I play with things."))
+
+(define (selene-bye knpc kpc)
+  (say knpc "[She calls out after your back] Be seeing you, hero!"))
+
+(define (selene-play knpc kpc)
+  (say knpc "Things... people..."))
+
+(define (selene-peop knpc kpc)
+  (say knpc "I like to make them do what I want."))
+
+(define (selene-want knpc kpc)
+  (say knpc "Whatever I want. I don't care. I just like to make people do it. "
+       "If they don't do it... [she shrugs and giggles]"))
+
+(define (selene-accu knpc kpc)
+  (say knpc "It's not so bad, hero. It's kind of fun."))
+
+(define (selene-fun knpc kpc)
+  (say knpc "Being Accursed? Sure it is! My favorite part is the sacrifices."))
+
+(define (selene-sacr knpc kpc)
+  (say knpc "You'll find out, silly!"))
+
+(define (selene-denn knpc kpc)
+  (say knpc "It's easy to make him do what I want. He's afraid of me. "
+       "And he wants me."))
+
+(define (selene-sila knpc kpc)
+  (say knpc "[She suddenly looks afraid, and becomes vicious] "
+       "Why are you bothering me? Go away!")
+  (kern-conv-end))
+
+(define selene-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default selene-default)
+       (method 'hail selene-hail)
+       (method 'bye  selene-bye)
+       (method 'job  selene-job)
+       (method 'name selene-name)
+       (method 'join selene-join)
+
+       (method 'play selene-play)
+       (method 'peop selene-peop)
+       (method 'want selene-want)
+       (method 'accu selene-accu)
+       (method 'fun  selene-fun)
+       (method 'sacr selene-sacr)
+       (method 'denn selene-denn)
+       (method 'sila selene-sila)
+       ))
+
+(define (mk-selene)
+  (bind 
+   (kern-mk-char 
+    'ch_selene           ; tag
+    "Selene"             ; name
+    selene-species         ; species
+    selene-occ              ; occ
+    s_townswoman     ; sprite
+    faction-men      ; starting alignment
+    0 2 1            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    selene-lvl
+    #f               ; dead
+    'selene-conv         ; conv
+    sch_selene           ; sched
+    'townsman-ai              ; special ai
+    nil              ; container
+    (list t_dagger)              ; readied
+    )
+   (selene-mk)))
diff --git a/worlds/haxima-1.002/sfx.png b/worlds/haxima-1.002/sfx.png
new file mode 100644 (file)
index 0000000..5ef9873
Binary files /dev/null and b/worlds/haxima-1.002/sfx.png differ
diff --git a/worlds/haxima-1.002/shapes.png b/worlds/haxima-1.002/shapes.png
new file mode 100644 (file)
index 0000000..3bee671
Binary files /dev/null and b/worlds/haxima-1.002/shapes.png differ
diff --git a/worlds/haxima-1.002/shard.scm b/worlds/haxima-1.002/shard.scm
new file mode 100644 (file)
index 0000000..85d61e8
--- /dev/null
@@ -0,0 +1,720 @@
+;;
+;; kern-mk-composite-map
+;;     with grid chunks of 32 x 32 tiles size
+;;     4 across, 4 down
+;; 
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; |  Grid XY=(0,0)       | |  Grid XY=(1,0)       | |  Grid XY=(2,0)       | |  Grid XY=(3,0)       |
+;; |NW=  0,0    NE= 31,0  | |NW= 32,0    NE= 63,0  | |NW= 64,0    NE= 95,0  | |NW= 96,0    NE=127,0  |
+;; |                      | |                      | |                      | |                      |
+;; |SW=  0,31   SE= 31,31 | |SW= 32,31   SE= 63,31 | |SW= 64,31   SE= 95,31 | |SW= 96,31   SE=127,31 |
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; 
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; |  Grid XY=(0,1)       | |  Grid XY=(1,1)       | |  Grid XY=(2,1)       | |  Grid XY=(3,1)       |
+;; |NW=  0,32   NE= 31,32 | |NW= 32,32   NE= 63,32 | |NW= 64,32   NE= 95,32 | |NW= 96,32   NE=127,32 |
+;; |                      | |                      | |                      | |                      |
+;; |SW=  0,63   SE= 31,63 | |SW= 32,63   SE= 63,63 | |SW= 64,63   SE= 95,63 | |SW= 96,63   SE=127,63 |
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; 
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; |  Grid XY=(0,2)       | |  Grid XY=(1,2)       | |  Grid XY=(2,2)       | |  Grid XY=(3,2)       |
+;; |NW=  0,64   NE= 31,64 | |NW= 32,64   NE= 63,64 | |NW= 64,64   NE= 95,64 | |NW= 96,64   NE=127,64 |
+;; |                      | |                      | |                      | |                      |
+;; |SW=  0,95   SE= 31,95 | |SW= 32,95   SE= 63,95 | |SW= 64,95   SE= 95,95 | |SW= 96,95   SE=127,95 |
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; 
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+;; |  Grid XY=(0,3)       | |  Grid XY=(1,3)       | |  Grid XY=(2,3)       | |  Grid XY=(3,3)       |
+;; |NW=  0,96   NE= 31,96 | |NW= 32,96   NE= 63,96 | |NW= 64,96   NE= 95,96 | |NW= 96,96   NE=127,96 |
+;; |                      | |                      | |                      | |                      |
+;; |SW=  0,127  SE= 31,127| |SW= 32,127  SE= 63,127| |SW= 64,127  SE= 95,127| |SW= 96,127  SE=127,127|
+;; +----------------------+ +----------------------+ +----------------------+ +----------------------+
+
+
+(kern-mk-composite-map
+    'm_shard     4 4
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 0,0 -- NW=(0,0) SE=(31,31)
+                       "*. *. *. *. ** ** *. *. ** *. *. *. *. ** *. ** ** ** *. *. *. ** ** *. *. ** *. *. ** ** ** ** "
+                       "** ** ** ** ** ** *. *. ** ** ** ** ** *. ** *. ** ** *. *. *. *. ** ** ** ** *. ** ** *. ** ** "
+                       "** *. *. *. *. *. *. *. *. *. *. ** ** ** ** *. ** ** ** ** ** ** ** ** ** ** *. ** *. *. ** ** "
+                       "*. ** *. *. *. ** ** ** *. ** *. ** ** ** ** *. ** *. ** ** ** *. *. ** *. ** ** ** *. *. *. *. "
+                       "*. *. *. ** ** *. *. *. *. ** ** ** ** ** ** *. ** ** ** ** *. ** ** *. ** *. *. ** ** ** *. ** "
+                       "** *. ** *. ** ** ** *. ** ** ** ** *. *8 *8 *8 *8 *8 *8 *8 *8 *8 *8 ** ** ** ** ** ** ** ** *. "
+                       "** *. *. ** ** ** *. *. ** *. *. *c ^g ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a *. ** ** *. *. ** ** "
+                       "** *. ** ** ** *. ** ** *. ** ^g ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a ** *. *. *. ** *. "
+                       "*. ** ** *. *. *. *. *. *. *4 ^^ ^^ ^^ .! ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a *8 *. ** ** *. "
+                       "*. ** ** ** ** ** ** ** *. *c ^^ ^c tb tt td ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *a ** ** "
+                       "** ** ** *. ** ** *. *. ** ^g ^^ %b %5 tt %b %d ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h *. ** "
+                       "*. *. ** ** *. *. ** *. *4 ^^ ^^ t7 %% ta tt tt tt t5 ^a ^^ ^^ ^^ ^^ ^^ ^c %3 %% %5 ^a ^^ *a ** "
+                       "*. ** *. ** *. ** ** *. *c ^^ ^^ tt %% %5 ta tt tt tt tt tt tt tt tt tt td %% -7 %% %5 ^^ ^h *a "
+                       "** *. *. ** ** *. ** *. ^g ^^ ^c te %% %c ^3 ^^ ^d tt tt tc %3 %% %5 te %3 -b -- -d %% ^^ ^^ ^^ "
+                       "*. *. *. *. ** ** ** *4 ^^ ^^ t7 %3 %c ^3 ^^ ^c %7 ta tt %3 %c ^7 %a %% %% %% -e %% %c ^^ ^^ ^^ "
+                       "*. ** *. *. *. ** ** *4 ^^ ^^ tt %% ^b ^^ ^c %3 %% %d tt %% ^b ^^ ^d %% t7 %a %% %c {B {{ ^^ tf "
+                       "** ** *. ** *. *. ** *4 ^^ ^^ te %a %% %% %% %% %% ^f tt %a %5 ^e %3 %c tt tt tt td %7 {E t7 {E "
+                       "*. *. ** *. ** ** ** *4 ^^ ^^ ^5 t7 ^f %% %% %% %% tb tt t5 %a %% %c t3 tt tt tt %3 %% %d tt %3 "
+                       "** *. ** *. ** ** ** ** ^j ^^ ^^ te %3 %c ^3 ^5 %% %5 ta tt tt tt tt tc t& tt tt %a %c t3 tt %% "
+                       "*. *. ** ** ** ** *. *. *5 ^^ ^^ ^5 %% ^b ^^ ^^ %% %% %5 t% ta tt tt %3 %5 ta tt tt tt tt tc %a "
+                       "*. ** ** ** ** ** ** *. *4 ^^ ^^ ^c %% %5 ^^ ^c %% %% %% ^7 t% tt tc %% %% %5 t% tt {# {{ {% t3 "
+                       "** *. *. ** *. ** ** *. *4 ^^ ^^ %3 %% %% ^^ %3 %% %% %c {1 tC tt %3 %c ^7 %a %5 tt {{ {{ {{ tt "
+                       "*. ** ** *. *. ** *. ** *4 ^^ ^^ %% ^f %% ^^ %a %% %% tb tt tt tt %% ^b ^^ ^d %% te {A {{ {C te "
+                       "** *. ** ** *. *. ** *. *4 ^^ ^^ %a %% %% ^^ ^5 %% %% %% %5 ta tt %a %d ^e %3 %% %5 tb tt td %3 "
+                       "** ** ** ** *. ** *. *. ** ^j ^^ ^5 %a %% ^a ^c %% %% -7 %% %5 tt tt t5 %b %% %% %% %5 te %3 %% "
+                       "*. ** *. *. *. *. *. *. *. *5 ^j ^^ ^5 %a %% %% %% -b -- -d %% tt ^f tt tt tt t5 %% %% %% %% -b "
+                       "*. ** *. ** *. ** *. *. *. *. *5 ^^ ^^ ^^ ^5 %a %% %% -e %% %c tt tt tt tt tt tt %% %c ^7 %a %% "
+                       "** *. ** ** ** ** *. *. *. *. *. ^j ^^ ^^ ^^ ^5 t7 %a %% %c t3 tc %3 %% %5 ta tt %e ^b ^^ ^d %a "
+                       "** ** *. *. *. ** *. *. *. ** *. ** *1 *5 ^^ ^^ ta tt tt tt tt %3 %% -7 %% %5 tt t5 %7 ^e %7 t3 "
+                       "** *. *. *. ** ** *. *. *. ** *. ** *. *4 ^^ ^^ {2 .. .. t% tt %% -b -- -d %% tt tt %a %% %c tt "
+                       "*. *. ** *. ** ** ** *. *. *. ** ** *. *4 ^^ ^^ {a .. .. .. tt %a %% -e %% %c tt tt tt tt tt tc "
+                       "** *. ** ** *. *. ** *. *. *. *. *. *. *4 ^^ ^^ {{ {a {8 .. ta t5 %a %% %c t3 tc t# {8 {8 .. .. "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 1,0 -- NW=(32,0) SE=(63,31)
+                       "** *. ** ** ** ** ** *. *. ** ** ** *. *. ** *. *. *. ** ** ** *. ** *. *. *. *. ** *. *. *. *. "
+                       "** *. ** *. ** *. ** *. *. ** ** ** ** ** *. ** ** *. *. *. *. *. ** *. ** ** *. *. *. ** *. *. "
+                       "** ** *. *. *. *. ** *. *. ** ** *. *. ** ** ** *. *. *. *. *. ** *. ** ** ** ** *. ** *. *. *. "
+                       "** *. ** ** *. *. *. *. ** ** *. *. *. ** *. *. *. *8 *8 *8 ** ** ** *. *. *. ** *. ** ** ** ** "
+                       "** *. *. ** ** *. *. ** ** ** ** *. *. ** ** *c ^g ^^ .. ^^ ^h *a ** ** ** ** ** *. *. ** *. *. "
+                       "** ** ** *. *. *. *. *. ** ** ** ** *. *. ** ^g ^^ {{ {6 {{ ^^ ^h ** ** *. *. *. *. ** *. ** ** "
+                       "*. *. *. ** *. ** *. *. ** ** *. *. *. *. *4 ^^ {{ {3 .. {5 {{ ^^ *2 ** ** ** *. ** ** ** *. ** "
+                       "*. *. *. ** ** ** *. *. ** ** *. ** ** *. ** ^j {{ {a .. {c ^^ ^l *. ** *. ** ** *. *. ** *. *. "
+                       "*. ** ** *. *. *. *. ** *. *. ** *. ** ** *. *5 {j {{ {e ^^ ^l *3 *. *. *. ** *. ** ** ** ** ** "
+                       "** ** *. *. *. ** *. ** ** ** ** *. *. ** *. *. *5 {j {{ {l *3 *. *. *. ** ** ** *. *. *. *. *. "
+                       "*. *. *. ** *. *. ** ** *. *. *. *. ** *. *8 *. *. *. *1 ** ** *. *. *. ** *. ** *. ** *. ** ** "
+                       "** *. *8 *8 ** *. *. ** *. ** ** *. *c {g {{ {h *a *. ** ** *. *. ** ** ** ** *. *. ** *. *. *. "
+                       "*c ^g ^^ ^^ ^h *a *8 *. ** *. *. *. {g {{ ^^ {{ {h ** *. *. ** *. ** ** *. ** ** *. ** *. *. *. "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^h ** *. ** *c {{ ^^ ^^ ^^ {{ *2 ** ** ** *. ** *. *. ** *. *. ** *. ** ** "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ *2 *. *c {g {{ {{ ^^ {{ {l *. ** ** *. ** *. ** *. ** ** *. *. ** ** *. "
+                       "{{ {{ {C tf {A {{ ^^ ^^ *2 *. {g {{ ^^ {{ {{ {l *3 ** *. *. *. ** *8 *. *. ** *. ** ** *. *8 *c "
+                       "%3 -7 %% %5 t7 {{ ^^ ^^ *a *4 {{ ^^ ^^ ^^ {{ *3 ** *. ** *8 *c ^g ^^ ^h *a *. ** *. ** ^g ^^ ^^ "
+                       "-b -- -d %% tt {{ ^^ ^^ ^h *e {{ {{ ^^ {{ {l ** ** *c ^g ^^ ^^ ^^ ^^ ^^ ^h *a *. *. *4 ^^ ^^ ^^ "
+                       "%% -e %% %c te {{ ^^ ^^ ^^ {{ {{ {{ {{ {{ *3 ** *c ^g ^^ ^^ ^^ {{ ^^ ^^ ^^ ^h *. *. *4 ^^ ^^ ^^ "
+                       "%% %% %% tf {B {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ *a *c ^g ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ *a *. *4 ^^ ^^ ^^ "
+                       "td %% %% %5 tf {A ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^h *e ^^ ^^ ^^ "
+                       "%3 %c ^7 %a %5 t7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "%% ^b ^^ ^d %% tt ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 {1 {1 {1 {5 {{ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "%% %5 ^e %3 %c te ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 tC t3 tt t5 tA {5 ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "-7 %% %% %c tf ^3 ^^ ^^ ^^ ^^ ^^ {{ {3 .. t3 tt tt tt t5 {4 {{ ^^ ^^ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ "
+                       "-- -d %% t7 ^3 ^^ ^^ ^^ ^^ ^^ ^^ {{ {a .. tt tt ~7 tt tt {4 {{ {{ ^^ {{ {{ ^^ {{ {{ ^^ ^^ ^^ ^^ "
+                       "-e %% %c te ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {2 ta tt ~6 tt tt tA {5 {{ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ "
+                       "%% %c t7 {# ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {2 t% tt ~6 ta tt t5 tA {5 {{ {{ {{ ^^ {{ {{ {{ {{ ^^ ^^ "
+                       "tt tt tc {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. tt ~a ~9 ~5 ta t5 tA {1 {1 {1 {1 {5 {{ {{ {{ {{ {{ "
+                       "/3 .. .. {5 {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 .. tC tt tt t5 ~a ~5 tt tt tt tt tt t5 tA {1 {1 {1 {1 {1 "
+                       "/7 .. .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ {{ {2 .. t3 tt tt tt t5 ~6 te ~3 ~9 ~9 ~5 ta tt tt tt tt tt t5 "
+                       "/7 .. .. .. {5 {{ {{ ^^ ^^ ^^ ^^ {{ {2 .. ta tt tt tt tt ~2 ~9 ~c t3 t5 ~2 ~9 ~9 ~9 ~9 ~9 ~5 ta "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 2,0 -- NW=(64,0) SE=(95,31)
+                       "*. *. *. ** ** ** ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "** ** ** ** *. *. *5 ^j ^^ ^^ ^^ ^l *3 *1 *1 *5 ^j ^^ ^^ ^^ ^l *3 *1 *1 *5 ^j ^^ ^^ ^^ ^^ ^c |# "
+                       "** ** ** ** ** ** *. *5 ^j ^^ ^l *3 ** ** ** ** *5 ^j ^^ ^l *3 *. ** ** ** *5 ^j ^^ ^^ ^^ || tt "
+                       "*. *. *. ** *. *. *. *. *5 ^^ *3 ** *c ^g ^h *a ** *5 ^^ *3 *. *c ^g ^h *a ** *5 ^^ ^^ *b *d tt "
+                       "** ** *. *. *. *. *. ** *4 ^^ *2 *. ^g ^^ ^^ ^h *. *4 ^^ *2 *. ^g ^^ ^^ ^h *. *4 ^^ tf .. .. {4 "
+                       "*. ** ** *. ** *. ** *. ** ^n ** *4 ^^ ^^ ^^ ^^ *a ** ^n *. *4 ^^ ^^ ^^ ^^ *a *c ^^ {2 .. *f tt "
+                       "** *. ** ** ** *. *. ** *. *. *. *c ^^ ^^ ^^ ^^ ^h *a *. *. *c ^^ ^^ ^^ ^^ tt .. ^^ {2 tb tt tt "
+                       "*. ** ** *. *. ** ^g ^h *a *8 *c ^g ^^ ^^ ^^ ^^ ^^ ^h *a *c ^g ^^ ^^ ^^ ^^ ^^ {2 {1 {4 ^^ ^5 |A "
+                       "*. ** *. *. ** *. ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ tb tt td ^^ ^^ ^^ "
+                       "*. ** *. ** ** ** *5 ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "** ** *. *. ** ** *. *5 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^~ ^^ ^^ ^^ "
+                       "** ** ** *. *. ** ** *c ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ "
+                       "*. *. *. *. ** ** ** ^g ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ "
+                       "** *. *. *. *. *. *4 ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^L -3 -1 -1 -1 -5 ^J {{ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ "
+                       "** *8 *8 *8 *. ** *c ^^ ^^ ^^ ^^ {{ {{ {{ ^L -3 -- -- -8 -- -- -5 {J {{ ^^ ^^ ^^ ^^ ^^ {{ ^^ {{ "
+                       "^g ^^ ^^ ^^ ^h *e ^g ^^ ^^ ^^ ^^ ^^ {{ {{ -3 -- -c ^G ^^ ^H -a -- -5 {{ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ -2 -- ^G ^^ ^^ ^^ ^H -- -4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ -2 -4 ^^ ^^ ^^ ^^ ^^ -2 -4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^L -- -4 {5 ^^ {7 ^^ {3 -2 -- ^J ^^ ^^ ^^ ^^ ^^ {{ {{ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {7 ^^ -3 -- -4 .. {1 /7 {1 .. -2 -- -5 ^^ {{ ^^ ^^ ^^ {{ {{ {3 "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {b .. {1 -a __ -c .. .. /7 .. .. -a __ -c {5 {{ {{ ^^ {{ {{ {3 .. "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ /0 /d /d == /d /d /d /9 /e /c /e __ /c /d /2 {A {{ {{ {3 .. .. "
+                       "^^ {{ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ /7 t7 -3 __ -- -5 ~A .. ~C -3 -- __ -5 .. /8 /d /e /c /e {8 .. "
+                       "^^ {{ {{ ^^ {{ {{ {{ {{ {{ {{ {C /7 tt -2 __ __ -- -- -1 -- -- __ __ -4 .. {c {{ {{ {{ {{ {{ {a "
+                       "{{ {{ {{ {{ {{ {3 {1 {1 {1 {1 /0 /a tt -a -- __ __ __ __ __ __ __ -- -c {4 {{ {{ ^^ ^^ {{ {{ {{ "
+                       "{{ {{ {{ {3 {1 tC tb tt tt t5 /7 tb tt tH -a -- -- __ __ __ __ -- -c ~# {4 {{ ^^ ^^ ^^ ^^ ^^ {{ "
+                       "^^ {{ {{ {2 t3 td ~3 ~9 ~5 tt /8 /2 tt tt tt tH -a -- __ __ -- -- ~B .. {4 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       "{{ {{ {3 .. tt ~3 ~c t7 ~6 ta t5 /7 ta tt || tt tM -- __ __ -- -- -- -5 ~A {1 {5 {{ {{ {{ ^^ ^^ "
+                       "{{ {3 .. tC tt ~6 t3 tt ~a ~5 tt /7 t% ta tt tt -3 -- __ __ -- __ __ -- -- -5 ~A {1 {5 {{ ^^ ^^ "
+                       "{1 .. tC t3 tc ~6 tt tt t5 ~6 tt /8 /2 .. tD tt -2 __ __ __ __ __ __ __ __ -- -- -5 {4 {{ {{ ^^ "
+                       "tE t3 tt tc ~3 ~c tt t& tt ~6 ta td /7 tb tt tc -- __ __ __ __ __ __ __ __ __ __ -- ~A {5 {{ ^^ "
+                       "tt tc ~3 ~9 ~c t3 tc .. tt ~a ~9 ~9 =| ~9 ~9 ~9 -- -- __ __ __ __ __ __ __ __ __ -- -5 {4 {{ ^^ "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 3,0 -- NW=(96,0) SE=(127,31)
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "tt tt tt *f ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "tc t& ta tt || ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {7 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       "^3 ^^ ^5 ta tt ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {3 .. {5 {{ {{ ^^ ^^ ^^ ^^ "
+                       "^^ .. ^^ tD tt ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {b .. .. .. {d {{ ^^ ^^ ^^ ^^ "
+                       "^^ ^~ ^^ tt *f ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a .. {c {{ {{ ^^ ^^ ^^ ^^ "
+                       "t5 .. t3 tt || ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {6 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       "tt *f tt |C ^3 ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {6 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {e ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ {{ {{ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ {7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ {{ {{ {{ {{ {3 {1 {1 {1 {1 {1 {1 {1 {1 {1 {1 {1 {1 {5 {{ {{ ^^ {{ /7 {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ {{ {{ {{ {3 {1 .. .. .. .. .. .. .. .. .. .. .. .. .. .. {5 {{ {{ {{ /b {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "{{ {{ {{ {3 .. .. tC t3 tt tt tt tt tt tt tt tt tt tt t5 .. .. {5 {{ {{ {6 {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       "{{ {{ {{ {2 .. t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tA .. .. {1 {1 /3 {1 {5 ^^ ^^ ^^ ^^ ^^ "
+                       "{{ {{ {3 .. .. tt tt tt || || || || || || || || || tt tt t5 .. .. .. .. /b .. .. {5 ^^ ^^ ^^ ^^ "
+                       "{{ {3 .. .. tC tt tt || || || || || || || || || || tt tt tL -3 -1 -5 .. .. /c /d /2 {1 {5 ^^ ^^ "
+                       "{3 .. .. tC t3 tt tt || || ~b ~9 ~9 ~9 ~9 ~5 || || || tt -3 -- -- -- ~A .. .. .. /b .. .. {5 ^^ "
+                       "{2 .. t3 tt tt tt tt || || || || || || |% ~6 |A || || tt -2 -- -- -- -5 .. .. .. /3 .. .. {4 ^^ "
+                       ".. .. tt tt tt || || || || || || || || || ~a ~5 |A || tL -- -- -- -- -- ~A .. .. /b .. .. {4 ^^ "
+                       ".. .. tt tt || || || || || || || || || || |% ~a ~5 tL -3 -- -- -- -- -- -- -5 ~A .. .. ~C _3 -- "
+                       ".. .. tt tt || || ~b ~9 ~9 ~9 ~9 ~9 ~5 |A || |D -- -- -- -- -- __ -- -- -- -- -- -1 -1 -- -- -- "
+                       ".. .. tt tt || || || || || || || |% ~a ~9 ~1 ~9 -8 -- -- -- -- __ __ __ -- -- -- -- -- -- -- -- "
+                       ".. .. tt tt tt || || || || || || || || |D ~6 |# || tH -- -- __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{2 .. ta tt tt || || || |C ~3 ~9 ~9 ~9 ~9 ~c || || || -2 -- __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{a .. t% tt tt || || ~b ~9 ~c |# || || || || || || tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{{ {a .. tt tt || || || || || || || || || || || || -3 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{{ {{ {2 ta tt tt || || || || || || || tt tt tt tt -2 -- __ -- __ __ __ __ __ __ __ __ __ __ __ "
+                       "^^ {{ {2 t% ta tt tt tt tt tt tt tt tt tt tt tt tc -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "^^ {{ {a .. .. t% ta tt tt tt tt tt tt tt tc t# .. -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "^^ ^^ {{ {a {8 {8 {8 .. .. .. .. .. .. {8 {8 {8 {8 -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "^^ {{ {{ {{ {{ {{ {{ {a {8 {8 {8 {8 {c {{ {{ {{ {{ -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 0,1 -- NW=(0,32) SE=(31,63)
+                       "*. ** *. *. ** ** ** ** *. ** *. *. ** *c ^^ ^^ {{ {{ {{ {a t% ta tt tt tt tc t# {# {{ {{ {a /0 "
+                       "*. ** ** *. *. ** ** *. *. *. *. *. ^g ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {a {8 {8 {4 {{ {{ ^^ {{ {{ /7 "
+                       "** *. *. ** ** ** *. *. ** *. *. *. ^j ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {6 {{ ^^ ^^ ^^ {{ /7 "
+                       "*. *. *. ** *. *. *. *. ** ** ** ** *5 ^j ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {6 {{ {{ ^^ {{ {C /7 "
+                       "** ** ** ** *. ** *. ** *. *. *. ** ** *5 ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a {5 {{ {{ {C /0 /a "
+                       "** ** ** ** *. *. *. ** *. *. *. *. *. *. *5 ^j ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a {9 {9 /0 /a {# "
+                       "** ** *. ** ** ** *. ** *. *. ** *. *. *. ** *5 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ /7 {# {{ "
+                       "*. *. ** ** *. *. ** ** *. ** *. ** *. *. *. *4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ /7 {{ {{ "
+                       "*. *. *. *. ** ** ** ** *. *. ** *. ** ** ** *4 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ /7 {1 {5 "
+                       "** ** ** ** ** *. ** *. ** *. *. ** ** *. ** *c ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {3 /7 .. .. "
+                       "** ** ** ** *. ** *. *. *. *. ** ** *. ** *c ^g ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {3 {1 .. /7 .. .. "
+                       "*. *. ** *. ** ** *. ** ** ** *. *. ** *c ^g ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {2 .. .. /7 .. .. "
+                       "*. ** ** ** *. ** *. *. ** *. ** ** *. ^g ^^ ^^ ^^ ^^ {{ {{ ~7 {{ {{ {{ {{ {3 .. .. .. /7 .. .. "
+                       "*. *. ** *. *c .i *a *. *. ** ** *. *4 ^^ ^^ ^^ {{ {{ {{ {{ ~6 {1 t3 tt t5 .. .. .. .. /7 .. .. "
+                       "*. ** *. *. .k .. .m *. *. *. *. *. *c ^^ ^^ ^^ {{ {{ {{ {3 ~6 .. te ~7 te .. .. .. .. /7 .. .. "
+                       "** *. ** *. *5 .n *3 ** *. *. *. ** ^g ^^ ^^ ^^ {{ {{ ~b ~9 ~4 .. .. ~6 .. .. .. .. .. /7 .. .. "
+                       "*. *. ** ** *. *. *. *. *. ** ** *4 ^^ ^^ ^^ ^^ {{ {{ {{ {2 ~6 .. .. ~6 .. .. .. .. .. /7 .. .. "
+                       "** *. ** ** *. *. *. ** *. *. *. *4 ^^ ^^ ^^ ^^ {{ {{ {3 .. ~a ~9 ~9 ~4 .. .. .. .. .. /7 .. .. "
+                       "*. *. *. ** ** ** ** *. ** *. ** *4 ^^ ^^ ^^ ^^ {{ {{ {2 .. .. .. .. ~6 .. .. .. .. .. /7 .. .. "
+                       "*. *. *. *. *. *. *. ** ** *. ** *c ^^ ^^ ^^ ^^ {{ {3 /0 /d /d /d /d == /d /d /d /d /d /7 .. .. "
+                       "** ** ** ** *. *. ** *. *. *c ^g ^^ ^^ ^^ ^^ ^^ {{ {2 /7 .. .. .. .. ~6 .. .. .. .. .. /8 /d /d "
+                       "*. *. *. *. ** ** *. ** *c ^g ^^ ^^ ^^ ^^ ^^ {{ {{ {2 /7 .. .. .. .. ~a ~9 ~9 ~5 .. .. .. .. .. "
+                       "** ** *. ** ** *. ** ** ^g ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {a /7 .. t3 td .. .. .. .. ~6 .. .. .. .. ~3 "
+                       "*. ** *. ** ** *. *. *4 ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ /7 tC tt ~b ~5 .. .. .. ~6 .. .. .. .. ~6 "
+                       "** ** ** *. ** ** ** *4 ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ {{ {{ /7 t3 tt td ~6 .. .. .. ~a ~9 -1 -1 -- -4 "
+                       "*. *. ** *. ** ** ** *4 ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ {{ {{ /7 tt ~b ~9 ~8 ~5 .. .. .. ~C -- __ __ -4 "
+                       "** *. *. *. *. *. ** *4 ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ {{ /7 ta t5 tA .. ~a ~1 ~9 ~1 -- -- __ __ -4 "
+                       "*. ** *. *. ** ** *. *4 ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ /7 t% tt td .. .. ~6 .. -a -- __ __ -- -- "
+                       "*. *. *. *. *. ** ** *4 ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {3 /7 tC tt ~b ~5 .. ~6 .. ~% -- -- -- -- -- "
+                       "*. ** ** ** ** ** *. *4 ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ {{ {2 /7 t3 tt td ~~ ~9 ~c .. .. -2 -- tG tH ~a "
+                       "** *. ** ** ** *. *. *c ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {2 /7 tt ~b ~9 ~c .. .. .. ~C -- -c tt tt tt "
+                       "** *. ** ** ** *. *. {g {{ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {2 /7 ta td .. .. .. .. .. -3 -- tG tt tt tt "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 1,1 -- NW=(32,32) SE=(63,63)
+                       "/a .. .. {8 .. {5 {{ {{ ^^ ^^ ^^ ^^ {2 .. t% tt tt tt tc ~6 t3 tt tt tt ~6 t3 tt tt tt t5 ~a ~9 "
+                       ".. .. {c {{ {a .. {5 {{ {{ ^^ ^^ ^^ {2 .. .. tt ~3 ~9 ~9 ~c tt t# tD tt ~6 tt t# {8 t% ta tt tt "
+                       ".. {c {{ {{ {{ {a {c {{ {{ ^^ ^^ ^^ {a .. .. tt ~6 t3 tt tt tc .. t3 tc ~6 tt {4 ^^ {a {8 {8 {8 "
+                       "{c {{ {{ {{ {{ {{ {{ {{ {{ {{ ^^ {{ {{ {2 tC tt ~6 tt t# {8 {8 .. tt ~3 ~c tt {4 ^^ ^^ ^^ {{ {{ "
+                       "{{ {{ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ {2 t3 tc ~6 tt {4 ^^ {{ {2 tt ~6 t3 tt tA {5 ^^ ^^ ^^ {{ "
+                       "{{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {3 tC tt ~3 ~c tt {4 ^^ ^^ {2 tt ~6 ta tt t5 {4 {{ ^^ ^^ ^^ "
+                       "{{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {b .. t3 tt ~6 t3 tt {4 {{ ^^ {2 tt ~a ~9 ~5 tt {4 {{ {{ ^^ ^^ "
+                       "{{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {2 tt tt ~e tt tt {c {{ {{ {2 ta tt t5 ~e tt {4 {{ {{ ^^ ^^ "
+                       "{{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {2 ta tt tt tt tc {{ ^^ ^^ {a {8 t% ta tt tc {4 {{ ^^ ^^ ^^ "
+                       "{1 {1 {5 {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {a t% ta tt tc t# {{ ^^ ^^ {{ {{ {a {8 {8 {8 {c ^^ ^^ ^^ ^^ "
+                       ".. .. t7 {A {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {a {8 {8 {c ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. tt ~7 t7 {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. te ~6 tt {A {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ {C tf {{ tf {A ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. .. ~6 tt td {5 {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tf t# {1 t% tf {{ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. .. ~6 tt ~3 ~9 ~9 ~9 ~9 ~d ^^ ^^ ^^ ^^ ^^ {{ {{ {2 .. {4 {{ {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. .. ~6 te ~6 t7 {# {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ tf tA /3 tC tf {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. .. ~a ~9 ~4 te {5 {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {% tf /7 tf {# ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {7 {{ "
+                       ".. .. .. .. .. ~~ ~9 ~9 ~5 tb td {A ^^ ^^ ^^ ^^ ^^ ^^ {% /7 {# ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {3 .. {5 "
+                       ".. ~3 ~9 ~9 ~9 ~c t3 t5 ~a ~1 ~d tf {{ ^^ ^^ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {b .. .. .. "
+                       ".. ~6 .. .. .. .. ta tt td ~6 tf {# {3 {1 tf ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {a .. {c "
+                       "/d == /d /d /2 .. .. .. .. == .. {1 {8 {c {{ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {e {{ "
+                       ".. ~6 .. .. /7 .. .. {8 tf ~6 tb td {A {{ {{ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "~9 ~c .. .. /7 .. {4 {{ {% ~a ~9 ~5 tf {{ ^^ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. .. .. /7 .. {4 {{ ^^ ^^ ^5 ~a ~d ^^ ^^ ^^ ^^ ^^ ^^ /7 ^^ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       ".. .. .. .. /7 .. {4 {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ /7 ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ {{ "
+                       ".. .. .. .. /7 .. .. {1 {5 {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {C /7 {A {{ {{ {C t7 {A {{ {{ ^^ ^^ ^^ {{ "
+                       ".. .. .. .. /8 /d /d /d /d /2 {{ ^^ ^^ ^^ ^^ {{ t3 tt t5 /7 t3 tt tt tt tt tt tt t5 {{ ^^ {{ {C "
+                       "~A .. .. .. .. .. .. {c {% /7 {{ ^^ ^^ {{ {{ {{ ta tt tc /7 ta tt tt tt tt tt tt tc {A {{ {C tf "
+                       "~5 ~A .. .. .. .. {c {{ {{ /7 {A ^^ ^^ ^^ {{ {3 .. /0 /d /9 /d /d /d /d /d /d /d /d /d /d /d /d "
+                       "-- -- ~5 ~A .. {4 {{ {{ {{ /8 /d {{ ^^ {{ /d /d /d /a .. .. .. .. t3 tt tt tt tt tt tt tt tt tt "
+                       "tH ~a -- ~~ ~9 ~9 ~9 ~9 ~5 {A {{ ^^ ^^ ^^ {{ {a .. .. .. .. .. .. ta tt tt tt tt tt tt || || tt "
+                       "tt tH ~~ -c {# {{ {{ {% ~a ~5 {{ {{ ^^ ^^ {{ {{ {2 .. .. .. .. .. .. t% tt tt tt tt || || || || "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 2,1 -- NW=(64,32) SE=(95,63)
+                       "~9 ~9 ~c t3 tt tc t# .. ta tt tt td /7 tb tt tt tH -- __ __ -- -- -- -- __ __ __ -- -4 {4 {{ ^^ "
+                       "tt tt tt tc t# {8 {8 .. .. .. .. .. /7 .. .. .. .. -a -8 -8 -c ~# ~% -- __ __ __ __ -4 {4 {{ {{ "
+                       "{8 {8 {8 {8 {c {{ {{ {a {8 .. /0 /d /a {8 .. .. .. .. {8 {8 {8 {8 {8 -a -- __ __ __ -- ~A {5 {{ "
+                       "{{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {a /7 {# {{ {{ {a {8 {8 {c {{ {{ {{ {{ {{ {H -- __ __ __ -- -- -1 -1 "
+                       "{{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ /7 {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ -2 __ __ __ __ __ __ __ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ /7 {{ ^^ ^^ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ -2 __ __ __ __ __ __ __ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ /7 ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ -a -- __ __ __ __ __ __ "
+                       "^c |# || |% ^a ^^ ^^ ^^ ^^ ^^ /8 /2 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^H -a -8 -- -- __ __ __ "
+                       "|# || || || |% ^a ^^ ^^ ^^ ^^ ^d /7 ^~ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c tf ^a ^^ ^^ ^^ ^H -a -- __ __ "
+                       "|| || || || || t5 ^a ^^ ^^ ^^ /0 /a ^^ ^^ ^^ ^c |& ^a ^^ tb tt td /7 t7 ^^ ^^ ^^ ^^ ^H -- -- __ "
+                       "|A || || || || tt t5 ^a ^^ ^c /7 ^3 ^^ ^^ ^^ |# || |% ^e /0 /d /d /a te ^^ ^^ ^^ ^^ ^^ -2 -- __ "
+                       "^5 |A || |C ^7 ta tt tt tt t5 /7 ^^ ^^ ^^ ^c || || || t5 /7 tb tt td ^3 ^^ ^^ ^^ ^^ ^^ -2 -- __ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^5 ta tt tc /7 ^a ^^ ^^ t3 tt || tt tt /7 ^3 ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^L -- -- __ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^5 /0 /d /9 /2 ^a ^c ta tt tt tt tc /7 ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ -b -- -- -- "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ /7 t3 t5 /8 /d /d /d /d /d /d /d /a t7 ^a ^^ ^^ ^^ ^^ ^^ ^^ ~% -a -- -- "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ /7 tt tt tt tt tt tt tt tt tt tt tt tt t5 ^a ^^ ^^ ^^ ^^ ^^ {2 .. ~% -- "
+                       "^^ ^^ ^^ ^^ ^^ {{ {{ {C /7 tt || || || |X || tt tt tt || || || tt tt t5 ^^ ^^ ^^ ^^ {a .. .. -a "
+                       "{{ {{ {{ {{ ^^ {{ /0 /d /a tt || |t || || || tt t| tt tt || || || tt tt ^^ ^^ ^^ ^^ ^^ {a .. ~% "
+                       "{9 {9 {5 {{ {{ {C /7 t3 tt tt || || |t || || || tt tt || || |t || || tt ^^ ^^ ^^ ^^ ^^ ^^ {a {8 "
+                       "{{ {{ {a {5 {C tf /7 tt || || || || || || || tt tt tt || || || |X || tt ^a ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ {{ {{ /0 /d /d /a tt || || |t || || || || || tt t| || |X || || || tt t5 ^^ ^^ ^^ ^^ ^^ ^^ ^c "
+                       "^^ ^^ {{ /7 t3 tt tt || |t || || |X || |t || || tt tt tt |t || || tt t| tt ^a ^^ ^^ ^^ ^^ ^^ t3 "
+                       "^^ {{ {C /7 tt || || || || || || || || || || || || tt tt || || || tt tt tt || |% ^a ^^ ^^ ^c tt "
+                       "{{ {C t7 /7 tt || || |X || || || tt || || || |t || tt tt tt || || || tt || || || |X || || tt tt "
+                       "{C tb tc /7 tt || |t || || tt tt tt || || || || || || tt tt || |X || || || || || || || || tt tt "
+                       "/0 /d /d /a tt || || || tt tt tt tt tt || |t || || || tt tt tt || || || |t || |C ^7 |A || tt t| "
+                       "/7 t3 tt tt tt tt || || tt tt || tt tt tt || tt tt tt t| tt || || || || || |X ^b ^^ ^5 tt tt tt "
+                       "/7 tt tt tt tt tt tt tt tt tt || || tt tt || tt || tt tt tt || || |t || || || |% ^^ ^^ ta tt tt "
+                       "/a tt tt tt t| tt tt t| tt || || || tt tt t| tt tt tt tt || || || || || |X || tt ^^ ^^ ^5 ta t| "
+                       "tt tt t| tt tt tt tt || || || |t |X || tt tt || || || || || || |X || || || || tc ^^ ^^ ^^ ^5 ta "
+                       "|| || tt tt tt || || |t || || || |t || || || |t || || || |t || || || |t || tt ^3 ^^ ^^ ^^ ^^ ^d "
+                       "|| || || tt tt || || || |X |t || || || || |X || || |t || || || || |X || || tc ^^ ^^ ^^ ^^ ^^ t3 "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 3,1 -- NW=(96,32) SE=(127,63)
+                       "^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {{ {L -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "^^ ^^ ^^ ^^ -7 {J {{ {{ {{ {{ {{ {{ {{ {{ {C ~C -3 -- __ __ __ __ __ __ __ __ __ ~~ ~~ ~~ __ __ "
+                       "^^ ^^ ^^ ^^ -2 -- _1 _1 _1 _1 _1 -1 -1 -1 -1 -- -- -- __ __ __ __ __ __ __ __ ~~ -- -- -- ~~ __ "
+                       "-1 -5 ^J ^L -- -- __ __ __ __ __ __ __ -- -- -- -- __ __ __ __ __ __ __ ~~ -- -- -c ^I -a -- __ "
+                       "-- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ ~~ -- -- ^K ^^ ^M -- __ "
+                       "-- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -- -- -- -5 ^N -3 -- __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- -- __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ ~~ ~~ ~~ ~~ ~~ -- -- -- -- ~~ ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -- -- -8 -8 -- -- -- -- -- -- -- -- __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c {G {{ {{ ^H -a -- -- -- -- -- -- __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- {G {{ ^^ ^^ ^^ ^M -- -c ^I -a -- -- __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ ^^ ^^ ^^ ^^ ~3 -- ^K ^^ ^M -- __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ {{ ^^ ^^ ^^ ~a -- -5 ^N -3 -- -- __ -- "
+                       "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -4 {{ {{ ^^ ^^ ^^ ^H ~a -- -- -- -- -- -- -- "
+                       "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c {{ ^^ ^^ ^^ {{ ^^ ^^ ^^ -- -- -- ^I -a -- "
+                       "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ -- {G {{ ^^ !3 !5 {{ !3 !5 ^^ -a -- -4 ^^ ^M -- "
+                       "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c {{ ^^ ^^ !a !! =! !! !c ^^ ^H -a -c ^^ -3 -- "
+                       "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- {G {{ ^^ ^^ ^^ !e {{ !e ^^ ^^ ^^ {{ {{ ^^ -2 __ "
+                       "-2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ {{ ^^ -2 __ "
+                       "-2 -- -- __ __ __ __ __ __ __ __ __ __ __ __ -4 {{ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ ^^ _2 __ "
+                       "-a -- -- -- -- __ __ __ __ __ __ __ __ __ __ -- {J {{ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^L __ __ "
+                       "tH -a -- -- -- -- __ __ __ __ __ __ __ __ __ -- -5 {{ ^^ ^^ ^^ {{ ^^ ^^ {{ {{ {{ ^^ ^L _3 __ __ "
+                       "tt tt tH -a -- -- __ __ __ __ __ __ __ __ __ __ -- {J {{ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ ^L _3 __ __ __ "
+                       "tt tt tt tH -- -- __ __ __ __ __ __ __ __ __ __ -- -- -5 ^J ^^ ^^ ^^ ^^ ^^ ^^ ^^ _3 __ __ __ __ "
+                       "tt tt tt tt -2 -- __ __ __ __ __ __ __ __ __ __ __ __ -- -- -5 ^J ^L -3 -5 ^J ^L __ __ __ __ __ "
+                       "tt tt tt tt -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- __ __ __ __ __ __ "
+                       "tt tt tt tt -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tt tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tt -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tL -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ -- -c ^I -a -- __ __ __ __ __ __ __ __ __ "
+                       "tt tt -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- ^K ^^ ^M -- __ __ __ __ __ __ __ __ __ "
+                       "tt tt -2 -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ -- -5 ^N -3 -- __ __ __ __ __ __ __ __ __ "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 0,2 -- NW=(0,64) SE=(31,95)
+                       "*. ** *. ** *. *. ** *5 {j {{ ^^ ^^ ^^ ^^ ^^ {{ {3 .. /7 .. .. .. .. .. .. ~C -- -- tJ tt tt tt "
+                       "** *. ** ** *. ** ** ** *5 {{ ^^ ^^ ^^ {{ {{ {3 .. .. /7 .. .. .. .. .. ~C ~3 -- -- -5 tJ tt tt "
+                       "** ** ** ** ** ** ** ** *c {{ ^^ ^^ {{ {{ /0 /d /d /d /9 /d /d /2 .. .. -3 -- -- __ -- -5 tt tt "
+                       "*. ** ** *. ** *. ** *c {g {{ ^^ ^^ {{ {3 /7 {c {{ {{ {{ {{ {a /7 .. .. -2 -- __ __ __ -4 tt tt "
+                       "** *. *. *. ** *. ** {g {{ ^^ ^^ ^^ {{ {2 /7 {{ {{ ^^ ^^ {{ {{ /7 .. ~C -- -- -- __ -- -c tt tt "
+                       "*. *. *. *. *. *. *c {{ ^^ ^^ ^^ ^^ {{ {2 /7 {{ ^^ ^^ ^^ ^^ {{ /7 .. -3 -- -- -- -- -c tG tt tt "
+                       "*. ** *. ** *. *c {g {{ ^^ ^^ ^^ ^^ {{ {2 /7 {{ ^^ ^^ ^^ ^^ {{ /7 .. -2 -- -- -c tG tt tt tt tt "
+                       "** *8 *8 *c {g {{ {{ ^^ ^^ ^^ ^^ ^^ {{ {2 /7 {{ {{ ^^ ^^ {{ {C /7 .. -2 -- -- tG tt tt tt tt tt "
+                       "^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {3 .. /7 {5 {{ {{ {{ {C /0 /a ~C -- -- -- tJ tt tt {# {{ {{ "
+                       "^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ {{ {{ {3 /0 /d /9 /d /d /d /d /d /a ~C -3 -- -- -- -5 tJ tc {{ ^^ ^^ "
+                       "^^ ^^ ^^ {{ {{ ^^ ^^ ^^ {{ {{ {3 .. /7 .. .. .. .. .. .. .. .. -3 -- -- -- ~~ -- -- -5 ^^ ^^ ^^ "
+                       "^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ {3 .. .. /7 .. .. .. .. .. .. .. ~C -- ~~ -- -- -- -- -- -c ^^ ^^ ^^ "
+                       "^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ {{ {2 .. .. /7 .. ~C _3 _1 _5 ~A ~C ~3 ~~ -- -- -- -- -- -- ^K ^^ ^^ ^^ "
+                       "^^ ^^ {{ {{ {{ ^^ ^^ ^^ {3 .. .. .. /7 ~C _3 __ __ __ __ __ __ __ __ -- -- -- -- -- -5 ^^ ^^ ^^ "
+                       "^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ {2 .. .. .. .. _3 __ __ __ __ __ __ __ __ __ __ -- __ __ __ -- ^J ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ {{ {{ {{ {2 .. .. .. .. _a __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 ^^ ^^ "
+                       "^^ ^^ ^^ ^^ {{ {L ~3 ~1 ~5 ~A .. .. .. ~% _a __ __ __ _c ~& _a __ __ __ __ __ __ __ __ -- ^J ^L "
+                       "^^ ^^ ^^ {{ {L ~3 ~~ ~~ ~~ ~~ ~5 .. .. .. ~% _a _8 _c ~# .. ~% -- __ __ __ __ __ __ __ -- -- -- "
+                       "^^ ^^ ^^ {{ ~3 ~~ -- ~~ ~~ ~~ ~~ ~A .. .. .. .. .. .. .. .. ~C -- __ __ __ __ __ __ __ __ __ __ "
+                       "^^ ^^ ^^ {{ ~2 -- -- -- -- -- ~~ ~5 ~A .. .. .. .. .. .. ~C -3 -- -- -- -- __ __ __ __ __ __ __ "
+                       "^^ ^^ ^^ {{ ~2 -- -- -- -- -- ~~ ~~ ~~ ~5 ~A .. .. ~C -3 -- -- ~~ ~~ ~~ -- -- __ __ __ __ __ __ "
+                       "^^ ^^ ^^ {{ ~a ~~ -- -- -- -- ~~ ~~ ~~ ~~ ~~ -1 -1 -- -- -- ~~ ~c ~& ~a ~~ -- __ __ __ __ __ __ "
+                       "^^ ^^ ^^ {{ {H ~a ~~ -- -- ~~ ~c ~& ~a ~~ ~~ ~~ ~~ ~~ ~~ -- ~~ ~B .. ~D ~~ -- __ -- -- -- -8 -- "
+                       "^^ ^^ ^^ ^^ {{ {H ~a ~~ ~~ ~~ ~B .. ~D ~~ -- -- -- -- -- -- ~~ ~5 ~E ~3 ~~ -- -- -- -c {G {{ {H "
+                       "^^ ^^ ^^ ^^ ^^ {{ {{ {H ~~ ~~ ~5 ~E ~3 ~~ -- -- -- -- -- -- -- ~~ ~~ ~~ -- -- -c {G {{ {{ ^^ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ~a ~~ ~~ ~~ ~~ -- -- -- -- -- -- -- -- -- -- -- -- ~~ {G {{ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {H ~a ~~ -- -- -- -- ~~ ~~ ~8 ~8 ~8 ~8 ~~ ~~ ~~ ~~ ~c {{ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {H ~a ~8 ~8 ~8 ~8 ~c {G {{ {{ {{ {{ {H ~a ~c {G {{ {{ ^^ ^^ ^^ ^^ {{ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {L "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -b -- "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {H -- "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 1,2 -- NW=(32,64) SE=(63,95)
+                       "tt tt ~6 {# {{ ^^ {{ {{ {% ~6 {A {{ {{ ^^ ^^ {{ tb tt td .. .. .. .. .. tt tt tt || || || || || "
+                       "tt tt ~6 {{ ^^ ^^ ^^ ^^ {{ ~a ~d {{ ^^ ^^ ^^ {{ {{ {{ {{ {a {8 {8 .. tC tt || || || || || || || "
+                       "tt tt ~6 {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {{ tb tt tt tt || || tt tt tt || "
+                       "tt tt ~6 {A {{ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {% ta tt tt tt tt tt tt tt "
+                       "tt tt ~a ~5 {A {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {% tt tt || tt tt tt || "
+                       "tt tt t5 ~a ~9 ~9 ~d {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ {{ tt tt || || || || || "
+                       "tt tt tt tt tt tt td {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {L ~7 {J {{ ^^ ^^ ^^ {{ tt tt tt tt tt tt tt "
+                       "tt tt tt tt tc {# {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ~b -- ~d {{ ^^ ^^ ^^ {{ te {# {{ {{ {{ {% ta "
+                       "{{ {% te {# {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {% ~6 {# {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+                       "^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~6 ^^ ^^ ^^ ^^ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c ~6 ^^ ^^ ^^ {{ {C ~7 {J {{ ^^ ^^ ^^ ^^ ^^ "
+                       "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ~3 ~c ^^ ~3 ~9 ~9 ~9 -- ~d {{ ^^ ^^ ^^ ^^ ^^ "
+                       "{{ ^^ ^^ ^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^c ~6 ^b ^c ~6 ^3 {{ {% ~e {G {{ ^^ ^^ {{ {{ {{ "
+                       "{{ ^^ {{ {{ {{ {{ {{ {7 {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ ~3 ~8 ~9 ~9 ~4 ^^ ^^ {{ {{ {{ ^^ ^^ {{ {{ {{ {C "
+                       "{{ {{ {{ {{ {{ {{ {3 .. {5 {{ {{ ^^ ^^ ^^ ^^ ^c ~6 ^3 ^^ ^5 ~6 ^a ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ t3 "
+                       "{L -3 -5 {J {{ {3 .. .. .. {5 {{ ^^ ^^ ^^ ^c ~3 ~c ^^ ^^ ^^ ~a ~9 ~d ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ta "
+                       "-3 -- -- -- -5 ~A .. .. .. {4 {{ {{ ^^ ^L -3 ~~ ^J ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {3 .. "
+                       "-- __ __ __ -- -5 ~A .. ~C -3 -1 -1 -1 -- -- -- -5 ^J ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ {{ {{ {2 .. "
+                       "__ __ __ __ __ -- -- -1 -- -- __ __ __ __ __ __ -- -- -5 ^J ^^ ^L -3 -1 -5 {J {{ {{ {{ {3 .. .. "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -1 -- -- __ -- -- _5 {J {{ {2 .. .. "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _1 _1 _5 ~A "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ _5 "
+                       "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-a -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{H -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{{ -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{{ -2 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "{L -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 2,2 -- NW=(64,64) SE=(95,95)
+                       "|| || || || tt || || || || || || || || || || || || || || || || || || || ^3 ^^ ^^ ^^ ^^ ^^ ^^ tt "
+                       "|| || || || tt tt || || || || tt || || || || || || || || || || || || || ^a ^^ ^^ ^^ ^^ ^^ ^^ tt "
+                       "tt tt tt || || tt || || tt tt tt || || || || || || || || || || || || || |% ^^ ^^ ^^ ^^ ^^ ^^ tt "
+                       "tt || tt || || tt tt tt tt || tt tt || || || || || || tt tt || || || || |C ^^ ^^ ^^ ^^ ^^ ^^ tt "
+                       "|| || tt tt tt tt tt || || || || tt || || || || || || tt tt tt || || || ^b ^^ ^^ ^^ ^^ ^^ ^c tt "
+                       "|| || || tt tt || || || || || tt tt || || || || || tt tt || tt tt tt || || ^a ^^ ^^ ^^ ^c t3 tt "
+                       "|| || tt tt || || || || tt tt tt tt tc {# {{ {{ {% tt || || || tt tt tt tt t5 ^a ^^ ^c t3 tt tt "
+                       "tt tt tt tt || || tt tt tt tc {# {{ {{ {{ ^^ ^^ {{ tt tt || tt tt tt tt tt tt t5 ^e t3 tt tt tL "
+                       "{% ta tt || || || tt {# {{ {{ {{ ^^ ^^ ^^ ^^ ^^ {{ tt ~b ~9 ~9 ~9 ~9 ~5 tt tt tt tt tt tt tt -3 "
+                       "{{ {% tt tt || tt tc {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ta tt tt tt tt t5 ~6 tt tt tt tt tt tt tL -- "
+                       "{{ {C tt tt tt tt {# {{ {{ ^^ ^^ ^^ ^^ ^^ {{ {{ tf {{ {{ {% ta tt tt ~6 ta tt tL -3 -1 -1 -- -- "
+                       "{{ t3 tt tt tt tc {{ {{ {{ {{ {{ {{ {{ ^^ ^^ {{ {{ ^^ ^^ {{ {% tt tt ~a ~1 ~9 ~~ ~~ -- -- -- -- "
+                       "{C tt tt tt t# .. {5 {{ {{ tb tt t5 {{ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tt tt t5 ~6 t7 -a -- -- -- -- -- "
+                       "t3 tt tt tc .. .. .. {1 {1 .. t% te {{ {{ ^^ ^^ ^^ ^^ ^^ ^^ {{ ta tt tt ~6 tt tM -- -- -- -- -8 "
+                       "tt t# .. .. .. .. .. .. .. .. .. .. {5 {{ {{ {{ ^^ ^^ ^^ ^^ {{ {% ta tc ~6 tL -3 -- -- -c tG tt "
+                       "tc .. .. .. .. .. .. .. .. .. ~C -3 -5 ~A {5 {{ {{ ^^ ^^ ^^ ^^ {{ {{ {% ~2 -- -- -- tG tt tt tt "
+                       ".. .. .. .. .. .. .. .. -b -1 -- -- -- -5 ~A {5 {{ ^^ ^^ ^^ ^^ ^^ {{ {{ -2 -- -- -- tJ tt tt tt "
+                       ".. .. .. .. .. .. .. .. ~% -- -- -- -- -- -5 ~A {{ ^^ ^^ ^^ ^^ {{ {{ {L -- -- -- -- -5 tJ tt tt "
+                       ".. .. .. .. .. .. .. .. ~C -- -- __ __ -- -- -5 {{ ^^ ^^ ^^ ^^ {{ {L -3 -- ~~ -- -- -- -5 tJ tL "
+                       ".. .. .. .. .. .. .. ~C -3 -- -- __ __ -- -- -- {J {{ {{ ^^ {{ -3 -- -- -- ~~ -- -- ~~ -- -- -- "
+                       ".. .. .. .. .. ~C -3 -- -- -- -- __ __ __ -- -- -- -5 {{ ^^ {{ -2 -- -- ~~ ~~ ~~ __ -- ~~ -- -- "
+                       "~A .. .. ~C -3 -- -- -- -- -- __ __ __ __ __ -- -- -- {J {{ {L -- -- __ __ ~~ __ __ __ __ ~~ ~~ "
+                       "__ _1 _1 -- -- -- -- -- __ __ __ __ __ __ __ __ -- -- -- -1 -- -- -- __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ -- -- -- __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+               ))
+       (kern-mk-map nil 32 32 pal_expanded
+               (list   ;; Block 3,2 -- NW=(96,64) SE=(127,95)
+                       "tt tt -a -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tt tH -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tt tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tt -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tt -2 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tt tL -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt tL -3 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-3 -- -- -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- -- -- -- ~~ ~~ ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- -c tI -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- tG tt -2 -- -- -8 -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- tJ tL -- -c tG tt tH -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- -- -- -- tG tt tt tt -2 __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "-- -- -- -4 tt tt tt tL -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tH -- -- -- tJ tt tL -3 -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+                       "tt -2 ~~ -- -- -1 -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- __ __ __ __ __ __ __ __ "
+                       "tL -- -- ~~ ~~ ~~ ~~ ~~ -- __ __ __ __ __ __ __ __ __ __ __ -- -c ~& -a -- __ __ __ __ __ __ __ "
+                       "-3 -- ~~ -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c ~# .. ~% -- __ __ __ __ __ __ __ "
+                       "-- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c ~# tC t7 .. -2 __ __ __ __ __ __ __ "
+                       "-- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~# tC t3 tt .. -a -- __ __ __ __ __ __ "
+                       "~~ -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -c tC t3 |. tt tA ~% -a -- __ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~# t3 |. |. |. tt td .. ~D ~~ __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -4 .. tt |. |. |. tc t# ~C -3 -- ~~ ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~A ta |. |. tc t# -3 -- -- -- -- ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 t% tt |. t# -3 -- -- -- -- -- ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~A ta tc {8 -2 -- -- -- -- -- ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 {# {{ {{ -a -- -- -- -- -- ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- {J ^^ ^^ {H -a -8 -c {G {M ~~ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 {J {{ ^^ {{ {{ {{ {L -3 -- __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -5 {J ^^ ^^ ^^ {L -3 -- __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -5 {J {L -3 -- __ __ __ __ "
+                       "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- __ __ __ __ __ "
+               ))
+
+    (kern-mk-map nil 32 32 pal_expanded
+      ;; Map Block #13/16 (0,3)
+      ;;   NW=  0,96   NE= 31,96  
+      ;;   SW=  0,127  SE= 31,127 
+      
+      (list
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      ;; Map Block #14/16 (1,3)
+      ;;   NW= 32,96   NE= 63,96  
+      ;;   SW= 32,127  SE= 63,127 
+      
+      (list
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- "
+        "-- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- "
+        "-- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- "
+        "{{ -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- "
+        "{{ -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- "
+        "{{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ {{ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- "
+        "{{ {{ ^^ {{ {{ -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- ~~ "
+        "{{ ^^ ^^ ^^ {{ -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- "
+        "{{ {{ ^^ {{ {{ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- {{ {{ "
+        "^^ {{ {{ {{ ^^ {{ {{ -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ {{ {{ {{ "
+        "^^ ^^ {{ ^^ ^^ ^^ {{ -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ ^^ ^^ {{ "
+        "^^ ^^ {{ {{ ^^ {{ {{ {{ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ {{ ^^ {{ "
+        "^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ ^^ {{ "
+        "^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ ^^ {{ "
+        "^^ ^^ ^^ ^^ {{ {{ ^^ {{ {{ {{ -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ ^^ ^^ "
+        "^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- {{ {{ ^^ "
+        "^^ ^^ ^^ ^^ ^^ ^^ {{ ^^ ^^ ^^ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- {{ {{ "
+        "^^ ^^ ^^ ^^ ^^ ^^ {{ {{ ^^ {{ {{ {{ -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ {{ ^^ {{ -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      ;; Map Block #15/16 (2,3)
+      ;;   NW= 64,96   NE= 95,96  
+      ;;   SW= 64,127  SE= 95,127 
+      
+      (list
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ ~~ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- ~~ ~~ ~~ -- __ __ -- __ -- __ -- -- -- -- -- -- -- -- -- -- -- -- __ __ __ __ __ __ __ __ __ "
+        "~~ {{ {{ {{ ~~ -- __ __ __ __ __ -- -- -- -- -- -- -- -- -- -- -- -- __ __ __ __ __ __ __ __ __ "
+        "{{ {{ ^^ {{ {{ -- __ __ __ __ -- -- -- .. .. .. .. .. .. .. -- -- -- __ __ __ __ __ __ __ __ __ "
+        "{{ ^^ ^^ ^^ {{ -- __ __ -- -- -- -- .. .. .. .. .. .. .. .. .. -- -- __ __ __ __ __ __ __ __ __ "
+        "{{ {{ ^^ {{ {{ -- __ __ -- -- -- .. .. .. .. tt tt tt .. .. .. -- -- ~~ __ __ __ __ __ __ __ __ "
+        "-- {{ {{ {{ -- __ __ __ -- -- .. .. .. .. tt tt tt tt tt .. .. -- -- -- ~~ ~~ ~~ ~~ __ __ __ __ "
+        "-- -- -- -- -- __ __ __ -- -- .. .. .. tt tt tt ^^ tt tt tt .. -- -- -- -- -- -- -- -- __ __ __ "
+        "__ __ __ __ __ __ __ __ -- -- .. .. .. tt tt ^^ ^^ ^^ tt tt tt tt -- -- {{ {{ {{ -- -- ~~ __ __ "
+        "__ __ __ __ __ __ __ __ -- -- .. .. .. tt tt tt ^^ ^^ ^^ tt tt tt tt {{ {{ ^^ {{ {{ -- ~~ __ __ "
+        "~~ __ __ __ __ __ __ __ __ -- .. .. .. .. tt tt tt tt ^^ ^^ ^^ tt tt {{ ^^ ^^ ^^ {{ -- -- ~~ ~~ "
+        "~~ ~~ __ __ __ __ __ __ __ -- .. .. .. .. td tt tt tt ^^ ^^ ^^ ^^ tt ^^ ^^ ^^ {{ {{ -- -- -- -- "
+        "~~ -- __ __ __ __ __ __ __ __ __ .. .. .. .. .. tt tt ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ -- -- {{ {{ {{ "
+        "-- -- __ __ __ __ __ __ __ __ __ .. .. .. .. .. .. tt tt ^^ ^^ -- -- ^^ {{ {{ -- -- {{ {{ ^^ {{ "
+        "{{ -- -- __ __ __ __ __ __ __ __ .. .. .. .. .. .. .. tt ^^ ^^ ^^ -- -- -- -- -- -- {{ ^^ ^^ ^^ "
+        "-- -- ~~ -- __ __ __ __ __ __ __ __ -- -- .. .. .. .. ^^ ^^ ^^ ^^ ^^ {{ ~~ ~~ ~~ -- {{ {{ ^^ {{ "
+        "-- ~~ ~~ ~~ __ __ __ __ __ __ __ __ __ -- -- -- -- ^^ ^^ ^^ {{ ^^ {{ -- -- -- -- -- -- {{ {{ {{ "
+        "-- -- ~~ -- -- __ __ __ __ __ __ __ __ __ -- -- -- -- ^^ {{ {{ {{ -- -- {{ {{ {{ -- -- -- -- -- "
+        "{{ -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- {{ -- -- {{ {{ ^^ {{ {{ -- -- {{ {{ "
+        "{{ {{ {{ -- -- -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- {{ ^^ ^^ ^^ {{ -- -- {{ ^^ "
+        "^^ {{ {{ {{ -- -- ~~ ~~ ~~ -- __ __ __ __ __ __ __ __ __ __ __ ~~ -- {{ {{ ^^ {{ {{ -- -- {{ ^^ "
+        "{{ {{ {{ -- -- -- -- ~~ -- -- -- __ __ __ __ __ __ __ __ __ __ ~~ -- -- {{ {{ {{ -- -- -- {{ {{ "
+        "-- -- -- -- -- -- -- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- -- -- -- -- -- -- {{ "
+        "-- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ~~ ~~ ~~ ~~ ~~ -- ~~ -- -- "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- -- -- ~~ ~~ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ -- __ __ __ "
+      )
+    )
+    (kern-mk-map nil 32 32 pal_expanded
+      ;; Map Block #16/16 (3,3)
+      ;;   NW= 96,96   NE=127,96  
+      ;;   SW= 96,127  SE=127,127 
+      
+      (list
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ {{ -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ {{ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ ^^ {{ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "^^ {{ {{ -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "{{ {{ -- -- ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "-- -- -- -- __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "~~ ~~ ~~ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+        ))
+)
+
+(kern-load "raise-merciful-death.scm")
+
+(kern-mk-place 
+ 'p_shard
+ "The Shard Surface"
+ nil          ; sprite 
+ m_shard      ; map
+ #f  ;; wraps
+ #f  ;; underground
+ #t  ;; wilderness
+ #f  ;; tmp combat place
+
+ ;; subplaces:
+ (list
+  (list p_moongate_clearing 51  46)
+  (list p_gregors_hut       61  67)
+  (list p_abandoned_farm    43  51)
+  (list p_trigrave          29  51)
+  (list p_enchanters_tower  29  21)
+  (list p_green_tower       80  59)
+  (list p_bole              86  40)
+  (list p_glasdrin          82  18)
+  (list p_oparine           12  78)
+  (list p_absalot           120  4)
+  (list p_engineers_hut     50   4)
+  (list p_void_temple        5  46)
+  (list p_poor_house        19  65)
+  (list p_ankh_shrine       97   4)
+  (list p_westpass          45  61)
+  (list p_eastpass          43  61)
+  (list p_ancient_derelict  43  17)
+  (list p_gate_to_absalot  120  10)
+  (list p_tower_of_absalot 120   8)
+  (list p_kun               60  38)
+  (list p_lost_halls_entrance (loc-x lost-halls-loc) (loc-y lost-halls-loc))
+  (list p_voidgap_entrance   7  75)
+  (list p_voidgap_exit       4  77)
+  )
+
+
+ nil ; neighbors
+
+ ;; objects:
+ (list
+
+  ;; moongates
+  (list (kern-tag 'mg-1 (mk-moongate 'ord)) 62 50) ;; near green tower
+  (list (kern-tag 'mg-2 (mk-moongate 'ord)) 34 56) ;; near trigrave
+  (list (kern-tag 'mg-3 (mk-moongate 'ord)) 19 82) ;; near oparine
+  (list (kern-tag 'mg-8 (mk-moongate 'ord)) 21 19) ;; near enchanter's tower
+  (list (kern-tag 'mg-5 (mk-moongate 'ord)) 56 27) ;; near kurpolis
+  (list (kern-tag 'mg-6 (mk-moongate 'ord)) 90 26) ;; near lost halls & the man
+  (list (kern-tag 'mg-7 (mk-moongate 'ord)) 125 18) ;; near absalot
+  (list (kern-tag 'mg-4 (mk-moongate 'ord)) 50 7) ;; engineer's hut
+
+  ;; npc party generator
+  (put (mk-edge-spawn-generator) 0 0)
+
+  ;; dungeons
+  (put (mk-dungeon 'p_kurpolis_entrance 9 10) 53 18)
+  (put (mk-dungeon 'p_mushroom_cave 7 12) 78 74)
+  (put (mk-dungeon 'p_necromancers_lair 9 9) 40 70)
+  (put (mk-dungeon 'p_smoldering_cave 9 9) 118 46)
+  (put (mk-dungeon 'p_slimy_cavern 8 30) 13 8)
+  
+  
+
+  ;; wreck of the Merciful Death
+  (put (mk-raise-listener 'raise-merciful-death nil) 
+       merciful-death-x 
+       merciful-death-y)
+
+  ;; Bandit Hideout
+  (put (mk-step-trig 'mk-bandit-hideout nil)
+       (loc-x bandit-hideout-loc)
+       (loc-y bandit-hideout-loc))
+
+  ;; Angriss's Lair
+  (put (mk-step-trig 'mk-angriss-lair nil)
+       (loc-x angriss-lair-loc)
+       (loc-y angriss-lair-loc))
+
+ ;; Brundegardt
+  (put (mk-step-trig 'mk-brundegardt nil)
+       (loc-x brundegardt-loc)
+       (loc-y brundegardt-loc))
+
+  ;; The MAN's hideout
+  (put (mk-step-trig 'mk-mans-hideout nil)
+       (loc-x the-mans-hideout-loc)
+       (loc-y the-mans-hideout-loc))
+
+
+
+  ) ;; end of objects
+
+ nil ; hooks
+ nil ; edge entrances
+ )
+
+(kern-obj-put-at (mk-world-musicdata 'ml-travelling) (list p_shard 0 0))
+(kern-place-add-on-entry-hook p_shard 'music-on-combat-entry)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/ship.png b/worlds/haxima-1.002/ship.png
new file mode 100644 (file)
index 0000000..3b756de
Binary files /dev/null and b/worlds/haxima-1.002/ship.png differ
diff --git a/worlds/haxima-1.002/shroom.scm b/worlds/haxima-1.002/shroom.scm
new file mode 100644 (file)
index 0000000..f7e4eb5
--- /dev/null
@@ -0,0 +1,230 @@
+;; shroom.scm - an old hag with an interesting history who lives in the
+;; northeast corner of green tower.
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Green Tower.
+;;----------------------------------------------------------------------------
+(define (mk-zone x y w h) (list 'p_green_tower x y w h))
+(kern-mk-sched 'sch_shroom
+               (list 0  0  (mk-zone 51 9  1  1)  "sleeping")
+               (list 5  0  (mk-zone 40 11 3  3)  "idle")
+               (list 6  0  (mk-zone 49 6  7  1)  "working")
+               (list 12 0  (mk-zone 50 9  1  1)  "eating")
+               (list 13 0  (mk-zone 49 6  7  1)  "working")
+               (list 18 0  (mk-zone 56 54 1  1)  "eating")
+               (list 19 0  (mk-zone 53 50 4  7)  "idle")
+               (list 21 0  (mk-zone 51 9  1  1)  "sleeping"))
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (shroom-mk gave-quest? finished-quest?) (list gave-quest? 
+                                                      finished-quest?))
+(define (shroom-gave-quest? shroom) (car shroom))
+(define (shroom-quest-done? shroom) (cadr shroom))
+(define (shroom-give-quest shroom) (set-car! shroom #t))
+(define (shroom-set-quest-done! shroom) (set-car! (cdr shroom) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Shroom is a female hedge-witch, who sells reagents and potions 
+;; in Green Tower.  She was once a battle-maiden fighting for 
+;; the forces of King Clovis in the Goblin Wars.
+;;----------------------------------------------------------------------------
+
+(define shroom-merch-msgs
+  (list "Yes, I trade in mushrooms and the like. Come by my shop in the northeast corner when I'm open."
+        "I know where to find the best in the forest."
+        "If you have something worthwhile perhaps I may be interested."
+        "I have mushrooms and other reagents to trade. Would you care to buy or sell?"
+        "Be careful with those."
+        "Don't try to pick your own. Kill you, the bad ones will!"
+        "Come back when you have more to sell."
+        "Have it your way."
+        "That was a pleasant little bit of business."
+        "I see. Perhaps you'd rather just chat with an old woman."
+   ))
+
+(define shroom-catalog
+  (list
+   (list sulphorous_ash (*  2 reagent-price-mult) "I have to travel far into the hills to find these foul-smelling clods.")
+   (list garlic         (*  3 reagent-price-mult) "This comes from my own garden. The cook in Bole loves my garlic.")
+   (list ginseng        (*  3 reagent-price-mult) "The forest folk have shown me where to gather wild ginseng.")
+   (list blood_moss     (*  4 reagent-price-mult) "The rare blood moss grows on dead wood in the deep forest.")
+   (list spider_silk    (*  5 reagent-price-mult) "Spider silk is common enough, but dangerous to gather.")
+   (list nightshade     (* 10 reagent-price-mult) "I must search near the rivers of the south to find the deadly nightshade.")
+   (list mandrake       (*  8 reagent-price-mult) "The mandrake root grows wild in these woods, but few know where to find it!")
+   
+   (list t_heal_potion  20 "Most dangerous, the woods are. Take some of these in case you have an accident.")
+   (list t_mana_potion  20 "One of these will refresh me enough to cast a light spell on the way home from a long day of picking.")
+   (list t_cure_potion  20 "If you're careless enough to get poisoned this will cure you.")
+   (list t_poison_immunity_potion 20 "I always drink one of these before gathering reagents in noxious bogs.")
+   (list t_slime_vial   20 "Lazy adventurers like these, so I carry them. As if there aren't enough slimes in the world.")
+   ))
+
+;; Shroom's merchant procedure
+(define (shroom-trade knpc kpc) (conv-trade knpc kpc "trade" shroom-merch-msgs shroom-catalog))
+
+;; Shroom's mushroom quest
+(define (shroom-wards knpc kpc)
+  (let ((shroom (kobj-gob-data knpc)))
+    (if (shroom-gave-quest? shroom)
+        ;; gave quest
+        (if (shroom-quest-done? shroom)
+            ;; quest already done
+            (say knpc "I've forgotten all the others.")
+            ;; quest NOT yet done
+            (begin
+              (say knpc "Bring me the mushrooms and I will teach ye the ward "
+                   "of fire. "
+                   "Do ye remember where they are?")
+              (if (kern-conv-get-yes-no? kpc)
+                  (say knpc "Well...")
+                  (say knpc "[sigh] Perhaps ye should write this down. "
+                       "Leave town and go south to the mountains by the sea. "
+                       "There you will find the cave entrance."))))
+        (begin
+          (say knpc "In my time I knew many battle wards. "
+               "Be wanting me to teach ye, now, won't ye?")
+          (if (kern-conv-get-yes-no? kpc)
+              (begin
+                (say knpc "I know a battle ward that will render fire harmless. "
+                     "But perhaps ye can do me a favor first, yes?")
+                (if (kern-conv-get-yes-no? kpc)
+                    (begin
+                      (say knpc "In a cave to the south grows "
+                           "a purple mushroom. Bring me one. Agreed?")
+                      (if (kern-conv-get-yes-no? kpc)
+                          (begin
+                            (say knpc "Good. A colony of slimes infests that "
+                                 "cave, so take plenty of flaming oil!")
+                            (shroom-give-quest shroom))
+                          (say knpc "Yes, perhaps ye are afraid.")))
+                    (say knpc "Naught for naught, youngling!")))
+              (say knpc "Of course, a skillful warrior such as you has "
+                   "nothing to learn from an old witch like me."))))))
+                               
+(define (shroom-hail knpc kpc)
+  (let ((shroom (kobj-gob-data knpc)))
+    (display "shroom: ")
+    (display shroom)(newline)
+    (if (shroom-gave-quest? shroom)
+        ;; gave quest
+        (if (shroom-quest-done? shroom)
+            ;; quest done
+            (say knpc "Hello again, young wanderer. Come visit a bit with old "
+               "Shroom.")
+            ;; quest not done yet
+            (if (in-inventory? kpc t_royal_cape)
+                (begin
+                  ;; player has shrooms
+                  (say knpc "Ah, ye have the mushroom, as I requested!")
+                  (kern-obj-remove-from-inventory kpc t_royal_cape 1)
+                  (shroom-set-quest-done! shroom)
+                  (say knpc "Now for your reward. The ward is called "
+                       "In Flam Sanct, of the first circle. Mix royal cape, "
+                       "sulphurous ash and garlic. Cast it on yourself or a companion "
+                       "and fire will not harm!"))
+                ;; player does NOT have shrooms yet
+                (say knpc "No purple mushroom yet, I see. No rush, dear. "
+                      "But I would like it before I die.")))
+        ;; has NOT given quest yet
+        (say knpc "Hello and well met."))))
+
+(define (shroom-thie knpc kpc)
+  (say knpc "I've seen no one strange about here."))
+
+(define (shroom-roya knpc kpc)
+  (say knpc "Do you know what the royal cape mushroom is for?")
+  (if (yes? kpc)
+      (say knpc "Very rare it is, but often found with yellow slimes.")
+      (say knpc "It is used in spells which absorb effects!")))
+
+(define (shroom-band knpc kpc)
+  (say knpc "Bandits? Yes, an old woman must be careful in the woods."))
+
+(define shroom-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "Long ago I might have "
+                                                "known about that.")))
+       (method 'hail shroom-hail)
+       (method 'bye (lambda (knpc kpc) (say knpc "Toodaloo!")))
+       (method 'job (lambda (knpc kpc) (say knpc "I sell potions, reagents "
+                                            "and the like.")))
+       (method 'name (lambda (knpc kpc) (say knpc "I'm known as Shroom. At "
+                                                "your service.")))
+       (method 'cape shroom-roya)
+       (method 'roya shroom-roya)
+       (method 'shro (lambda (knpc kpc) (say knpc "Mushrooms are my "
+                                                "specialty. That's why they "
+                                                "call me Shroom.")))
+       (method 'maid (lambda (knpc) (say knpc "[she grins with crooked "
+                                           "teeth] Is it so hard to believe I "
+                                           "was once a fair war-maiden? [she "
+                                           "cackles obscenely]")))
+       (method 'mush shroom-trade)
+       (method 'buy (lambda (knpc kpc) (conv-trade knpc kpc "buy" shroom-merch-msgs shroom-catalog)))
+       (method 'trad shroom-trade)
+       (method 'sell (lambda (knpc kpc) (conv-trade knpc kpc "sell" shroom-merch-msgs shroom-catalog)))
+       (method 'reag shroom-trade)
+       (method 'poti shroom-trade)
+       (method 'join (lambda (knpc) (say knpc "You're too young for me, "
+                                         "sweetie!")))
+       (method 'gen (lambda (knpc) (say knpc "Aye, a handsome young man he "
+                                        "was, once. He could stay up all night"
+                                        " in bed! But gone a bit strange, he "
+                                        "has, befriending the goblins and all "
+                                        "that.")))
+       (method 'stra (lambda (knpc) (say knpc "He meets them in the forest "
+                                            "and runs with their hunts. "
+                                            "Half-goblin he nearly is; "
+                                            "learned their ways he has. But "
+                                            "ye could never tell him what to "
+                                            "do, the silly man.")))
+       (method 'gobl (lambda (knpc) (say knpc "I trade with them now and "
+                                            "then. Their shamans know well "
+                                            "the plants in these woods. I "
+                                            "even speak a little. Know some "
+                                            "of their magic. But I never "
+                                            "trust them.")))
+       (method 'thie shroom-thie)
+       (method 'trus (lambda (knpc) (say knpc "The goblins will turn on us "
+                                          "when their opportunity comes. I "
+                                          "would do the same in their "
+                                          "place!")))
+       (method 'wars (lambda (knpc) (say knpc "Ha! Yes, I fought the goblins. "
+                                         "Long ago that was. People forget.")))
+       (method 'ward shroom-wards)
+       (method 'band shroom-band)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-shroom tag)
+  (bind 
+   (kern-mk-char tag                 ; tag
+                 "Shroom"            ; name
+                 sp_human            ; species
+                 nil                 ; occ
+                 s_companion_druid   ; sprite
+                 faction-men         ; starting alignment
+                 1 6 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 3  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'shroom-conv        ; conv
+                 sch_shroom          ; sched
+                 'townsman-ai                 ; special ai
+                 (mk-inventory (list (list 1 t_sword)))                 ; container
+                 (list t_armor_leather)                 ; readied
+                 )
+   (shroom-mk #f #f)))
diff --git a/worlds/haxima-1.002/signs.png b/worlds/haxima-1.002/signs.png
new file mode 100644 (file)
index 0000000..274983c
Binary files /dev/null and b/worlds/haxima-1.002/signs.png differ
diff --git a/worlds/haxima-1.002/silas.scm b/worlds/haxima-1.002/silas.scm
new file mode 100644 (file)
index 0000000..0694538
--- /dev/null
@@ -0,0 +1,410 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define silas-lvl 8)
+(define silas-species sp_human)
+(define silas-occ oc_wizard)
+(define shrine-path-x 97)
+(define shrine-path-y 5)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Old Absalot
+;;----------------------------------------------------------------------------
+(define silas-bed oa-bed1)
+(define silas-mealplace oa-tbl3)
+(define silas-workplace oa-temple)
+(define silas-leisureplace oa-baths)
+(kern-mk-sched 'sch_silas
+               (list 0  0 silas-bed          "sleeping")
+               (list 7  0 silas-mealplace    "eating")
+               (list 8  0 silas-workplace    "working")
+               (list 12 0 silas-mealplace    "eating")
+               (list 13 0 silas-workplace    "working")
+               (list 18 0 silas-mealplace    "eating")
+               (list 19 0 silas-leisureplace "idle")
+               (list 22 0 silas-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (silas-mk) 
+  (list #f (mk-quest) #f))
+(define (silas-set-will-help! gob) (set-car! gob #t))
+(define (silas-will-help? gob) (car gob))
+(define (silas-quest gob) (cadr gob))
+(define (silas-met? gob) (caddr gob))
+(define (silas-set-met! gob) (set-car! (cddr gob) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Silas is the leader of the evil cult of the Accursed.
+;; He is a wizard of considerable power.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (silas-hail knpc kpc)
+  (if (silas-met? (kobj-gob-data knpc))
+      (say knpc "Hello again, Wanderer.")
+      (begin
+        (silas-set-met! (kobj-gob-data knpc))
+        (say knpc "[You meet a charming older man] Hail, traveler. "
+             "If I am not mistaken, you are a Wanderer. Am I right?")
+        (if (yes? kpc)
+            (say knpc "I knew it! I've actually been expecting you.")
+            (say knpc "[He clearly does not believe you] "
+                 "Really, you are too modest. "
+                 "I've been expecting you for some time.")))))
+
+(define (silas-default knpc kpc)
+  (say knpc "I'm afraid I cannot help you with that."))
+
+(define (silas-name knpc kpc)
+  (say knpc "Forgive me, I am Silas. And you, my friend, "
+       "need no introduction."))
+
+(define (silas-ask-help knpc kpc)
+  (cond ((yes? kpc)
+         (say knpc "I can't tell you how gratified I am to hear that. "
+              "With you on my side we will bring a new age of hope and "
+              "peace to the Shard. When you are ready to begin, "
+              "I have a quest for you.")
+         (silas-set-will-help! (kobj-gob-data knpc))
+         (make-allies knpc kpc)
+         )
+        (else
+         (say knpc "Although success is most doubtful now, "
+              "I shall have to do my best without you. "
+              "It is a pity. You know, in the past, the appearance of a "
+              "Wanderer always occurred at a pivotal moment in history. "
+              "The actions -- or inactions -- of the Wanderer sometimes "
+              "decided the fate of the world for centuries thereafter.")
+         )))
+
+(define (silas-join knpc kpc)
+  (say knpc "[Chuckling] Actually, I was hoping to convince you to join ME. "
+       "I have a most difficult job ahead of me, but with your help I know it "
+       "can be done. Will you help me?")
+  (silas-ask-help knpc kpc)
+  )
+
+(define (silas-job knpc kpc)
+  (say knpc "My goal is to bring a new golden age to the Shard. "
+       "Many obstacles lie before me, "
+       "and I greatly need someone with your talents. "
+       "Will you help me, Wanderer? I cannot do this without you.")
+  (silas-ask-help knpc kpc)
+  )
+
+(define (silas-help knpc kpc)
+  (say knpc "Will you help me in my task?")
+  (silas-ask-help knpc kpc)
+  )
+
+(define (silas-bye knpc kpc)
+  (say knpc "Farewell, Wanderer, and good fortune!"))
+
+;; Tier 2
+(define (silas-expe knpc kpc)
+  (say knpc "Yes, I have heard of your coming. "
+       "I knew that sooner or later you would appear. "
+       "I have studied the history of the Wanderers quite extensively."))
+(define (silas-hist knpc kpc)
+  (say knpc "When the library above was burnt most of the archives were lost. "
+       "I'm afraid the best record of the Wanderers is now in this feeble book. "
+       "[He taps his head]"))
+(define (silas-wand knpc kpc)
+  (say knpc "All Wanderers arrive through the Shrine Gate, as you did. But did you know there is another Gate?")
+  (if (yes? kpc)
+      (say knpc "You are well-learned already! Of course I am speaking of the Demon Gate.")
+      (say knpc "Indeed there is. It is known as the Demon Gate.")))
+
+(define (silas-demo knpc kpc)
+  (say knpc "For a long time the Demon Gate connected the Shard to other worlds. "
+       "This was a golden age of progress and enlightenment, "
+       "when Wizards from this world and others would freely mingle, "
+       "sharing knowledge and commerce.")
+  (prompt-for-key)
+  (say knpc "But eventually, trouble began to brew. "
+       "One of the other worlds began to conquer the others, "
+       "using the gate to move its armies. For fear that the Shard also would "
+       "be invaded our Wizards sealed the Demon Gate with eight locks, and divided the "
+       "keys among themselves for safe-keeping."))
+
+(define (silas-key knpc kpc)
+  (if (any-in-inventory? kpc rune-types)
+      (say knpc "The keys are special runes, like the one you already carry.")
+      (say knpc "The keys are special runes. Unfortunately, they have been lost through the ages.")))
+
+(define (silas-rune knpc kpc)
+  (say knpc "I have made it my goal to recover all of the lost runes. Even if "
+       "we choose to keep the Demon Gate locked forever, we should at least know that "
+       "the runes are all accounted for and safely guarded. Don't you agree?")
+  (if (yes? kpc)
+      (say knpc "Of course, it is merely sound policy.")
+      (say knpc "But consider if the runes were to fall into the wrong hands, "
+           "or if some day we should need to evacuate the Shard, "
+           "or if we needed to call on assistance from the other worlds? "
+           "Surely it is good to have the option of opening the Demon Gate, "
+           "even if we never intend to exercise it.")))
+
+;; Accursed, Wise
+(define (silas-accu knpc kpc)
+  (say knpc "[He chuckles] Yes, I am Accursed. Unfortunately that name has come "
+       "to be demonized by the popular imagination. All sorts of wild tales abound "
+       "regarding our supposed activities. I assure you that none of them are true. But "
+       "we cannot defend ourselves by revealing what we really do, for we are all sworn "
+       "to secrecy."))
+
+(define (silas-secr knpc kpc)
+  (say knpc "The rites of the Accursed are kept secret to protect them from "
+       "profane people, and to protect foolish people from attempting them! They are "
+       "sacred and dangerous, and not intended for the uninitiated. But I assure you, "
+       "they do not involve anything harmful to innocents!"))
+
+(define (silas-wise knpc kpc)
+  (say knpc "Ah, yes. The so-called Wise. You know, they are part of a "
+       "venerable and useful tradition. At least, it was a useful tradition in bygone "
+       "days. [Sigh] I fear that now the Wise are as often an impediment to the Shard as "
+       "they are a help. Consider this whole business with Absalot."))
+(define (silas-absa knpc kpc)
+  (say knpc "By now you are no doubt familiar with the story. The Enchanter, in "
+       "misguided jealousy of our secrets, is obsessed with eliminating the "
+       "Accursed. The Stewardess of Glasdrin is hungry for power, and dreams of a "
+       "military empire. She plans to conquer or raze the cities of the Shard one by "
+       "one, Absalot was merely the first and most convenient target. She easily "
+       "manipulated the evidence against Absalot and convinced the other cities and the "
+       "Enchanter to destroy it. The rest is history."))
+
+;; Philosophy
+(define (silas-evil knpc kpc)
+  (say knpc "What, really, is evil? Mind you, I am not saying that evil does "
+       "not exist. I simply ask you to challenge your conventional notions of what is "
+       "evil. If an authoritative figure tells us something is wrong, shall we take "
+       "them at their word? Are the authorities not people like us, with their own "
+       "agendas? Everyone acts from their own selfish motives, you know, whether or not "
+       "they admit it.")
+  (prompt-for-key)
+  (say knpc "And indeed, Wanderer, that is as it should be! All should strive "
+       "after their own interests, for that is the natural way of things. All Men are "
+       "pieces in a game they cannot avoid playing. To deny the game, to deny one's own "
+       "part in it, to accept the belief that one's own interests are not as important "
+       "as those of another, these are all deceptions propogated by one's opponents."))
+
+(define (silas-good knpc kpc)
+  (say knpc "You ask me of good, and I ask you in return, what is it that you "
+       "most desire? A thing has value only when it is desired by Men. How ironic, that "
+       "Men are taught to suppress their desires, to quench them with forbearance, as "
+       "if they were evil because they were desires, when in fact the opposite is true! "
+       "I tell you a great secret, it is the desire of certain Men that all other Men "
+       "quench their desires!"))
+
+(define (silas-desi knpc kpc)
+  (say knpc "Yes, as the spirit animates the flesh, so desire animates the "
+       "spirit. Without it the spirit is listless and void. This is the first step of "
+       "the Accursed, to acknowledge their own desires as what they are: the ultimate "
+       "good, worthy of all sacrifice and all striving."))
+
+(define (silas-sacr knpc kpc)
+  (say knpc "The doctrine of the Accursed holds that sacrifice is the ladder of "
+       "desire. Sacrifice is the inevitable outcome of choice, for not all things are "
+       "possible! To make the object of desires possible, other possibilities must be "
+       "denied. As the branch of a tree can be cut by shears, so each choice one makes "
+       "shears off an entire branch of the future. That is what we mean by sacrifice: "
+       "the pruning of the tree of possibilities."))
+
+;; People
+(define (silas-ench knpc kpc)
+  (say knpc "'Tis a pity he is such a foe to the Accursed. But I'm afraid he is "
+       "old and inflexible, and once he has decided something is evil there is no "
+       "changing his mind. Unfortunately his notions of good and evil are misguided and "
+       "unworkable."))
+
+(define (silas-deni knpc kpc)
+  (say knpc "Dennis is an earnest but frankly unimaginative young man."))
+
+(define (silas-sele knpc kpc)
+  (say knpc "Selene is a talented young woman. "
+       "Unfortunately her powers will always be inhibited by her insatiable "
+       "cruelty."))
+;; Quest-related
+(define (silas-ques knpc kpc)
+  (let* ((gob (kobj-gob-data knpc))
+        (quest (silas-quest gob)))
+
+    (define (has-all-runes?)
+      (all-in-inventory? kpc rune-types))
+
+    (define (missing-only-s-rune?)
+      (all-in-inventory? kpc
+                         (filter (lambda (ktype)
+                                   (not (eqv? ktype t_rune_s)))
+                                 rune-types)))
+
+    (define (give-last-rune)
+      (say knpc "I see you have all save 1 of the runes. Please forgive me for "
+           "a small deception, but I have hidden the last rune here in Old "
+           "Absalot. Consider it one last test for you to find it.")
+       (quest-data-update-with 'questentry-rune-s 'silasinfo 1 (quest-notify nil))
+       (quest-data-assign-once 'questentry-rune-s)
+       )
+
+    (define (continue-quest) 
+      (say knpc "I see you are still missing at least one rune. Don't give up, "
+           "Wanderer! Ask among the Wise, delve into the deeps, search far and wide."))
+
+    (define (end-quest)
+      (quest-done! quest #t)
+      (say knpc "Well done, Wanderer! You have collected all the lost runes, "
+           "a feat worthy of legend. Well done, indeed!")
+      (prompt-for-key)
+      (say knpc "Now that all the runes are recovered, it is imperative that "
+           "they be kept safe. Forgive me for being overly suspicious, but I do not trust "
+           "their keeping to the Wise, not even to the Enchanter himself.")
+      (prompt-for-key)
+      (say knpc "I know what you are thinking, my friend, but perish the thought! "
+           "I could not possibly keep them here with me. Nor do I want to. "
+           "No, I have something much more daring in mind. ")
+      (prompt-for-key)
+      (say knpc "Wanderer, the time has come to grasp the nettle. Indeed, I "
+           "sense that this is what brought you to the Shard. Take the keys, find the Gate, "
+           "and unlock it. Face what lies within. Be bold, and you will usher in a New "
+           "Age. Will you do this?")
+      (if (yes? kpc)
+          (say knpc "Then I will tell you a great secret hidden even from the "
+               "Wise: the gods yet live, as do their foes. I know not which you will face. But "
+               "this I know: their foes sealed the Gate. ")
+          (say knpc "[His shoulders slump] It was not your burden to bear, "
+               "Wanderer, for you are a stranger to this "
+               "world. Keep the keys safe, at least, if you will not change your mind.")))
+           
+    (define (offer-quest)
+      (say knpc "Wanderer, I have a most important task for you: find the eight "
+           "rune-keys which lock the Demon Gate. Will you do this?")
+      (if (yes? kpc)
+          (begin
+            (quest-accepted! quest #t)
+            (cond
+               ((has-all-runes?)
+                       (say knpc "You already have the runes?")
+                       (prompt-for-key)
+                       (end-quest)
+                       )
+               ((missing-only-s-rune?)
+                       (give-last-rune))
+               (#t
+                       (say knpc "I know I can count on you. There is a most clever man, "
+                       "an Alchemist, who lives on Oparine. Perhaps you know of him already. He would "
+                       "be a good place to start."))
+             ))
+          (say knpc "It is imperative that we find them. I am disappointed, my "
+               "friend, but no doubt you have your reasons.")))
+
+    (if (silas-will-help? gob)
+        (if (quest-done? quest)
+            (say knpc "Seek the Demon Gate!")
+            (if (quest-accepted? quest)
+                (if (has-all-runes?)
+                    (end-quest)
+                    (if (missing-only-s-rune?)
+                        (give-last-rune)
+                        (continue-quest)))
+                (offer-quest)))
+        (say knpc "Join me, and there will be quests and glory in abundance. "
+             "You will become the most famous Wanderer -- indeed, "
+             "the greatest hero of the Shard -- for all time."))
+    ))
+
+(define (pissed-off-silas knpc kpc)
+  (map (lambda (tag)
+         (if (defined? tag)
+             (let ((kchar (eval tag)))
+               (if (is-alive? kchar)
+                   (begin
+                     (kern-being-set-base-faction kchar faction-accursed)
+                     (kern-char-set-schedule kchar nil)
+                     )))))
+       (list 'ch_silas 'ch_dennis 'ch_selene))
+  (make-enemies knpc kpc)
+  )
+
+(define (silas-noss knpc kpc)
+  (say knpc "[His face freezes] How did you learn that name, friend?")
+  (kern-conv-get-reply kpc)
+  (say knpc "Have you been nosing around in other people's property?")
+  (if (yes? kpc)
+      (say knpc "How unfortunate. I'm afraid it is time for you to leave.")
+      (say knpc "I think you have. I think you have been misbehaving, "
+           "and now you are telling a fib. You are not welcome here. "
+           "Leave at once."))
+  (pissed-off-silas knpc kpc)
+  (kern-conv-end)
+  )
+
+(define silas-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default silas-default)
+       (method 'hail silas-hail)
+       (method 'bye  silas-bye)
+       (method 'job  silas-job)
+       (method 'name silas-name)
+       (method 'join silas-join)
+
+       (method 'absa silas-absa)
+       (method 'accu silas-accu)
+       (method 'demo silas-demo)
+       (method 'deni silas-deni)
+       (method 'denn silas-deni)
+       (method 'desi silas-desi)
+       (method 'ench silas-ench)
+       (method 'evil silas-evil)
+       (method 'expe silas-expe)
+       (method 'gate silas-demo)
+       (method 'good silas-good)
+       (method 'help silas-help)
+       (method 'hist silas-hist)
+       (method 'key  silas-key)
+       (method 'keys silas-key)
+       (method 'noss silas-noss)
+       (method 'ques silas-ques)
+       (method 'rune silas-rune)
+       (method 'sacr silas-sacr)
+       (method 'secr silas-secr)
+       (method 'sele silas-sele)
+       (method 'task silas-job)
+       (method 'wand silas-wand)
+       (method 'wise silas-wise)
+       ))
+
+(define (mk-silas)
+  (bind 
+   (kern-mk-char 
+    'ch_silas           ; tag
+    "Silas"             ; name
+    silas-species         ; species
+    silas-occ              ; occ
+    s_silas     ; sprite
+    faction-men      ; starting alignment
+    0 5 0            ; str/int/dex
+    2 1              ; hp mod/mult
+    2 1              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+       0
+    silas-lvl
+    #f               ; dead
+    'silas-conv         ; conv
+    sch_silas           ; sched
+    'spell-sword-ai  ; special ai
+    nil              ; container
+    (list t_stun_wand) ; readied
+    )
+   (silas-mk)))
diff --git a/worlds/haxima-1.002/skills.scm b/worlds/haxima-1.002/skills.scm
new file mode 100644 (file)
index 0000000..ef9c7ae
--- /dev/null
@@ -0,0 +1,279 @@
+;;----------------------------------------------------------------------------
+;; Skill procedures
+;;
+;; Skill procedures should not do any requirements-checking because the kernel
+;; checks all requirements before allowing them to be called. Skill procedures
+;; should always return (ie, evaluate to) one of the standard result-* codes
+;; (eg, result-ok, result-no-target, etc... see naz.scm).
+
+(define (skill-jump kactor)
+  (define (range)
+    (let ((x (* (occ-ability-stracro kactor) (kern-obj-get-ap kactor))))
+      (cond ((> x 1000) 4) ;; inconceivable!
+            ((> x 500) 3)
+            ((> x 150) 2)
+            (else 0))))
+  (if (has-effect? kactor ef_fatigue)
+      result-not-now
+      (cast-ui-ranged-loc powers-jump
+                          kactor
+                          (range)
+                          0)))
+
+(define (skill-sprint kactor)
+  (if (has-effect? kactor ef_fatigue)
+      result-not-now
+      (let* ((origin (kern-obj-get-location kactor))
+             (kplace (loc-place origin))
+             (sprint-max-range (+ 2 (occ-ability-stracro kactor)))
+             (sprint-max-cost (* sprint-max-range (kern-obj-get-ap kactor)))
+             )
+        (define (too-far? origin dest)
+          (let ((path (line (loc-x origin) (loc-y origin) 
+                            (loc-x dest) (loc-y dest))))
+            (let ((cost (foldr (lambda (d xy)
+                                 (+ d 
+                                    (kern-place-get-movement-cost (mk-loc kplace
+                                                                          (car xy) 
+                                                                          (cdr xy)) 
+                                                                  kactor)
+                                    ))
+                               0
+                               path)))
+              (> cost sprint-max-cost))))
+        (define (checkloc x y)
+          (let ((dest (mk-loc kplace x y)))
+            (and (kern-place-is-passable dest kactor)
+                 (not (occupied? dest))
+                 (kern-in-los? origin dest)
+                 (not (too-far? origin dest))
+                 )))
+        (cast-ui-template-loc powers-sprint
+                              kactor
+                              (kern-mk-templ origin sprint-max-range 'checkloc)
+                              0))))
+
+(define (skill-wriggle kactor)
+  ;; fixme: use smart target that only suggests viable locations?
+  (cast-ui-ranged-loc powers-wriggle kactor 1 0))
+
+(define (check-wriggle kactor)
+  (cond ((null? (kern-char-get-arms kactor)) #t)
+        (else
+         (kern-log-msg "Must unready arms!")
+         #f
+         )))
+      
+
+(load "disarm-trap.scm")
+  
+(define (skill-stealth kactor)
+  (kern-obj-add-effect kactor ef_stealth nil)
+  result-ok)
+
+(define (skill-butcher kactor)
+  (cast-ui-ranged-any powers-butcher
+                      kactor 1 (occ-ability-crafting kactor)
+                      (mk-ifc-query 'butcher)))
+
+(define (skill-pickpocket kactor)
+  (cast-ui-basic-ranged-spell powers-pickpocket 
+                              kactor 
+                              1 
+                              (occ-ability-thief kactor)
+                              ))
+
+;;----------------------------------------------------------------------------
+;; Skill declarations
+;;
+;; (kern-mk-skill <tag>
+;;                <name>
+;;                <description>
+;;                <ap-consumed>
+;;                <mp-consumed>
+;;                <can-use-in-wilderness?>
+;;                <is-passive?>
+;;                <yusage-proc>
+;;                <yusage-special-check-proc>
+;;                <list-of-required-tools>
+;;                <list-of-required-consumables>)
+
+(define (mk-skill name description ap-cost mp-cost use-in-wilderness
+                  is-passive yusage-proc yusage-special-check-proc list-of-required-tools list-of-required-consumables)
+  (kern-mk-skill name description ap-cost mp-cost use-in-wilderness
+                 is-passive yusage-proc yusage-special-check-proc list-of-required-tools list-of-required-consumables))
+                                       
+
+(define sk_jump
+  (mk-skill "Jump" "Jump over impassable terrain"
+            0
+            0 
+            #f
+            #f
+           'skill-jump
+            nil
+            nil
+            nil
+            ))
+
+(define sk_arm_trap
+  (mk-skill "Arm Trap" "Allows character to use beartraps and caltrops"
+            0
+            0
+            #f
+            #t
+            nil
+            nil
+            nil
+            nil
+            ))
+
+(define sk_sprint
+  (mk-skill "Sprint" "Move quickly, in a straight line, for a short distance"
+            0
+            0
+            #f
+            #f
+            'skill-sprint
+            nil
+            nil
+            nil
+            nil
+            ))
+
+(define sk_wriggle
+  (mk-skill "Wriggle" "Squeeze through tight spots"
+            base-move-ap   ;; ap
+            0              ;; mp
+            #f             ;; wilderness?
+            #f             ;; passive?
+            'skill-wriggle ;; yusage 
+            'check-wriggle ;; yusage check
+            nil            ;; tools
+            (list (list t_grease 1)) ;; material
+            ))
+
+(define sk_disarm_trap
+  ;; fixme: should some special tools be required?
+  (mk-skill "Disarm Trap" "Disarm a trap on a door or chest"
+            0              ;; ap
+            0              ;; mp
+            #f             ;; wilderness?
+            #f             ;; passive?
+            'skill-disarm-trap ;; yusage 
+            nil            ;; yusage check
+            nil            ;; tools
+            nil            ;; material
+            ))
+
+(define sk_stealth
+  (mk-skill "Stealth" "Avoid detection"
+            base-move-ap   ;; ap
+            0              ;; mp
+            #f             ;; wilderness?
+            #f             ;; passive?
+            'skill-stealth ;; yusage 
+            nil            ;; yusage check
+            nil            ;; tools
+            nil            ;; material
+            ))
+
+(define sk_reach
+  (mk-skill "Reach" "Handle objects more than one tile away"
+            base-move-ap   ;; ap
+            0              ;; mp
+            #f             ;; wilderness?
+            #t             ;; passive?
+            nil            ;; yusage 
+            nil            ;; yusage check
+            nil            ;; tools
+            nil            ;; material
+            ))
+
+(define sk_butcher
+  (mk-skill "Butcher" "Turn an animal corpse into food or materials"
+            0              ;; ap
+            0              ;; mp
+            #f             ;; wilderness?
+            #f             ;; passive?
+            'skill-butcher ;; yusage 
+            nil            ;; yusage check
+            nil            ;; tools (fixme: add knife)
+            nil            ;; material
+            ))
+
+(define sk_pickpocket
+  (mk-skill "Pickpocket" "Take something from an NPC"
+            base-move-ap   ;; ap
+            0              ;; mp
+            #f             ;; wilderness?
+            #f             ;; passive?
+            'skill-pickpocket ;; yusage 
+            nil            ;; yusage check
+            nil            ;; tools
+            nil            ;; material
+            ))
+
+(define sk_unlock
+  (mk-skill "Unlock" "Unlock a door with a picklock"
+            0
+            0
+            #f
+            #t ;; passive
+            'skill-unlock
+            nil
+            (list t_picklock)
+            nil
+            ))
+
+;;----------------------------------------------------------------------------
+;; Skill Set declarations
+;;
+;; The number preceeding the skill name is the minimum level needed to use the
+;; skill.
+
+(define sks_warrior
+  (kern-mk-skill-set "Warrior" (list
+                                (list 1 sk_sprint)
+                                (list 2 sk_jump)
+                                )))
+
+(define sks_ranger
+  (kern-mk-skill-set "Ranger" (list
+                                (list 1 sk_sprint)
+                                (list 2 sk_jump)
+                                (list 3 sk_arm_trap)
+                                (list 5 sk_stealth)
+                                )))
+
+(define sks_wrogue
+  (kern-mk-skill-set "Wrogue" (list 
+                               (list 1 sk_sprint)
+                               (list 1 sk_arm_trap)
+                               (list 2 sk_unlock)
+                               (list 2 sk_disarm_trap)
+                               (list 3 sk_jump)
+                               (list 3 sk_wriggle)
+                               (list 4 sk_reach)
+                               (list 4 sk_pickpocket)
+                               (list 5 sk_stealth)
+                               )))
+
+(define sks_wright
+  (kern-mk-skill-set "Wright" (list 
+                               (list 1 sk_arm_trap)
+                               (list 2 sk_unlock)
+                               (list 3 sk_disarm_trap)
+                               )))
+
+(define sks_wanderer 
+  (kern-mk-skill-set "Wanderer" (list 
+                               (list 2 sk_sprint)
+                               (list 3 sk_jump)
+                               (list 3 sk_unlock)
+                               (list 4 sk_arm_trap)
+                               (list 4 sk_disarm_trap)
+                               (list 5 sk_reach)
+                               (list 5 sk_pickpocket)
+                               (list 6 sk_stealth)
+                               )))
diff --git a/worlds/haxima-1.002/slimy-cavern-zones.scm b/worlds/haxima-1.002/slimy-cavern-zones.scm
new file mode 100644 (file)
index 0000000..a4830d4
--- /dev/null
@@ -0,0 +1,8 @@
+;;----------------------------------------------------------------------------
+;; Zones for Slimey Cavern
+;;
+;; Zones are rectangles for a particular place. They're used by NPC schedules,
+;; AI and conversation scripts.
+;;----------------------------------------------------------------------------
+(define slimey-cavern-prison-cell      (mk-rect 12  1   3   2))
+(define slimey-cavern-prison-cell-exit (mk-rect 13  4   1   1))
diff --git a/worlds/haxima-1.002/slimy-cavern.scm b/worlds/haxima-1.002/slimy-cavern.scm
new file mode 100644 (file)
index 0000000..9e19f44
--- /dev/null
@@ -0,0 +1,130 @@
+;;----------------------------------------------------------------------------
+;; Slimy Cavern
+;;
+;;  Wherein the player fights some slimes, some bandits, and optionally rescues
+;;  Roland.
+;;----------------------------------------------------------------------------
+
+(kern-load "slimy-cavern-zones.scm")
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "roland.scm")
+
+;; ----------------------------------------------------------------------------
+;; Map
+;; ----------------------------------------------------------------------------
+(kern-mk-map 
+ 'm_slimy_cavern 16 32 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn r8 r8 r8 rn "
+               "rn rn rn rn rn r8 r8 r8 r8 r8 rn r4 .. .. .. r2 "
+               "rn rn rn rn rc .. .. && .. .. ra r4 .. .. .. r2 "
+               "rn r8 r8 rc bb .. .. .. .. .. bb rr rr .. r3 rn "
+               "r4 bb .. .. bb .. .. .. .. .. bb .. .. .. ra rn "
+               "r4 bb .. .. .. bb bb .. bb bb .. .. .. .. .. r2 "
+               "r4 .. .. .. .. .. .. .. .. .. .. .. .. .. .. r2 "
+               "r4 bb .. .. .. .. .. .. .. .. .. .. .. .. r3 rn "
+               "rn r5 bb .. .. .. .. .. .. .. .. .. r3 r9 r8 rn "
+               "rn r8 rd .. .. .. .. .. .. .. .. .. r6 .. .. r2 "
+               "r4 .. .. .. .. .. .. r3 r5 .. .. r3 r4 .. .. r2 "
+               "r4 .. r7 .. rf bb r3 r8 r8 r5 .. r2 r4 .. r3 rn "
+               "rc %7 re .. .. .. r6 .. .. re .. ra rc .. r2 rn "
+               "~~ b~ b~ rf .. .. r6 .. .. .. .. .. .. .. r2 rn "
+               "r5 ~a b~ ~4 .. .. ra r5 .. r3 r5 .. r3 r1 rn rn "
+               "rn rd %a ~a ~9 ~1 b~ ra r1 rn rc .. ra rn rn rn "
+               "r4 .. .. .. .. ~a b~ b~ ra rc .. .. .. r2 rn rn "
+               "r4 .. r7 .. %f r7 b~ ~~ bb %7 .. .. .. ra rn rn "
+               "r4 .. r2 r1 r1 r8 rd b~ ~~ ~5 %5 .. .. %7 ra rn "
+               "r4 .. ra r8 r4 .. .. rf %% ~a b~ ~9 b~ ~1 ~5 ra "
+               "r4 .. .. .. r6 .. %b %% %% %% %c .. %% b~ ~8 ~~ "
+               "rn r1 r5 .. r6 .. .. r3 r5 .. .. .. %e rb r9 r1 "
+               "rn rn rc .. ra r1 r1 r8 rc .. .. .. .. .. bb r2 "
+               "rn rc .. .. .. ra rc .. .. .. r7 .. .. .. .. r2 "
+               "r4 .. .. .. .. .. .. .. r3 r1 r4 .. .. .. .. r2 "
+               "r4 .. .. .. .. r3 r1 r9 r8 r8 rn r5 .. .. r3 rn "
+               "rn r5 .. .. r3 rn rc .. .. .. ra rn r5 .. r2 rn "
+               "rn r8 rd .. ra rc .. .. .. .. .. ra rc .. ra rn "
+               "r4 .. .. .. .. .. .. .. .. .. .. .. .. .. .. r2 "
+               "r4 .. r3 r1 r1 r5 .. .. .. .. .. r7 .. rf .. r2 "
+               "r4 .. r2 rn rn rn r5 .. .. .. r3 r4 .. .. .. r2 "
+               "rn r1 rn rn rn rn rn r1 r1 r1 rn rn r1 r1 r1 rn "
+       )
+ )
+
+;;----------------------------------------------------------------------------
+;; Special Objects
+;;----------------------------------------------------------------------------
+(define rolands-chest
+  (mk-chest
+   nil ;; trap
+   '(
+    ;; Food
+    (2 t_food)
+
+    ;; Arms
+    (1 t_2H_sword)
+    (1 t_armor_chain)
+    (1 t_iron_helm)
+
+    ;; Hints/instructions
+    )))
+
+(define (mk-green-slime-verbose msg)
+  (kern-log-msg msg)
+  (mk-npc 'green-slime 3))
+  
+
+(kern-mk-place 'p_slimy_cavern    ; tag
+               "Slimy Cavern"     ; name
+               nil                ; sprite
+               m_slimy_cavern     ; map
+               #f                 ; wraps
+               #t                 ; underground
+               #f                 ; large-scale (wilderness)
+               #f                 ; tmp combat place
+               nil                ; subplaces
+               nil                ; neighbors
+
+               ;; objects
+               (list
+                (put (mk-monman) 0 0)
+
+                ;; loot and loose-lying objects
+                (list rolands-chest 9 2)
+                (put (mk-corpse-with-loot) 12 21)
+
+                ;; Trapped chest with some reasonably nice thiefly items
+                (put (mk-chest 'poison-trap
+                               '((1 t_in_ex_por_scroll)
+                                 (1 t_wis_quas_scroll)
+                                 (3 t_gem)
+                                 (5 t_picklock)
+                                 (50 t_gold_coins)
+                                 ))
+                     5 2)
+
+                ;; terrain features
+                (list (mk-ladder-up 'p_shard 13 8) 8 30)
+                (list (mk-bridge 'north) 4 15)
+                (list (mk-bridge 'north) 11 19)                
+
+                ;; doors/mechanisms
+                (list (mk-door-full 'windowed-wood-door-in-rock #t #f nil) 13 3)
+
+                ;; existing npc's
+                (put (mk-npc 'blackguard 2) 5 4)
+                (put (mk-npc 'blackguard 2) 9 4)
+                (put (mk-npc 'blackguard 2) 9 2)
+                (put (spawn-pt 'green-slime) 9 17)
+                (put (spawn-pt 'green-slime) 10 18)
+                (put (spawn-pt 'green-slime) 13 18)
+                (put (mk-roland) 14 1)
+
+                )
+               (list 'on-entry-to-dungeon-room) ; hooks
+               nil ; edge entrances
+               )
+
+(mk-place-music p_slimy_cavern 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/slywan.scm b/worlds/haxima-1.002/slywan.scm
new file mode 100644 (file)
index 0000000..c496d24
--- /dev/null
@@ -0,0 +1,137 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define slywan-lvl 2)
+(define slywan-species sp_human)
+(define slywan-occ oc_wrogue)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the monster town of Kun.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_slywan
+               (list 0 0 kun-road "working")
+               (list 2 0 campfire-2 "sleeping")
+               (list 9 0 cantina-9 "idle")
+               (list 14 0 black-market "idle")
+               (list 17 0 cantina-9 "idle")
+               (list 23 0 kun-road "working")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (slywan-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Slywan is a thief (an accomplished pickpocket) 
+;; living in the monster village of Kun.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (slywan-hail knpc kpc)
+  (kern-log-msg "You meet a lithe man.")
+  (say knpc "G'day")
+  )
+
+(define (slywan-default knpc kpc)
+  (say knpc "[He shrugs and smiles wanly]")
+  )
+
+(define (slywan-name knpc kpc)
+  (say knpc "Slywan, at your service")
+  )
+
+(define (slywan-join knpc kpc)
+  (say knpc "Sorry, mate")
+  )
+
+(define (slywan-job knpc kpc)
+  (say knpc "This and that. You know.")
+  )
+
+(define (slywan-bye knpc kpc)
+  (let ((q (min (kern-player-get-gold)
+                (kern-dice-roll "1d20"))))
+    (take-player-gold q)
+    (kern-obj-add-to-inventory knpc t_gold_coins q)
+    (say knpc "Seeya")
+    ))
+
+(define (slywan-this knpc kpc)
+  (say knpc "And that"))
+
+(define (slywan-that knpc kpc)
+  (say knpc "And this"))
+
+(define (slywan-bust knpc kpc)
+  (say knpc "Oops! Gotta go!")
+  (kern-obj-add-effect knpc ef_invisibility nil)
+  (kern-char-set-fleeing knpc #t)
+  (kern-being-set-current-faction knpc faction-outlaw)
+  (kern-conv-end)
+  )
+
+(define (slywan-thie knpc kpc)
+  (say knpc "What? Did somebody steal from gold from you?")
+  (if (yes? kpc)
+      (begin
+        (say knpc "Surely you're not accusing me?")
+        (if (yes? kpc)
+            (slywan-bust knpc kpc)
+            (say knpc "Oh... heh. Of course not. Sorry, I didn't see anything.")))
+      (say knpc "You're lucky, this is a rough town. Don't trust anybody!")))
+
+(define slywan-conv
+  (ifc nil
+
+       ;; basics
+       (method 'default slywan-default)
+       (method 'hail slywan-hail)
+       (method 'bye  slywan-bye)
+       (method 'job  slywan-job)
+       (method 'name slywan-name)
+       (method 'join slywan-join)
+
+       (method 'this slywan-this)
+       (method 'that slywan-that)
+       (method 'bust slywan-bust)
+       (method 'thie slywan-thie)
+       (method 'gold slywan-thie)
+       (method 'stol slywan-thie)
+       ))
+
+(define (mk-slywan)
+  (bind 
+   (kern-char-force-drop
+   (kern-mk-char 
+    'ch_slywan           ; tag
+    "Slywan"             ; name
+    slywan-species         ; species
+    slywan-occ              ; occ
+    s_brigand     ; sprite
+    faction-men      ; starting alignment
+    1 0 4            ; str/int/dex
+    0  ; hp bonus
+    0 ; hp per-level bonus
+    0 ; mp off
+    1 ; mp gain
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0
+    slywan-lvl
+    #f               ; dead
+    'slywan-conv         ; conv
+    sch_slywan           ; sched
+    'townsman-ai              ; special ai
+    (mk-inventory nil) ;; container
+    (list t_sword
+                                                t_armor_leather
+                                                )               ; readied
+    )
+   #t)
+   (slywan-mk)))
diff --git a/worlds/haxima-1.002/sounds.scm b/worlds/haxima-1.002/sounds.scm
new file mode 100644 (file)
index 0000000..94ac93b
--- /dev/null
@@ -0,0 +1,181 @@
+
+(kern-mk-sound 'sound-damage         "damage.wav")
+(kern-mk-sound 'sound-walking        "walk.wav")
+;(kern-mk-sound 'sound-splashing      "rowing.wav")
+(kern-mk-sound 'sound-splashing      "water2.wav")
+(kern-mk-sound 'sound-squishing      "walk.wav") ;; fixme
+(kern-mk-sound 'sound-moongate-enter "enter_moongate.wav")
+(kern-mk-sound 'sound-cannon-fire    "cannon.wav")
+(kern-mk-sound 'sound-clock          "ticktock.wav")
+(kern-mk-sound 'sound-clock-chime    "gong.wav")
+(kern-mk-sound 'sound-river          "river.wav")
+(kern-mk-sound 'sound-wind          "wind_1a.wav")
+(kern-mk-sound 'sound-missile          "swish.wav")
+(kern-mk-sound 'sound-explode          "boom.wav")
+(kern-mk-sound 'sound-lightning        "lightning.wav")
+(kern-mk-sound 'sound-fireblast       "fireblast.wav")
+
+;; Aliases
+(define sound-ship-move sound-splashing)
+
+;; ambient sound 'object'
+
+(define ambience-ifc
+    (ifc '()
+         (method 'exec
+                 (lambda (ksound)
+                   (kern-sound-play-ambient (eval (gob ksound)) (kern-obj-get-location ksound))
+                   ))
+         (method 'on-entry
+                 (lambda (ksound)
+                   (kern-sound-play-ambient (eval (gob ksound)) (kern-obj-get-location ksound))
+                   ))
+         ))
+
+(mk-obj-type 't_ambience nil
+             '()
+             layer-mechanism ambience-ifc)
+
+(define (mk-ambient-sound soundtag)
+  (let ((ksound (kern-mk-obj t_ambience 1)))
+    (bind ksound soundtag)
+    ksound))
+
+;;==========================================================================
+;; music
+
+(define default-music "music/ballad.ogg")
+
+(define (music-list . entries)
+       (if (null? entries)
+               (list default-music)
+               entries
+       )
+)
+
+(load "music/music.scm")
+
+(println ml-battle-music)
+
+(define music (list nil nil))
+
+(define (music-play-track file)
+       (set-car! music file)
+       (kern-music-play file)
+)
+
+(define (music-handler filelist)
+       (set-car! (cdr music) filelist)
+       (if (or (null? (car music))
+                               (not (in-text-list? (car music) filelist)))
+               (music-play-track (random-select (cadr music)))
+       ))
+               
+(define (music-cue filelist)
+       (set-car! (cdr music) filelist)
+       )
+       
+(define (music-cue-ref listref)
+       (let ((cuelist (safe-eval listref)))
+               (if (not (null? cuelist))
+                       (music-cue cuelist))
+       ))
+       
+(define (music-fake-current)
+       (if (not (null? (cadr music)))
+                       (set-car! music (car (cadr music)))
+               ))
+               
+(music-handler (list default-music))
+
+(define (music-change-handler player)
+       (if (not (null? (cadr music)))
+                       (music-play-track (random-select (cadr music)))
+               )
+       )
+       
+(kern-add-hook 'music_change_hook 'music-change-handler)
+       
+;;combo play + cue, with sensible eval and null behaviour
+(define (music-set-pair immediate therafter)
+       (let* ((imm (safe-eval immediate))
+                       (ther (safe-eval therafter))
+                       (cuelist (if (null? imm)
+                                                               nil
+                                                               ther))
+                       (playlist (if (null? imm)
+                                                               ther
+                                                               imm))
+                       )
+               (if (not (null? playlist))
+                       (music-handler playlist))
+               (if (not (null? cuelist))
+                       (music-cue cuelist))
+       ))
+
+
+;;==================================================================================
+;; interactive music handler
+
+(mk-obj-type 't_sounddata nil nil layer-none nil)
+
+;; use kern-set-combat-state-listener to call this
+;; do it on system startup too (kern-set-gamestart-hook)
+(define (music-on-combat-change player)
+  (let ((playerloc (player-member-loc)))
+    (if (notnull? playerloc)
+        (let ((dataslist (kplace-get-objects-of-type playerloc t_sounddata)))
+          (if (notnull? dataslist)
+              (let* ((sounddata (gob (car dataslist)))
+                     (oldstate (car sounddata))
+                     (newstate (null? (all-hostiles (car (kern-party-get-members player)))))
+                     )
+                (set-car! sounddata newstate)
+                (if newstate
+                    (if oldstate
+                        (music-set-pair nil (list-ref sounddata 1))
+                        (music-set-pair (list-ref sounddata 4) (list-ref sounddata 1))
+                        )
+                    (if oldstate
+                        (music-set-pair (list-ref sounddata 2) (list-ref sounddata 3))
+                        (music-set-pair nil (list-ref sounddata 3))
+                        )
+                    )
+                ))
+          ))))
+    
+;; use place entry hooks to call this
+(define (music-on-combat-entry playerloc player)
+       (let ((dataslist (kplace-get-objects-of-type playerloc t_sounddata)))
+               (if (not (null? dataslist))
+                       (let ((sounddata (gob (car dataslist)))
+                                       (newstate (null? (all-hostiles (car (kern-party-get-members player)))))
+                                       )
+                               (set-car! sounddata newstate)
+                               (if newstate
+                                       (music-set-pair nil (list-ref sounddata 1))
+                                       (music-set-pair (list-ref sounddata 2) (list-ref sounddata 3))
+                               )               
+                               (music-fake-current)            
+                       ))
+       ))              
+
+;; use this to make data object
+(define (mk-sounddata normal engagement combat victory)
+       (bind (kern-obj-set-visible (kern-mk-obj t_sounddata 1) #f)
+               (list #t normal engagement combat victory)
+       ))
+       
+;;normal combat music entries
+(define (mk-basic-musicdata noncombatml)
+       (mk-sounddata noncombatml 'ml-battle-intro 'ml-battle-music 'ml-battle-over))
+       
+;;world music entries dont use combat stuff
+(define (mk-world-musicdata noncombatml)
+       (mk-sounddata noncombatml nil noncombatml nil))
+       
+;; do-it-all method- adds an object and the hook to a place
+(define (mk-place-music place noncombatml)
+       (kern-obj-put-at (mk-basic-musicdata noncombatml) (list place 0 0))
+       (kern-place-add-on-entry-hook place 'music-on-combat-entry))
+       
diff --git a/worlds/haxima-1.002/special.png b/worlds/haxima-1.002/special.png
new file mode 100644 (file)
index 0000000..88753c8
Binary files /dev/null and b/worlds/haxima-1.002/special.png differ
diff --git a/worlds/haxima-1.002/special.scm b/worlds/haxima-1.002/special.scm
new file mode 100644 (file)
index 0000000..dec95ad
--- /dev/null
@@ -0,0 +1,127 @@
+;;----------------------------------------------------------------------------
+;; Special -- one-off stuff that needs to be kern-loaded and doesn't really fit
+;; anywhere else.
+;;----------------------------------------------------------------------------
+
+(kern-mk-sprite-set 'ss_special 32 32 3 3 0 0 "special.png")
+
+(kern-mk-sprite 's_gold_skull ss_special 1 0 #f 0)
+(kern-mk-sprite 's_power_core ss_special 1 1 #f 0)
+
+;;----------------------------------------------------------------------------
+;; Bandit-Hideout generator -- 
+;; procedure invoked by a step trigger to place the bandit hideout on the world map.
+;; Should return true iff it triggers to remove the step generator that invokes it.
+;;----------------------------------------------------------------------------
+(define bandit-hideout-loc (list 'p_shard 72 63))
+(define (mk-bandit-hideout kbeing)
+  (if (eqv? kbeing 
+            (kern-get-player))
+      (begin
+        (kern-log-msg "You stumble upon a hidden forest glade.\nKnavish figures skulk about with drawn blades!")
+        (kern-place-set-subplace p_bandit_hideout_l1
+                                 (eval-loc bandit-hideout-loc))
+        (kern-map-set-dirty)
+        #t)
+      #f))
+
+
+;;----------------------------------------------------------------------------
+;; Angriss Lair generator -- procedure invoked by a step trigger to create
+;; Angriss's Lair. Should return true iff it triggers to remove the step
+;; generator that invokes it.
+;;----------------------------------------------------------------------------
+(define angriss-lair-loc (list 'p_shard 88 69))
+(define (mk-angriss-lair kbeing)
+  (if (eqv? kbeing 
+            (kern-get-player))
+      (begin
+        (kern-log-msg "The forest grows wild...\nThe trees here are choked with webbing, and horrid wrapped HUSKS dangle.\nYou have found the entrance to Angriss's Lair!")
+        (kern-place-set-subplace p_angriss_lair 
+                                 (eval-loc angriss-lair-loc))
+        (kern-map-set-dirty)
+        #t)
+      #f))
+
+
+;;----------------------------------------------------------------------------
+;; Mans-Hideout generator -- 
+;; procedure invoked by a step trigger to place the MAN's hideout on the world map.
+;; Should return true iff it triggers to remove the step generator that invokes it.
+;;----------------------------------------------------------------------------
+(define the-mans-hideout-loc (list 'p_shard 92 10))
+(define (mk-mans-hideout kbeing)
+  (if (eqv? kbeing 
+            (kern-get-player))
+      (begin
+        (kern-log-msg "You find a hidden entrance to a secure, undisclosed location!")
+        (kern-place-set-subplace p_mans_hideout
+                                 (eval-loc the-mans-hideout-loc))
+        (kern-map-set-dirty)
+        #t)
+      #f))
+
+
+;;----------------------------------------------------------------------------
+;; Brundegardt generator -- 
+;; procedure invoked by a step trigger to place Brundegardt on the world map.
+;; Should return true iff it triggers to remove the step generator that invokes it.
+;;----------------------------------------------------------------------------
+(define brundegardt-loc (list 'p_shard 76 40))
+(define (mk-brundegardt kbeing)
+  (if (eqv? kbeing 
+            (kern-get-player))
+      (begin
+        (kern-log-msg "Through a hidden track, you find a strange forested nook in the mountainside!")
+        (kern-place-set-subplace p_brundegardt
+                                 (eval-loc brundegardt-loc))
+        (kern-map-set-dirty)
+        #t)
+      #f))
+
+
+;; ----------------------------------------------------------------------------
+;; The Warritrix's note
+;; ----------------------------------------------------------------------------
+(mk-reusable-item 
+ 't_warritrix_orders "Military Orders" s_lexicon norm
+ (lambda (klexicon kuser)
+   (kern-ui-page-text
+   "Orders to the Warritrix"
+   "Ever faithful servant of Glasdrin,"
+   "we suspect a coven of the Accursed are hiding"
+   "in the deeps of the Lost Halls. Proceed at"
+   "once to investigate. Leave no cavern"
+   "unexplored.\n"
+   "--Commander Jeffries\n"
+   "P.S. These orders are to be destroyed."
+   )))
+
+
+;; Kraken lakes kraken trigger
+(define (spawn-kraken-lakes-sea-serpent kbeing)
+  (kern-log-msg "Your disturb something in the water...")
+  (kern-obj-put-at (spawn-npc 'kraken 8) (mk-loc p_deepness 31 34))
+  (kern-obj-put-at (spawn-npc 'kraken 8) (mk-loc p_deepness 32 35))
+  (kern-obj-put-at (spawn-npc 'kraken 8) (mk-loc p_deepness 30 29))
+  #t)
+
+;; Locations referred to more than once
+(define lost-halls-loc (list 'p_shard 39 75))
+
+;; Power core for voidship
+(mk-quest-obj-type 't_power_core "ancient power core" s_power_core layer-item obj-ifc)
+
+;; Luximene begins the game as a Lich King, when defeated he drops his skull,
+;; which can be used with the Necromancer to summon his shade.
+(mk-quest-obj-type 't_lich_skull "King Luximenes skull" s_gold_skull layer-item obj-ifc)
+
+;; grow -- trigger hook fx to create items (eg, growing reagents, hence the name)
+(define (grow-trig ktrig ktype-tag dice)
+  (println "grow-trig")
+  (println "  ktrig=" ktrig)
+  (println "  ktype-tag=" ktype-tag)
+  (println "  dice=" dice)
+  (kern-obj-put-at (kern-mk-obj (eval ktype-tag) (kern-dice-roll 
+                                       dice))
+                   (kern-obj-get-location ktrig)))
diff --git a/worlds/haxima-1.002/species.scm b/worlds/haxima-1.002/species.scm
new file mode 100644 (file)
index 0000000..ac86b53
--- /dev/null
@@ -0,0 +1,192 @@
+;;----------------------------------------------------------------------------
+;; Morphologies
+;;
+;; Slots should be listed in desired paper-doll rendering order, bottom layer
+;; to top.
+(define humanoid
+  (list 
+   slot-armor
+   slot-boot
+   slot-helm
+   slot-amulet
+   slot-ring
+   slot-ring
+   slot-weapon-or-shield
+   slot-weapon-or-shield
+   ))
+
+(define giant
+  (list
+   slot-armor
+   slot-boot
+   slot-helm
+   slot-helm
+   slot-amulet
+   slot-amulet
+   slot-ring
+   slot-ring
+   slot-weapon-or-shield
+   slot-weapon-or-shield
+   slot-weapon-or-shield
+   slot-weapon-or-shield
+   ))
+
+;;----------------------------------------------------------------------------
+;; species
+
+(define (rel-spd speed)
+       (/ (* speed-human speed) 100))
+
+;; mk-species -- register a species type with the kernel
+(define (mk-species tag name str int dex spd con mag vr mmode weap morph xp sspr armordice mvsnd)
+  (kern-mk-species tag name str int dex (rel-spd spd) vr mmode 
+                   con 
+                   (max (round (/ con 10)) 1)
+                   mag 
+                   (max (round (/ mag 2)) 1)
+                   sspr
+                   weap #t sound-damage 
+                   mvsnd
+                   xp
+                   #f ;; stationary?
+                   armordice
+                   morph nil)) 
+
+(define (mk-stationary-species tag name str int dex spd con mag vr mmode weap morph xp sspr armordice)
+  (kern-mk-species tag name str int dex (rel-spd spd) vr mmode 
+                   con 
+                   (max (round (/ con 10)) 1)
+                   mag 
+                   (max (round (/ mag 2)) 1)
+                   sspr
+                   weap #t sound-damage 
+                   nil
+                   xp 
+                   #t ;; stationary?
+                   armordice
+                   morph nil)) 
+
+;; Note: SF Bug# [ 1523228 ] "AI not moving to attack" was almost certainly
+;; caused by the limited vision radius of most species not reaching across the
+;; 19x19 combat map. This is intentional, I think the player should have the
+;; opportunity to escape some NPC's or sneak up on others because the foe's
+;; vision is handicapped. However, this is not the situation for sea battles,
+;; where most player character's won't be able to close with distant sea
+;; critters. So make all sea creatures have at least 19 vision radius, but
+;; leave the rest as-is.
+
+;; st = strength, in = intelligence, dx = dexterity (10 is human average)
+;; spd = AP per turn (speed-human is a common value) 
+;; bHP = basis for max HP   (max HP = bHP + level * bHP/10)
+;; bMP = basis for max Mana (max MP = bMP + level * bMP/10)
+;; vr = vision radius (0..19)
+;;          tag                 name             st in dx   spd bHP bMP  vr mmode           weap         morph    xp sspr               armrdc  mvsnd
+(mk-species 'sp_balron          "balron"         50 50 50   100  50  10  13 mmode-fly       t_horns      giant    50 s_asleep           nil     sound-walking   )
+(mk-species 'sp_bull            "bull"           20  1  5   100  20   0   6 mmode-walk      t_horns      nil       2 s_bull             nil     sound-walking   )
+(mk-species 'sp_cave_goblin     "cave goblin"    12  8 12   100  12   2  14 mmode-walk      t_hands      humanoid  2 s_asleep           nil     sound-walking   )
+(mk-species 'sp_forest_goblin   "forest goblin"   8 10 14   100   8   4  16 mmode-walk      t_hands      humanoid  2 s_asleep           nil     sound-walking   )
+(mk-species 'sp_ghast           "ghast"          10 10 10   100  10   2   8 mmode-phase     t_hands      humanoid  2 s_asleep           nil     nil             )
+(mk-species 'sp_gint            "gint"           50  3  8   100  50   2  20 mmode-large     t_hands      giant    10 s_asleep           nil     sound-walking   )
+(mk-species 'sp_green_slime     "green slime"     2  2  2   100   6   0   5 mmode-walk      t_acid_spray nil       2 s_slime_asleep     nil     sound-squishing )
+(mk-species 'sp_fire_slime      "fire slime"      2  2  2   100   6   0   5 mmode-walk      t_fire_glob  nil       2 s_red_slime_asleep nil     sound-squishing )
+(mk-species 'sp_human           "human"          10 10 10   100  10   2  13 mmode-walk      t_hands      humanoid  2 s_asleep           nil     sound-walking   )
+(mk-species 'sp_insect          "insects"         1  1 18   200   3   0   4 mmode-hover     t_stinger    nil       1 nil                nil     nil             )
+(mk-species 'sp_nixie           "nyad"           10 10 10   100  10   2  19 mmode-fish      t_hands      humanoid  2 s_shoals           nil     sound-splashing )
+(mk-species 'sp_queen_spider    "queen spider"   18  6 12   100  20   4  10 mmode-crawl     t_G_fangs    nil       4 s_asleep           "1d2"   sound-walking   )
+(mk-species 'sp_skeleton        "skeleton"       12  8 12   100  12   2  10 mmode-walk      t_hands      humanoid  3 s_asleep           nil     sound-walking   )
+(mk-species 'sp_snake           "snake"           2  2 14   100   6   0   6 mmode-walk      t_fangs      nil       1 s_asleep           nil     sound-walking   )
+(mk-species 'sp_bat             "bat"             2  2 14   120   2   0  19 mmode-fastfly   t_fangs      nil       1 s_asleep           nil     nil             )
+(mk-species 'sp_rat             "rat"             4  2 12   100   6   0   6 mmode-crawl     t_F_fangs    nil       1 s_asleep           nil     nil             )
+(mk-species 'sp_spider          "spider"         12  6 14   120   8   2  10 mmode-fastcrawl t_fangs      nil       2 s_asleep           nil     sound-walking   )
+(mk-species 'sp_statue          "statue"          1  1  1   100  99   0   1 mmode-none      nil          nil       0 nil                "16"    nil             )
+(mk-species 'sp_troll           "troll"          14  6 12   100  20   2  10 mmode-walk      t_horns      humanoid  3 s_asleep           nil     sound-walking   )
+(mk-species 'sp_yellow_slime    "yellow slime"    4  4  4   100  12   2   6 mmode-walk      t_acid_spray nil       2 nil                nil     sound-squishing )
+(mk-species 'sp_kraken          "kraken"         30  3 20   100  30   4  19 mmode-fish      t_tentacles  nil      10 s_shoals           "1d4"   sound-splashing ) 
+(mk-species 'sp_great_kraken    "kraken"         10  5  8   100  30   0  19 mmode-fish      t_G_fangs    nil      10 s_shoals           "1d4"   sound-splashing ) 
+(mk-species 'sp_kraken_tentacle "kraken"         30  1 20   100  10   2  19 mmode-fish      t_tentacles  nil      10 s_shoals           nil     sound-splashing ) 
+(mk-species 'sp_sea_serpent     "sea serpent"    20  2 14   100  20   4  19 mmode-fish      t_G_fangs    nil       8 s_asleep           "2d4"   sound-walking   ) 
+(mk-species 'sp_wolf            "wolf"            8  2 12   100   8   0  13 mmode-fastrun   t_fangs      nil       2 s_asleep           nil     sound-walking   ) 
+(mk-species 'sp_gazer           "gazer"           6 20  6   100  10   8  16 mmode-hover     t_prismatic_gaze nil   8 s_gazer_asleep     nil     nil             ) 
+(mk-species 'sp_headless        "headless"       12  0 10   100  14   0   6 mmode-walk      t_hands      humanoid  2 s_asleep           nil     sound-walking   ) 
+(mk-species 'sp_wisp            "wisp"            2 20 16   140   8   8   9 mmode-hover     nil          nil       4 nil                nil     nil             ) 
+(mk-species 'sp_dragon          "dragon"         20 10 10   100  50   8   9 mmode-fly       t_G_fangs    nil      20 s_dragon_asleep    "2d4"   sound-walking   )
+(mk-species 'sp_zorn            "zorn"           10 10 10   100  10   2   9 mmode-phase     t_beak       nil       4 s_asleep           nil     sound-walking   ) 
+(mk-species 'sp_demon           "demon"          14 14 14   100  14   8  12 mmode-fly       t_hands      humanoid  8 s_asleep           nil     sound-walking   ) 
+(mk-species 'sp_lich            "lich"           12 14 14   100  20  10   9 mmode-walk      t_hands      humanoid  8 s_asleep           nil     sound-walking   )
+(mk-species 'sp_carabid         "carabid"        30  1 10   100   8   0   3 mmode-walk      t_pincers    nil       8 s_carabid_asleep   "4d4+4" sound-walking   )
+(mk-species 'sp_ratling         "ratling"         6  8 14   110   4   2  12 mmode-fastrun   t_F_fangs    humanoid  2 s_asleep           nil     sound-walking   )
+(mk-species 'sp_griffin         "griffin"        20  8 12   120  25   0  19 mmode-fly       t_beak       nil       3 s_griffin_asleep   nil     nil             )
+(mk-species 'sp_griffin_chick   "griffin chick"   5  8 10   100   8   0  19 mmode-fastfly   t_beak       nil       2 s_griffin_chick_asleep nil nil             )
+(mk-species 'sp_deer            "deer"            7  1 14   120   8   0  13 mmode-fastrun   t_horns      nil       1 s_asleep           nil     sound-walking   ) 
+(mk-species 'sp_chicken         "chicken"         1  1  3   100   1   0  13 mmode-walk      t_beak       nil       1 s_asleep           nil     sound-walking   ) 
+;;          tag                 name             st in dx   spd bHP bMP  vr mmode           weap         morph    xp sspr               armrdc  mvsnd
+
+;; species that don't move around
+;;                     tag          name         st in dx   spd bHP bMP vr mmode           weap         morph    xp sspr     armrdc
+(mk-stationary-species 'sp_dryad    "dryad"      12 12  4   100  12   6   6 mmode-walk      nil          nil       8 s_forest nil  )
+(mk-stationary-species 'sp_hydra    "hydra"      20  2 10   140  30   8   6 mmode-walk      t_tentacles  nil      10 nil      nil  )
+(mk-stationary-species 'sp_mimic    "mimic"      11  3 10   100  15   0   5 mmode-walk      t_fangs      nil       2 s_chest  "1d2")
+
+;;----------------------------------------------------------------------------
+;; This list of the undead species is used by spells which affect the undead.
+;;----------------------------------------------------------------------------
+(define undead-species-tags
+  (list sp_skeleton sp_lich sp_ghast))
+
+(define (species-is-undead? species)
+  (foldr (lambda (x undead) (or x (eqv? species undead)))
+         #f undead-species-tags))
+
+(define (is-undead? kchar)
+  (species-is-undead? (kern-char-get-species kchar)))
+
+;; ----------------------------------------------------------------------------
+;; Species immunities
+;; ----------------------------------------------------------------------------
+(define (species-is-immune-to-ensnare? species)
+  (or (eqv? species sp_spider)
+      (eqv? species sp_queen_spider)))
+
+(define (species-is-immune-to-paralyze? species)
+  (eqv? species sp_balron)
+  )
+
+;;----------------------------------------------------------------------------
+;; Trigger to generate slimes
+;;----------------------------------------------------------------------------
+(define (slime-gen-target-loc kgen)
+  (let* ((kplace (loc-place (kern-obj-get-location kgen)))
+        (gob (gob-data (kobj-gob kgen)))
+        (x (car gob))
+        (y (cadr gob)))
+    (display "gob:")(display gob)(newline)
+    (mk-loc kplace x y)))
+
+(define (slime-generator-step kgen kstepper)
+  (define (mkslime)
+    (kern-log-msg "A slime emerges from the ooze!")
+    (mk-green-slime))
+  (let* ((kplace (loc-place (kern-obj-get-location kstepper)))
+         (slimes (filter is-green-slime? (kern-place-get-beings kplace))))
+    (if (< (length slimes) 1)
+        (psummon (slime-gen-target-loc kgen)
+                 mkslime
+                 (kern-dice-roll "1d2")))))
+
+(define slime-generator-ifc
+  (ifc '()
+       (method 'step slime-generator-step)))
+
+(mk-obj-type 't_slime_generator nil nil layer-mechanism slime-generator-ifc)
+
+(define (mk-slime-generator x y)
+  (kern-obj-set-visible (bind (kern-mk-obj t_slime_generator 1)
+                              (list x y))
+                        #f))
+
+;;----------------------------------------------------------------------------
+;; On-death closures
+(define (drop kchar . stuff)
+  (map (lambda (ktype) (kern-obj-put-at (kern-mk-obj ktype 1) 
+                                        (kern-obj-get-location kchar))) 
+       stuff))
diff --git a/worlds/haxima-1.002/spells.png b/worlds/haxima-1.002/spells.png
new file mode 100644 (file)
index 0000000..3ff3522
Binary files /dev/null and b/worlds/haxima-1.002/spells.png differ
diff --git a/worlds/haxima-1.002/spells.scm b/worlds/haxima-1.002/spells.scm
new file mode 100644 (file)
index 0000000..0d75359
--- /dev/null
@@ -0,0 +1,379 @@
+;; ----------------------------------------------------------------------------
+;; Set the list of magic syllables we'll use in our game. The kernel sets a max
+;; limit of 26 (one for each letter of the alphabet) largely for reasons I am
+;; not willing to address at this point.
+;; ----------------------------------------------------------------------------
+
+(kern-set-spell-words "An"
+                      "Bet"
+                      "Corp"
+                      "Des"
+                      "Ex"
+                      "Flam"
+                      "Grav"                       
+                      "Hur"
+                      "In"
+                      "Jux"
+                      "Kal"
+                      "Lor"
+                      "Mani"
+                      "Nox"
+                      "Ort"
+                      "Por"
+                      "Quas"
+                      "Rel"
+                      "Sanct"
+                      "Tym"
+                      "Uus"
+                      "Vas"
+                      "Wis"
+                      "Xen"
+                      "Ylem"
+                      "Zu")
+
+;; ----------------------------------------------------------------------------
+;; The only purpose of this list is to prevent the scheme gc from harvesting
+;; the spell interfaces which are created on-the-fly in mk-spell. Without this
+;; I'd have to explicitly assign a variable to each ifc, which is needlessly
+;; verbose.
+;; ----------------------------------------------------------------------------
+
+(define spell-ifcs '())
+
+;; ----------------------------------------------------------------------------
+;; mk-spell creates a spell interface on the fly, puts it on the spell-ifcs to
+;; prevent the gc from getting it, registers a new object type for the spell
+;; with the kernel, and then adds it to the list of spells known to the kernel.
+;; ----------------------------------------------------------------------------
+(define (mk-spell tag name cast-handler magic-words level context sprite
+                  reagents)
+  (let ((spell-ifc (ifc obj-ifc (method 'cast cast-handler))))
+    (set! spell-ifcs (cons spell-ifc spell-ifcs))
+    (kern-add-spell (mk-obj-type tag name nil layer-none spell-ifc)
+                    magic-words 
+                    level  ;; level
+                    level  ;; mana cost
+                    context 
+                    (/ (* (+ level 1) base-spell-ap) 2) ;; action point cost
+                    sprite ;; sprite (FIXME)
+                    reagents
+                    )))
+
+
+  
+;; ============================================================================
+;; Wind spell support
+;; ============================================================================
+
+(define (get-line origin dir n)
+  ;;(println "   get-line:" origin "," dir "," n)
+  (cond ((= n 0) 
+         ;;(println "    nil") 
+         nil)
+        (else
+         (cons origin
+               (get-line (loc-offset origin dir) dir (- n 1))))))
+
+(define (get-cone-vert origin depth dy)
+  ;;(println " get-cone-vert:" origin "," depth "," dy)
+  (let ((place (loc-place origin)))
+    (define (get-lines x y n h)
+      ;;(println "  get-lines:" x "," y "," n "," h)
+      (if (< h 0) nil
+          (let ((line (filter (lambda (a) (and (kern-in-los? origin a)
+                                               (kern-is-valid-location? a)
+                                               (terrain-ok-for-field? a)))
+                              (get-line (mk-loc place x y) east n))))
+            ;;(println "   line:" line)
+            (cons line
+                  (get-lines (if (= x 0) 0 (- x 1))
+                             (+ y dy) 
+                             (+ n (if (= x 0) 1 2))
+                             (- h 1))))))
+    (get-lines (loc-x origin)
+               (loc-y origin)
+               1 
+               depth)))
+
+(define (get-cone-horz origin depth dx)
+  (let ((place (loc-place origin)))
+    (define (get-lines x y n h)
+      (if (< h 0) nil
+          (cons (filter (lambda (a) (and (kern-in-los? origin a)
+                                         (kern-is-valid-location? a)
+                                         (terrain-ok-for-field? a)))
+                        (get-line (mk-loc place x y) south n))
+                (get-lines (+ x dx)
+                           (if (= y 0) 0 (- y 1))
+                           (+ n (if (= y 0) 1 2))
+                           (- h 1)))))
+    (get-lines (loc-x origin)
+               (loc-y origin)
+               1 
+               depth)))
+
+(define (get-cone origin depth dir)
+  ;;(println "get-cone:" origin "," depth "," dir)
+  (cond ((= dir north) (get-cone-vert origin 
+                                      (min depth (loc-y origin)) 
+                                      -1))
+        ((= dir east) (get-cone-horz origin 
+                                     (min depth
+                                          (- (kern-place-get-width (loc-place origin))
+                                             (loc-x origin)))
+                                     1))
+        ((= dir south) (get-cone-vert origin 
+                                      (min depth 
+                                           (- (kern-place-get-height (loc-place origin))
+                                              (loc-y origin)))
+                                      1))
+        ((= dir west) (get-cone-horz origin
+                                     (min depth (loc-x origin))
+                                     -1))
+        (else nil)))
+
+(define (cast-wind-spell origin proc field-type)
+  (let ((dir (ui-get-direction)))
+    (if (null? dir) nil
+        (begin
+          (define (dropfield loc)
+            (if (kern-is-valid-location? loc)
+                (kern-obj-put-at (kern-mk-obj field-type 1) loc)))
+          (define (is-my-field? kobj) (eqv? field-type (kern-obj-get-type kobj)))
+          (define (rmfield loc)
+            (if (> (kern-dice-roll "2d20") 16)
+                (let ((fields (filter is-my-field? (kern-get-objects-at loc))))
+                  (cond ((null? fields) nil)
+                        (else
+                         (kern-obj-remove (car fields)))))))
+          (define (doline line)
+            (map (lambda (loc)
+                   (map proc (kern-get-objects-at loc)))
+                 line)
+            (map dropfield line)
+            (kern-map-repaint)
+            (map rmfield line)
+            )
+          (let ((lines (get-cone origin 10 dir)))
+            (cond ((null? lines) nil)
+                  (else
+                   (map doline (cdr lines))
+                   (kern-map-repaint))))))))
+
+;; This version:
+;;   o has caller-limited depth
+;;   o has caller-specified direction
+;;   o applies caller-specified proc to each location
+;; (Note: currently used for the spider's web-spew "spell")
+(define (cast-wind-spell2 origin proc dir depth)
+  ;;(println "cast-wind-spell2:" origin "," proc "," dir "," depth)
+  (define (dropfield loc)
+    (if (kern-is-valid-location? loc)
+        (proc loc)))
+  (define (doline line)
+    (map dropfield line)
+    (kern-map-repaint))
+  (let ((lines (get-cone origin depth dir)))
+    (cond ((null? lines) nil)
+          (else
+           ;;(println " doing lines")
+           (map doline (cdr lines))
+           (kern-map-repaint)))))
+                  
+
+;;----------------------------------------------------------------------------
+;; Core actions behind spells, special abilities, etc. No UI prompting, no mana
+;; or level checking, no mana decrementing -- that all needs to be handled by
+;; the callers. All of these calls must return #t on success or #f on
+;; failure. No further details as to cause of failure are required.
+;;----------------------------------------------------------------------------
+
+
+(define (resurrect kchar)
+  (kern-char-resurrect kchar)
+  #t)
+
+;; ----------------------------------------------------------------------------
+;; All the spell cast handlers are listed here. These are the procedures that
+;; get called whenever a spell is cast.
+;; ----------------------------------------------------------------------------
+
+(define (cast-on-party-member spell)
+  (let ((ktarg (kern-ui-select-party-member)))
+    (if (null? ktarg)
+        result-no-target
+        (if (spell ktarg)
+            result-ok
+            result-no-effect))))
+                 
+
+;;----------------------------------------------------------------------------
+;; Spell accessors
+;;----------------------------------------------------------------------------
+(define (spell-name spell) (cadr spell))
+(define (spell-handler spell) (caddr spell))
+(define (spell-level spell) (list-ref spell 4))
+(define (spell-cost spell) (spell-level spell))
+(define (spell-ap spell) (spell-level spell))
+
+;; ----------------------------------------------------------------------------
+;; This is the table of spells.
+;; ----------------------------------------------------------------------------
+
+;; Spell sprite set
+(kern-mk-sprite-set 'ss_spells 32 32 8 8 0 0 "spells.png")
+
+(define (mk-sprite tag offset)
+  (kern-mk-sprite tag ss_spells 1 offset #f 0))
+
+(mk-sprite 's_an_nox            0)
+(mk-sprite 's_an_zu             1)
+(mk-sprite 's_grav_por          2)
+(mk-sprite 's_in_lor            3)
+(mk-sprite 's_mani              4)
+(mk-sprite 's_wis_sanct         5)
+(mk-sprite 's_an_sanct_ylem     6)
+(mk-sprite 's_ylem_an_ex        7)
+(mk-sprite 's_sanct_nox         8)
+(mk-sprite 's_an_sanct          9)
+(mk-sprite 's_sanct            10)
+(mk-sprite 's_an_xen_corp      11)
+(mk-sprite 's_in_wis           12)
+(mk-sprite 's_kal_xen          13)
+(mk-sprite 's_rel_hur          14)
+(mk-sprite 's_in_nox_por       15)
+(mk-sprite 's_an_xen_bet       16)
+(mk-sprite 's_bet_flam_hur     17)
+(mk-sprite 's_in_flam_grav     18)
+(mk-sprite 's_in_nox_grav      19)
+(mk-sprite 's_in_zu_grav       20)
+(mk-sprite 's_vas_flam         21)
+(mk-sprite 's_vas_lor          22)
+(mk-sprite 's_in_flam_sanct    23)
+(mk-sprite 's_an_grav          24)
+(mk-sprite 's_in_sanct_grav    25)
+(mk-sprite 's_in_sanct         26)
+(mk-sprite 's_wis_quas         27)
+(mk-sprite 's_bet_por          28)
+(mk-sprite 's_vas_sanct_nox    29)
+(mk-sprite 's_in_ex_por        30)
+(mk-sprite 's_an_ex_por        31)
+(mk-sprite 's_in_bet_xen       32)
+(mk-sprite 's_in_zu            33)
+(mk-sprite 's_vas_mani         34)
+(mk-sprite 's_rel_tym          35)
+(mk-sprite 's_in_an            36)
+(mk-sprite 's_wis_an_ylem      37)
+(mk-sprite 's_an_xen_ex        38)
+(mk-sprite 's_in_vas_por_ylem  39)
+(mk-sprite 's_quas_an_wis      40)
+(mk-sprite 's_vas_uus_ylem     41)
+(mk-sprite 's_in_rel_por       42)
+(mk-sprite 's_vas_por          43)
+(mk-sprite 's_in_nox_hur       44)
+(mk-sprite 's_in_zu_hur        45)
+(mk-sprite 's_in_quas_corp     46)
+(mk-sprite 's_in_quas_wis      47)
+(mk-sprite 's_sanct_lor        48)
+(mk-sprite 's_xen_corp         49)
+(mk-sprite 's_in_quas_xen      50)
+(mk-sprite 's_kal_xen_nox      51)
+(mk-sprite 's_in_flam_hur      52)
+(mk-sprite 's_in_vas_grav_corp 53)
+(mk-sprite 's_an_tym           54)
+(mk-sprite 's_kal_xen_corp     55)
+(mk-sprite 's_in_mani_corp     56)
+(mk-sprite 's_vas_rel_por      57)
+(mk-sprite 's_vas_an_nox       58)
+(mk-sprite 's_ort_grav         59)
+(mk-sprite 's_bet_ylem_hur     60)
+(mk-sprite 's_rel_xen_quas     61)
+
+;; ----------------------------------------------------------------------------
+;; Now rip through the list of spells, adding them to the kernel.
+;; ----------------------------------------------------------------------------
+
+;;         tag               name                               handler          code   L context       sprite             mixture
+;;         ==========        ================================   =======          ====   = =========     ======             =======
+;; First Circle
+(mk-spell 'an_nox           "Cure Poison <An Nox>"              an-nox           "AN"   1 context-any   s_an_nox           (list garlic ginseng))
+(mk-spell 'an_zu            "Awaken <An Zu>"                    an-zu            "AZ"   1 context-any   s_an_zu            (list garlic ginseng))
+(mk-spell 'grav_por         "Magic Missile <Grav Por>"          grav-por         "GP"   1 context-town  s_grav_por         (list sulphorous_ash black_pearl))
+(mk-spell 'in_lor           "Light <In Lor>"                    in-lor           "IL"   1 context-any   s_in_lor           (list sulphorous_ash))
+(mk-spell 'mani             "Minor Healing <Mani>"              mani             "M"    1 context-any   s_mani             (list ginseng spider_silk))
+(mk-spell 'wis_sanct        "Detect Traps <Wis Sanct>"          wis-sanct        "WS"   1 context-town  s_wis_sanct        (list sulphorous_ash))
+(mk-spell 'an_sanct_ylem    "Disarm Trap <An Sanct Ylem>"       an-sanct-ylem    "ASY"  1 context-town  s_an_sanct_ylem    (list blood_moss))
+(mk-spell 'ylem_an_ex       "Web <Ylem An Ex>"                  ylem-an-ex       "YAE"  1 context-town  s_ylem_an_ex       (list spider_silk black_pearl))
+(mk-spell 'bet_ylem_hur     "Conjure Smoke <Bet Ylem Hur>"      bet-ylem-hur     "BYH"  1 context-town  s_bet_ylem_hur     (list sulphorous_ash))
+
+;; Second Circle
+(mk-spell 'sanct_nox        "Poison Ward <Sanct Nox>"           sanct-nox        "SN"   2 context-any   s_sanct_nox        (list nightshade garlic t_royal_cape))
+(mk-spell 'an_sanct         "Unlock <An Sanct>"                 an-sanct         "AS"   2 context-town  s_an_sanct         (list sulphorous_ash blood_moss))
+(mk-spell 'sanct            "Lock <Sanct>"                      sanct            "S"    2 context-town  s_sanct            (list sulphorous_ash spider_silk))
+(mk-spell 'an_xen_corp      "Turn Undead <An Xen Corp>"         an-xen-corp      "AXC"  2 context-town  s_an_xen_corp      (list garlic sulphorous_ash))
+(mk-spell 'in_wis           "Locate <In Wis>"                   in-wis           "IW"   2 context-any   s_in_wis           (list nightshade))
+(mk-spell 'in_bet_xen       "Summon Vermin <In Bet Xen>"        in-bet-xen       "IBX"  2 context-town  s_in_bet_xen       (list spider_silk blood_moss sulphorous_ash))
+(mk-spell 'rel_hur          "Change Wind <Rel Hur>"             rel-hur          "RH"   2 context-any   s_rel_hur          (list sulphorous_ash blood_moss))
+(mk-spell 'in_nox_por       "Poison Bolt <In Nox Por>"          in-nox-por       "INP"  2 context-town  s_in_nox_por       (list nightshade blood_moss black_pearl))
+(mk-spell 'an_xen_bet       "Calm Spiders <An Xen Bet>"         an-xen-bet       "AXB"  2 context-town  s_an_xen_bet       (list spider_silk garlic))
+(mk-spell 'bet_flam_hur     "Fire Spray <Bet Flam Hur>"         bet-flam-hur     "BFH"  2 context-town  s_bet_flam_hur     (list black_pearl sulphorous_ash blood_moss))
+(mk-spell 'in_quas_wis      "Vision <In Quas Wis>"              in-quas-wis      "IQW"  2 context-any   s_in_quas_wis      (list nightshade mandrake))
+(mk-spell 'xen_zu           "Sleep <Xen Zu>"                    xen-zu           "XZ"   2 context-town  s_in_zu            (list spider_silk ginseng))
+
+;; Third Circle
+(mk-spell 'in_flam_grav     "Fire Field <In Flam Grav>"         in-flam-grav     "IFG"  3 context-town  s_in_flam_grav     (list sulphorous_ash black_pearl spider_silk))
+(mk-spell 'in_nox_grav      "Poison Field <In Nox Grav>"        in-nox-grav      "ING"  3 context-town  s_in_nox_grav      (list nightshade black_pearl spider_silk))
+(mk-spell 'in_zu_grav       "Sleep Field <In Zu Grav>"          in-zu-grav       "IZG"  3 context-town  s_in_zu_grav       (list ginseng black_pearl spider_silk))
+(mk-spell 'vas_flam         "Fire Ball <Vas Flam>"              vas-flam         "VF"   3 context-town  s_vas_flam         (list sulphorous_ash black_pearl))
+(mk-spell 'vas_lor          "Great Light <Vas Lor>"             vas-lor          "VL"   3 context-any   s_vas_lor          (list mandrake sulphorous_ash))
+(mk-spell 'in_flam_sanct    "Fire Ward <In Flam Sanct>"         in-flam-sanct    "IFS"  3 context-any   s_in_flam_sanct    (list garlic sulphorous_ash t_royal_cape))
+(mk-spell 'vas_an_nox       "Mass Cure Poison <Vas An Nox>"     vas-an-nox       "VAN"  3 context-any   s_vas_an_nox       (list mandrake garlic ginseng))
+(mk-spell 'an_ort_xen       "Dispel Magic <An Ort Xen>"         an-ort-xen       "AOX"  3 context-any   s_in_an            (list garlic mandrake sulphorous_ash))
+
+;; Fourth Circle
+(mk-spell 'an_grav          "Dispel Field <An Grav>"            an-grav          "AG"   4 context-any   s_an_grav          (list black_pearl sulphorous_ash))
+;;(mk-spell 'uus_por        "Ascend <Uus Por>"                  uus-por          "UP"   4 context-any   nil                (list blood_moss spider_silk))
+;;(mk-spell 'des_por        "Descend <Des Por>"                 des-por          "DP"   4 context-any   nil                (list blood_moss spider_silk))
+(mk-spell 'in_sanct_grav    "Force Field <In Sanct Grav>"       in-sanct-grav    "ISG"  4 context-town  s_in_sanct_grav    (list mandrake black_pearl spider_silk))
+(mk-spell 'in_sanct         "Protection <In Sanct>"             in-sanct         "IS"   4 context-any   s_in_sanct         (list sulphorous_ash ginseng garlic))
+(mk-spell 'wis_quas         "Reveal <Wis Quas>"                 wis-quas         "WQ"   4 context-any   s_wis_quas         (list nightshade sulphorous_ash))
+(mk-spell 'bet_por          "Blink <Bet Por>"                   bet-por          "BP"   4 context-town  s_bet_por          (list black_pearl blood_moss))
+(mk-spell 'vas_sanct_nox    "Mass Poison Ward <Vas Sanct Nox>"  vas-sanct-nox    "VSN"  3 context-any   s_vas_sanct_nox    (list mandrake nightshade garlic t_royal_cape))
+(mk-spell 'ort_grav         "Lightning Bolt <Ort Grav>"         ort-grav         "OG"   1 context-town  s_ort_grav         (list black_pearl mandrake sulphorous_ash))
+
+;; Fifth Circle
+(mk-spell 'in_ex_por        "Magic Unlock <In Ex Por>"          in-ex-por        "IEP"  5 context-any   s_in_ex_por        (list sulphorous_ash blood_moss))
+(mk-spell 'an_ex_por        "Magic Lock <An Ex Por>"            an-ex-por        "AEP"  5 context-any   s_an_ex_por        (list sulphorous_ash blood_moss garlic))
+(mk-spell 'in_zu            "Mass Sleep <In Zu>"                in-zu            "IZ"   5 context-town  s_in_zu            (list nightshade spider_silk ginseng))
+(mk-spell 'vas_mani         "Great Heal <Vas Mani>"             vas-mani         "VM"   5 context-any   s_vas_mani         (list mandrake spider_silk ginseng))
+(mk-spell 'rel_tym          "Quickness <Rel Tym>"               rel-tym          "RT"   5 context-any   s_rel_tym          (list sulphorous_ash blood_moss mandrake))
+(mk-spell 'kal_xen          "Summon Beast <Kal Xen>"            kal-xen          "KX"   5 context-town  s_kal_xen          (list spider_silk mandrake))
+(mk-spell 'rel_xen_quas     "Illusion of Beastliness <Rel Xen Quas>" rel-xen-quas "RXQ" 5 context-town  s_rel_xen_quas     (list nightshade blood_moss))
+
+;; Sixth Circle
+(mk-spell 'in_an            "Negate Magic <In An>"              in-an            "IA"   6 context-any   s_in_an            (list garlic mandrake sulphorous_ash))
+(mk-spell 'wis_an_ylem      "X-Ray Vision <Wis An Ylem>"        wis-an-ylem      "WAY"  6 context-any   s_wis_an_ylem      (list mandrake sulphorous_ash))
+(mk-spell 'an_xen_ex        "Charm <An Xen Ex>"                 an-xen-ex        "AXE"  6 context-town  s_an_xen_ex        (list black_pearl nightshade spider_silk))
+(mk-spell 'in_vas_por_ylem  "Tremor <In Vas Por Ylem>"          in-vas-por-ylem  "IVPY" 6 context-town  s_in_vas_por_ylem  (list mandrake blood_moss sulphorous_ash))
+(mk-spell 'quas_an_wis      "Confusion <Quas An Wis>"           quas-an-wis      "QAW"  6 context-town  s_quas_an_wis      (list mandrake nightshade))
+(mk-spell 'vas_uus_ylem     "Raise Ship <Vas Uus Ylem>"         vas-uus-ylem     "VUY"  6 context-world s_vas_uus_ylem     (list mandrake blood_moss spider_silk))
+(mk-spell 'in_rel_por       "Telekinesis <In Rel Por>"          in-rel-por       "IRP"  6 context-town  s_in_rel_por       (list black_pearl blood_moss spider_silk))
+(mk-spell 'vas_por          "Teleport Party <Vas Por>"          vas-por          "VP"   6 context-world s_vas_por          (list mandrake black_pearl blood_moss))
+
+;; Seventh Circle
+(mk-spell 'in_nox_hur       "Poison Wind <In Nox Hur>"          in-nox-hur       "INH"  7 context-town  s_in_nox_hur       (list nightshade sulphorous_ash blood_moss))
+(mk-spell 'in_zu_hur        "Wind of Sleep <In Zu Hur>"         in-zu-hur        "IZH"  7 context-town  s_in_zu_hur        (list mandrake ginseng blood_moss))
+(mk-spell 'in_quas_corp     "Fear <In Quas Corp>"               in-quas-corp     "IQC"  7 context-town  s_in_quas_corp     (list nightshade mandrake garlic))
+(mk-spell 'sanct_lor        "Invisibility <Sanct Lor>"          sanct-lor        "SL"   7 context-any   s_sanct_lor        (list nightshade mandrake blood_moss))
+(mk-spell 'xen_corp         "Death Bolt <Xen Corp>"             xen-corp         "XC"   7 context-town  s_xen_corp         (list nightshade black_pearl))
+(mk-spell 'in_quas_xen      "Clone <In Quas Xen>"               in-quas-xen      "IQX"  7 context-town  s_in_quas_xen      (list nightshade mandrake sulphorous_ash spider_silk blood_moss ginseng))
+
+;; Eighth Circle
+(mk-spell 'kal_xen_nox      "Summon Slime <Kal Xen Nox>"        kal-xen-nox      "KXN"  8 context-town  s_kal_xen_nox      (list spider_silk mandrake nightshade))
+(mk-spell 'in_flam_hur      "Flame Wind <In Flam Hur>"          in-flam-hur      "IFH"  8 context-town  s_in_flam_hur      (list mandrake sulphorous_ash blood_moss))
+(mk-spell 'in_vas_grav_corp "Death Wind <In Vas Grav Corp>"     in-vas-grav-corp "IVGC" 8 context-town  s_in_vas_grav_corp (list mandrake sulphorous_ash nightshade))
+(mk-spell 'an_tym           "Time Stop <An Tym>"                an-tym           "AT"   8 context-any   s_an_tym           (list mandrake garlic blood_moss))
+(mk-spell 'kal_xen_corp     "Summon Undead <Kal Xen Corp>"      kal-xen-corp     "KXC"  8 context-town  s_kal_xen_corp     (list spider_silk mandrake nightshade))
+(mk-spell 'in_mani_corp     "Resurrection <In Mani Corp>"       in-mani-corp     "IMC"  8 context-any   s_in_mani_corp     (list garlic ginseng spider_silk sulphorous_ash blood_moss mandrake))
+(mk-spell 'vas_rel_por      "Gate <Vas Rel Por>"                vas-rel-por      "VRP"  8 context-any   s_vas_rel_por      (list sulphorous_ash mandrake black_pearl))
+
diff --git a/worlds/haxima-1.002/spider.scm b/worlds/haxima-1.002/spider.scm
new file mode 100644 (file)
index 0000000..b9cd9bd
--- /dev/null
@@ -0,0 +1,192 @@
+;; Local variables
+(define spider-melee-weapon t_hands)
+
+;; Remapped display and newline to local procs so they can be disabled/enabled
+;; for debug more conveniently
+; (define (spider-display . args) 
+;   (display (kern-get-ticks))
+;   (display ":")
+;   (apply display args))
+; (define (spider-newline) (newline))
+
+(define (spider-display . args) )
+(define (spider-newline) )
+
+;; ----------------------------------------------------------------------------
+;; Spider Egg
+;; 
+;; ----------------------------------------------------------------------------
+
+(define spider-egg-hatch-time 10)
+(define (spider-egg-gob-mk) (list spider-egg-hatch-time))
+(define (spider-egg-hatch-timer gob) (car gob))
+(define (spider-egg-set-hatch-timer! gob val) (set-car! gob val))
+(define (spider-egg-hatch-timer-expired? gob) (= 0 (spider-egg-hatch-timer gob)))
+(define (spider-egg-dec-hatch-timer! gob)
+  (spider-egg-set-hatch-timer! gob
+                               (- (spider-egg-hatch-timer gob)
+                                  1)))
+
+;; spider-egg-disturbed - obsolete function that would return true if any
+;; neighboring tiles contained non-spiders. I discontinued it because it made
+;; eggs run too slowly (about 30ms per). Replaced it with a simple egg timer.
+(define (spider-egg-disturbed kegg)
+  (spider-display "spider-egg-disturbed")(spider-newline)
+  (define (check val loc)
+    ;;(display "loc:")(display loc)(newline)
+    (or val
+        (foldr (lambda (a b) (or a
+                                 (and (obj-is-char? b)
+                                      (not (is-spider? b)))))
+               #f
+               (kern-get-objects-at loc))))
+  (let ((loc (kern-obj-get-location kegg)))
+    (kern-fold-rect (loc-place loc)
+                    (- (loc-x loc) 2)
+                    (- (loc-y loc) 2)
+                    5
+                    5
+                    check
+                    #f)))
+
+(define (spider-egg-hatch kegg)
+  (spider-display "spider-egg-hatch")(spider-newline)
+  (kern-log-msg "A spider hatches!")
+  (kern-obj-put-at (mk-npc 'giant-spider (calc-level)) (kern-obj-get-location kegg))
+  (kern-obj-remove kegg))
+
+(define (spider-egg-exec kegg)
+  (let ((gob (kobj-gob-data kegg)))
+    (if (spider-egg-hatch-timer-expired? gob)
+        (spider-egg-hatch kegg)
+        (spider-egg-dec-hatch-timer! gob))))
+
+(define spider-egg-ifc
+  (ifc '()
+       (method 'exec spider-egg-exec)))
+
+(mk-obj-type 'spider-egg-type
+             "spider egg"
+             s_magic
+             layer-item
+             spider-egg-ifc)
+
+(define (mk-spider-egg)
+  (bind (kern-mk-obj spider-egg-type 1)
+        (spider-egg-gob-mk)))
+
+;; ----------------------------------------------------------------------------
+;; Spider "Skills"
+;; ----------------------------------------------------------------------------
+
+(define (suck-hp kspider ktarg amount)
+  (kern-log-msg (kern-obj-get-name kspider) 
+                " sucks the juices from " 
+                (kern-obj-get-name ktarg))
+  (let ((amount (min amount (kern-char-get-hp ktarg))))
+    (kern-obj-apply-damage ktarg nil amount)
+    (kern-obj-heal kspider amount)))
+
+(define (spider-paralyze ktarg)
+  (spider-display "spider-paralyze")(spider-newline)
+  (paralyze ktarg))
+
+(define (ensnare-loc loc)
+  (spider-display "ensnare-loc")(spider-newline)
+  (kern-obj-put-at (kern-mk-obj web-type 1) loc))
+
+
+
+;; ----------------------------------------------------------------------------
+;; Spider AI
+;; ----------------------------------------------------------------------------
+(define (spider-is-aggressive? kspider)
+  (> (kern-char-get-hp kspider)
+     (/ (* 4 (kern-char-get-max-hp kspider)) 5)))
+
+(define (is-queen-spider? kspider)
+  (eqv? (kern-char-get-species kspider) sp_queen_spider))
+
+(define (spider-try-to-lay-egg kspider)
+  (spider-display "spider-try-to-lay-egg")(spider-newline)
+  (let ((loc (kern-obj-get-location kspider)))
+    (if (and (not (is-object-type-at? loc spider-egg-type))
+             (> (kern-dice-roll "1d20") 18))
+        (kern-obj-put-at (mk-spider-egg) loc))))
+
+(define (spider-no-hostiles kspider)
+  (spider-display "spider-no-hostiles")(spider-newline)
+  (let ((loc (kern-obj-get-location kspider)))
+    (if (not (is-object-type-at? loc web-type))
+        (ensnare-loc loc))
+    (if (is-queen-spider? kspider)
+        (spider-try-to-lay-egg kspider)))
+  (wander kspider))
+
+(define (is-helpless? kchar)
+  (or (kern-char-is-asleep? kchar)
+      (is-ensnared? kchar)
+      (is-paralyzed? kchar)))
+
+(define (spider-attack-helpless-foe kspider kfoe)
+  (define (attack kspider coords)
+    (spider-display "spider-attack")(spider-newline)
+    (if (is-paralyzed? kfoe)
+        (suck-hp kspider kfoe (kern-dice-roll "1d6"))
+        (spider-paralyze kfoe)))
+  (spider-display "spider-attack-helpless-foe")(spider-newline)
+  (do-or-goto kspider (kern-obj-get-location kfoe) attack))
+
+(define (spider-foe-in-range-of-web-spew? kspider kfoe)
+  (spider-display "spider-foe-in-range-of-web-spew?")(spider-newline)
+  (< (kern-get-distance (kern-obj-get-location kspider)
+                        (kern-obj-get-location kfoe))
+     (/ (kern-char-get-level kspider) 2)))
+
+(define (spider-pathfind-to-foe kspider kfoe)
+  (spider-display "spider-pathfind-to-foe")(spider-newline)
+  (pathfind kspider (kern-obj-get-location kfoe)))
+
+(define (spider-try-to-spew-web kspider foe)
+  (spider-display "spider-try-to-spew-web")(spider-newline)
+  (if (and (can-use-ability? web-spew kspider)
+           (spider-foe-in-range-of-web-spew? kspider foe))
+      (use-ability web-spew kspider foe)
+      (spider-attack-helpless-foe kspider foe)))
+
+(define (spider-no-helpless-foes kspider foes)
+  (spider-display "spider-no-helpless-foes")(spider-newline)
+  (if (is-queen-spider? kspider)
+      (spider-try-to-spew-web kspider (closest-obj 
+                                            (kern-obj-get-location kspider)
+                                            foes))
+      (if (spider-is-aggressive? kspider)
+          (spider-attack-helpless-foe kspider 
+                                      (closest-obj 
+                                       (kern-obj-get-location kspider)
+                                       foes))
+          (evade kspider foes))))
+
+(define (spider-hostiles kspider foes)
+  (spider-display "spider-hostiles")(spider-newline)
+  (let ((helpless-foes (filter is-helpless? foes)))
+    (if (null? helpless-foes)
+        (spider-no-helpless-foes kspider foes)
+        (spider-attack-helpless-foe kspider 
+                                         (closest-obj 
+                                          (kern-obj-get-location kspider)
+                                          helpless-foes)))))
+
+(define spider-bad-fields
+  (filter (lambda (x) (and (not (eqv? x web-type))
+                           (not (eqv? x F_web_perm))))
+          all-field-types))
+
+(define (spider-ai kspider)
+  (spider-display "spider-ai")(spider-newline)
+  (or (get-off-bad-tile? kspider)
+      (let ((foes (all-visible-hostiles kspider)))
+        (if (null? foes)
+            (spider-no-hostiles kspider)
+            (spider-hostiles kspider foes))
+        #t)))
diff --git a/worlds/haxima-1.002/splash.png b/worlds/haxima-1.002/splash.png
new file mode 100644 (file)
index 0000000..ef3b6ad
Binary files /dev/null and b/worlds/haxima-1.002/splash.png differ
diff --git a/worlds/haxima-1.002/sprite-sets.scm b/worlds/haxima-1.002/sprite-sets.scm
new file mode 100644 (file)
index 0000000..2c56f10
--- /dev/null
@@ -0,0 +1,41 @@
+;;----------------------------------------------------------------------------
+;; Images
+;;----------------------------------------------------------------------------
+;; 'ss_sprite_set_name tile_pix_w tile_pix_h tiles_h tiles_w x_offset y_offset "path/filename"
+;;
+;;                  'ss_sprite_set_name 
+;;                  |                    tile_pixels_wide tile_pixels_high
+;;                  |                    |       sheet_tiles_high sheet_tiles_wide
+;;                  |                    |       |       sheet_pixels_x_offset sheet_pixels_y_offset
+;;                  |                    |       |       |     "path/filename"
+;;                  |                    |       |       |     |
+;;                  v                    v       v       v     v
+;;----------------------------------------------------------------------------
+(kern-mk-sprite-set 'ss_u4_shapes        32 32   16 16   0 0  "shapes.png")
+(kern-mk-sprite-set 'ss_u4_charset       8  16    8 16   0 0  "charset.png")
+(kern-mk-sprite-set 'ss_frame            16 16    4  4   0 0  "frame.png")
+(kern-mk-sprite-set 'ss_rune             32 32    4  8   0 0  "rune.png")
+(kern-mk-sprite-set 'ss_addon            32 32   16  8   0 0  "addons.png")
+(kern-mk-sprite-set 'ss_moons            16 16    4  8   0 0  "moons.png")
+(kern-mk-sprite-set 'ss_signs            32 32    1  8   0 0  "signs.png")
+(kern-mk-sprite-set 'ss_runestones       32 32    4  8   0 0  "runestones.png")
+(kern-mk-sprite-set 'ss_newmonst         32 32   16  8   0 0  "newmonst.png") 
+(kern-mk-sprite-set 'ss_newfolks         32 32   16  8   0 0  "newfolks.png")
+(kern-mk-sprite-set 'ss_buildings        32 32    1  2   0 0  "tower.png")
+(kern-mk-sprite-set 'ss_overlays         32 32   13  8   0 0  "newterrain.png")
+(kern-mk-sprite-set 'ss_effects          8  16    3  16  0 0  "effects.png")
+(kern-mk-sprite-set 'ss_bigobjects       40 40    8  8   0 0  "bigobjects.png")
+(kern-mk-sprite-set 'ss_humanoids        32 32   16  8   0 0  "humanoids.png")
+(kern-mk-sprite-set 'ss_people           32 32   16  8   0 0  "hirespeople.png")
+(kern-mk-sprite-set 'ss_monsters         32 32   16  8   0 0  "monsters.png")
+(kern-mk-sprite-set 'ss_ship             32 32    8  8   0 0  "ship.png")
+(kern-mk-sprite-set 'ss_sfx              32 32    8  8   0 0  "sfx.png")
+(kern-mk-sprite-set 'ss_creatures        32 32   16  8   0 0  "creatures.png")
+(kern-mk-sprite-set 'ss_tools            32 32    8  8   0 0  "tools.png")
+(kern-mk-sprite-set 'ss_quests           32 32   16  8   0 0  "quests.png")
+
+
+;; New paper-doll sprite sets
+(kern-mk-sprite-set 'ss_bodies     32 32 4 4 0 0 "bodies.png")
+(kern-mk-sprite-set 'ss_adornments 32 32 4 4 0 0 "adornments.png")
+(kern-mk-sprite-set 'ss_clothes    32 32 5 4 0 0 "clothes.png")
diff --git a/worlds/haxima-1.002/sprites.scm b/worlds/haxima-1.002/sprites.scm
new file mode 100644 (file)
index 0000000..efaeefb
--- /dev/null
@@ -0,0 +1,818 @@
+;;----------------------------------------------------------------------------
+;; Sprites
+;;----------------------------------------------------------------------------
+;; 's_some_sprite ss_some_sprite_set num_tiles tile_number wave_sprite facing_value
+;; 
+;; facing_value is the sum of all facings provided by this sprite.
+;; The value is determined by adding:
+;;    1 NorthWest
+;;    2 North
+;;    4 NorthEast
+;;    8 West
+;;   16 Here
+;;   32 East
+;;   64 SouthWest
+;;  128 South
+;;  256 SouthEast
+;;  512 Up
+;; 1024 Down
+;; 
+;; Common values include:
+;;   0 Default facing (only 1 facing, used for all directions)
+;;  40 WE facing
+;; 170 NSEW facing
+;;----------------------------------------------------------------------------
+
+;(kern-mk-sprite 's_deep          ss_u4_shapes 1  0 #t 0 )
+;(kern-mk-sprite 's_shallow       ss_u4_shapes 1  1 #t 0 )
+;(kern-mk-sprite 's_shoals        ss_u4_shapes 1  2 #t 0 )
+(kern-mk-sprite 's_bog           ss_u4_shapes 1  3 #f 0 )
+(kern-mk-sprite 's_grass         ss_u4_shapes 1  4 #f 0 )
+
+;(kern-mk-sprite 's_trees         ss_u4_shapes 1  5 #f 0 )
+;(kern-mk-sprite 's_forest        ss_u4_shapes 1  6 #f 0 )
+;(kern-mk-sprite 's_hills         ss_u4_shapes 1  7 #f 0 )
+;(kern-mk-sprite 's_mountains     ss_u4_shapes 1  8 #f 0 )
+;(kern-mk-sprite 's_dungeon       ss_u4_shapes 1  9 #f 0 )
+(kern-mk-sprite 's_town          ss_u4_shapes 1 10 #f 0 )
+(kern-mk-sprite 's_keep          ss_u4_shapes 1 11 #f 0 )
+(kern-mk-sprite 's_hamlet        ss_u4_shapes 1 12 #f 0 )
+(kern-mk-sprite 's_leftwing      ss_u4_shapes 1 13 #f 0 )
+(kern-mk-sprite 's_castle        ss_u4_shapes 1 14 #f 0 )
+(kern-mk-sprite 's_rightwing     ss_u4_shapes 1 15 #f 0 )
+(kern-mk-sprite 's_cobblestone   ss_u4_shapes 1 22 #f 0 )
+(kern-mk-sprite 's_ew_bridge     ss_u4_shapes 1 23 #f 0 )
+(kern-mk-sprite 's_ballon        ss_u4_shapes 1 24 #f 0 )
+(kern-mk-sprite 's_bridge_top    ss_u4_shapes 1 25 #f 0 )
+(kern-mk-sprite 's_bridge_bottom ss_u4_shapes 1 26 #f 0 )
+(kern-mk-sprite 's_ladder_up     ss_u4_shapes 1 27 #f 0 )
+(kern-mk-sprite 's_ladder_down   ss_u4_shapes 1 28 #f 0 )
+(kern-mk-sprite 's_ruin          ss_u4_shapes 1 29 #f 0 )
+(kern-mk-sprite 's_shrine        ss_u4_shapes 1 30 #f 0 )
+
+(kern-mk-sprite 's_pillar      ss_u4_shapes 1 48 #f 0 )
+(kern-mk-sprite 's_wall_b      ss_u4_shapes 1 49 #f 0 )
+(kern-mk-sprite 's_wall_a      ss_u4_shapes 1 50 #f 0 )
+(kern-mk-sprite 's_wall_c      ss_u4_shapes 1 51 #f 0 )
+(kern-mk-sprite 's_wall_d      ss_u4_shapes 1 52 #f 0 )
+(kern-mk-sprite 's_mast        ss_u4_shapes 1 53 #f 0 )
+(kern-mk-sprite 's_ships_wheel ss_u4_shapes 1 54 #f 0 )
+;(kern-mk-sprite 's_boulder     ss_u4_shapes 1 55 #f 0 )
+;(kern-mk-sprite 's_asleep      ss_u4_shapes 1 56 #f 0 )
+;(kern-mk-sprite 's_wall_rock   ss_u4_shapes 1 57 #f 0 )
+(kern-mk-sprite 's_door_locked ss_u4_shapes 1 58 #f 0 )
+(kern-mk-sprite 's_door        ss_u4_shapes 1 59 #f 0 )
+;(kern-mk-sprite 's_chest       ss_u4_shapes 1 60 #f 0 )
+(kern-mk-sprite 's_ankh        ss_u4_shapes 1 61 #f 0 )
+(kern-mk-sprite 's_flagstone   ss_u4_shapes 1 62 #f 0 )
+(kern-mk-sprite 's_deck        ss_u4_shapes 1 63 #f 0 )
+
+(kern-mk-sprite 's_moongate_quarter        ss_u4_shapes 1 64 #f 0 )
+(kern-mk-sprite 's_moongate_half           ss_u4_shapes 1 65 #f 0 )
+(kern-mk-sprite 's_moongate_three_quarters ss_u4_shapes 1 66 #f 0 )
+(kern-mk-sprite 's_moongate_full           ss_u4_shapes 1 67 #f 0 )
+
+(kern-mk-sprite 's_field_poison ss_u4_shapes 1 68 #t 0 )
+(kern-mk-sprite 's_field_energy ss_u4_shapes 1 69 #t 0 )
+(kern-mk-sprite 's_field_fire   ss_u4_shapes 1 70 #t 0 )
+(kern-mk-sprite 's_field_sleep  ss_u4_shapes 1 71 #t 0 )
+(kern-mk-sprite 's_wall         ss_u4_shapes 1 72 #f 0 )
+(kern-mk-sprite 's_secret_door  ss_u4_shapes 1 73 #f 0 )
+(kern-mk-sprite 's_altar_obj        ss_u4_shapes 1 74 #f 0 )
+(kern-mk-sprite 's_lava         ss_u4_shapes 1 76 #t 0 )
+(kern-mk-sprite 's_projectile   ss_u4_shapes 1 77 #f 0 )
+(kern-mk-sprite 's_magic        ss_u4_shapes 1 78 #f 0 )
+;;(kern-mk-sprite 's_hit          ss_u4_shapes 1 79 #f 0 )
+;;(kern-mk-sprite 's_guard        ss_u4_shapes 2 80 #f 0 )
+;;(kern-mk-sprite 's_townsman     ss_u4_shapes 2 82 #f 0 )
+;;(kern-mk-sprite 's_bard         ss_u4_shapes 2 84 #f 0 )
+;;(kern-mk-sprite 's_jester       ss_u4_shapes 2 86 #f 0 )
+;;(kern-mk-sprite 's_beggar       ss_u4_shapes 2 88 #f 0 )
+;;(kern-mk-sprite 's_child        ss_u4_shapes 2 90 #f 0 )
+(kern-mk-sprite 's_bull         ss_u4_shapes 2 92 #f 0 )
+(kern-mk-sprite 's_lord         ss_u4_shapes 2 94 #f 0 )
+
+(kern-mk-sprite 's_A ss_u4_shapes 1  96 #f 0 )
+(kern-mk-sprite 's_B ss_u4_shapes 1  97 #f 0 )
+(kern-mk-sprite 's_C ss_u4_shapes 1  98 #f 0 )
+(kern-mk-sprite 's_D ss_u4_shapes 1  99 #f 0 )
+(kern-mk-sprite 's_E ss_u4_shapes 1 100 #f 0 )
+(kern-mk-sprite 's_F ss_u4_shapes 1 101 #f 0 )
+(kern-mk-sprite 's_G ss_u4_shapes 1 102 #f 0 )
+(kern-mk-sprite 's_H ss_u4_shapes 1 103 #f 0 )
+(kern-mk-sprite 's_I ss_u4_shapes 1 104 #f 0 )
+(kern-mk-sprite 's_J ss_u4_shapes 1 105 #f 0 )
+(kern-mk-sprite 's_K ss_u4_shapes 1 106 #f 0 )
+(kern-mk-sprite 's_L ss_u4_shapes 1 107 #f 0 )
+(kern-mk-sprite 's_M ss_u4_shapes 1 108 #f 0 )
+(kern-mk-sprite 's_N ss_u4_shapes 1 109 #f 0 )
+(kern-mk-sprite 's_O ss_u4_shapes 1 110 #f 0 )
+(kern-mk-sprite 's_P ss_u4_shapes 1 111 #f 0 )
+(kern-mk-sprite 's_Q ss_u4_shapes 1 112 #f 0 )
+(kern-mk-sprite 's_R ss_u4_shapes 1 113 #f 0 )
+(kern-mk-sprite 's_S ss_u4_shapes 1 114 #f 0 )
+(kern-mk-sprite 's_T ss_u4_shapes 1 115 #f 0 )
+(kern-mk-sprite 's_U ss_u4_shapes 1 116 #f 0 )
+(kern-mk-sprite 's_V ss_u4_shapes 1 117 #f 0 )
+(kern-mk-sprite 's_W ss_u4_shapes 1 118 #f 0 )
+(kern-mk-sprite 's_X ss_u4_shapes 1 119 #f 0 )
+(kern-mk-sprite 's_Y ss_u4_shapes 1 120 #f 0 )
+(kern-mk-sprite 's_Z ss_u4_shapes 1 121 #f 0 )
+
+(kern-mk-sprite 's_counter_2x1_c ss_u4_shapes 1 122 #f 0 )
+(kern-mk-sprite 's_counter_2x1_e ss_u4_shapes 1 123 #f 0 )
+(kern-mk-sprite 's_counter_2x1_w ss_u4_shapes 1 124 #f 0 )
+(kern-mk-sprite 's_counter_1x1   ss_u4_shapes 1 125 #f 0 )
+
+(kern-mk-sprite 's_blank          ss_u4_shapes 1 126 #f 0 )
+(kern-mk-sprite 's_null           ss_u4_shapes 1 126 #f 0 )
+(kern-mk-sprite 's_wall_stone     ss_u4_shapes 1 127 #f 0 )
+
+(kern-mk-sprite 's_pirate_left    ss_u4_shapes 1 128 #f 0 )
+(kern-mk-sprite 's_pirate_front   ss_u4_shapes 1 129 #f 0 )
+(kern-mk-sprite 's_pirate_right   ss_u4_shapes 1 130 #f 0 )
+(kern-mk-sprite 's_pirate_back    ss_u4_shapes 1 131 #f 0 )
+
+;;(kern-mk-sprite 's_nixie          ss_u4_shapes 2 132 #f 0 )
+(kern-mk-sprite 's_kraken         ss_u4_shapes 2 134 #f 0 )
+(kern-mk-sprite 's_sea_serpent    ss_u4_shapes 2 136 #f 0 )
+(kern-mk-sprite 's_sea_horse      ss_u4_shapes 2 138 #f 0 )
+(kern-mk-sprite 's_whirlpool      ss_u4_shapes 2 140 #f 0 )
+(kern-mk-sprite 's_tornado        ss_u4_shapes 2 142 #f 0 )
+
+(kern-mk-sprite 's_rat            ss_u4_shapes 4 144 #f 0 )
+(kern-mk-sprite 's_bat            ss_u4_shapes 4 148 #f 0 )
+(kern-mk-sprite 's_spider         ss_u4_shapes 4 152 #f 0 )
+(kern-mk-sprite 's_ghost          ss_u4_shapes 4 156 #f 0 )
+(kern-mk-sprite 's_slime          ss_u4_shapes 4 160 #f 0 )
+(kern-mk-sprite 's_slime_asleep   ss_u4_shapes 1 160 #f 0 )
+;;(kern-mk-sprite 's_troll          ss_u4_shapes 4 164 #f 0 )
+(kern-mk-sprite 's_gremlin        ss_u4_shapes 4 168 #f 0 )
+(kern-mk-sprite 's_mimic          ss_u4_shapes 4 172 #f 0 )
+(kern-mk-sprite 's_reaper         ss_u4_shapes 4 176 #f 0 )
+(kern-mk-sprite 's_insects        ss_u4_shapes 4 180 #f 0 )
+;;(kern-mk-sprite 's_gazer          ss_u4_shapes 4 184 #f 0 )
+(kern-mk-sprite 's_deathknight         ss_u4_shapes 4 188 #f 0 )
+(kern-mk-sprite 's_orc            ss_u4_shapes 4 192 #f 0 )
+;;(kern-mk-sprite 's_skeleton       ss_u4_shapes 4 196 #f 0 )
+;;(kern-mk-sprite 's_brigand        ss_u4_shapes 4 200 #f 0 )
+(kern-mk-sprite 's_snake          ss_u4_shapes 4 204 #f 0 )
+;;(kern-mk-sprite 's_ettin          ss_u4_shapes 4 208 #f 0 )
+;;(kern-mk-sprite 's_headless       ss_u4_shapes 4 212 #f 0 )
+(kern-mk-sprite 's_cyclops        ss_u4_shapes 4 216 #f 0 )
+(kern-mk-sprite 's_wisp           ss_u4_shapes 4 220 #f 0 )
+;;(kern-mk-sprite 's_wizard         ss_u4_shapes 4 224 #f 0 )
+;;(kern-mk-sprite 's_lich           ss_u4_shapes 4 228 #f 0 )
+(kern-mk-sprite 's_drake          ss_u4_shapes 4 232 #f 0 )
+(kern-mk-sprite 's_zorn           ss_u4_shapes 4 236 #f 0 )
+;;(kern-mk-sprite 's_demon          ss_u4_shapes 4 240 #f 0 )
+(kern-mk-sprite 's_hydra          ss_u4_shapes 4 244 #f 0 )
+;;(kern-mk-sprite 's_dragon         ss_u4_shapes 4 248 #f 0 )
+;;(kern-mk-sprite 's_balron         ss_u4_shapes 4 252 #f 0 )
+
+(kern-mk-sprite 's_frame_ulc   ss_frame 1  0 #f 0 )
+(kern-mk-sprite 's_frame_td    ss_frame 1  1 #f 0 )
+(kern-mk-sprite 's_frame_urc   ss_frame 1  2 #f 0 )
+(kern-mk-sprite 's_frame_endu  ss_frame 1  3 #f 0 )  ; top of vertical bar, currently unused
+(kern-mk-sprite 's_frame_tr    ss_frame 1  4 #f 0 )
+(kern-mk-sprite 's_frame_plus  ss_frame 1  5 #f 0 )  ; center crosspiece, currently unused
+(kern-mk-sprite 's_frame_tl    ss_frame 1  6 #f 0 )
+(kern-mk-sprite 's_frame_vert  ss_frame 1  7 #f 0 )
+(kern-mk-sprite 's_frame_llc   ss_frame 1  8 #f 0 )
+(kern-mk-sprite 's_frame_tu    ss_frame 1  9 #f 0 )
+(kern-mk-sprite 's_frame_lrc   ss_frame 1 10 #f 0 )
+(kern-mk-sprite 's_frame_endb  ss_frame 1 11 #f 0 )  ; bottom of vertical bar, currently unused
+(kern-mk-sprite 's_frame_endl  ss_frame 1 12 #f 0 )
+(kern-mk-sprite 's_frame_horz  ss_frame 1 13 #f 0 )
+(kern-mk-sprite 's_frame_endr  ss_frame 1 14 #f 0 )
+(kern-mk-sprite 's_frame_dot   ss_frame 1 15 #f 0 )  ; disconnected disk, currently unused
+
+(kern-mk-sprite 'ls_ankh          ss_u4_charset 1  0 #f 0 )
+(kern-mk-sprite 'ls_shield        ss_u4_charset 1  1 #f 0 )
+(kern-mk-sprite 'ls_holey_wall    ss_u4_charset 1  2 #f 0 )
+(kern-mk-sprite 'ls_wall          ss_u4_charset 1  3 #f 0 )
+(kern-mk-sprite 'ls_updown_arrow  ss_u4_charset 1  4 #f 0 )
+(kern-mk-sprite 'ls_down_arrow    ss_u4_charset 1  5 #f 0 )
+(kern-mk-sprite 'ls_up_arrow      ss_u4_charset 1  6 #f 0 )
+(kern-mk-sprite 'ls_holey_ankh    ss_u4_charset 1  7 #f 0 )
+(kern-mk-sprite 'ls_white_ball    ss_u4_charset 1  8 #f 0 )
+(kern-mk-sprite 'ls_copyright     ss_u4_charset 1  9 #f 0 )
+(kern-mk-sprite 'ls_trademark     ss_u4_charset 1 10 #f 0 )
+(kern-mk-sprite 'ls_male          ss_u4_charset 1 11 #f 0 )
+(kern-mk-sprite 'ls_female        ss_u4_charset 1 12 #f 0 )
+(kern-mk-sprite 'ls_hbar          ss_u4_charset 1 13 #f 0 )
+(kern-mk-sprite 'ls_vbar          ss_u4_charset 1 13 #f 0 )
+(kern-mk-sprite 'ls_square        ss_u4_charset 1 14 #f 0 )
+(kern-mk-sprite 'ls_blue_ball     ss_u4_charset 1 15 #f 0 )
+(kern-mk-sprite 'ls_hbar_right    ss_u4_charset 1 16 #f 0 )
+(kern-mk-sprite 'ls_hbar_left     ss_u4_charset 1 17 #f 0 )
+(kern-mk-sprite 'ls_vbar_top      ss_u4_charset 1 16 #f 0 )
+(kern-mk-sprite 'ls_vbar_bottom   ss_u4_charset 1 17 #f 0 )
+(kern-mk-sprite 'ls_blank_one     ss_u4_charset 1 18 #f 0 )
+(kern-mk-sprite 'ls_dot_dot_dot   ss_u4_charset 1 19 #f 0 )
+(kern-mk-sprite 'ls_whirlpool     ss_u4_charset 4 28 #f 0 )
+(kern-mk-sprite 'ls_blank_three   ss_u4_charset 1 32 #f 0 )
+
+(kern-mk-sprite 's_rune_A      ss_rune 1  0 #f 0 )
+(kern-mk-sprite 's_rune_B      ss_rune 1  1 #f 0 )
+(kern-mk-sprite 's_rune_C      ss_rune 1  2 #f 0 )
+(kern-mk-sprite 's_rune_D      ss_rune 1  3 #f 0 )
+(kern-mk-sprite 's_rune_E      ss_rune 1  4 #f 0 )
+(kern-mk-sprite 's_rune_F      ss_rune 1  5 #f 0 )
+(kern-mk-sprite 's_rune_G      ss_rune 1  6 #f 0 )
+(kern-mk-sprite 's_rune_H      ss_rune 1  7 #f 0 )
+(kern-mk-sprite 's_rune_I      ss_rune 1  8 #f 0 )
+(kern-mk-sprite 's_rune_J      ss_rune 1  9 #f 0 )
+(kern-mk-sprite 's_rune_K      ss_rune 1 10 #f 0 )
+(kern-mk-sprite 's_rune_L      ss_rune 1 11 #f 0 )
+(kern-mk-sprite 's_rune_M      ss_rune 1 12 #f 0 )
+(kern-mk-sprite 's_rune_N      ss_rune 1 13 #f 0 )
+(kern-mk-sprite 's_rune_O      ss_rune 1 14 #f 0 )
+(kern-mk-sprite 's_rune_P      ss_rune 1 15 #f 0 )
+(kern-mk-sprite 's_rune_Q      ss_rune 1 16 #f 0 )
+(kern-mk-sprite 's_rune_R      ss_rune 1 17 #f 0 )
+(kern-mk-sprite 's_rune_S      ss_rune 1 18 #f 0 )
+(kern-mk-sprite 's_rune_T      ss_rune 1 19 #f 0 )
+(kern-mk-sprite 's_rune_U      ss_rune 1 20 #f 0 )
+(kern-mk-sprite 's_rune_V      ss_rune 1 21 #f 0 )
+(kern-mk-sprite 's_rune_W      ss_rune 1 22 #f 0 )
+(kern-mk-sprite 's_rune_X      ss_rune 1 23 #f 0 )
+(kern-mk-sprite 's_rune_Y      ss_rune 1 24 #f 0 )
+(kern-mk-sprite 's_rune_Z      ss_rune 1 25 #f 0 )
+(kern-mk-sprite 's_rune_TH     ss_rune 1 26 #f 0 )
+(kern-mk-sprite 's_rune_EE     ss_rune 1 27 #f 0 )
+(kern-mk-sprite 's_rune_NG     ss_rune 1 28 #f 0 )
+(kern-mk-sprite 's_rune_EA     ss_rune 1 29 #f 0 )
+(kern-mk-sprite 's_rune_ST     ss_rune 1 30 #f 0 )
+(kern-mk-sprite 's_rune_DOTSEP ss_rune 1 31 #f 0 )
+
+(kern-mk-sprite 's_crosshair            ss_addon 1  0 #f   0 )
+(kern-mk-sprite 's_blackgate_quarter        ss_addon 1 1 #f 0 )
+(kern-mk-sprite 's_blackgate_half           ss_addon 1 2 #f 0 )
+(kern-mk-sprite 's_blackgate_three_quarters ss_addon 1 3 #f 0 )
+(kern-mk-sprite 's_blackgate_full           ss_addon 1 4 #f 0 )
+(kern-mk-sprite 's_horse                ss_addon 1  5 #f  40 )
+(kern-mk-sprite 's_happy_monster_face   ss_addon 1  7 #f   0 )
+(kern-mk-sprite 's_ship                 ss_addon 1  8 #f 170 )
+(kern-mk-sprite 's_queen_spider         ss_addon 4 12 #f 0 )
+(kern-mk-sprite 's_hdoor                ss_addon 1 19 #f 0 )
+(kern-mk-sprite 's_hdoor_locked         ss_addon 1 20 #f 0 )
+(kern-mk-sprite 's_portcullis_down      ss_addon 1 21 #f 0 )
+(kern-mk-sprite 's_portcullis_up        ss_addon 1 22 #f 0 )
+(kern-mk-sprite 's_forest_yellow        ss_addon 1 23 #f 0 )
+(kern-mk-sprite 's_L_lever_up           ss_addon 1 24 #f 0 )
+(kern-mk-sprite 's_L_lever_down         ss_addon 1 25 #f 0 )
+(kern-mk-sprite 's_R_lever_up           ss_addon 1 26 #f 0 )
+(kern-mk-sprite 's_R_lever_down         ss_addon 1 27 #f 0 )
+(kern-mk-sprite 's_floor_plate          ss_addon 1 28 #f 0 )
+(kern-mk-sprite 's_ns_bridge            ss_addon 1 29 #f 0 )
+(kern-mk-sprite 's_forest_purple        ss_addon 1 30 #f 0 )
+(kern-mk-sprite 's_forest_red           ss_addon 1 31 #f 0 )
+(kern-mk-sprite 's_trees_orange         ss_addon 1 32 #f 0 )
+(kern-mk-sprite 's_trees_yellow         ss_addon 1 33 #f 0 )
+(kern-mk-sprite 's_trees_purple         ss_addon 1 34 #f 0 )
+(kern-mk-sprite 's_trees_red            ss_addon 1 35 #f 0 )
+(kern-mk-sprite 's_bed                  ss_addon 1 36 #f 0 )
+(kern-mk-sprite 's_fireplace            ss_addon 2 37 #f 0 )
+;;(kern-mk-sprite 's_gwen                 ss_addon 2 40 #f 0 )
+(kern-mk-sprite 's_yellow_slime         ss_addon 4 42 #f 0 )
+(kern-mk-sprite 's_yellow_slime_asleep  ss_addon 1 42 #f 0 )
+(kern-mk-sprite 's_wall_torch           ss_addon 2 46 #f 0 )
+(kern-mk-sprite 's_water_elemental      ss_addon 1 48 #t 0 )
+(kern-mk-sprite 's_toy_horse                                  ss_addon 1 55 #f 0 )
+;;(kern-mk-sprite 's_closed_solid_wood_door_in_stone            ss_addon 1 49 #f 0 )
+;;(kern-mk-sprite 's_open_door_in_stone                         ss_addon 1 50 #f 0 )
+;;(kern-mk-sprite 's_locked_solid_wood_door_in_stone            ss_addon 1 51 #f 0 )
+;;(kern-mk-sprite 's_magically_locked_solid_wood_door_in_stone  ss_addon 3 52 #f 0 )
+(kern-mk-sprite 's_rock_arch                                    ss_addon 1 49 #f 0 )
+(kern-mk-sprite 's_stone_arch                                   ss_addon 1 50 #f 0 )
+(kern-mk-sprite 's_door_wood                                    ss_addon 1 51 #f 0 )
+(kern-mk-sprite 's_door_lock                                    ss_addon 1 52 #f 0 )
+(kern-mk-sprite 's_door_windowed                                ss_addon 1 53 #f 0 )
+(kern-mk-sprite 's_door_magiclock                               ss_addon 3 59 #f 0 )
+;;(kern-mk-sprite 's_closed_solid_wood_door_in_rock             ss_addon 1 56 #f 0 )
+;;(kern-mk-sprite 's_open_door_in_rock                          ss_addon 1 57 #f 0 )
+;;(kern-mk-sprite 's_locked_solid_wood_door_in_rock             ss_addon 1 58 #f 0 )
+;;(kern-mk-sprite 's_magically_locked_solid_wood_door_in_rock   ss_addon 3 59 #f 0 )
+;;(kern-mk-sprite 's_closed_windowed_wood_door_in_rock          ss_addon 1 68 #f 0 )
+;;(kern-mk-sprite 's_locked_windowed_wood_door_in_rock          ss_addon 1 69 #f 0 )
+(kern-mk-sprite 's_smoke                                      ss_addon 2 68 #f 0)
+(kern-mk-sprite 's_spider_web                                 ss_addon 1 70 #f 0)
+(kern-mk-sprite 's_corpse                                     ss_addon 1 71 #f 0)
+;;(kern-mk-sprite 's_magically_locked_windowed_wood_door_in_rock ss_addon 3 76 #f 0 )
+(kern-mk-sprite 's_deep_lava                                   ss_addon 1 79 #t 0)
+(kern-mk-sprite 's_golden_skeleton_key  ss_addon 1 77 #f 0)
+(kern-mk-sprite 's_arrow_slit       ss_addon 1 62 #f 0 )
+(kern-mk-sprite 's_window_in_stone  ss_addon 1 63 #f 0 )
+(kern-mk-sprite 's_trail_0  ss_addon 1 64 #f 0 )
+(kern-mk-sprite 's_trail_1  ss_addon 1 65 #f 0 )
+(kern-mk-sprite 's_trail_2  ss_addon 1 66 #f 0 )
+(kern-mk-sprite 's_trail_3  ss_addon 1 67 #f 0 )
+(kern-mk-sprite 's_trail_4  ss_addon 1 72 #f 0 )
+(kern-mk-sprite 's_trail_5  ss_addon 1 73 #f 0 )
+(kern-mk-sprite 's_trail_6  ss_addon 1 74 #f 0 )
+(kern-mk-sprite 's_trail_7  ss_addon 1 75 #f 0 )
+(kern-mk-sprite 's_trail_8  ss_addon 1 80 #f 0 )
+(kern-mk-sprite 's_trail_9  ss_addon 1 81 #f 0 )
+(kern-mk-sprite 's_trail_a  ss_addon 1 82 #f 0 )
+(kern-mk-sprite 's_trail_b  ss_addon 1 83 #f 0 )
+;;(kern-mk-sprite 's_chanticleer ss_addon 2 84 #f 0)
+(kern-mk-sprite 's_stars       ss_addon 2 86 #f 0)
+(kern-mk-sprite 's_trail_c  ss_addon 1 88 #f 0 )
+(kern-mk-sprite 's_trail_d  ss_addon 1 89 #f 0 )
+(kern-mk-sprite 's_trail_e  ss_addon 1 90 #f 0 )
+(kern-mk-sprite 's_trail_f  ss_addon 1 91 #f 0 )
+(kern-mk-sprite 's_townswoman ss_addon 2 92 #f 0)
+;;(kern-mk-sprite 's_fat_townswoman ss_addon 2 97 #f 0)
+;;(kern-mk-sprite 's_lady ss_addon 2 99 #f 0)
+;;(kern-mk-sprite 's_doorway ss_addon 1 101 #f 0)
+(kern-mk-sprite 's_goblin_child ss_addon 2 102 #f 0)
+(kern-mk-sprite 's_purple_spider ss_addon 4 104 #f 0)
+;;(kern-mk-sprite 's_brigandess ss_addon 4 108 #f 0)
+(kern-mk-sprite 's_wolf ss_addon 4 112 #f 0)
+(kern-mk-sprite 's_void_ship ss_addon 1 116 #f 170)
+;;(kern-mk-sprite 's_human_knight ss_addon 4 120 #f 0 )
+(kern-mk-sprite 's_red_slime ss_addon 4 124 #f 0)
+(kern-mk-sprite 's_red_slime_asleep ss_addon 1 124 #f 0)
+(kern-mk-sprite 's_active_altar_obj ss_addon 4 128 #f 0)
+(kern-mk-sprite 's_tentacle ss_addon 4 132 #f 0)
+(kern-mk-sprite 's_sludge ss_addon 1 136 #t 0)
+(kern-mk-sprite 's_dirt ss_addon 1 137 #f 0)
+(kern-mk-sprite 's_gravel ss_addon 1 138 #f 0)
+(kern-mk-sprite 's_great_kraken ss_addon 2 139 #f 0)
+(kern-mk-sprite 's_shallow_sludge ss_addon 1 143 #t 0)
+(kern-mk-sprite 's_weather_vane ss_addon 1 144 #f 170)
+(kern-mk-sprite 's_mouse        ss_addon 2 148 #f 0)
+(kern-mk-sprite 's_eye_closed   ss_addon 1 150 #f 0)
+(kern-mk-sprite 's_eye_open     ss_addon 1 151 #f 0)
+
+(kern-mk-sprite 's_full_moon                ss_moons 1 0 #f 0 )
+(kern-mk-sprite 's_wane_three_quarter_moon  ss_moons 1 1 #f 0 )
+(kern-mk-sprite 's_wane_half_moon           ss_moons 1 2 #f 0 )
+(kern-mk-sprite 's_wane_quarter_moon        ss_moons 1 3 #f 0 )
+(kern-mk-sprite 's_new_moon                 ss_moons 1 4 #f 0 )
+(kern-mk-sprite 's_wax_quarter_moon         ss_moons 1 5 #f 0 )
+(kern-mk-sprite 's_wax_half_moon            ss_moons 1 6 #f 0 )
+(kern-mk-sprite 's_wax_three_quarter_moon   ss_moons 1 7 #f 0 )
+
+(kern-mk-sprite 's_yellow_full_moon                ss_moons 1 8 #f 0 )
+(kern-mk-sprite 's_yellow_wane_three_quarter_moon  ss_moons 1 9 #f 0 )
+(kern-mk-sprite 's_yellow_wane_half_moon           ss_moons 1 10 #f 0 )
+(kern-mk-sprite 's_yellow_wane_quarter_moon        ss_moons 1 11 #f 0 )
+(kern-mk-sprite 's_yellow_new_moon                 ss_moons 1 12 #f 0 )
+(kern-mk-sprite 's_yellow_wax_quarter_moon         ss_moons 1 13 #f 0 )
+(kern-mk-sprite 's_yellow_wax_half_moon            ss_moons 1 14 #f 0 )
+(kern-mk-sprite 's_yellow_wax_three_quarter_moon   ss_moons 1 15 #f 0 )
+
+(kern-mk-sprite 's_blue_full_moon                ss_moons 1 16 #f 0 )
+(kern-mk-sprite 's_blue_wane_three_quarter_moon  ss_moons 1 17 #f 0 )
+(kern-mk-sprite 's_blue_wane_half_moon           ss_moons 1 18 #f 0 )
+(kern-mk-sprite 's_blue_wane_quarter_moon        ss_moons 1 19 #f 0 )
+(kern-mk-sprite 's_blue_new_moon                 ss_moons 1 20 #f 0 )
+(kern-mk-sprite 's_blue_wax_quarter_moon         ss_moons 1 21 #f 0 )
+(kern-mk-sprite 's_blue_wax_half_moon            ss_moons 1 22 #f 0 )
+(kern-mk-sprite 's_blue_wax_three_quarter_moon   ss_moons 1 23 #f 0 )
+
+(kern-mk-sprite 's_sun                      ss_moons 1 24 #f 0 )
+
+(kern-mk-sprite 's_torch_sign ss_signs     1 0 #f 0)
+(kern-mk-sprite 's_shield_sign ss_signs    1 1 #f 0)
+(kern-mk-sprite 's_ankh_sign ss_signs      1 2 #f 0)
+(kern-mk-sprite 's_beer_sign ss_signs      1 3 #f 0)
+(kern-mk-sprite 's_bed_sign ss_signs       1 4 #f 0)
+(kern-mk-sprite 's_potion_sign ss_signs    1 5 #f 0)
+(kern-mk-sprite 's_mushroom_sign ss_signs  1 6 #f 0)
+(kern-mk-sprite 's_axe_sign ss_signs  1 8 #f 0)
+(kern-mk-sprite 's_key_sign ss_signs  1 9 #f 0)
+(kern-mk-sprite 's_book_sign ss_signs  1 10 #f 0)
+
+(define (mk-sprite tag offset)
+  (kern-mk-sprite tag ss_runestones 1 offset #f 0))
+(mk-sprite 's_runestone_a 0)
+(mk-sprite 's_runestone_b 1) 
+(mk-sprite 's_runestone_c 2) 
+(mk-sprite 's_runestone_d 3)
+(mk-sprite 's_runestone_e 4)
+(mk-sprite 's_runestone_f 5)
+(mk-sprite 's_runestone_g 6)
+(mk-sprite 's_runestone_h 7)
+(mk-sprite 's_runestone_i 8)
+(mk-sprite 's_runestone_j 9)
+(mk-sprite 's_runestone_k 10)
+(mk-sprite 's_runestone_l 11)
+(mk-sprite 's_runestone_m 12)
+(mk-sprite 's_runestone_n 13)
+(mk-sprite 's_runestone_o 14)
+(mk-sprite 's_runestone_p 15)
+(mk-sprite 's_runestone_q 16)
+(mk-sprite 's_runestone_r 17)
+(mk-sprite 's_runestone_s 18)
+(mk-sprite 's_runestone_t 19)
+(mk-sprite 's_runestone_u 20)
+(mk-sprite 's_runestone_v 21)
+(mk-sprite 's_runestone_w 22)
+(mk-sprite 's_runestone_x 23)
+(mk-sprite 's_runestone_y 24)
+(mk-sprite 's_runestone_z 25)
+(mk-sprite 's_runestone_group 26)
+(mk-sprite 's_runestone_ankh 31)
+
+(kern-mk-sprite 's_fgob_stalker ss_humanoids  4 0 #f 0 )
+(kern-mk-sprite 's_fgob_archer ss_humanoids   4 8 #f 0 )
+(kern-mk-sprite 's_fgob_civilian ss_humanoids 4 16 #f 0 )
+(kern-mk-sprite 's_fgob_shaman ss_humanoids   4 24 #f 0 )
+(kern-mk-sprite 's_cgob_berserk ss_humanoids  4 4 #f 0 )
+(kern-mk-sprite 's_cgob_slinger ss_humanoids  4 12 #f 0 )
+(kern-mk-sprite 's_cgob_civilian ss_humanoids 4 20 #f 0 )
+(kern-mk-sprite 's_cgob_shaman ss_humanoids   4 28 #f 0 )
+(kern-mk-sprite 's_gint_party ss_humanoids 4 32 #f 0 )
+(kern-mk-sprite 's_deathknight ss_humanoids 4 36 #f 0 )
+(kern-mk-sprite 's_gint_mage_party ss_humanoids 4 40 #f 0 )
+(kern-mk-sprite 's_troll ss_humanoids 4 48 #f 0 )
+(kern-mk-sprite 's_troll_geomancer ss_humanoids 4 44 #f 0 )
+(kern-mk-sprite 's_headless ss_humanoids 4 52 #f 0 )
+(kern-mk-sprite 's_demon ss_humanoids 4 56 #f 0 )
+(kern-mk-sprite 's_ratling ss_humanoids 4 64 #f 0)
+(kern-mk-sprite 's_ratling_sorcerer ss_humanoids 4 68 #f 0)
+(kern-mk-sprite 's_deatharcher ss_humanoids 4 72 #f 0 )
+(kern-mk-sprite 's_skeleton       ss_humanoids 4 76 #f 0 )
+(kern-mk-sprite 's_spearskeleton     ss_humanoids 4 80 #f 0 )
+(kern-mk-sprite 's_skeletonarcher    ss_humanoids 4 84 #f 0 )
+(kern-mk-sprite 's_lich           ss_humanoids 4 88 #f 0 )
+(kern-mk-sprite 's_nixie_civilian    ss_humanoids 4 92 #f 0 )
+(kern-mk-sprite 's_nixie_spear          ss_humanoids 4 96 #f 0 )
+(kern-mk-sprite 's_nixie_sword          ss_humanoids 4 100 #f 0 )
+
+(kern-mk-sprite 's_gint ss_bigobjects 4 0 #f 0 )
+(kern-mk-sprite 's_gint_mage ss_bigobjects 4 4 #f 0 )
+(kern-mk-sprite 's_balron   ss_bigobjects 4 8 #f 0 )
+(kern-mk-sprite 's_dex_statue   ss_bigobjects 1 12 #f 0 )
+(kern-mk-sprite 's_str_statue   ss_bigobjects 1 13 #f 0 )
+(kern-mk-sprite 's_int_statue   ss_bigobjects 1 14 #f 0 )
+(kern-mk-sprite 's_towertown_ruin   ss_bigobjects 1 15 #f 0 )
+(kern-mk-sprite 's_dragon   ss_bigobjects 4 16 #f 0 )
+(kern-mk-sprite 's_dragon_asleep   ss_bigobjects 1 20 #f 0 )
+(kern-mk-sprite 's_tower   ss_bigobjects 2 22 #f 0 )
+(kern-mk-sprite 's_towertown   ss_bigobjects 2 24 #f 0 )
+
+
+;;----------------------------------------------------------------------------
+;;;; (kern-mk-sprite 's_wanderer ss_addon 2 94 #f 0)
+;;;; (kern-mk-sprite 's_avatar             ss_u4_shapes 1 31 #f 0 )
+;;;; (kern-mk-sprite 's_companion_wizard   ss_u4_shapes 2 32 #f 0 )
+;;;; (kern-mk-sprite 's_companion_bard     ss_u4_shapes 2 34 #f 0 )
+;;;; (kern-mk-sprite 's_companion_fighter  ss_u4_shapes 2 36 #f 0 )
+;;;; (kern-mk-sprite 's_companion_druid    ss_u4_shapes 2 38 #f 0 )
+;;;; (kern-mk-sprite 's_companion_tinker   ss_u4_shapes 2 40 #f 0 )
+;;;; (kern-mk-sprite 's_companion_paladin  ss_u4_shapes 2 42 #f 0 )
+;;;; (kern-mk-sprite 's_companion_ranger   ss_u4_shapes 2 44 #f 0 )
+;;;; (kern-mk-sprite 's_companion_shepherd ss_u4_shapes 2 46 #f 0 )
+
+(kern-mk-sprite 's_wanderer ss_people 4 0 #f 0 )
+(kern-mk-sprite 's_avatar   ss_people 4 4 #f 0 )
+(kern-mk-sprite 's_companion_wizard ss_people 4 8 #f 0 )
+(kern-mk-sprite 's_companion_bard ss_people 4 12 #f 0 )
+(kern-mk-sprite 's_companion_fighter ss_people 4 16 #f 0 )
+(kern-mk-sprite 's_companion_druid ss_people 4 20 #f 0 )
+(kern-mk-sprite 's_companion_tinker ss_people 4 24 #f 0 )
+(kern-mk-sprite 's_companion_paladin ss_people 4 28 #f 0 )
+(kern-mk-sprite 's_companion_ranger ss_people 4 32 #f 0 )
+(kern-mk-sprite 's_companion_shepherd ss_people 4 36 #f 0 )
+(kern-mk-sprite 's_old_mage ss_people 4 40 #f 0 )
+(kern-mk-sprite 's_black_mage ss_people 4 44 #f 0 )
+(kern-mk-sprite 's_guard ss_people 4 48 #f 0 )
+(kern-mk-sprite 's_plain_mage ss_people 4 52 #f 0 )
+(kern-mk-sprite 's_townsman ss_people 2 56 #f 0 )
+(kern-mk-sprite 's_townswoman ss_people 2 58 #f 0 )
+(kern-mk-sprite 's_brigand ss_people 4 60 #f 0 )
+(kern-mk-sprite 's_red_wizard ss_people 4 64 #f 0 )
+(kern-mk-sprite 's_xbowguard ss_people 2 68 #f 0 )
+(kern-mk-sprite 's_lady ss_people 2 70 #f 0 )
+(kern-mk-sprite 's_cloaked_female ss_people 4 72 #f 0 )
+(kern-mk-sprite 's_brigandess ss_people 4 76 #f 0 )
+(kern-mk-sprite 's_fat_townswoman ss_people 4 80 #f 0 )
+(kern-mk-sprite 's_knight ss_people 4 84 #f 0 )
+(kern-mk-sprite 's_minstrel ss_people 2 88 #f 0 )
+(kern-mk-sprite 's_beggar ss_people 2 90 #f 0 )
+(kern-mk-sprite 's_jester ss_people 4 92 #f 0 )
+(kern-mk-sprite 's_child ss_people 2 96 #f 0 )
+(kern-mk-sprite 's_asleep      ss_people 1 98 #f 0 )
+(kern-mk-sprite 's_ranger_captain ss_people 4 104 #f 0)
+(kern-mk-sprite 's_old_ranger ss_people 4 108 #f 0)
+(kern-mk-sprite 's_old_townsman ss_people 4 112 #f 0)
+(kern-mk-sprite 's_fallen_paladin ss_people 4 116 #f 0)
+
+(kern-mk-sprite 's_carabid ss_monsters 4 0 #f 0)
+(kern-mk-sprite 's_carabid_asleep ss_monsters 1 0 #f 0)
+(kern-mk-sprite 's_griffin ss_monsters 4 4 #f 0)
+(kern-mk-sprite 's_griffin_asleep ss_monsters 1 4 #f 0)
+(kern-mk-sprite 's_griffin_chick ss_monsters 4 12 #f 0)
+(kern-mk-sprite 's_griffin_chick_asleep ss_monsters 1 12 #f 0)
+(kern-mk-sprite 's_gazer          ss_monsters 4 8 #f 0 )
+(kern-mk-sprite 's_gazer_asleep   ss_monsters 1 16 #f 0 )
+(kern-mk-sprite 's_dragon_party   ss_monsters 4 20 #f 0 )
+
+(kern-mk-sprite 's_deer ss_creatures 4 0 #f 0)
+(kern-mk-sprite 's_chicken ss_creatures 2 4 #f 0)
+
+;;(kern-mk-sprite 's_tower ss_buildings 2 0 #f 0)
+
+(kern-mk-sprite 's_trees         ss_overlays 1  20 #f 0 )
+(kern-mk-sprite 's_forest        ss_overlays 1  21 #f 0 )
+(kern-mk-sprite 's_hills         ss_overlays 1  22 #f 0 )
+(kern-mk-sprite 's_mountains     ss_overlays 1  23 #f 0 )
+(kern-mk-sprite 's_dungeon       ss_overlays 1  24 #f 0 )
+(kern-mk-sprite 's_statue        ss_overlays 1  25 #f 0 )
+;(kern-mk-sprite 's_secret_rock   ss_overlays 1  26 #f 0 )
+(kern-mk-sprite 's_blank                ss_overlays 1  27 #f 0 )
+(kern-mk-sprite 's_boulder_over  ss_overlays 1  68 #f 0 )
+(kern-mk-sprite 's_boulder       ss_overlays 1  69 #f 0 )
+(kern-mk-sprite 's_wall_rock     ss_overlays 1  72 #f 0 )
+(kern-mk-sprite 's_secret_rock     ss_overlays 1  73 #f 0 )
+(kern-mk-sprite 's_window_in_rock     ss_overlays 1  74 #f 0 )
+(kern-mk-sprite 's_nat_rock           ss_overlays 1  75 #f 0 )
+(kern-mk-sprite 's_nat_rock_s         ss_overlays 1  76 #f 0 )
+(kern-mk-sprite 's_nat_rock_n         ss_overlays 1  77 #f 0 )
+(kern-mk-sprite 's_nat_rock_w         ss_overlays 1  78 #f 0 )
+(kern-mk-sprite 's_nat_rock_e         ss_overlays 1  79 #f 0 )
+(kern-mk-sprite 's_secret_nrock       ss_overlays 1  83 #f 0 )
+(kern-mk-sprite 's_headless_w_sword_statue ss_overlays 1 104 #f 0)
+
+(kern-mk-sprite 's_gold_cobble  ss_overlays 1 105 #f 0)
+(kern-mk-sprite 's_cyan_cobble  ss_overlays 1 106 #f 0)
+(kern-mk-sprite 's_gray_cobble  ss_overlays 1 107 #f 0)
+(kern-mk-sprite 's_blue_cobble  ss_overlays 1 108 #f 0)
+(kern-mk-sprite 's_olive_cobble ss_overlays 1 109 #f 0)
+(kern-mk-sprite 's_white_cobble ss_overlays 1 110 #f 0)
+(kern-mk-sprite 's_black_tile   ss_overlays 1 111 #f 0)
+(kern-mk-sprite 's_gold_spiral_tile   ss_overlays 1 112 #f 0)
+(kern-mk-sprite 's_blue_spiral_tile   ss_overlays 1 113 #f 0)
+(kern-mk-sprite 's_tombstone          ss_overlays 1 114 #f 0)
+(kern-mk-sprite 's_tombstone2         ss_overlays 1 115 #f 0)
+
+(kern-mk-sprite 's_bulwark_ew     ss_ship 1  0 #f 0 )
+(kern-mk-sprite 's_bulwark_ns     ss_ship 1  1 #f 0 )
+(kern-mk-sprite 's_deck_w         ss_ship 1  2 #f 0 )
+(kern-mk-sprite 's_deck_e         ss_ship 1  3 #f 0 )
+(kern-mk-sprite 's_deck_n         ss_ship 1  4 #f 0 )
+(kern-mk-sprite 's_deck_s         ss_ship 1  5 #f 0 )
+(kern-mk-sprite 's_stair_n         ss_ship 1  6 #f 0 )
+(kern-mk-sprite 's_stair_s         ss_ship 1  7 #f 0 )
+(kern-mk-sprite 's_bulwark_ne         ss_ship 1 8 #f 0 )
+(kern-mk-sprite 's_bulwark_se         ss_ship 1 9 #f 0 )
+(kern-mk-sprite 's_bulwark_nw         ss_ship 1 10 #f 0 )
+(kern-mk-sprite 's_bulwark_sw         ss_ship 1 11 #f 0 )
+(kern-mk-sprite 's_stair_w         ss_ship 1  12 #f 0 )
+(kern-mk-sprite 's_stair_e         ss_ship 1  13 #f 0 )
+(kern-mk-sprite 's_tank_d         ss_ship 1  14 #f 0 )
+(kern-mk-sprite 's_tank_l         ss_ship 1  15 #f 0 )
+(kern-mk-sprite 's_tank_nw         ss_ship 1  16 #f 0 )
+(kern-mk-sprite 's_tank_ne         ss_ship 1  17 #f 0 )
+(kern-mk-sprite 's_tank_sw         ss_ship 1  24 #f 0 )
+(kern-mk-sprite 's_tank_se         ss_ship 1  25 #f 0 )
+(kern-mk-sprite 's_shipswheel      ss_ship 1  18 #f 170 )
+(kern-mk-sprite 's_cannon          ss_ship 1  26 #f 170 )
+
+;(define s_altar (mk-composite-sprite (list s_cobblestone s_altar_obj)))
+;(define s_active_altar (mk-composite-sprite (list s_cobblestone s_active_altar_obj)))
+
+(define s_altar (mk-composite-sprite (list s_grass s_altar_obj)))
+(define s_active_altar (mk-composite-sprite (list s_grass s_active_altar_obj)))
+(define s_overgrown_altar (mk-composite-sprite (list s_trees s_altar_obj)))
+
+
+;;----------------------------------------------------------------------------
+;; Terrain overlay pieces
+(define (mk-sprite tag offset)
+  (kern-mk-sprite tag ss_overlays 1 offset #f 0))
+(mk-sprite 's_grass_nw 0)
+(mk-sprite 's_grass_ne 1)
+(mk-sprite 's_grass_se 2)
+(mk-sprite 's_grass_sw 3)
+(mk-sprite 's_grass_n  8)
+(mk-sprite 's_grass_e  9)
+(mk-sprite 's_grass_s  10)
+(mk-sprite 's_grass_w  11)
+
+;;----------------------------------------------------------------------------
+;; Hill overlay pieces
+(define (mk-sprite tag offset)
+  (kern-mk-sprite tag ss_overlays 1 offset #f 0))
+(mk-sprite 's_hill_e  12)
+(mk-sprite 's_hill_s  13)
+(mk-sprite 's_hill_w  14)
+(mk-sprite 's_hill_n  15)
+
+;;----------------------------------------------------------------------------
+;; Trees overlay pieces
+(mk-sprite 's_treesi_nw 28)
+(mk-sprite 's_treesi_ne 29)
+(mk-sprite 's_treesi_se 30)
+(mk-sprite 's_treesi_sw 31)
+(mk-sprite 's_treeso_nw 32)
+(mk-sprite 's_treeso_ne 33)
+(mk-sprite 's_treeso_se 34)
+(mk-sprite 's_treeso_sw 35)
+(mk-sprite 's_grasso_nw 36)
+(mk-sprite 's_grasso_ne 37)
+(mk-sprite 's_grasso_se 38)
+(mk-sprite 's_grasso_sw 39)
+(mk-sprite 's_grassi_c  7)
+(mk-sprite 's_trees_nw 48)
+(mk-sprite 's_trees_ne 49)
+(mk-sprite 's_trees_se 50)
+(mk-sprite 's_trees_sw 51)
+(mk-sprite 's_trees_c 52)
+(mk-sprite 's_hills_c 53)
+(mk-sprite 's_hills_nw 56)
+(mk-sprite 's_hills_ne 57)
+(mk-sprite 's_hills_se 58)
+(mk-sprite 's_hills_sw 59)
+(mk-sprite 's_mount_c 54)
+(mk-sprite 's_mount_nw 60)
+(mk-sprite 's_mount_ne 61)
+(mk-sprite 's_mount_se 62)
+(mk-sprite 's_mount_sw 63)
+(mk-sprite 's_forest_c 55)
+(mk-sprite 's_forest_nw 64)
+(mk-sprite 's_forest_ne 65)
+(mk-sprite 's_forest_se 66)
+(mk-sprite 's_forest_sw 67)
+
+(kern-mk-sprite 's_deep          ss_overlays 1  4 #t 0 )
+(kern-mk-sprite 's_shallow       ss_overlays 1  5 #t 0 )
+(kern-mk-sprite 's_shoals        ss_overlays 1  6 #t 0 )
+
+;; Character effect icons shown in the ztats window
+(kern-mk-sprite 's_torchlight  ss_effects 1  0 #f 0 )
+(kern-mk-sprite 's_light       ss_effects 1  1 #f 0 )
+(kern-mk-sprite 's_poison      ss_effects 1 2 #f 0 )
+(kern-mk-sprite 's_disease     ss_effects 1 3 #f 0 )
+(kern-mk-sprite 's_im_poison   ss_effects 1 4 #f 0 )
+(kern-mk-sprite 's_sleep       ss_effects 1 5 #f 0 )
+(kern-mk-sprite 's_protect     ss_effects 1 6 #f 0 )
+(kern-mk-sprite 's_charm       ss_effects 1 7 #f 0 )
+(kern-mk-sprite 's_invis       ss_effects 1 8 #f 0 )
+(kern-mk-sprite 's_spider_calm ss_effects 1 9 #f 0 )
+(kern-mk-sprite 's_drunk       ss_effects 1 10 #f 0 )
+(kern-mk-sprite 's_im_disease  ss_effects 1 11 #f 0 )
+(kern-mk-sprite 's_tangle      ss_effects 1 12 #f 0 )
+(kern-mk-sprite 's_im_paralyse ss_effects 1 13 #f 0 )
+(kern-mk-sprite 's_im_fire     ss_effects 1 14 #f 0 )
+(kern-mk-sprite 's_im_death    ss_effects 1 15 #f 0 )
+(kern-mk-sprite 's_im_charm    ss_effects 1 16 #f 0 )
+(kern-mk-sprite 's_im_sleep    ss_effects 1 17 #f 0 )
+(kern-mk-sprite 's_paralyse    ss_effects 1 18 #f 0 )
+(kern-mk-sprite 's_unrest       ss_effects 1 24 #f 0 )
+
+;; Global effect icons shown in the foogod window
+(kern-mk-sprite 's_time_stop    ss_effects 1 19 #f 0)
+(kern-mk-sprite 's_quicken      ss_effects 1 20 #f 0)
+(kern-mk-sprite 's_magic_negated ss_effects 1 21 #f 0)
+(kern-mk-sprite 's_reveal        ss_effects 1 22 #f 0)
+(kern-mk-sprite 's_xray_vision   ss_effects 1 23 #f 0)
+
+
+;; convenient alia
+(define s_shepherd s_companion_shepherd)
+(define s_ranger s_companion_ranger)
+(define s_blue_wizard s_companion_wizard)
+(define s_wizard s_red_wizard)
+(define s_fighter s_companion_fighter)
+(define s_gwen s_cloaked_female)
+(define s_silas s_plain_mage)
+(define s_enchanter s_old_mage)
+(define s_necromancer s_black_mage)
+(define s_chanticleer s_minstrel)
+
+;; Humanoid paper-doll-ready sprites
+(define (mk-sprite tag sprite-set offset n-frames)
+  (kern-mk-sprite tag sprite-set n-frames offset #f 0))
+(mk-sprite 's_hum_body   ss_bodies     0 4)
+
+(mk-sprite 's_hum_beard          ss_adornments 0 1)
+(mk-sprite 's_hum_med_hair_gold  ss_adornments 4 1)
+(mk-sprite 's_hum_long_hair_gold ss_adornments 5 1)
+
+(mk-sprite 's_hum_pants  ss_clothes    0 1)
+(mk-sprite 's_hum_shirt  ss_clothes    4 1)
+(mk-sprite 's_hum_robe   ss_clothes    8 4)
+(mk-sprite 's_hum_belt   ss_clothes    12 1)
+(mk-sprite 's_hum_mantle ss_clothes    16 1)
+
+;;----------------------------------------------------------------------------
+;; Color conversion matrices - used as parms to the
+;; kern-sprite-apply-matrix. By convention, names are mat_<color>, where
+;; <color> is the target color and the source is assumed to be gray. To
+;; translate other colors, eg from red to blue, use a name like mat_red_blue.
+;;
+(define mat_red '((0 0 2)
+                  (0 0 0)
+                  (0 0 0)
+                  (0 0 0)))
+
+(define mat_green '((0 0 0)
+                    (0 2 0)
+                    (0 0 0)
+                    (0 0 0)))
+
+(define mat_blue '((0 0 0)
+                   (0 0 0)
+                   (0 0 2)
+                   (0 0 0)))
+
+(define mat_white '((3 0 0)
+                    (0 3 0)
+                    (0 0 3)
+                    (0 0 0)))
+
+(define mat_yellow '((3 0 0)
+                     (0 3 0)
+                     (0 0 0)
+                     (0 0 0)))
+
+(define mat_gold_to_midnight '((0 0 0.25)
+                               (0 0.25 0)
+                               (0.25 0 0)
+                               (0 0 0)))
+
+(define mat_blue_to_green '((1 0 0)
+                            (0 0 1)
+                            (0 1 0)
+                            (0 0 0)))
+
+;;----------------------------------------------------------------------------
+;; Sprites derived from other sprites via color conversion
+(define (mk-sprite tag matrix)
+  (kern-sprite-apply-matrix (kern-sprite-clone s_hum_robe tag) matrix))
+
+(mk-sprite 's_hum_robe_red    mat_red)
+(mk-sprite 's_hum_robe_green  mat_green)
+(mk-sprite 's_hum_robe_blue   mat_blue)
+(mk-sprite 's_hum_robe_white  mat_white)
+(mk-sprite 's_hum_robe_yellow mat_yellow)
+
+(define (mk-sprite tag matrix)
+  (kern-sprite-apply-matrix (kern-sprite-clone s_hum_mantle tag) matrix))
+
+(mk-sprite 's_hum_mantle_red    mat_red)
+(mk-sprite 's_hum_mantle_green  mat_green)
+(mk-sprite 's_hum_mantle_blue   mat_blue)
+(mk-sprite 's_hum_mantle_white  mat_white)
+(mk-sprite 's_hum_mantle_yellow mat_yellow)
+
+(define (mk-sprite tag matrix base)
+  (kern-sprite-apply-matrix (kern-sprite-clone base tag) matrix))
+
+(mk-sprite 's_hum_med_hair_midnight  mat_gold_to_midnight s_hum_med_hair_gold)
+(mk-sprite 's_hum_long_hair_midnight mat_gold_to_midnight s_hum_long_hair_gold)
+
+
+;;--------------------------------------------------------------------------
+;; 'special effects'
+
+(kern-mk-sprite 's_heart            ss_sfx   1  0 #f 0 )
+(kern-mk-sprite 's_hit         ss_sfx   1  1 #f 0 )
+(kern-mk-sprite 's_magicflash    ss_sfx   1  2 #f 0 )
+(kern-mk-sprite 's_lightning     ss_sfx   3  3 #f 495 )
+(kern-mk-sprite 's_field_energy ss_sfx   1  27 #t 0 )
+(kern-mk-sprite 's_field_fire   ss_sfx   1  28 #t 0 )
+(kern-mk-sprite 's_field_poison ss_sfx   1  29 #t 0 )
+(kern-mk-sprite 's_field_sleep  ss_sfx   1  30 #t 0 )
+(kern-mk-sprite 's_field_acid   ss_sfx   1  31 #t 0 )
+
+;;----------------------------------------------------------------------------
+;; Tools
+(kern-mk-sprite 's_torch    ss_tools 1 0 #f 0)
+(kern-mk-sprite 's_picklock ss_tools 1 1 #f 0)
+(kern-mk-sprite 's_gem      ss_tools 1 2 #f 0)
+(kern-mk-sprite 's_shovel   ss_tools 1 3 #f 0)
+(kern-mk-sprite 's_pick     ss_tools 1 4 #f 0)
+(kern-mk-sprite 's_sextant  ss_tools 1 5 #f 0)
+(kern-mk-sprite 's_chrono   ss_tools 1 6 #f 0)
+(kern-mk-sprite 's_clock_stopped    ss_tools 1 7 #f 0)
+(kern-mk-sprite 's_clock_body    ss_tools 2 8 #f 0)
+(kern-mk-sprite 's_clock_hand_n    ss_tools 1 10 #f 0)
+(kern-mk-sprite 's_clock_hand_ne    ss_tools 1 11 #f 0)
+(kern-mk-sprite 's_clock_hand_se    ss_tools 1 12 #f 0)
+(kern-mk-sprite 's_clock_hand_s    ss_tools 1 13 #f 0)
+(kern-mk-sprite 's_clock_hand_sw    ss_tools 1 14 #f 0)
+(kern-mk-sprite 's_clock_hand_nw    ss_tools 1 15 #f 0)
+(kern-mk-sprite 's_clock_spin            ss_tools 6 10 #f 0)
+(kern-mk-sprite 's_mirror_fg             ss_tools 1 16 #f 0)
+(kern-mk-sprite 's_mirror_bg_flagstones   ss_tools 1 17 #f 0)
+(kern-mk-sprite 's_mirror_bg   ss_tools 1 18 #f 0)
+(kern-mk-sprite 's_bookshelf   ss_tools 1 23 #f 0)
+(kern-mk-sprite 's_grease      ss_tools 1 24 #f 0)
+(kern-mk-sprite 's_rope_hook   ss_tools 1 25 #f 0)
+
+(kern-mk-sprite 's_chest              ss_tools 1 32 #f 0)
+(kern-mk-sprite 's_locked_chest       ss_tools 1 33 #f 0)
+(kern-mk-sprite 's_magic_chest        ss_tools 4 34 #f 0)
+(kern-mk-sprite 's_magic_locked_chest ss_tools 4 38 #f 0)
+
+;;------------------------------------------------
+;; Quest icons (well, many quests will use stuff already in the game, but whatever)
+
+(kern-mk-sprite 's_quest_start ss_quests 1 0 #f 0 )
+(kern-mk-sprite 's_quest_wise ss_quests 1 1 #f 0 )
diff --git a/worlds/haxima-1.002/start-new-game.scm b/worlds/haxima-1.002/start-new-game.scm
new file mode 100644 (file)
index 0000000..e513da2
--- /dev/null
@@ -0,0 +1,478 @@
+;;----------------------------------------------------------------------------
+;; The very first line of any session file should be (load "naz.scm"). This
+;; bootstraps some procedures that we need to continue. This is the only place
+;; you should use 'load'. Every other place you want to load a file you should
+;; user 'kern-load'. 'kern-load' ensures that a saved session will be able to
+;; load the file, too.
+;;----------------------------------------------------------------------------
+(load "naz.scm")
+(kern-script-version "0.7.0")
+
+;; Setup progress bar for loading. I arrived at the number by printing the
+;; current number of steps in src/foogod.c:foogod_progress_bar_finish().
+(kern-progress-bar-start "Loading" 205)
+
+;; Wrap the original definition of (load ...) with one that advances the
+;; progress bar.
+(define original-load load)  
+(define (load file)
+  (kern-progress-bar-advance 1)
+  (original-load file)
+  )
+
+;;----------------------------------------------------------------------------
+;; Load the read-only game data. See the note on 'kern-load' vs 'load' above.
+;;----------------------------------------------------------------------------
+(kern-load "game.scm")
+(kern-load "quests-mech.scm")
+(kern-load "camping-map.scm")
+
+(kern-load "quests-data-static.scm")
+(kern-load "zones.scm")
+(kern-load "runes.scm")
+(kern-load "prices.scm")
+(kern-load "special.scm")
+(kern-load "town-entry.scm")
+(kern-load "pseudorandom-map.scm")
+(kern-load "endless-deeps-mech.scm")
+(kern-load "lost-halls-mech.scm")
+(kern-load "voidgap-mech.scm")
+(kern-load "player.scm")
+
+;;----------------------------------------------------------------------------
+;; Time -- this needs to be set before loading any dungeon rooms
+;;----------------------------------------------------------------------------
+(define hour 07)
+(define minutes 00)
+(define time-in-minutes (+ (* hour 60) minutes))
+(define game-start-time (time-mk 1611 0 0 0 hour minutes))
+
+(kern-set-clock 
+ 1611 ; year
+ 0 ; month
+ 0 ; week
+ 0 ; day
+ hour  ; hour
+ minutes ; minutes
+ )
+
+;; NPC's who inhabit multiple places
+(kern-load "gregor.scm")
+(kern-load "kalcifax.scm")
+
+;;----------------------------------------------------------------------------
+;; Places
+;;----------------------------------------------------------------------------
+(load "gregors-hut.scm")
+(load "moongate-clearing.scm")
+(load "abandoned-farm.scm")
+(load "abandoned-cellar.scm")
+(load "slimy-cavern.scm")
+(load "trigrave.scm")
+(load "lost-halls.scm")
+(load "enchanters-tower.scm")
+(load "green-tower.scm")
+(load "green-tower-lower.scm")
+(load "mushroom-cave.scm")
+(load "goblin-kingdoms.scm")
+(load "treasury.scm")
+(load "bole.scm")
+(load "glasdrin.scm")
+(load "oparine.scm")
+(load "traps_1.scm")
+(load "traps_2.scm")
+(load "traps_3.scm")
+(load "traps_4.scm")
+(load "thiefs_den.scm")
+(load "keep.scm")
+(load "absalot.scm")
+(load "old-absalot.scm")
+(load "engineers-hut.scm")
+(load "mans-hideout.scm")
+(load "necromancers-lair.scm")
+(load "fire_sea.scm")
+(load "void-temple.scm")
+(load "merciful-death.scm")
+(load "angriss-lair.scm")
+(load "poor-house.scm")
+(load "prison.scm")
+(load "ankh-shrine.scm")
+(load "kraken-lakes.scm")
+(load "endless-deeps.scm")
+(load "forsaken-prison.scm")
+(load "old-mine.scm")
+(load "lich-tomb.scm")
+(load "altar-room.scm")
+(load "dank-cave.scm")
+(load "eastpass.scm")
+(load "westpass.scm")
+(load "crypt.scm")
+(load "ancient-derelict.scm")
+(load "road_to_absalot.scm")
+(load "kun.scm")
+(load "gamestart.scm")
+(load "bandit-hideout.scm")
+(load "brundegardt.scm")
+(load "voidgap-passage.scm")
+
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+ (kern-mk-char 
+  'ch_wanderer
+  "The Wanderer"        ; name
+  sp_human              ; species
+  oc_wanderer           ; occ
+  s_wanderer    ; sprite
+  faction-player        ; starting alignment
+  6 6 6                ; str/int/dex
+  pc-hp-off
+  pc-hp-gain
+  pc-mp-off
+  pc-mp-gain
+  max-health 0 max-health 0 1  ; hp/xp/mp/AP_per_turn/lvl
+  #f                    ; dead
+  nil                   ; conv
+  nil                   ; sched
+  nil                   ; special ai
+  nil                   ; container
+  nil                   ; readied
+  )
+
+
+
+; ;; For test
+; (kern-mk-char 
+;  'ch_thorald_greybeard ; tag
+;  "Thorald Greybeard"   ; name
+;  sp_human              ; species
+;  oc_wizard             ; occ
+;  s_companion_wizard    ; sprite
+;  faction-player        ; starting alignment
+;  0 10 2                ; str/int/dex
+;  0 1                   ; hp mod/mult
+;  10 5                  ; mp mod/mult
+;  240 0 8 speed-human-med-armor 8             ; hp/xp/mp/AP_per_turn/lvl
+;  #f                    ; dead
+;  nil                   ; conv
+;  nil                   ; sched
+;  nil                   ; special ai
+;  nil                   ; container
+;  ;;(list t_doom_staff)         ; readied
+;  nil
+;  )
+;;----------------------------------------------------------------------------
+;; Player Party
+;;----------------------------------------------------------------------------
+(bind 
+ (kern-mk-player
+  'player                     ; tag
+  s_wanderer         ; sprite
+  "Walk"                      ; movement description
+  sound-walking               ; movement sound
+  1                           ; food
+  0                           ; gold
+  (* 60 60 5)                 ; turns to next meal (5 hours)
+  nil                         ; formation
+  m_campsite                  ; campsite map
+  nil                         ; campsite formation
+  nil                         ; vehicle
+  ;; inventory
+  (kern-mk-inventory nil)
+  nil ;; party members (should be nil for initial load file)
+  )
+ (tbl-mk))
+
+;;----------------------------------------------------------------------------
+;; Party members
+;;----------------------------------------------------------------------------
+(kern-party-add-member player ch_wanderer)
+;;(kern-party-add-member player ch_thorald_greybeard)
+
+
+;;----------------------------------------------------------------------------
+;; Places
+;;----------------------------------------------------------------------------
+(load "shard.scm")
+
+;;----------------------------------------------------------------------------
+;; Astronomy
+;;----------------------------------------------------------------------------
+(kern-mk-astral-body
+ 'sun              ; tag
+ "Fyer (the sun)"  ; name
+ 1                 ; relative astronomical distance 
+ 1                 ; minutes per phase (n/a for sun)
+ (/ (* 24 60) 360) ; minutes per degree
+ 0                 ; initial arc
+ 0                 ; initial phase
+ '()               ; script interface
+ ;; phases:
+ (list 
+  (list s_sun 255 "full")
+  )
+ )
+
+;;----------------------------------------------------------------------------
+;; Lumis is the source gate, which means it opens the source moongates on its
+;; phases. We designate this by using the source-moon-ifc as its ifc.
+;;
+;; Note: the arc and phase are calculated to give the moon the right orientation
+;; with respect to phase vs sun position
+;;----------------------------------------------------------------------------
+(mk-moon 'lumis  ; tag
+         "Lumis" ; name
+         5       ; hours per phase
+         60      ; hours per revolution
+         22      ; initial arc
+         0       ; initial phase
+         'source-moon-ifc ; ifc
+         ;; gates (moons are fixed at 8 phases in mk-moon):
+         (list 'mg-1 'mg-2 'mg-3 'mg-4
+               'mg-5 'mg-6 'mg-7 'mg-8
+               )
+         "yellow")
+
+;;----------------------------------------------------------------------------
+;; Ord is the destination gate, which means its phase decides the destination
+;; when the player steps through a moongate. We designate this by giving it a
+;; nil ifc. Note that its gates do not need to be listed in the same order as
+;; Lumis. In fact, they don't even need to be the same set of gates.
+;;
+;; Note: the arc and phase are calculated to give the moon the right orientation
+;; with respect to phase vs sun position
+;;----------------------------------------------------------------------------
+(mk-moon 'ord    ; tag
+         "Ord"   ; name
+         9       ; hours per phase
+         36      ; hours per revolution
+         67     ; initial arc
+         7       ; initial phase
+         nil     ; ifc
+         ;; gates (moons are fixed at 8 phases in mk-moon):
+         (list 'mg-1 'mg-2 'mg-3 'mg-4
+               'mg-5 'mg-6 'mg-7 'mg-8
+               )
+         "blue")
+
+;; ----------------------------------------------------------------------------
+;; The diplomacy table. Each entry defines the attitude of the row to the
+;; column. Note that attitudes are not necessarily symmetric. Negative values
+;; are hostile, positive are friendly.
+;;
+;; Note: factions should always be allied with themselves in order for
+;; summoning AI to work properly.
+;;       
+;; Formatted for spreadsheet
+;; ----------------------------------------------------------------------------
+(kern-mk-dtable                                                                                                                                        
+        ;;      non pla men cgb acc mon tro spd out gnt dem fgb prs gla                
+        (list   2   0   0   0   -1  -2  -2  -2  0   -2  -2  0   0   0    ) ;; none
+        (list   0   2   2   -2  -2  -2  -2  -2  -2  -2  -2  -2  2   2    ) ;; player
+        (list   -1  2   2   -1  -2  -2  -2  -2  -2  -2  -2  -2  2   2    ) ;; men
+        (list   -1  -2  -2  2   -1  -2  0   -2  -2  -1  -2  -2  0   -2   ) ;; cave goblin
+        (list   -1  -2  -1  -1  2   -2  -1  -1  -2  -1  -2  -2  0   -2   ) ;; accursed
+        (list   -2  -2  -2  -2  -2  2   -2  0   -2  0   -2  0   0   -2   ) ;; monsters
+        (list   -2  -2  -2  0   -1  -2  2   -2  -2  -1  -2  -1  0   -2   ) ;; hill trolls
+        (list   -2  -2  -2  -2  -1  0   -2  2   -2  -1  -2  0   0   -2   ) ;; wood spiders
+        (list   0   -2  -2  -2  -2  -2  -2  -2  2   -2  -2  -1  0   -2   ) ;; outlaws
+        (list   -2  -2  -2  -1  -1  0   -1  -1  -2  2   -2  -1  0   -2   ) ;; gint
+        (list   -2  -2  -2  -2  -2  -2  -2  -2  -2  -2  2   -2  0   -2   ) ;; demon
+        (list   0   -2  -2  -2  -2  0   -2  0   -1  -1  -2  2   0   -2   ) ;; forest goblin
+        (list   0   2   2   0   0   0   0   0   0   0   0   0   2   2    ) ;; prisoners
+        (list   -1  2   2   -1  -2  -2  -2  -2  -2  -2  -2  -2  2   2    ) ;; glasdrin
+)                                                                                                                                      
+
+
+;;----------------------------------------------------------------------------
+;; Startup - this is a one-time only script that runs when the player starts
+;; the game for the first time (or whenever he starts over from scratch,
+;; loading the game from this file). It sets up the story a bit.
+;;
+;; The camera should center on the moongate clearing. Then, a gate should rise
+;; from the ground, pause, then sink back down, leaving the player's sleep
+;; sprite on the ground. Another pause, and then the player should wake up.
+;;----------------------------------------------------------------------------
+(define (start-scene kplayer)
+
+  (kern-log-msg "A dark gate rises in a quiet clearing...")
+  (moongate-animate black-gate blackgate-stages)
+  (kern-sleep 2000)
+
+  (kern-log-enable #f)
+  (kern-char-set-sleep ch_wanderer #t)
+  (kern-obj-put-at kplayer (list p_moongate_clearing 11 12))
+
+  (kern-log-enable #t)
+  (kern-log-msg "Then closes without a trace...")
+  (moongate-animate black-gate (reverse blackgate-stages))
+  (kern-sleep 1000)
+  
+  (kern-log-msg "You lie dreaming for a while, of another life...")
+  (kern-sleep 2000)
+
+  (kern-log-enable #f)
+  (kern-char-set-sleep ch_wanderer #f)
+  (kern-player-set-follow-mode)
+  (kern-log-enable #t)  
+  (kern-log-msg "...then awaken to a strange new world.")
+  (kern-log-msg "To the southwest you see a cave.")
+  )
+
+(define (simple-start kplayer)
+  (kern-obj-put-at kplayer (list p_shard 76 114)))
+  
+(define (create-char kplayer)
+ (kern-obj-put-at kplayer (list p_char_setup 10 17)
+                   ))
+      
+;;----------------------------------------------------------------------------
+;; To skip the extended start scene comment out this next line and uncomment
+;; the line after it.
+;;----------------------------------------------------------------------------
+;;(kern-set-start-proc start-scene)
+;;(kern-set-start-proc simple-start)
+(kern-add-hook 'new_game_start_hook 'create-char)
+(load "quests-data.scm")
+(quest-assign (quest-data-get 'questentry-charcreate))
+
+(kern-progress-bar-finish)
+(println "r2g")
+
+
+;;quickstart stuff for playtesting
+
+(if #f
+    (begin
+      (kern-obj-put-at 
+       (mk-chest
+        nil ;; trap
+        
+        '(
+         
+         ;; Food
+         ( 1000 t_food)
+         
+         ;; Gold
+         ( 1000 t_gold_coins)
+         
+         ;; Reagents
+         ( 55 sulphorous_ash)
+         ( 55 ginseng)
+         ( 55 garlic)
+         ( 55 spider_silk)
+         ( 53 blood_moss)
+         ( 53 black_pearl)
+         ( 51 nightshade)
+         ( 51 mandrake)
+         
+         ;; Items
+         ( 9 t_vas_mani_scroll)
+         ( 9 t_in_ex_por_scroll)
+         ( 9 t_sanct_lor_scroll)
+         ( 9 t_wis_quas_scroll)
+         ( 9 t_xen_corp_scroll)
+         ( 9 t_an_xen_ex_scroll)
+         ( 9 t_vas_rel_por_scroll)
+         ( 59 t_gem)
+         ( 9 t_cure_potion)
+         ( 9 t_mana_potion)
+         ( 99 t_xp_potion)
+         ( 99 t_str_potion)
+         ( 99 t_dex_potion)
+         ( 99 t_int_potion)
+         ( 99 t_info_potion)
+         ( 99 t_torch)
+         ( 99 t_picklock)
+         ( 9 t_pick)
+         ( 2 t_dragons_blood)
+         ( 2 t_hydras_blood)
+         ( 2 t_shovel)
+        ;; ( 1 t_rune_k)
+         
+         
+         ;; Arms
+        ( 1 t_dagger)
+        ( 1 t_mace)
+        ( 1 t_axe)
+        ( 1 t_sword)
+        ( 1 t_2H_axe)
+        ( 1 t_2H_sword)
+        ( 1 t_morning_star)
+        ( 1 t_halberd)
+        ( 1 t_staff)
+
+        ( 1 t_dagger_4)
+         ( 1 t_sword_4)
+         ( 1 t_morning_star_2)
+        ( 1 t_stun_wand)
+        ( 1 t_doom_staff)
+        ( 1 t_eldritch_blade)
+        ( 1 t_mystic_sword)
+        ( 1 t_flaming_sword)
+
+         ( 1 t_shield)
+        ( 1 t_scratched_shield)
+
+        ( 1 t_leather_helm)
+        ( 1 t_chain_coif)
+        ( 1 t_iron_helm)
+
+        ( 1 t_armor_leather)
+        ( 1 t_armor_chain)
+        ( 1 t_armor_plate)
+
+         ( 1 t_iron_helm_4)
+        ( 1 t_armor_leather_4)
+        ( 1 t_armor_chain_4)
+         ( 1 t_armor_plate_4)
+
+        ( 1 t_chrono)
+        ( 1 t_spiked_shield)
+
+        ( 1 t_sling)
+        ( 3 t_spear)
+
+         ( 1 t_sling_4)
+        ( 1 t_magic_axe)
+
+        (20 t_oil)
+        (20 t_slime_vial)
+
+        (  1 t_self_bow)
+        (  1 t_bow)
+        (  1 t_long_bow)
+        (  1 t_great_bow)
+        (500 t_arrow)
+
+        (  1 t_lt_crossbow)
+        (  1 t_crossbow)
+        (  1 t_hvy_crossbow)
+        (  1 t_trpl_crossbow)
+        (500 t_bolt)
+
+         ))
+       (list p_char_setup 16 17))
+       
+      (kern-obj-put-at
+       (mk-ladder-down 'p_moongate_clearing 18 18) 
+       (list p_char_setup 17 17))
+       
+      (kern-obj-put-at
+       (mk-ladder-down 'p_trigrave 16 16) 
+       (list p_char_setup 17 16))
+       
+       (kern-obj-put-at
+       (mk-ladder-down 'p_fire_sea 4 4) 
+       (list p_char_setup 17 15))
+       
+      (kern-obj-put-at
+       (mk-ladder-down 'p_oparine 1 1) 
+       (list p_trigrave 17 16))
+       
+       (kern-obj-put-at
+       (mk-ladder-down 'p_lost_garrison 22 22) 
+       (list p_oparine 1 1))
+       
+    ))
diff --git a/worlds/haxima-1.002/statue-of-justice.scm b/worlds/haxima-1.002/statue-of-justice.scm
new file mode 100644 (file)
index 0000000..a750e29
--- /dev/null
@@ -0,0 +1,183 @@
+;;----------------------------------------------------------------------------
+;; This is the special statue that stands in the courtyard of Glasdrin. When
+;; attacked, it speaks. This requires two objects: an object with a type in
+;; order to support the 'attack interface, and a character type to have the
+;; conversation. The illusion is that they are both the same object.
+;;----------------------------------------------------------------------------
+
+(define (soj-strike kobj kpc)
+  (let ((kchar (mk-talking-statue)))
+    (kern-obj-put-at kchar (kern-obj-get-location kobj))
+    (kern-conv-begin kchar)
+    (kern-obj-remove kchar)
+    ))
+
+
+(mk-obj-type 't_statue_of_justice "ancient statue" s_headless_w_sword_statue layer-mechanism
+             (ifc nil
+                  (method 'xamine (lambda (knpc kpc)
+                                    (kern-log-msg "A worn engraving reads 'STRIKE FOR JUSTICE'")))
+                  (method 'attack soj-strike)
+                  ))
+
+(define (soj-accuse knpc kpc)
+  (say knpc "Whom do you accuse?")
+  (let ((kchar (ui-target (kern-obj-get-location kpc) 19 obj-is-char?)))
+    (cond ((null? kchar)
+           (say knpc "Do you wish to withdraw your charge?")
+           (cond ((yes? kpc)
+                  (say knpc "Cursed are you: for trifling with serious matters, "
+                       "a trifling nuisance will haunt your sleep.")
+                  (unrest-curse-apply-new kpc 'insect-party-l1)
+                  (kern-conv-end))
+                 (else
+                  (soj-accuse knpc kpc))
+                 ))
+          (else
+           (say knpc "Are you certain that you wish to accuse " (kern-obj-get-name kchar) "?")
+           (cond ((no? kpc)
+                  (soj-accuse knpc kpc))
+                 (else
+                  (say knpc (kern-obj-get-name kchar) ", you stand accused by " (kern-obj-get-name kpc) ". ")
+                  (soj-get-evidence knpc kpc kchar)
+                  ))
+           ))
+    ))
+
+(define (soj-get-evidence knpc kpc kchar)
+  (say knpc (kern-obj-get-name kpc) ", produce your evidence.")
+  (let ((ktype (kern-ui-select-item kpc)))
+    (cond ((null? ktype)
+           (say knpc "Do you have any other evidence?")
+           (cond ((no? kpc)
+                  (shake-map 15)
+                  (say knpc "For accusing another with insufficient evidence, "
+                       "you are guilty of bearing false witness. "
+                       "Your punishment is exile.")
+                  ;; todo: implement exile
+                  (make-enemies knpc kpc)
+                  (kern-obj-relocate kpc
+                                     (kern-place-get-location (loc-place (kern-obj-get-location knpc)))
+                                     nil)
+                  (kern-conv-end)
+                  )
+                 (else (soj-get-evidence knpc kpc kchar))
+                 ))
+          ((or (not (equal? ktype t_stewardess_journal))
+              (not (defined? 'ch_steward))
+              (not (equal? kchar ch_steward)))
+           (say knpc "Justice will weigh the evidence.")
+           (log-dots 10 1000)
+           (say knpc "The evidence is insufficient.")
+           (prompt-for-key)
+           (soj-get-evidence knpc kpc kchar)
+           )
+          (else
+           (say knpc "Justice will weigh the evidence.")
+           (log-dots 10 1000)
+           (say knpc (kern-obj-get-name kchar) ", you are guilty of betrayal. Your punishment is death, "
+                "and may your name be a curse forevermore.")
+           (aside kpc 'ch_ini "Justice at last!")
+           (kern-being-set-current-faction kchar faction-monster)
+           (quest-data-update-with 'questentry-warritrix 'avenged 1 (quest-notify (grant-party-xp-fn 200)))
+
+           (if (defined? 'ch_jeffreys)
+                       (begin
+                               (kern-char-set-sched ch_jeffreys sch_jeff_resigned)
+                               (kern-obj-set-sprite ch_jeffreys s_fallen_paladin)
+                       )
+               )
+
+           (if (defined? 'ch_valus)
+                       (begin
+                               (kern-char-set-sched ch_valus sch_jeff)
+                               (kern-obj-set-sprite ch_valus s_companion_paladin)
+                       )
+               )
+
+           (kern-conv-end)
+           ))
+    ))
+           
+                  
+
+(define (soj-hail knpc kpc)
+  (say knpc "Do you seek justice?")
+  (cond ((no? kpc)
+         (say knpc "Then cursed are you: an unjust man would live among beasts, "
+              "so beasts will give you no rest.")
+         (unrest-curse-apply-new kpc 'wolf-party-l2)
+         (kern-conv-end))
+        (else
+         (say knpc "Speak truly, or be cursed. Do you accuse another of theft, false witness, oath-breaking, or betrayal?")
+         (cond ((no? kpc) 
+                (say knpc "Then go in peace, and do not strike me again in vain.")
+                (kern-conv-end))
+               (else
+                (say knpc "Be warned! If you accuse with insufficient evidence, you shall be guilty of bearing false witness, and shall be punished. "
+                     "Are you certain you want to accuse another at this time?")
+                (cond ((no? kpc)
+                       (say knpc "If you accuse truly, then go in peace and gather more evidence. But if you accuse falsely, do not strike me again.")
+                       (kern-conv-end))
+                      (else
+                       (say knpc "JUSTICE SUMMONS THE ASSEMBLY!")
+                       (shake-map 5)
+                       (soj-assemble-everyone (kern-obj-get-location knpc))
+                       (soj-accuse knpc kpc))
+                      ))
+               ))
+        ))
+
+(define (soj-assemble-everyone loc)
+  (define (assemble townsfolk)
+    (kern-map-repaint)
+    (if (not (null? townsfolk))
+        (assemble (filter notnull? 
+                          (map (lambda (kchar)
+                                 (cond ((in-range? loc 2 kchar) nil)
+                                       (else
+                                        (pathfind kchar loc)
+                                        kchar)))
+                               townsfolk)))))
+  (assemble (filter (lambda (kchar)
+                      (let ((gob (gob kchar)))
+                        (and (not (null? gob))
+                             (pair? gob)
+                             (eq? 'townsman (car gob)))))
+                    (kern-place-get-beings (loc-place loc))))
+  )
+
+(define soj-conv
+  (ifc basic-conv
+       (method 'hail soj-hail)
+       ))
+
+(define (soj-ai knpc)
+  #t)
+
+(define (mk-talking-statue)
+  (let ((kchar 
+         (kern-mk-char 
+          'ch_soj           ; tag
+          "Statue of Justice"     ; name
+          sp_statue         ; species
+          nil              ; occ
+          s_headless_w_sword_statue     ; sprite
+          faction-glasdrin      ; starting alignment
+          0 0 0            ; str/int/dex
+          0 0              ; hp mod/mult
+          0 0              ; mp mod/mult
+          1000 ; hp
+          0                   ; xp
+          0 ; mp
+          0
+          9                ; lvl
+          #f               ; dead
+          'soj-conv         ; conv
+          nil           ; sched
+          'soj-ai              ; special ai
+          nil              ; container
+          nil              ; readied
+          )))
+    (kern-char-set-known kchar #t)
+    kchar))
diff --git a/worlds/haxima-1.002/step.scm b/worlds/haxima-1.002/step.scm
new file mode 100644 (file)
index 0000000..054f55f
--- /dev/null
@@ -0,0 +1,107 @@
+(define (trig-mk proc-tag args) (cons proc-tag args))
+(define (trig-proc trg) (eval (car trg)))
+(define (trig-args trg) (cdr trg))
+(define (trig-invoke trg . more-args)
+  (println "more-args: " more-args)
+  (println "trig-args: " (trig-args trg))
+  (apply (trig-proc trg) 
+         (append more-args (trig-args trg))))
+
+;;----------------------------------------------------------------------------
+;; Step trigger -- executes a named procedure whan a character steps on it.
+;; The procedure should expect a kernel being as the first arg followed by
+;; the optional args.
+;;----------------------------------------------------------------------------
+(define (step-trig-exec ktrig kbeing)
+  (let ((trg (gob ktrig)))
+    (if (trig-invoke trg kbeing)
+        (kern-obj-remove ktrig))))
+
+(define step-trig-ifc
+  (ifc '()
+       (method 'step step-trig-exec)))
+
+(mk-obj-type 't_step_trig nil nil layer-mechanism step-trig-ifc)
+
+(define (mk-step-trig proc-tag . args)
+  (bind (make-invisible (kern-mk-obj t_step_trig 1))
+        (trig-mk proc-tag args)))
+
+;;-----------------------------------------------------------------------------
+;; Sense trigger -- just like a step trigger, but responds to the 'sense signal
+;; instead, which is sent anytime a character enters or leaves its tile
+;;-----------------------------------------------------------------------------
+(define sense-trig-ifc
+  (ifc '()
+       (method 'sense step-trig-exec)))
+
+(mk-obj-type 't_sense_trig nil nil layer-mechanism sense-trig-ifc)
+
+(define (mk-sense-trig proc-tag . args)
+  (bind (make-invisible (kern-mk-obj t_sense_trig 1))
+        (trig-mk proc-tag args)))
+
+;;----------------------------------------------------------------------------
+;; Procedure for use with step or sense triggers. kchar is the character which
+;; caused the trigger by stepping on the tile (or off it, in the case of a
+;; sense trigger). target-tag is the object which will receive the message
+;; sigval.
+;;
+;; Example:
+;;
+;;   (put (kern-tag 'p1 (mk-portcullis)) 3 4)
+;;   (put (mk-sense-trig 'generic-trig-exec 'p1 'signal) 10 23)
+;;
+;; Whenever anybody enters tile (10, 23), the portcullis at (3, 4) will open in
+;; response to the "signal" message. . When they leave, it will close again.
+;;----------------------------------------------------------------------------
+(define (generic-trig-exec kchar target-tag sigval)
+  (send-signal kchar (eval target-tag) sigval)
+  #f)
+
+;;----------------------------------------------------------------------------
+;; 'on trigger -- object which executes a named procedure when it gets the 'on
+;; signal from something.
+;;----------------------------------------------------------------------------
+(define (on-trig-exec ktrig)
+  (let ((trg (gob ktrig)))
+    (if (trig-invoke trg ktrig)
+        (kern-obj-remove ktrig))))
+
+(define on-trig-ifc
+  (ifc '()
+       (method 'on on-trig-exec)))
+
+(mk-obj-type 't_on_trig nil nil layer-mechanism on-trig-ifc)
+
+(define (mk-on-trig proc-tag args)
+  (bind (make-invisible (kern-mk-obj t_on_trig 1))
+        (trig-mk proc-tag args)))
+
+;;------------------------------------------------------------------------
+;; sensor pad - sends a remote-sensor ifc call when it detects someone
+;;     enters or leaves its tile
+;;------------------------------------------------------------------------
+
+(define char-sensor-ifc
+  (ifc '() (method 'sense
+                   (lambda (ksensor kuser)
+                     (send-signal kuser (eval (gob ksensor)) 'remote-sensor)
+                     ))
+       ))
+
+(mk-obj-type 't_char_sensor nil nil layer-mechanism char-sensor-ifc)
+
+(define (mk-char-sensor target-tag)
+  (bind (make-invisible (kern-mk-obj t_char_sensor 1))
+        target-tag))
+
+;;----------------------------------------------------------------------------
+;; Terrain-changer -- procedure for a step trigger to set the terrain at (x, y)
+;; to kter. kbeing triggered the step. This returns #t so that it is used only
+;; once.
+;;
+(define (terrain-changer kbeing x y kter)
+  (kern-place-set-terrain (list (get-place kbeing) x y)
+                          (eval kter))
+  #t)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/steward.scm b/worlds/haxima-1.002/steward.scm
new file mode 100644 (file)
index 0000000..2b85bed
--- /dev/null
@@ -0,0 +1,229 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Glasdrin
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_stew
+               (list 0  0  gv-bed       "sleeping")
+               (list 7  0  ghg-s4       "eating")
+               (list 8  0  gc-hall "idle")
+               (list 12 0  ghg-s1       "eating")
+               (list 13 0  gc-hall "idle")
+               (list 18 0  ghg-s1       "eating")
+               (list 19 0  gc-hall "idle")
+               (list 20 0  gv-bed       "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (stew-mk) (list 'townsman #f))
+(define (stew-met? stew) (cadr stew))
+(define (stew-met! stew) (set-car! (cdr stew) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Victoria is the temporal ruler of Glasdrin, 
+;; bearing the title of Stewardess.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (stew-hail knpc kpc)
+  (if (not (stew-met? (kobj-gob-data knpc)))
+      (begin
+        (say knpc "[You meet a stately woman with an air of authority] "
+             "Hail, Wanderer. I have heard of your coming.")
+        (stew-met! (kobj-gob-data knpc)))
+      (say knpc "[You meet a stately woman with an air of authority] "
+           "Hail again, Wanderer.")))
+
+(define (stew-default knpc kpc)
+  (say knpc "I cannot help you with that."))
+
+(define (stew-name knpc kpc)
+  (say knpc "I am Victoria, Stewardess of Glasdrin."))
+
+(define (stew-join knpc kpc)
+  (say knpc "How bold!"))
+
+(define (stew-job knpc kpc)
+  (say knpc "I am the Stewardess of Glasdrin."))
+
+(define (stew-bye knpc kpc)
+  (say knpc "Keep to the path, Wanderer."))
+
+;; Warritrix...
+(define (stew-warr knpc kpc)
+  (cond ((player-found-warritrix?)
+      (if (ask? knpc kpc "I heard of her passing. Surely you do not think I had anything to do with it?")
+          (begin
+            (say knpc "If you dare to accuse me, strike the statue in the courtyard. "
+                 "But I warn you: you are a homeless vagrant, and I am ruler of the most powerful city in the land. "
+                 "It will be my word against yours, and we deal harshly with false accusers.")
+            (aside kpc 'ch_ini "Doubt not, you treacherous witch, that we will accuse you, "
+                   "and with more than just words.")
+            )
+          (say knpc "Of course not. Ignore the rumours. They are spread by jealous political rivals.")
+          ))
+      ((quest-data-assigned? 'questentry-wise)
+               (say knpc "I have not seen her in some time. I believe she has been called away on some errand.")
+               (quest-data-update 'questentry-warritrix 'assignment 1)
+               )
+       (else
+               (say knpc "One of our finest warriors. I believe she is out on patrol right now.")
+                (quest-data-update 'questentry-warritrix 'general-loc 1)
+                )
+      ))
+
+(define (stew-erra knpc kpc)
+  (say knpc "Speak with Commander Jeffries, he may know the details."))
+
+;; Steward...
+(define (stew-stew knpc kpc)
+  (say knpc "Glasdrin is ruled by an elected Steward, "
+       "who is charged with the safekeeping of the City and the Realm. "
+       ))
+
+(define (stew-real knpc kpc)
+  (say knpc "The Realm of Glasdrin extends west to the Fens and southeast to "
+       "the Great Wood. We also maintain a presence between the surface and "
+       "the Underworld."))
+
+;; Rune...
+(define (stew-rune knpc kpc)
+       (if (quest-data-assigned? 'questentry-wise)
+               (say knpc "I know the Warritrix wore... wears a Rune about her neck, "
+                       "but I know not what it signifies.")
+               (say knpc "I know the Warritrix wears a Rune about her neck, "
+                       "but I know not what it signifies.")
+               )
+       (quest-data-assign-once 'questentry-rune-l)
+       )
+
+(define (stew-wore knpc kpc)
+       (if (quest-data-assigned? 'questentry-wise)
+               (say knpc "What are you implying? It was merely a slip of the tongue.")
+               (stew-default knpc kpc)
+       ))
+
+;; Absalot...
+(define (stew-absa knpc kpc)
+  (say knpc "Absalot was a cancer on the land. It had to be removed "
+       "completely before its evil spread. Surely you see the wisdom "
+       "of this?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "The loss of innocent lives is always a tragedy, but it is "
+           "impossible to fight wars without them.")
+      (say knpc "What do you know of affairs of state? You are little more "
+           "than a common rogue.")))
+
+(define (stew-inno knpc kpc)
+  (say knpc "Not all the citizens of Absalot were wicked, "
+       "but they tolerated wickedness in their midst."))
+
+(define (stew-wick knpc kpc)
+  (say knpc "The people of Absalot engaged in human sacrifice and "
+       "demon-worship. They began to have converts in other cities, even "
+       "here."))
+
+(define (stew-conv knpc kpc)
+  (say knpc "When we learned of them, we burned them at the stake. "
+       "I met with the Wise and the leaders of the other cities to decide "
+       "what to do.")
+  (prompt-for-key)
+  (say knpc "Some of the Wise were squeamish, but in the end "
+       "we overruled their dissent and formed a coalition army. "
+       "It marched on Absalot, razed it and sealed "
+       "the passage so that none may build on that site ever again."))
+
+(define (stew-wise knpc kpc)
+  (say knpc "The Wise are an aid to the rulers of the cities, but alone they "
+       "have little power. Even the Enchanter could not stand against the "
+       "armed might of Glasdrin should he ever stand in our way.")
+       (quest-wise-subinit 'questentry-enchanter)
+       )
+
+(define (stew-rogu knpc kpc)
+  (say knpc "Where do you come from? What is your purpose in our land? "
+       "For all we know you are a spy, a scout at the vanguard of an alien "
+       "army. Are you?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Hmm. If I believed you I would throw you to the inquisitors "
+           "and torture the truth out of you. But I think you are a poser "
+           "and a self-inflated fool. You will vanish into obscurity like "
+           "the Wanderers that preceded you.")
+      (say knpc "No, I think you are merely a vagabond, here by "
+           "accident. All the same, I will be watching you carefully, "
+           "Wanderer. If you betray my city you will know my wrath at the "
+           "hands of our torturers."))
+  (kern-conv-end))
+
+;; Townspeople...
+(define (stew-glas knpc kpc)
+  (say knpc "Glasdrin is a beacon of light in these dark times. "
+       "Time and again her paladins have sacrificed for the good of "
+       "the realm, and turned back the tide of darkness. The Peninsula "
+       "owes much to this city."))
+
+(define (stew-unde knpc kpc)
+  (say knpc "The Underworld is a sunless realm where monsters breed. "
+       "I am committed to purging it of these evil creatures, "
+       "for they are a menace to all."))
+
+(define stew-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'default stew-default)
+       (method 'hail stew-hail)
+       (method 'bye  stew-bye)
+       (method 'job  stew-job)
+       (method 'name stew-name)
+       (method 'join stew-join)
+
+       (method 'city stew-glas)
+       (method 'glas stew-glas)
+       (method 'warr stew-warr)
+       (method 'erra stew-erra)
+       (method 'stew stew-stew)
+       (method 'real stew-real)
+       (method 'absa stew-absa)
+       (method 'wore stew-wore)
+       (method 'rune stew-rune)
+       (method 'inno stew-inno)
+       (method 'wick stew-wick)
+       (method 'conv stew-conv)
+       (method 'wise stew-wise)
+       (method 'rogu stew-rogu)
+       (method 'unde stew-unde)
+       ))
+
+(define (mk-steward)
+  (bind 
+   (kern-char-force-drop
+    (kern-mk-char 'ch_steward         ; tag
+                  "Victoria"          ; name
+                  sp_human            ; species
+                  nil                 ; occ
+                  s_lady              ; sprite
+                  faction-glasdrin         ; starting alignment
+                  1 3 0               ; str/int/dex
+                  0 0                 ; hp mod/mult
+                  0 0                 ; mp mod/mult
+                  max-health -1 max-health 0 6  ; hp/xp/mp/AP_per_turn/lvl
+                  #f                  ; dead
+                  'stew-conv          ; conv
+                  sch_stew            ; sched
+                  'townsman-ai                 ; special ai
+                  (mk-inventory (list (list 1 t_sword_4)
+                                      (list 1 t_stewardess_chest_key)
+                                      ))    ; container
+                  nil                 ; readied
+                  )
+    #t)
+   (stew-mk)))
diff --git a/worlds/haxima-1.002/swish.wav b/worlds/haxima-1.002/swish.wav
new file mode 100644 (file)
index 0000000..561aea9
Binary files /dev/null and b/worlds/haxima-1.002/swish.wav differ
diff --git a/worlds/haxima-1.002/talking-ankh.scm b/worlds/haxima-1.002/talking-ankh.scm
new file mode 100644 (file)
index 0000000..158368f
--- /dev/null
@@ -0,0 +1,105 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define ankh-lvl 9)
+(define ankh-species sp_statue)
+(define ankh-occ nil)
+
+(kern-mk-map
+ 'm_hidden_city 19 19 pal_expanded
+       (list
+       "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn  "
+       "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn  "
+       "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn  "
+       "rn rn rn rn rn r8 r8 r8 r8 r8 r8 r8 r8 r8 rn rn rn rn rn  "
+       "rn rn rn rn rc *3 *1 *1 *1 *1 *1 *1 *1 *5 ra rn rn rn rn  "
+       "rn rn rn r4 *3 ** *. *8 *8 *8 *8 *8 ** *. *5 r2 rn rn rn  "
+       "rn rn rn r4 *2 ** xx xx xx xx xx xx xx ** *4 r2 rn rn rn  "
+       ".. xx xx xx xx xx xx pp ,, ,, ,, pp xx *2 *4 r2 rn rn rn  "
+       "tt ,, ,, ,, ,, ,, ,, ,, cc cc cc ,, xx *2 *4 r2 rn rn rn  "
+       ".. cc dd cc cc cc cc cc cc cc cc ,, xx *2 *4 r2 rn rn rn  "
+       ",, ,, .. ,, ,, ,, ,, ,, cc cc cc ,, xx *2 *4 r2 rn rn rn  "
+       "xx rn xx xx xx xx xx pp ,, cc ,, pp xx *2 *4 r2 rn rn rn  "
+       "rn rn rn r4 *2 *. xx xx ,, cc ,, xx xx *. *4 r2 rn rn rn  "
+       "rn rn rn r4 *a *. ** *5 ,, cc ,, *3 ** *. *c r2 rn rn rn  "
+       "rn rn rn rn r5 *a ** *4 ,, cc ,, *2 *. *c r3 rn rn rn rn  "
+       "rn rn rn rn rn r5 ** *4 ,, cc ,, *2 *. r3 rn rn rn rn rn  "
+       "rn rn rn rn rn r4 *2 *4 ,, cc ,, *2 *4 r2 rn rn rn rn rn  "
+       "rn rn rn rn rn r4 *2 *4 ,, cc ,, *2 *4 r2 rn rn rn rn rn  "
+       "rn rn rn rn rn r4 ** ** ,, cc ,, ** *. r2 rn rn rn rn rn  "
+       )
+)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (ankh-mk)
+  (list #f))
+(define (ankh-done? gob) (car gob))
+(define (ankh-done! gob) (set-car! gob #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (ankh-hail knpc kpc)
+  (let ((gob (kobj-gob-data knpc)))
+    (if (not (ankh-done? gob))
+        (begin
+          (say knpc "[A vibrating voice fills your head] "
+               "At the dawn of the next age, how will the world be made?")
+          (let ((resp (kern-conv-get-reply kpc)))
+            (if (not (eq? resp 'anew))
+                (say knpc "Then the new age has not yet come.")
+                (begin
+                  (say knpc "THEN THE NEW AGE HAS BEGUN!")
+                  (shake-map 15)
+                  (kern-map-flash 500)
+                  (shake-map 15)
+                  (kern-map-flash 500)          
+                  (shake-map 15)
+                  (ankh-done! gob)
+                  (blit-map (loc-place (kern-obj-get-location knpc))
+                    0 0 31 31 m_hidden_city)
+                  ))
+            (kern-conv-end))))))
+        
+
+(define ankh-conv
+  (ifc basic-conv
+       (method 'hail ankh-hail)
+       ))
+
+(define (ankh-ai knpc)
+  #t)
+
+(define (mk-talking-ankh)
+  (bind 
+   (kern-mk-char 
+    'ch_ankh           ; tag
+    "Ankh"             ; name
+    ankh-species         ; species
+    ankh-occ              ; occ
+    s_ankh     ; sprite
+    faction-men      ; starting alignment
+    0 0 0            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    (max-hp ankh-species ankh-occ ankh-lvl 0 0) ; hp
+    0                   ; xp
+    (max-mp ankh-species ankh-occ ankh-lvl 0 0) ; mp
+               0
+    ankh-lvl
+    #f               ; dead
+    'ankh-conv         ; conv
+    nil           ; sched
+    'ankh-ai              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   (ankh-mk)))
diff --git a/worlds/haxima-1.002/tbl.scm b/worlds/haxima-1.002/tbl.scm
new file mode 100644 (file)
index 0000000..8be1ba6
--- /dev/null
@@ -0,0 +1,71 @@
+;; (*tbl* (k1 v1) (k2 v2) ...)
+
+(define (tbl-mk)
+  (list '*tbl*))
+
+;; the val for key (#f if none)
+(define (tbl-get tbl key)
+  (let ((kvpair (assoc key (cdr tbl))))
+    (if kvpair
+        (cadr kvpair)
+        nil)))
+
+;; add key/val or replace the current val of key
+(define (tbl-set! tbl key val)
+  (let ((kvpair (assoc key (cdr tbl))))
+    (if kvpair
+        (set-cdr! kvpair (list val))
+        (set-cdr! tbl 
+                  (cons (cons key (list val)) 
+                        (cdr tbl))))))
+
+;; append val to the value of key;
+;; if key is not there make a new list with just val
+;; if current value is not a list, converts it to a list first
+(define (tbl-append! tbl key val)
+  (let ((entry (assoc key (cdr tbl))))
+     (cond ((or (not entry)
+               (not (pair? (cdr entry))))
+               (tbl-set! tbl key (list val)))
+        ((not (pair? (cadr entry)))
+               (set-cdr! entry (list (cons val (cdr entry)))))
+        (#t 
+               (set-cdr! entry (list (cons val (cadr entry))))))))
+
+;; run a procedure on each value in the table
+(define (tbl-for-each-val fx tbl)
+  (for-each (lambda (entry)
+              (println "tbl-for-each-val:entry=" entry)
+              (println "cdr=" (cdr entry))
+              (apply fx (cdr entry)))
+            (cdr tbl)))
+
+;; remove the entry that matches key
+(define (tbl-rm! tbl key)
+  (if (pair? (cdr tbl))
+      (if (equal? key (caadr tbl))
+          (set-cdr! tbl (cddr tbl))
+          (tbl-rm! (cdr tbl) key))))
+
+;; set table values from name/value list
+(define (tbl-set-all! tbl entrydata)
+       (if (not (null? entrydata))
+               (begin
+                       (tbl-set! tbl (car entrydata) (car (cdr entrydata)))
+                       (tbl-set-all! tbl (cddr entrydata))
+               )
+       ))
+
+(define (tbl-build . entrydata)
+       (let ((tbl (tbl-mk)))
+               (tbl-set-all! tbl entrydata)
+               tbl
+       ))
+
+(define (is-tbl? tbl)
+  (and (pair? tbl)
+       (equal? (car tbl) '*tbl*)
+       )
+  )
+       
+       
\ No newline at end of file
diff --git a/worlds/haxima-1.002/tblit.scm b/worlds/haxima-1.002/tblit.scm
new file mode 100644 (file)
index 0000000..422f941
--- /dev/null
@@ -0,0 +1,53 @@
+;;----------------------------------------------------------------------------
+;; tblit.scm - a terrain-blitting mech
+;;----------------------------------------------------------------------------
+
+;; Some convenient maps for blitting
+(kern-mk-map
+ 'm_hall_section 3 3 pal_expanded
+ (list
+  ",, ,, ,,"
+  ",, ,, ,,"
+  ",, ,, ,,"
+  ))
+
+(kern-mk-map
+ 'm_deck_section 3 3 pal_expanded
+ (list
+  "ee ee ee"
+  "ee ee ee"
+  "ee ee ee"
+  ))
+
+
+;; A curried wrapper for kern-blit-map (note that place may legitimately be
+;; null during startup)
+(define (blit-map place x y w h map)
+  (if (notnull? place)
+      (kern-blit-map (kern-place-map place) x y map 0 0 w h)))
+                         
+;; Syntactic sugar to set blitter state
+(define (tblit-mk place-tag x y w h map-tag) (list place-tag x y w h map-tag))
+
+;; Do the blit upon receiving an "on" signal.
+(define (tblit-on kobj)
+  (apply blit-map (map safe-eval (kobj-gob-data kobj))))
+
+;; Blit mechs are not visible.
+(define (tblit-init kobj)
+  (kern-obj-set-visible kobj #f))
+
+;; A blitter mech responds to an "on" signal by executing the blit
+(define tblit-ifc
+  (ifc '()
+       (method 'on tblit-on)
+       (method 'init tblit-init)))
+
+;; The kernel object type of a blitter
+(mk-obj-type 't_terrain_blitter '() '() layer-mechanism 
+             tblit-ifc)
+
+;; Constructor
+(define (mk-tblitter place-tag x y w h map-tag)
+  (bind (kern-mk-obj t_terrain_blitter 1)
+        (tblit-mk place-tag x y w h map-tag)))
diff --git a/worlds/haxima-1.002/terrain-to-ptype.scm b/worlds/haxima-1.002/terrain-to-ptype.scm
new file mode 100644 (file)
index 0000000..45b6a03
--- /dev/null
@@ -0,0 +1,158 @@
+;; terrain to party type
+
+;; ttp-entry: each row in the subtable for a terrain in the terrain-to-ptype
+;; table is one of these
+(define (ttp-entry-mk ptype level occur)
+  (list ptype level occur))
+(define (ttp-entry-ptype ttpe) (car ttpe))
+(define (ttp-entry-level ttpe) (cadr ttpe))
+(define (ttp-entry-occur ttpe) (caddr ttpe))
+
+(define terrain-to-ptype-tbl
+  (list
+   (list t_grass 
+         (ttp-entry-mk 'forest-goblin-party-l1 1 1)
+         (ttp-entry-mk 'bandit-party-l1        1 1)
+         (ttp-entry-mk 'headless-party-l1      1 1)
+         (ttp-entry-mk 'forest-goblin-party-l2 2 1)
+         (ttp-entry-mk 'bandit-party-l2        2 1)
+         (ttp-entry-mk 'bandit-party-l3        3 1)
+         (ttp-entry-mk 'headless-party-l3      3 1)
+         (ttp-entry-mk 'bandit-party-l4        4 1)
+         (ttp-entry-mk 'accursed-party-l4      4 1)
+         (ttp-entry-mk 'militia-party-l4       4 1)
+         (ttp-entry-mk 'bandit-party-l5        5 1)
+         (ttp-entry-mk 'headless-party-l5      5 1)
+         (ttp-entry-mk 'accursed-party-l5      5 1)
+         (ttp-entry-mk 'accursed-party-l6      6 1)
+         )
+   (list t_forest 
+         (ttp-entry-mk 'forest-goblin-party-l1 1 1)
+         (ttp-entry-mk 'wolf-party-l1          1 1)
+         (ttp-entry-mk 'wolf-party-l2          2 1)
+         (ttp-entry-mk 'dryad-party-l3         3 1)
+         (ttp-entry-mk 'forest-goblin-party-l3 3 1)
+         (ttp-entry-mk 'spider-party-l3        3 1)
+         (ttp-entry-mk 'forest-goblin-party-l4 4 1)
+         (ttp-entry-mk 'spider-party-l4        4 1)
+         (ttp-entry-mk 'dryad-party-l4         4 1)
+         (ttp-entry-mk 'wisp-party-l5          5 1)
+         (ttp-entry-mk 'dryad-party-l5         5 1)
+         )
+   (list t_trees
+         (ttp-entry-mk 'forest-goblin-party-l1 1 1)
+         (ttp-entry-mk 'forest-goblin-party-l2 2 1)
+         (ttp-entry-mk 'forest-goblin-party-l3 3 1)
+         (ttp-entry-mk 'wolf-party-l1          1 1)
+         (ttp-entry-mk 'wolf-party-l2          2 1)
+         (ttp-entry-mk 'spider-party-l3        3 1)
+         (ttp-entry-mk 'spider-party-l4        4 1)
+         (ttp-entry-mk 'snake-party-l1         1 1)
+         (ttp-entry-mk 'bat-party-l1           1 1)
+         (ttp-entry-mk 'rat-party-l1           1 1)
+         )
+   (list t_hills 
+         (ttp-entry-mk 'spider-party-l3 3 30)
+         (ttp-entry-mk 'spider-party-l4 4 30)
+         (ttp-entry-mk 'troll-party-l3  3 30)
+         (ttp-entry-mk 'troll-party-l4  4 30)
+         (ttp-entry-mk 'gint-party-l4   4 20)
+         (ttp-entry-mk 'gint-party-l5   5 20)
+         (ttp-entry-mk 'gint-party-l6   6 20)
+         (ttp-entry-mk 'dragon-party-l7 7 6)
+         )
+   (list t_mountains 
+         (ttp-entry-mk 'nil              0 100)
+         (ttp-entry-mk 'bat-party-l1     1 20)
+         (ttp-entry-mk 'griffin-party-l3 3 10)
+         (ttp-entry-mk 'dragon-party-l6  6 1)
+         (ttp-entry-mk 'dragon-party-l8  8 1)
+         )
+   (list t_bog
+         (ttp-entry-mk 'skeleton-party-l2     2 1)
+         (ttp-entry-mk 'ghast-party           2 1)  
+         (ttp-entry-mk 'green-slime-party-l2  2 1)
+         (ttp-entry-mk 'skeleton-party-l3     3 1)
+         (ttp-entry-mk 'yellow-slime-party-l3 3 1)
+         (ttp-entry-mk 'skeleton-party-l4     4 1)
+         (ttp-entry-mk 'lich-party-l5         5 1)
+         (ttp-entry-mk 'hydra-party-l5        5 1)
+         )
+   (list t_shoals
+         (ttp-entry-mk 'nil                  0 4)
+         (ttp-entry-mk 'nixie-party-l2       2 4)
+         (ttp-entry-mk 'kraken-party-l3      3 2)
+         (ttp-entry-mk 'sea-serpent-party-l3 3 1)
+         )
+   (list t_shallow
+         (ttp-entry-mk 'nil                  0 16)
+         (ttp-entry-mk 'kraken-party-l3      3 6)
+         (ttp-entry-mk 'sea-serpent-party-l3 3 6)
+         (ttp-entry-mk 'nixie-party-l3       3 16)
+         (ttp-entry-mk 'nixie-party-l4       4 16)
+         (ttp-entry-mk 'nixie-party-l5       5 16)
+         (ttp-entry-mk 'dragon-party-l6      6 3)
+         )
+   (list t_deep
+         (ttp-entry-mk 'nil                  0 96)
+         (ttp-entry-mk 'kraken-party-l3      3 8)
+         (ttp-entry-mk 'sea-serpent-party-l3 3 8)
+         (ttp-entry-mk 'pirate-party-l3      3 8)
+         (ttp-entry-mk 'pirate-party-l4      4 8)
+         (ttp-entry-mk 'skeleton-pirates-l4  4 8)
+         (ttp-entry-mk 'dragon-party-l6      6 3)
+         (ttp-entry-mk 'dragon-party-l8      8 3)
+         )
+   (list t_lava
+         (ttp-entry-mk 'fire-slime-party-l4 4 20)
+         (ttp-entry-mk 'dragon-party-l6 6 1)
+         (ttp-entry-mk 'dragon-party-l8 8 1)
+         )
+   ))
+
+;;----------------------------------------------------------------------------
+;; "private"
+(define (terrain-to-ptypes kter)
+  (let ((entry (assoc kter terrain-to-ptype-tbl)))
+    (if (not entry)
+        nil
+        (cdr entry)
+        )))
+
+(define (ttp-list-modulus entries)
+  (foldr (lambda (sum entry)
+           (+ sum (ttp-entry-occur entry)))
+         0
+         entries))
+
+(define (ttp-list-lookup entries n)
+  (cond ((null? entries) nil)
+        (else
+         (if (< n (ttp-entry-occur (car entries)))
+             (begin
+               (eval (ttp-entry-ptype (car entries)))
+               )
+             (ttp-list-lookup (cdr entries)
+                              (- n (ttp-entry-occur (car entries)))
+                              )))))
+
+(define (ttp-list-filter entries lvl)
+  (filter (lambda (entry)
+            (<= (ttp-entry-level entry) lvl))
+          entries))
+
+(define (ttp-list-select entries lvl)
+  (let ((entries (ttp-list-filter entries lvl)))
+    (if (null? entries)
+        nil
+        (let ((n (modulo (random-next) 
+                         (ttp-list-modulus entries))))
+          (ttp-list-lookup entries n)))))
+
+;;----------------------------------------------------------------------------
+;; public
+(define (terrain-to-ptype kter lvl)
+  (let ((subtable (assoc kter terrain-to-ptype-tbl)))
+    (if (not subtable)
+        nil
+        (ttp-list-select (cdr subtable) lvl))))
diff --git a/worlds/haxima-1.002/terrains.scm b/worlds/haxima-1.002/terrains.scm
new file mode 100644 (file)
index 0000000..86cfca3
--- /dev/null
@@ -0,0 +1,470 @@
+;;----------------------------------------------------------------------------
+;; Terrains
+;;----------------------------------------------------------------------------
+
+(define (terrain-effect-burn obj)
+  (kern-obj-apply-damage obj "burning" 10))
+
+(define (terrain-effect-poison obj)
+  (if (and (> (kern-dice-roll "1d20") 10)
+           (kern-obj-is-being? obj)
+           (kern-obj-add-effect obj ef_poison nil))
+      (kern-log-msg "Noxious fumes!")))
+       
+;; swamp logic:
+;; 1) swamp only effects you on your turn (ie the 'slow progress' doesnt mean you get whacked 3 times before your next turn)
+;;                     this is calculated by whether your character speed is enough to bring your ap positive in your next turn
+;; 2) swamp is weaker in the worldmap, where you are assumed to have some lattitude to go around the noxious bits
+;; 3) swamp gives 'noxious fumes' feedback if someone in your party gets poisoned, or you see an individual critter get poisoned
+;;       you dont get feedback when a npc party moves over swamp
+(define (terrain-effect-swamp obj)
+  (if (and (kern-obj-is-being? obj)
+                       (if (kern-place-is-wilderness? (loc-place (kern-obj-get-location obj)))
+                               (> (kern-obj-get-ap (kern-char-get-party obj)) (- 0 (kern-char-get-speed obj)))
+                               (> (kern-obj-get-ap obj) (- 0 (kern-char-get-speed obj)))
+                               ))
+       (let* (
+                       (difficulty
+                               (cond ((< (kern-obj-get-movecost obj pclass-canfly) cant) 1)
+                                       ((kern-place-is-wilderness? (loc-place (kern-obj-get-location obj))) 4)
+                                       (else 6)
+                               ))
+                       (avoid (* 2 (occ-ability-dexdefend obj)))
+                       (avoidroll (- (kern-dice-roll (mkdice 1 (+ avoid difficulty))) avoid ))
+                       (strength (kern-char-get-strength obj))
+                       (resistroll (- (kern-dice-roll (mkdice 1 (+ strength 10))) strength ))
+                       )
+               (if (> avoidroll 0)
+                       (if (> resistroll 0)
+                               (begin
+                                       (kern-obj-add-effect obj ef_poison nil)
+                                       (if (kern-place-is-wilderness? (loc-place (kern-obj-get-location obj)))
+                                               (if (is-player-party-member? obj)
+                                                       (kern-log-msg "Noxious fumes!"))
+                                               (msg-log-visible (kern-obj-get-location obj) "Noxious fumes!")
+                                       )                       
+                               )
+                       ))
+       )))
+       
+(define (terrain-effect-lava obj)
+  (if (eqv? (kern-obj-get-movecost obj pclass-canfly) cant)
+       (if (and (kern-obj-is-being? obj)
+                       (kern-place-is-wilderness? (loc-place (kern-obj-get-location obj))))
+               (let* ((avoid (* 2 (occ-ability-dexdefend obj)))
+                               (avoidroll (- (kern-dice-roll (mkdice 1 (+ avoid 5))) avoid)))
+                       (if (> avoidroll 0)
+                               (generic-burn obj (mkdice avoidroll 4)))
+               )
+               (burn obj))))
+
+(define (terrain-effect-torch obj)
+       (generic-burn obj "1d4"))
+
+;; opacity constants:
+(define opq 12) ;; opaque
+(define hvy 5)  ;; heavy
+(define dns 3)  ;; dense
+(define lgt 2)  ;; light (density)
+(define trn 0)  ;; transparent
+
+(define terrains
+  (list
+   ;;    tag                name            pclass           sprite               t light step-on
+   ;;    =================  ==============  =============    ==============       = ===== =======
+   (list 't_stars           "stars"         pclass-space     s_stars             trn 0 'chasm-fall)
+   (list 't_deep            "deep water"    pclass-deep      s_deep              trn 0 nil)
+   (list 't_sunlit_deep     "deep water"    pclass-deep      s_deep              trn 64 nil)
+   (list 't_shallow         "water"          pclass-deep      s_shallow          trn 0 nil)
+   (list 't_blendable_shoals "shallow water" pclass-shoals    s_shoals           trn 0 nil)
+   (list 't_shoals          "shallow water" pclass-shoals    s_shoals            trn 0 nil)
+   (list 't_sludge          "oily sludge"   pclass-sludge    s_sludge            trn 0 nil)
+   (list 't_shallow_sludge  "oily sludge"   pclass-shallows  s_shallow_sludge    trn 0 nil)
+   (list 't_grass           "grass"         pclass-grass     s_grass             trn 0 nil)
+   (list 't_sunlit_grass    "grass"         pclass-grass     s_grass             trn 64 nil)
+   (list 't_dirt            "dirt"          pclass-grass     s_dirt              trn 0 nil)
+   (list 't_gravel          "gravel"        pclass-grass     s_gravel            trn 0 nil)
+   (list 't_trees_v         "trees"         pclass-trees     s_trees             trn 0 nil)
+   (list 't_trees           "trees"         pclass-trees     s_trees             lgt 0 nil)
+   (list 't_trees_d         "trees"         pclass-trees     s_trees             dns 0 nil)
+
+   (list 't_forest_v        "forest"        pclass-forest    s_forest            trn 0 nil)
+   (list 't_forest          "forest"        pclass-forest    s_forest            hvy 0 nil)
+   (list 't_forest_d        "forest"        pclass-forest    s_forest            7   0 nil)
+   (list 't_forest_l        "forest"        pclass-forest    s_forest            dns 0 nil)
+   (list 't_forest_b        "forest"        pclass-forest    s_forest            opq 0 nil)
+
+   (list 't_hills           "hills"         pclass-hills     s_hills             dns 0 nil)
+   (list 't_mountains_v     "mountains"     pclass-vmountains s_mountains         trn 0 nil)
+   (list 't_mountains_b     "mountains (below)"     pclass-space s_mountains         trn 0 nil)
+   (list 't_mountains       "mountains"     pclass-mountains s_mountains         opq 0 nil)
+   (list 't_fake_mountains  "mountains"     pclass-grass     s_mountains         opq 0 nil)
+   (list 't_bog             "bog"           pclass-hills    s_bog               trn 0 'terrain-effect-swamp)
+   (list 't_lava            "lava"          pclass-hills     s_lava              trn  128 'terrain-effect-lava)
+   (list 't_fake_lava       "lava"          pclass-grass     s_lava              trn  128 nil)
+   (list 't_deep_lava       "deep lava"     pclass-deep      s_deep_lava         trn   16 'great-burn)
+   (list 't_fire_terrain    "fire"          pclass-grass     s_field_fire        trn  512 'burn)
+   (list 't_fireplace       "fireplace"     pclass-grass     s_fireplace         trn 2048 'burn)
+
+   (list 't_cobblestone     "cobblestone"   pclass-grass     s_cobblestone       trn 0 nil)
+   (list 't_gold_cobble     "cobblestone"   pclass-grass     s_gold_cobble       trn 0 nil)
+   (list 't_cyan_cobble     "cobblestone"   pclass-grass     s_cyan_cobble       trn 0 nil)
+   (list 't_gray_cobble     "cobblestone"   pclass-grass     s_gray_cobble       trn 0 nil)
+   (list 't_blue_cobble     "cobblestone"   pclass-grass     s_blue_cobble       trn 0 nil)
+   (list 't_olive_cobble     "cobblestone"   pclass-grass     s_olive_cobble       trn 0 nil)
+   (list 't_white_cobble     "cobblestone"   pclass-grass     s_white_cobble       trn 0 nil)
+   (list 't_black_tile     "floor tile"   pclass-grass     s_black_tile       trn 0 nil)
+   (list 't_gold_spiral_tile     "floor tile"   pclass-grass     s_gold_spiral_tile       trn 0 nil)
+   (list 't_blue_spiral_tile     "floor tile"   pclass-grass     s_blue_spiral_tile       trn 0 nil)
+   (list 't_tombstone       "tombstone"     pclass-boulder s_tombstone trn 0 nil)
+   (list 't_tombstone2       "tombstone"     pclass-boulder s_tombstone2 trn 0 nil)
+
+   (list 't_impassable_cobblestone    "cobblestone"   pclass-wall     s_cobblestone       trn 0 nil)
+   (list 't_flagstones      "flagstones"    pclass-grass     s_flagstone         trn 0 nil)
+   (list 't_inv_wall        "flagstones"    pclass-repel     s_flagstone         trn 0 'burn)
+   (list 't_doorway         "doorway"       pclass-grass     s_stone_arch        trn 0 nil) ;;dont use this if poss
+   (list 't_leftwing        "castle wall"   pclass-wall      s_leftwing          trn 0 nil)
+   (list 't_rightwing       "castle wall"   pclass-wall      s_rightwing         trn 0 nil)
+   (list 't_ship_hull       "ship's bulwark"   pclass-wall      s_wall           trn 0 nil)
+   (list 't_ship_hull2      "ship's hull"   pclass-wall      s_wall              opq 0 nil)
+   (list 't_sh_hull_NE      "ship's hull"   pclass-wall      s_wall_b            trn 0 nil)
+   (list 't_sh_hull_NW      "ship's hull"   pclass-wall      s_wall_a            trn 0 nil)
+   (list 't_sh_hull_SE      "ship's hull"   pclass-wall      s_wall_c            trn 0 nil)
+   (list 't_sh_hull_SW      "ship's hull"   pclass-wall      s_wall_d            trn 0 nil)
+   (list 't_mast            "mast"          pclass-wall      s_mast              trn 0 nil)
+   (list 't_ships_wheel     "ship's wheel"  pclass-wall      s_ships_wheel       trn 0 nil)
+   (list 't_deck            "deck"          pclass-grass     s_deck              trn 0 nil)
+   (list 't_boulder         "boulder"       pclass-boulder   s_boulder           lgt 0 nil)
+   (list 't_wall_rock_v     "rock wall"     pclass-wall      s_wall_rock         trn 0 nil)
+   (list 't_wall_rock       "rock wall"     pclass-wall      s_wall_rock         opq 0 nil)
+   (list 't_fake_wall_rock  "rock wall"     pclass-forest    s_secret_rock       opq 0 nil)
+   (list 't_wall_v          "wall"          pclass-wall      s_wall_stone        trn 0 nil)
+   (list 't_wall            "wall"          pclass-wall      s_wall_stone        opq 0 nil)
+   (list 't_fake_wall       "wall"          pclass-forest    s_wall_stone        opq 0 nil)
+   (list 't_wall_torch      "wall torch"    pclass-wall      s_wall_torch        opq 1024 'terrain-effect-torch)
+   (list 't_arrow_slit      "arrow slit"    pclass-bars      s_arrow_slit        trn 0 nil)
+   (list 't_window_in_stone "window"        pclass-bars      s_window_in_stone   trn 0 nil)
+   (list 't_window_in_rock  "window"        pclass-bars      s_window_in_rock    trn 0 nil)
+   (list 't_secret_door     "secret door"   pclass-grass     s_secret_door       opq 0 nil)
+   (list 't_sea_wall_v      "sea wall"      pclass-wall      s_wall              trn 0 nil)
+   (list 't_sea_wall        "sea wall"      pclass-wall      s_wall              opq 0 nil)
+   (list 't_sea_wall_NE     "sea wall"      pclass-wall      s_wall_b            opq 0 nil)
+   (list 't_sea_wall_NW     "sea wall"      pclass-wall      s_wall_a            opq 0 nil)
+   (list 't_sea_wall_SE     "sea wall"      pclass-wall      s_wall_c            opq 0 nil)
+   (list 't_sea_wall_SW     "sea wall"      pclass-wall      s_wall_d            opq 0 nil)
+   (list 't_ankh            "ankh"          pclass-wall      s_ankh              trn 0 nil)
+   (list 't_statue          "statue"        pclass-wall      s_statue            trn 0 nil)
+   (list 't_altar           "altar"         pclass-boulder      s_altar             trn 0 nil)
+   (list 't_rune_altar      "rune altar"    pclass-boulder      s_altar             trn 64 nil)
+   (list 't_active_altar    "activated rune altar" pclass-boulder s_active_altar    trn 512 nil)
+   (list 't_pillar          "pillar"        pclass-wall      s_pillar            trn 0 nil)
+   (list 't_false_pillar    "pillar"        pclass-grass     s_pillar            trn 0 nil)
+   (list 't_counter_2x1_w   "counter"       pclass-boulder   s_counter_2x1_w     trn 0 nil)
+   (list 't_counter_2x1_c   "counter"       pclass-boulder   s_counter_2x1_c     trn 0 nil)
+   (list 't_counter_2x1_e   "counter"       pclass-boulder   s_counter_2x1_e     trn 0 nil)
+   (list 't_counter_1x1     "counter"       pclass-boulder   s_counter_1x1       trn 0 nil)
+   (list 't_bridge_WE       "bridge"        pclass-bridge    s_ew_bridge         trn 0 nil)
+   (list 't_bridge_NS       "bridge"        pclass-bridge    s_ns_bridge         trn 0 nil)
+   (list 't_lava_bridge_NS  "bridge"        pclass-bridge    s_ns_bridge         trn 0 nil)
+   (list 't_chasm           "chasm"         pclass-space     s_null              trn 0 nil)
+   (list 't_void            "empty space"   pclass-space     s_null       trn 0 nil)
+   (list 't_trail_0         "trail"         pclass-grass     s_trail_0           trn 0 nil)
+   (list 't_trail_1         "trail"         pclass-grass     s_trail_1           trn 0 nil)
+   (list 't_trail_2         "trail"         pclass-grass     s_trail_2           trn 0 nil)
+   (list 't_trail_3         "trail"         pclass-grass     s_trail_3           trn 0 nil)
+   (list 't_trail_4         "trail"         pclass-grass     s_trail_4           trn 0 nil)
+   (list 't_trail_5         "trail"         pclass-grass     s_trail_5           trn 0 nil)
+   (list 't_trail_6         "trail"         pclass-grass     s_trail_6           trn 0 nil)
+   (list 't_trail_7         "trail"         pclass-grass     s_trail_7           trn 0 nil)
+   (list 't_trail_8         "trail"         pclass-grass     s_trail_8           trn 0 nil)
+   (list 't_trail_9         "trail"         pclass-grass     s_trail_9           trn 0 nil)
+   (list 't_trail_a         "trail"         pclass-grass     s_trail_a           trn 0 nil)
+   (list 't_trail_b         "trail"         pclass-grass     s_trail_b           trn 0 nil)
+   (list 't_trail_c         "trail"         pclass-grass     s_trail_c           trn 0 nil)
+   (list 't_trail_d         "trail"         pclass-grass     s_trail_d           trn 0 nil)
+   (list 't_trail_e         "trail"         pclass-grass     s_trail_e           trn 0 nil)
+   (list 't_trail_f         "trail"         pclass-grass     s_trail_f           trn 0 nil)
+   (list 't_A               "an A"          pclass-wall      s_A                 trn 0 nil)
+   (list 't_B               "a B"           pclass-wall      s_B                 trn 0 nil)
+   (list 't_fake_B          "a B"           pclass-forest    s_B                 trn 0 nil)
+   (list 't_C               "a C"           pclass-wall      s_C                 trn 0 nil)
+   (list 't_D               "a D"           pclass-wall      s_D                 trn 0 nil)
+   (list 't_E               "an E"          pclass-wall      s_E                 trn 0 nil)
+   (list 't_F               "an F"          pclass-wall      s_F                 trn 0 nil)
+   (list 't_G               "a G"           pclass-wall      s_G                 trn 0 nil)
+   (list 't_H               "an H"          pclass-wall      s_H                 trn 0 nil)
+   (list 't_I               "an I"          pclass-wall      s_I                 trn 0 nil)
+   (list 't_J               "a J"           pclass-wall      s_J                 trn 0 nil)
+   (list 't_K               "a K"           pclass-wall      s_K                 trn 0 nil)
+   (list 't_L               "an L"          pclass-wall      s_L                 trn 0 nil)
+   (list 't_M               "an M"          pclass-wall      s_M                 trn 0 nil)
+   (list 't_N               "an N"          pclass-wall      s_N                 trn 0 nil)
+   (list 't_O               "an O"          pclass-wall      s_O                 trn 0 nil)
+   (list 't_fake_O          "an O"          pclass-forest    s_O                 trn 0 nil)
+   (list 't_P               "a P"           pclass-wall      s_P                 trn 0 nil)
+   (list 't_Q               "a Q"           pclass-wall      s_Q                 trn 0 nil)
+   (list 't_R               "an R"          pclass-wall      s_R                 trn 0 nil)
+   (list 't_S               "an S"          pclass-wall      s_S                 trn 0 nil)
+   (list 't_T               "a T"           pclass-wall      s_T                 trn 0 nil)
+   (list 't_U               "a U"           pclass-wall      s_U                 trn 0 nil)
+   (list 't_V               "a V"           pclass-wall      s_V                 trn 0 nil)
+   (list 't_W               "a W"           pclass-wall      s_W                 trn 0 nil)
+   (list 't_X               "an X"          pclass-wall      s_X                 trn 0 nil)
+   (list 't_Y               "a Y"           pclass-wall      s_Y                 trn 0 nil)
+   (list 't_Z               "a Z"           pclass-wall      s_Z                 trn 0 nil)
+   (list 't_rune_A          "a runic A"        pclass-wall      s_rune_A      trn 0 nil)
+   (list 't_rune_B          "a runic B"        pclass-wall      s_rune_B      trn 0 nil)
+   (list 't_rune_C          "a runic C"        pclass-wall      s_rune_C      trn 0 nil)
+   (list 't_rune_D          "a runic D"        pclass-wall      s_rune_D      trn 0 nil)
+   (list 't_rune_E          "a runic E"        pclass-wall      s_rune_E      trn 0 nil)
+   (list 't_rune_F          "a runic F"        pclass-wall      s_rune_F      trn 0 nil)
+   (list 't_rune_G          "a runic G"        pclass-wall      s_rune_G      trn 0 nil)
+   (list 't_rune_H          "a runic H"        pclass-wall      s_rune_H      trn 0 nil)
+   (list 't_rune_I          "a runic I"        pclass-wall      s_rune_I      trn 0 nil)
+   (list 't_rune_J          "a runic J"        pclass-wall      s_rune_J      trn 0 nil)
+   (list 't_rune_K          "a runic K"        pclass-wall      s_rune_K      trn 0 nil)
+   (list 't_rune_L          "a runic L"        pclass-wall      s_rune_L      trn 0 nil)
+   (list 't_rune_M          "a runic M"        pclass-wall      s_rune_M      trn 0 nil)
+   (list 't_rune_N          "a runic N"        pclass-wall      s_rune_N      trn 0 nil)
+   (list 't_rune_O          "a runic O"        pclass-wall      s_rune_O      trn 0 nil)
+   (list 't_rune_P          "a runic P"        pclass-wall      s_rune_P      trn 0 nil)
+   (list 't_rune_Q          "a runic Q"        pclass-wall      s_rune_Q      trn 0 nil)
+   (list 't_rune_R          "a runic R"        pclass-wall      s_rune_R      trn 0 nil)
+   (list 't_rune_S          "a runic S"        pclass-wall      s_rune_S      trn 0 nil)
+   (list 't_rune_T          "a runic T"        pclass-wall      s_rune_T      trn 0 nil)
+   (list 't_rune_U          "a runic U"        pclass-wall      s_rune_U      trn 0 nil)
+   (list 't_rune_V          "a runic V"        pclass-wall      s_rune_V      trn 0 nil)
+   (list 't_rune_W          "a runic W"        pclass-wall      s_rune_W      trn 0 nil)
+   (list 't_rune_X          "a runic X"        pclass-wall      s_rune_X      trn 0 nil)
+   (list 't_rune_Y          "a runic Y"        pclass-wall      s_rune_Y      trn 0 nil)
+   (list 't_rune_Z          "a runic Z"        pclass-wall      s_rune_Z      trn 0 nil)
+   (list 't_rune_TH         "a runic TH"        pclass-wall      s_rune_TH     trn 0 nil)
+   (list 't_rune_EE         "a runic EE"        pclass-wall      s_rune_EE     trn 0 nil)
+   (list 't_rune_NG         "a runic NG"        pclass-wall      s_rune_NG     trn 0 nil)
+   (list 't_rune_EA         "a runic EA"        pclass-wall      s_rune_EA     trn 0 nil)
+   (list 't_rune_ST         "a runic ST"        pclass-wall      s_rune_ST     trn 0 nil)
+   (list 't_rune_DOT        "a runic ."        pclass-wall      s_rune_DOTSEP trn 0 nil)
+   (list 't_equip_sign    "an equipment shop sign" pclass-wall s_torch_sign      opq 0 nil)
+   (list 't_weapon_sign   "an arms shop sign" pclass-wall s_shield_sign          opq 0 nil)
+   (list 't_healer_sign   "a hospital sign" pclass-wall s_ankh_sign              opq 0 nil)
+   (list 't_tavern_sign   "a tavern sign" pclass-wall s_beer_sign                opq 0 nil)
+   (list 't_inn_sign      "an inn sign" pclass-wall s_bed_sign                   opq 0 nil) 
+   (list 't_alchemy_sign      "an alchemy sign" pclass-wall s_potion_sign        opq 0 nil) 
+   (list 't_magic_sign      "a reagent shop sign" pclass-wall s_mushroom_sign    opq 0 nil) 
+   (list 't_str_sign      "a sign of strength" pclass-wall s_axe_sign            trn 1024 nil) 
+   (list 't_dex_sign      "a sign of dexterity" pclass-wall s_key_sign           trn 1024 nil) 
+   (list 't_wis_sign      "a sign of wisdom" pclass-wall s_book_sign             trn 1024 nil) 
+   (list 't_nat_rock      "natural stone wall" pclass-wall s_nat_rock            opq 0 nil) 
+   (list 't_fake_wall_nrock  "natural stone wall" pclass-forest  s_secret_nrock   opq 0 nil)
+   ))
+
+(map (lambda (terrain) (apply kern-mk-terrain terrain)) terrains)
+
+;;----------------------------------------------------------------------------
+;; Make some blended shore terrain types
+
+(define (mk-shore-terrain tag . sprites)
+  (kern-mk-terrain tag "shallow water" pclass-shoals
+                   (mk-composite-sprite (cons s_shoals sprites))
+                   trn 0 nil))
+
+(mk-shore-terrain 't_shore_n  s_grass_n )
+(mk-shore-terrain 't_shore_w  s_grass_w )
+(mk-shore-terrain 't_shore_nw s_grass_nw)
+(mk-shore-terrain 't_shore_e  s_grass_e )
+(mk-shore-terrain 't_shore_ne s_grass_ne)
+(mk-shore-terrain 't_shore_we s_grass_e s_grass_w)
+(mk-shore-terrain 't_shore_nwe s_grass_ne s_grass_nw)
+(mk-shore-terrain 't_shore_s  s_grass_s )
+(mk-shore-terrain 't_shore_ns s_grass_s s_grass_n)
+(mk-shore-terrain 't_shore_ws s_grass_sw)
+(mk-shore-terrain 't_shore_nws s_grass_sw s_grass_nw)
+(mk-shore-terrain 't_shore_es s_grass_se)
+(mk-shore-terrain 't_shore_nes s_grass_se s_grass_ne)
+(mk-shore-terrain 't_shore_wes s_grass_se s_grass_sw)
+(mk-shore-terrain 't_shore_c s_grass_se s_grass_sw s_grass_ne s_grass_nw)
+
+(define tset_shore
+(list
+   t_shoals    ;; 0: none
+   t_shore_n   ;; 1: north
+   t_shore_w   ;; 2: west
+   t_shore_nw  ;; 3: north west
+   t_shore_e   ;; 4: east
+   t_shore_ne  ;; 5: east north
+   t_shore_we  ;; 6: east west
+   t_shore_nwe ;; 7: east west north
+   t_shore_s   ;; 8: south
+   t_shore_ns  ;; 9: south north
+   t_shore_ws  ;; 10: south west
+   t_shore_nws ;; 11: south west north
+   t_shore_es  ;; 12: south east
+   t_shore_nes ;; 13: south east north
+   t_shore_wes ;; 14: south east west
+   t_shore_c ;; 15: south east west north
+   ))
+   
+(define tset_water
+(append tset_shore
+          (list t_shoals
+                t_shallow
+                t_deep
+                t_sunlit_deep
+                t_bridge_WE
+                t_bridge_NS)))
+
+;;----------------------------------------------------------------------------
+;; bits of ship
+
+;; regular terrains
+
+(map
+       (lambda (terrainentry)
+               (apply
+                       (lambda (tag name pclass opacity sprite)
+                               (kern-mk-terrain tag name pclass sprite
+                                       opacity 0 nil)
+                       )
+                       terrainentry
+               )
+       )
+       (list
+       
+(list 't_bulwark_x_ns "bulwark" pclass-wall opq s_bulwark_ns)
+(list 't_bulwark_x_ew "bulwark" pclass-wall opq s_bulwark_ew)
+       
+(list 't_bulwark_v_ne "bulwark" pclass-boulder trn s_bulwark_sw)
+(list 't_bulwark_v_nw "bulwark" pclass-boulder trn s_bulwark_se)
+(list 't_bulwark_v_se "bulwark" pclass-boulder trn s_bulwark_nw)
+(list 't_bulwark_v_sw "bulwark" pclass-boulder trn s_bulwark_ne)
+       
+(list 't_bulwark_x_ne "bulwark" pclass-wall opq s_bulwark_sw)
+(list 't_bulwark_x_nw "bulwark" pclass-wall opq s_bulwark_se)
+(list 't_bulwark_x_se "bulwark" pclass-wall opq s_bulwark_nw)
+(list 't_bulwark_x_sw "bulwark" pclass-wall opq s_bulwark_ne)
+
+(list 't_stair_un "stairs" pclass-grass trn s_stair_n)
+(list 't_stair_uw "stairs" pclass-grass trn s_stair_w)
+(list 't_stair_ue "stairs" pclass-grass trn s_stair_e)
+(list 't_stair_us "stairs" pclass-grass trn s_stair_s)
+
+(list 't_tank_l "metal tank" pclass-mountains opq s_tank_l)
+(list 't_tank_d "metal tank" pclass-mountains opq s_tank_d)
+(list 't_tank_nw "metal tank" pclass-mountains opq s_tank_nw)
+(list 't_tank_ne "metal tank" pclass-mountains opq s_tank_ne)
+(list 't_tank_sw "metal tank" pclass-mountains opq s_tank_sw)
+(list 't_tank_se "metal tank" pclass-mountains opq s_tank_se)
+
+       )
+)
+       
+               
+;; composite terrains
+(map
+       (lambda (terrainentry)
+               (apply
+                       (lambda (tag name pclass opacity sprites)
+                               (kern-mk-terrain tag name pclass (mk-composite-sprite sprites)
+                                       opacity 0 nil)
+                               )
+                       terrainentry
+               )
+       )
+       (list
+       
+(list 't_rail_ew "railing" pclass-boulder trn (list s_deck s_bulwark_ew))
+(list 't_rail_ns "railing" pclass-boulder trn (list s_deck s_bulwark_ns))
+
+(list 't_bulwark_n "bulwark" pclass-boulder trn (list s_shallow s_deck_s s_bulwark_ew))
+(list 't_bulwark_w "bulwark" pclass-boulder trn (list s_shallow s_deck_e s_bulwark_ns))
+(list 't_bulwark_e "bulwark" pclass-boulder trn (list s_shallow s_deck_w s_bulwark_ns))
+(list 't_bulwark_s "bulwark" pclass-boulder trn (list s_shallow s_deck_n s_bulwark_ew))
+
+(list 't_bulwark_v_n "bulwark" pclass-boulder trn (list s_deck_s s_bulwark_ew))
+(list 't_bulwark_v_w "bulwark" pclass-boulder trn (list s_deck_e s_bulwark_ns))
+(list 't_bulwark_v_e "bulwark" pclass-boulder trn (list s_deck_w s_bulwark_ns))
+(list 't_bulwark_v_s "bulwark" pclass-boulder trn (list s_deck_n s_bulwark_ew))
+
+(list 't_bulwark_w_ne "bulwark" pclass-boulder trn (list s_shallow s_bulwark_sw))
+(list 't_bulwark_w_nw "bulwark" pclass-boulder trn (list s_shallow s_bulwark_se))
+(list 't_bulwark_w_se "bulwark" pclass-boulder trn (list s_shallow s_bulwark_nw))
+(list 't_bulwark_w_sw "bulwark" pclass-boulder trn (list s_shallow s_bulwark_ne))
+
+(list 't_bulwark_d_ne "bulwark" pclass-boulder trn (list s_deck s_bulwark_ne))
+(list 't_bulwark_d_nw "bulwark" pclass-boulder trn (list s_deck s_bulwark_nw))
+(list 't_bulwark_d_se "bulwark" pclass-boulder trn (list s_deck s_bulwark_se))
+(list 't_bulwark_d_sw "bulwark" pclass-boulder trn (list s_deck s_bulwark_sw))
+
+(list 't_tank_d_nw "metal tank" pclass-mountains opq (list s_deck s_tank_nw))
+(list 't_tank_d_ne "metal tank" pclass-mountains opq (list s_deck s_tank_ne))
+(list 't_tank_d_sw "metal tank" pclass-mountains opq (list s_deck s_tank_sw))
+(list 't_tank_d_se "metal tank" pclass-mountains opq (list s_deck s_tank_se))
+
+       )
+)
+                                    
+;;----------------------------------------------------------------------------
+
+(define bad-terrain-list
+  (list t_bog
+        t_lava
+        t_deep_lava
+        t_fire_terrain
+        t_fireplace
+        t_inv_wall
+        t_wall_torch
+        ))
+
+(define inflammable-terrain-list
+  (list t_bog
+        t_deep
+        t_shallow
+        t_shoals
+        t_sunlit_deep
+        t_stars
+               t_void
+               t_chasm
+        ))
+               
+(load "blendterrains.scm")
+
+(define (is-bad-terrain? kter)
+  (in-list? kter bad-terrain-list))
+
+(define (is-inflammable-terrain? kter)
+  (in-list? kter inflammable-terrain-list))
+
+(define (is-deck? kter)
+       (in-list? kter 
+               (list
+                       t_deck
+                       t_ship_hull
+                       t_ship_hull2
+                       t_mast
+                       t_ships_wheel
+                       
+                       t_bulwark_v_ne
+                       t_bulwark_v_nw
+                       t_bulwark_v_se
+                       t_bulwark_v_sw
+                       
+                       t_bulwark_n
+                       t_bulwark_w
+                       t_bulwark_e
+                       t_bulwark_s
+                       
+                       t_bulwark_w_ne
+                       t_bulwark_w_nw
+                       t_bulwark_w_se
+                       t_bulwark_w_sw
+                       
+                       t_bulwark_d_ne
+                       t_bulwark_d_nw
+                       t_bulwark_d_se
+                       t_bulwark_d_sw
+                       
+                       t_bulwark_v_n
+                       t_bulwark_v_w
+                       t_bulwark_v_e
+                       t_bulwark_v_s
+       )))
diff --git a/worlds/haxima-1.002/tetzl.scm b/worlds/haxima-1.002/tetzl.scm
new file mode 100644 (file)
index 0000000..3d1def5
--- /dev/null
@@ -0,0 +1,67 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define tetzl-lvl 2)
+(define tetzl-species sp_spider)
+(define tetzl-occ oc_wright)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the monster village of Kun.
+;;----------------------------------------------------------------------------
+(define tetzl-bed campfire-3)
+(define tetzl-mealplace cantina-1)
+(define tetzl-workplace cantina-1)
+(define tetzl-leisureplace cantina-1)
+(kern-mk-sched 'sch_tetzl
+               (list 0  0 tetzl-bed          "sleeping")
+               (list 7  0 tetzl-mealplace    "eating")
+               (list 8  0 tetzl-workplace    "working")
+               (list 12 0 tetzl-mealplace    "eating")
+               (list 13 0 tetzl-workplace    "working")
+               (list 18 0 tetzl-mealplace    "eating")
+               (list 19 0 tetzl-leisureplace "idle")
+               (list 22 0 tetzl-bed          "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (tetzl-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Tetzl is a sentient spider of giant size, 
+;; living in the monster village of Kun.
+;; 
+;; Currently, no dialog or quests, but this seems a missed opportunity...
+;;----------------------------------------------------------------------------
+
+
+(define (mk-tetzl)
+  (bind 
+   (kern-mk-char 
+    'ch_tetzl           ; tag
+    "Tetzl"             ; name
+    tetzl-species         ; species
+    tetzl-occ              ; occ
+    s_spider     ; sprite
+    faction-men      ; starting alignment
+    1 0 1            ; str/int/dex
+    0 0              ; hp mod/mult
+    0 0              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+       0
+    tetzl-lvl
+    #f               ; dead
+    nil         ; conv
+    sch_tetzl           ; sched
+    nil              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   (tetzl-mk)))
diff --git a/worlds/haxima-1.002/the-man.scm b/worlds/haxima-1.002/the-man.scm
new file mode 100644 (file)
index 0000000..c8ac98d
--- /dev/null
@@ -0,0 +1,239 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define the-man-start-lvl 9)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In The MAN's hideout, a secure undisclosed location.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_man
+               (list 0  0 mans-bed    "sleeping")
+               (list 7  0 mans-supper "eating")
+               (list 8  0 mans-hall   "idle")
+               (list 12 0 mans-supper "eating")
+               (list 13 0 mans-tools  "idle")
+               (list 15 0 mans-hall   "idle")
+               (list 18 0 mans-supper "eating")
+               (list 19 0 mans-dock   "idle")
+               (list 22 0 mans-bed    "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (man-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Yvonne, known as "The MAN", is a female rogue of pre-eminent skill,
+;; living in a secure undisclosed location (The MAN's hideout).
+;; 
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (man-hail knpc kpc)
+  (say knpc "[You meet an attractive, middle-aged woman with a catlike poise "
+       "and easy bearing] Hello, Good-looking."))
+
+(define (man-default knpc kpc)
+  (say knpc "You've got me there, hotshot."))
+
+(define (man-name knpc kpc)
+  (say knpc "I'm Yvonne. But everybody calls me The MAN."))
+
+(define (man-join knpc kpc)
+  (say knpc "Can't say I'm not tempted, handsome, but when it comes to "
+       "business I like to work alone."))
+
+(define (man-job knpc kpc)
+  (say knpc "Hm. How shall I put this? I suppose the truth is easiest: "
+       "I'm a Wrogue."))
+
+(define (man-bye knpc kpc)
+  (say knpc "Bye bye..."))
+
+
+;; Misc
+(define (man-man knpc kpc)
+  (say knpc "[She laughs easily] Were you expecting someone... manlier?")
+  (kern-conv-get-yes-no? kpc)
+  (say knpc "The MAN is an acronym for the Mistress of Acquisitive "
+       "Nature. Do you like it?")
+  (kern-conv-get-yes-no? kpc)
+  (say knpc "I think it was the Engineer who originally coined it. "
+       "You know those engineering types, suckers for an acronym."))
+
+(define (man-wrog knpc kpc)
+  (say knpc "A Wrogue specializes in breaking rules. Tell me, stranger, "
+       "do you like to break the rules?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "[She feigns a shocked look. It really is quite fetching.] "
+           "Naughty boy! I may have to edify your character with a "
+           "spanking before you leave.")
+      (say knpc "Oh, so you're a square? I do like squares. Perhaps you'll "
+           "rub off on me. [She gives you a cutely innocent look]")))
+
+(define (man-rule knpc kpc)
+  (say knpc "A rule, a lock, a secret, a riddle. I love to break them all "
+       "and see what lies behind. It's curiousity mainly, and the challenge "
+       "of the crack. Look around, do you see much wealth here in my home?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Sigh. Either you come from a poor childhood or you haven't "
+           "bothered to look.")
+      (say knpc "No, despite my moniker I'm not that acquisitive. There's no "
+           "pleasure for me in HAVING, only in DOING. Once a thing is done "
+           "I've no further interest in it. The most interesting and valuable "
+           "things I've acquired are secrets.")))
+
+(define (man-secr knpc kpc)
+  (say knpc "Just try me."))
+
+(define (man-enem knpc kpc)
+  (say knpc "The Warritrix has a mighty enemy in the person of the "
+       "Stewardess of Glasdrin."))
+
+(define (man-stew knpc kpc)
+  (say knpc "I read her diary once. She really ought to keep it locked up "
+       "better. She hates the Warritrix for defying her at Absalot."))
+
+(define (man-hate knpc kpc)
+  (say knpc "You can read the Stewardess's diary for yourself. "
+       "Would you like to know how?")
+  (if (yes? kpc)
+      (say knpc "Just remember two little words: Wis Quas. "
+           "I'm sure a sharp guy like you can figure out the rest.")
+      (say knpc "Oh, but you're missing out! "
+           "It's simply dripping with political intrigue.")))
+
+
+;; Wise Queries
+(define (man-wiza knpc kpc)
+  (say knpc "Yes, they're powerful. But I've pilfered their secrets."))
+
+(define (man-wrig knpc kpc)
+  (say knpc "A clever bunch, but they've yet to design a lock I can't crack."))
+
+(define (man-warr knpc kpc)
+  (say knpc "The Warritrix is legendary for her noble demeanor. I do not know "
+       "her well, but I do know her enemies, perhaps better than she."))
+
+(define (man-necr knpc kpc)
+  (say knpc "A useful fellow, the dead know many things forgotten by the "
+       "living, and he knows how to charm them."))
+
+(define (man-alch knpc kpc)
+  (say knpc "I understand he's a clever little worm, but I don't have much "
+       "to do with him."))
+
+(define (man-engi knpc kpc)
+  (say knpc "I'd love to challenge myself with a lock of his design, but "
+       "alas, he keeps no secrets or treasure to lock up!"))
+
+(define (man-ench knpc kpc)
+  (say knpc "My most favorite wizard. I do love to hear him go on and on in "
+       "that virtuous vein of his! But he really should keep his stuff more "
+       "secure."))
+
+;; Accursed Queries
+(define (man-accu knpc kpc)
+  (say knpc "They speak of freedom, by which they mean the freedom to enslave others. "
+       "Some who would break the rules join them, only to find themselves enchained. "
+       "A nasty bunch."))
+
+
+;; Rune
+(define (man-rune knpc kpc)
+  (say knpc "Runes... I once knew a pirate that carried a Rune. Have you "
+       "heard the tale of Ghertie and the Merciful Death?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "You are already well-traveled. I like an experienced man.")
+      (say knpc "Ask around Oparine about Ghertie."))
+  (say knpc "If you can find where the Merciful Death lies you can raise it "
+       "with a spell. Do you know the spell?")
+  (if (kern-conv-get-yes-no? kpc)
+      (say knpc "Well, aren't we the accomplished magician? I hope you don't "
+           "know any love spells, Wizard!")
+      (begin
+                       (say knpc "Mix mandrake, blood moss and spider silk, then chant Vas "
+                       "Uus Ylem next to the spot where the ship has sunk.")
+                       (quest-data-update 'questentry-rune-c 'shipraise 1)
+               )
+       )
+  (say knpc "Ghertie will not give up the location of her ship freely. But "
+       "even the dead have desires, indeed that is the worst part of "
+       "death! And Ghertie desires nothing more than ^c+mrevenge^c-. Mark that word "
+       "well, and remember it when you meet her ghost.")
+       (quest-data-update 'questentry-rune-c 'info 1)
+       (quest-data-assign-once 'questentry-rune-c)
+       (quest-data-update 'questentry-ghertie 'ghertieid 1)
+       (quest-data-update-with 'questentry-ghertie 'revenge 1 (quest-notify nil))
+       (quest-data-assign-once 'questentry-ghertie)
+       )
+
+(define (man-chan knpc kpc)
+  (say knpc "So you've met Chanticleer? No doubt HE was the one who told you where to find me! "
+       "[Sigh] Well, I hope the irresponsible wrogue is well."))
+
+(define man-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'default man-default)
+       (method 'hail man-hail)
+       (method 'bye  man-bye)
+       (method 'job  man-job)
+       (method 'name man-name)
+       (method 'join man-join)
+       
+       ;; special
+       (method 'man man-man)
+       (method 'wrog man-wrog)
+       (method 'rogu man-wrog)  ;; a synonym
+       (method 'rule man-rule)
+       (method 'secr man-secr)
+       (method 'enem man-enem)
+       (method 'stew man-stew)
+       (method 'diar man-hate)
+       (method 'evid man-hate)
+       (method 'hate man-hate)
+       (method 'wiza man-wiza)
+       (method 'wrig man-wrig)
+       (method 'warr man-warr)
+       (method 'necr man-necr)
+       (method 'alch man-alch)
+       (method 'engi man-engi)
+       (method 'ench man-ench)
+       (method 'accu man-accu)
+       (method 'rune man-rune)
+       (method 'chan man-chan)
+       ))
+
+(define (mk-the-man)
+  (bind 
+   (kern-mk-char 'ch_man           ; tag
+                 "The MAN"             ; name
+                 sp_human            ; species
+                 oc_wrogue           ; occ
+                 s_brigandess        ; sprite
+                 faction-men         ; starting alignment
+                 0 3 10               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health ; hp
+                 -1                   ; xp
+                 max-health ; mp
+                 0
+                 the-man-start-lvl
+                 #f                  ; dead
+                 'man-conv         ; conv
+                 sch_man           ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 (list t_armor_leather_4
+                               t_leather_helm_2
+                               t_magic_axe)                 ; readied
+                 )
+   (man-mk)))
diff --git a/worlds/haxima-1.002/thiefs_den.scm b/worlds/haxima-1.002/thiefs_den.scm
new file mode 100644 (file)
index 0000000..e1ad809
--- /dev/null
@@ -0,0 +1,110 @@
+;; ----------------------------------------------------------------------------
+;; Map
+;; ----------------------------------------------------------------------------
+  (kern-mk-map
+    'm_thiefs_den 19 19 pal_expanded
+    (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx && ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, pp ,, ,, ,, ,, ,, ,, ,, ,, ,, pp ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, ,, pp ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+    )
+  )
+;;----------------------------------------------------------------------------
+;; Characters
+;;----------------------------------------------------------------------------
+(kern-load "mouse.scm")
+(mk-mouse)
+
+;;----------------------------------------------------------------------------
+;; Special Objects
+;;----------------------------------------------------------------------------
+;(kern-load "thiefs_den_mechs.scm")
+
+;;----------------------------------------------------------------------------
+;; Other dungeon rooms
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Place
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_thiefs_den ; tag
+ "Thief's Den"   ; name
+ nil              ; sprite
+ m_thiefs_den  ; map
+ #f               ; wraps
+ #t                     ; underground
+ #f                     ; large-scale (wilderness)
+ #f                     ; tmp combat place
+ nil                    ; subplaces
+ nil ;; neighbors 
+ ;; objects
+ (list
+
+  (put ch_mouse 3 3)
+  (put (mk-ladder-up 'p_traps_4 9 7) 9 9)
+
+  ;; foods
+  (put (kern-mk-obj t_food 10) 4 1)
+  (put (kern-mk-obj t_wine 1) 4 2)
+
+  ;; potions
+  (put (kern-mk-obj t_cure_potion 1) 3 4)
+  (put (kern-mk-obj t_mana_potion 1) 4 5)
+  (put (kern-mk-obj t_heal_potion 1) 5 5)
+  (put (kern-mk-obj t_poison_immunity_potion 1) 6 5)
+  (put (kern-mk-obj t_invisibility_potion 1) 7 5)
+
+  ;; tools
+  (put (kern-mk-obj t_torch 1) 8 5)
+  (put (kern-mk-obj t_picklock 1) 8 6)
+  (put (kern-mk-obj t_gem      1) 8 7)
+
+  ;; scrolls
+  (put (kern-mk-obj t_an_tym_scroll 1) 9 7)
+  (put (kern-mk-obj t_in_mani_corp_scroll 1) 10 7)
+  (put (kern-mk-obj t_vas_rel_por_scroll 1) 10 8)
+  (put (kern-mk-obj t_sanct_lor_scroll 1) 10 10)
+  (put (kern-mk-obj t_in_quas_xen_scroll 1) 9 10)
+  (put (kern-mk-obj t_an_xen_ex_scroll 1) 8 9)
+  (put (kern-mk-obj t_in_an_scroll 1) 7 9)
+  (put (kern-mk-obj t_in_ex_por_scroll 1) 6 9)
+  (put (kern-mk-obj t_vas_mani_scroll 1) 6 8)
+  (put (kern-mk-obj t_wis_quas_scroll 1) 6 7)
+
+ ;; spellbooks
+(put (kern-mk-obj t_spell_book_illusion_1          1)  3  1)
+(put (kern-mk-obj t_spell_book_force_magick_fields 1)  2 12)
+(put (kern-mk-obj t_spell_book_force_magick_matter 1) 16 17)
+
+  ;; lucre
+  (put (kern-mk-obj t_gold_coins 74) 6 2)
+  (put (kern-mk-obj t_gold_coins 112) 2 9)
+  (put (kern-mk-obj t_gold_coins 243) 1 17)
+  (put (kern-mk-obj t_gold_coins 30) 7 3)
+  
+  ;; door
+  (put (mk-bed) 3 1)
+  
+  )
+ (list 'quest-thiefrune-den5) ; hooks
+ nil ; edge entrances
+ )
+
+(mk-place-music p_thiefs_den 'ml-dungeon-adventure)
diff --git a/worlds/haxima-1.002/thorald.scm b/worlds/haxima-1.002/thorald.scm
new file mode 100644 (file)
index 0000000..139eb31
--- /dev/null
@@ -0,0 +1,96 @@
+;; Thorald is a character in the Tutorial game.
+
+
+(define (thorald-mixi knpc kpc)
+  (say knpc "To M)ix spells first press the 'M' key. "
+       "Then type the first letter of each spell syllable followed by ENTER. "
+       "For example, In Ex Por would be: i, e, p, ENTER.")
+  (prompt-for-key)
+  (say knpc "Next, select the reagents using the space bar. ")
+  (prompt-for-key)
+  (say knpc "Next, press ENTER and type the number of mixtures to make. "
+       "Just mix 1 for now. ")
+  (prompt-for-key)
+  (say knpc "You can see what spells you have mixed with the Z)tatus command. "
+       "Why don't you try mixing one now? Talk to me again when you've succeeded.")
+  (kern-conv-end)
+  )
+
+(define conv-thorald
+  (ifc nil
+       (method 'bye
+               (lambda (knpc kpc)
+                 (say knpc "Oh, I'm sure we'll be seeing more of each other.")))
+       (method 'default 
+               (lambda (knpc kpc)
+                 (say knpc "I can't help you with that.")))
+       (method 'hail
+               (lambda (knpc kpc)
+                 (kern-log-msg "You meet a bored old man.")
+                 (if (in-inventory? kpc in_ex_por)
+                     (say knpc "I see you have an In Ex Por spell. "
+                          "Ask me about casting it if you don't know how.")
+                     (say knpc "Welcome to the tutorial. Why don't you ask me about my job, "
+                          "or maybe that door over there.")
+                     )))
+       (method 'join
+               (lambda (knpc kpc)
+                 (say knpc "Yes, let's get this show on the road. "
+                      "Press 'F' and I'll follow you. "
+                      "Later if you want me to take turns moving with you, press 'F' again. "
+                      "And if you want me to explore while you wait, press '2'. "
+                      "You can always press 'F' again to get me to follow you.")
+                 (join-player knpc)
+                 (kern-conv-end)
+                 ))
+       (method 'name
+               (lambda (knpc kpc)
+                 (say knpc "I'm Thorald. Hi.")))
+       (method 'job
+               (lambda (knpc kpc)
+                 (say knpc "I'm just the hired help.")))
+       (method 'door
+               (lambda (knpc kpc)
+                 (say knpc "Yes, I know a spell that can open that magically locked door. "
+                      "Imagine that! Why don't you ask me about it?")
+                 ))
+       (method 'spel
+               (lambda (knpc kpc)
+                 (say knpc "The In Ex Por spell unlocks magically locked doors. "
+                      "To mix it you'll need sulphurous ash and blood moss. "
+                      "Ask me about mixing if you don't know how.")))
+       (method 'mix thorald-mixi)
+       (method 'mixi thorald-mixi)
+       (method 'cast
+               (lambda (knpc kpc)
+                 (say knpc "To C)ast a spell press 'c' and then enter the first letter of each magic word. "
+                      "For example, to cast In Ex Por you enter 'i', 'e' and 'p'. "
+                      "Use backspace if you mess up. "
+                      "When the spell is right hit ENTER to cast it. "
+                      "In Ex Por requires you to target the door.")))
+       ))
+       
+(define (thorald-ai kchar) #t)
+
+(define (mk-thorald)
+  (kern-mk-char 
+   'ch_thorald ; tag
+   "Thorald Greybeard"   ; name
+   sp_human              ; species
+   oc_wrogue             ; occ
+   s_companion_wizard    ; sprite
+   faction-player        ; starting alignment
+   0 10 2                ; str/int/dex
+   0 1                   ; hp mod/mult
+   10 5                  ; mp mod/mult
+   240 -1 8 0 8             ; hp/xp/mp/AP_per_turn/lvl
+   #f                    ; dead
+   'conv-thorald         ; conv
+   nil                   ; sched
+   'thorald-ai           ; special ai
+   nil                   ; container
+   (list t_sling
+         t_armor_leather
+         )
+   nil
+   ))
diff --git a/worlds/haxima-1.002/thud.scm b/worlds/haxima-1.002/thud.scm
new file mode 100644 (file)
index 0000000..652c6e5
--- /dev/null
@@ -0,0 +1,133 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define thud-start-lvl  6)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In Bole
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_thud
+               (list 0  0  bole-bedroom-thud "idle")
+               (list 9  0  bole-dining-hall  "idle")
+               (list 10 0  bole-courtyard   "idle")
+               (list 12 0  bole-dining-hall   "idle")
+               (list 23 0  bole-bedroom-thud "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (thud-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Thud is the bodyguard of Kathryn, and currently abides in Bole,
+;; where they seek a certain thief.  Various other NPCs suggest
+;; that Thud is at best half human, perhaps having ogre blood,
+;; or a sorcerous (summoned or vat-born) origin...
+;; 
+;; Thud is a potential party member (and an eventual betrayer).
+;; He accompanies Kathrun, and joins the party when and if she does.
+;;----------------------------------------------------------------------------
+(define (thud-hail knpc kpc)
+  (say knpc "[You are certain that the figure before you is part ogre. "
+       "Three meters tall and smoldering with menace, he regards you with "
+       "half-lidded eyes.]"))
+
+(define (thud-default knpc kpc)
+  (say knpc "[His threatening gaze does not waver]"))
+
+(define (thud-name knpc kpc)
+  (say knpc "Thud no like you."))
+
+(define (thud-join knpc kpc)
+  (if (is-player-party-member? ch_kathryn)
+      (begin
+        (say knpc "[Seeing Kathryn with you, he grunts his assent]")
+        (kern-char-join-player knpc)
+        (kern-conv-end))
+      (say knpc "[He sneers]")))
+
+(define (thud-job knpc kpc)
+  (say knpc "Thud love kill."))
+
+(define (thud-kathryn knpc kpc)
+  (say knpc "Thud no kill"))
+
+(define (thud-thud knpc kpc)
+  (say knpc "You talk me? YOU TALK ME?! THUD PICK TEETH WITH YOU BONES!!"))
+
+(define (thud-thief knpc kpc)
+  (say knpc "[He becomes enraged] THIEF TRICK THUD! THUD FIND THIEF! THUD KILL THIEF!"))
+
+(define (thud-find knpc kpc)
+  (say knpc "[He calms down a bit] Red Lady find thief. He no can hide."))
+
+(define (thud-red-lady knpc kpc)
+  (say knpc "[He gives you a murderous look] You stay away Red Lady."))
+
+(define thud-conv
+  (ifc nil
+       (method 'default thud-default)
+       (method 'hail thud-hail)
+       (method 'bye 
+               (lambda (knpc kpc) 
+                 (say knpc "[His eyes bore into your back as you walk away]")))
+       (method 'job  thud-job)
+       (method 'name thud-name)
+       (method 'join thud-join)
+
+       (method 'find thud-find)
+       (method 'kath thud-kathryn)
+       (method 'kill thud-job)
+       (method 'lady thud-red-lady)
+       (method 'love thud-job)
+       (method 'red  thud-red-lady)
+       (method 'thie thud-thief)
+       (method 'thud thud-thud)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-thud)
+  (bind 
+    (kern-char-arm-self
+     (kern-mk-char 
+      'ch_thud ;;.....tag
+      "Thud" ;;.......name
+      sp_troll ;;.....species
+      oc_warrior ;;...occupation
+      s_troll ;;......sprite
+      faction-men ;;..faction
+      4 ;;............custom strength modifier
+      0 ;;............custom intelligence modifier
+      2 ;;............custom dexterity modifier
+      2 ;;............custom base hp modifier
+      1 ;;............custom hp multiplier (per-level)
+      0 ;;............custom base mp modifier
+      0 ;;............custom mp multiplier (per-level)
+      max-health;;..current hit points
+      -1  ;;...........current experience points
+      max-health ;;..current magic points
+      0
+      thud-start-lvl  ;;..current level
+      #f ;;...........dead?
+      'thud-conv ;;...conversation (optional)
+      sch_thud ;;.....schedule (optional)
+      'townsman-ai ;;..........custom ai (optional)
+      nil ;;..........container (and contents)
+      ;;.........readied arms (in addition to the container contents)
+      (list
+       t_2h_axe
+       t_iron_helm
+       t_armor_plate
+       )
+      nil ;;..........hooks in effect
+      ))
+   (thud-mk)))
diff --git a/worlds/haxima-1.002/ticktock.wav b/worlds/haxima-1.002/ticktock.wav
new file mode 100644 (file)
index 0000000..2ccf1cd
Binary files /dev/null and b/worlds/haxima-1.002/ticktock.wav differ
diff --git a/worlds/haxima-1.002/tim.scm b/worlds/haxima-1.002/tim.scm
new file mode 100644 (file)
index 0000000..e063314
--- /dev/null
@@ -0,0 +1,116 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define tim-start-lvl 4)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the Tower of Brundegart (p_brundegardt_tower_4), locked outside.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (tim-mk) (list #f #f))
+(define (tim-caught? gob) (car gob))
+(define (tim-caught! gob) (set-car! gob #t))
+(define (tim-met? gob) (cadr gob))
+(define (tim-met! gob) (set-car! (cdr gob) #t))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Tim is a maimed, drooling madman, currently trapped outside 
+;; the Tower of Brundegart.
+;; 
+;; Once a seeker of knowledge (and power), 
+;; his body was ravaged by griffins (and their hungry chicks), 
+;; and his mind broken by contact with the EYE of Brundegart.
+;; (One rather assumes the maiming did not help his mental state, 
+;; for that matter...)
+;;----------------------------------------------------------------------------
+(define (tim-hail knpc kpc)
+  (meet "You meet a drooling madman with only one arm.")
+  (say knpc "I have seen the eye!"))
+
+(define (tim-eye knpc kpc)
+  (say knpc "So wise I am now, because of the eye. Would you be wise?")
+  (cond ((yes? knpc)
+         (say knpc "Alas, my friend, I have lost the key!"))
+        (else
+         (say knpc "Fool!")
+         (kern-conv-end))))
+
+(define (tim-key knpc kpc)
+  (say knpc "It was my key! I found it on the dead man. "
+       "First they took my arm, then the lion-birds took my key!"))
+
+(define (tim-arm knpc kpc)
+  (say knpc "They chose me as I walked among the hills, "
+       "and brought me here to feed their young."))
+
+(define (tim-name knpc kpc)
+  (say knpc "Do not pretend to not know me! "
+       "One who is all-wise is necessarily famous! That's logic!"))
+
+(define (tim-job knpc kpc)
+  (say knpc "I will bring enlightenment to the world!"))
+
+(define (tim-enli knpc kpc)
+  (say knpc "Yes! The eye! The eye... [He curls into a fetal ball and sobs]")
+  (kern-conv-end))
+
+(define (tim-lion knpc kpc)
+  (say knpc "[He shrieks and cowers] Do you see them?! "
+       "Have they come for my other arm?  The chicks are so hungry! So cruel!"))
+
+(define tim-conv
+  (ifc nil
+       (method 'hail tim-hail)
+       (method 'eye  tim-eye)
+       (method 'key  tim-key)
+       (method 'arm  tim-arm)
+       (method 'name tim-name)
+       (method 'job  tim-job)
+       (method 'enli tim-enli)
+       (method 'lion tim-lion)
+       ))
+
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-tim)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     'ch_tim ;;..........tag
+     "Tim" ;;.......name
+     sp_human ;;.....species
+     oc_wizard ;;.. .occupation
+     s_wizard ;;..sprite
+     faction-men ;;..faction
+     +1 ;;...........custom strength modifier
+     0 ;;...........custom intelligence modifier
+     +1 ;;...........custom dexterity modifier
+     +1 ;;............custom base hp modifier
+     +1 ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0
+     tim-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'tim-conv ;;...conversation (optional)
+     nil ;;sch_tim ;;.....schedule (optional)
+     nil ;;..........custom ai (optional)
+     nil ;;..............container (and contents)
+     nil ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (tim-mk)))
diff --git a/worlds/haxima-1.002/timer.scm b/worlds/haxima-1.002/timer.scm
new file mode 100644 (file)
index 0000000..6a71da3
--- /dev/null
@@ -0,0 +1,52 @@
+;; A generic timer mech
+
+(define (tmr-mk targ timeout sig)
+  (list targ timeout 0 #f sig))
+
+(define (tmr-targ tmr) (car tmr))
+(define (tmr-timeout tmr) (cadr tmr))
+(define (tmr-count tmr) (caddr tmr))
+(define (tmr-on? tmr) (cadddr tmr))
+(define (tmr-sig tmr) (list-ref tmr 4))
+
+(define (tmr-set-count! tmr val) (set-car! (cddr tmr) val))
+(define (tmr-set-start! tmr val) (set-car! (cdddr tmr) val))
+
+(define (tmr-expired? tmr) (>= (tmr-count tmr) (tmr-timeout tmr)))
+(define (tmr-stop! tmr) 
+  (tmr-set-count! tmr 0)
+  (tmr-set-start! tmr #f))
+(define (tmr-inc! tmr) (tmr-set-count! tmr (+ 1 (tmr-count tmr))))
+
+(define (ktmr-start! ktmr) 
+  (let ((tmr (kobj-gob-data ktmr)))
+    (tmr-set-count! tmr 0)
+    (tmr-set-start! tmr #t)))
+
+(define (ktmr-exec ktmr)
+  (let ((tmr (kobj-gob-data ktmr)))
+    (display "tmr-exec")(newline)
+    (if (tmr-on? tmr)
+        (begin
+          (display "tmr-on")(newline)
+          (tmr-inc! tmr)
+          (if (tmr-expired? tmr)
+              (let* ((tag (tmr-targ tmr))
+                     (targ (safe-eval tag)))
+                (display "timer-expired")(newline)
+                (display "timer-sig:")(display (tmr-sig tmr))(newline)
+                (tmr-stop! tmr)
+                (if (notnull? tag)
+                    (signal-kobj targ (tmr-sig tmr) targ ktmr))))))))
+
+(define timer-ifc
+  (ifc nil
+       (method 'exec ktmr-exec)
+       (method 'start ktmr-start!)
+       ))
+
+(mk-obj-type 't_timer "timer" '() layer-mechanism timer-ifc)
+
+(define (mk-timer target-tag timeout sig)
+  (bind (kern-mk-obj t_timer 1)
+        (tmr-mk target-tag timeout sig)))
diff --git a/worlds/haxima-1.002/tools.png b/worlds/haxima-1.002/tools.png
new file mode 100644 (file)
index 0000000..8f95bd4
Binary files /dev/null and b/worlds/haxima-1.002/tools.png differ
diff --git a/worlds/haxima-1.002/tools.scm b/worlds/haxima-1.002/tools.scm
new file mode 100644 (file)
index 0000000..ec1e125
--- /dev/null
@@ -0,0 +1,390 @@
+;; ----------------------------------------------------------------------------
+;; tools.scm -- "usable" stuff that isn't a book, scroll or potion
+;; ----------------------------------------------------------------------------
+
+;; torch -- use two in-lor spells
+(mk-usable-item 't_torch "torch" s_torch norm
+                (lambda (kobj kuser) 
+                  (kern-obj-add-effect kuser ef_torchlight nil)
+                  result-ok))
+
+;; picklock
+(define (picklock-proc kchar ktarg)
+  (let ((dc ((kobj-ifc ktarg) 'get-unlock-dc ktarg kchar)))
+    (if (= 0 dc) 
+        ;; difficulty=0 means it is no longer locked
+        (kern-char-task-abort kchar)
+        (let ((roll (kern-dice-roll "1d20+4"))
+              (bonus (kern-dice-roll (string-append "1d" (number->string (occ-ability-thief kchar)))))
+              (finish-dc (* 2 dc))
+              )
+          ;; roll to complete
+          ;(println "complete: " roll "+" bonus " vs " finish-dc)
+          (if (or (= 20 roll) (> (+ roll bonus ) finish-dc))
+              (let ((roll (kern-dice-roll "1d20"))
+                    (bonus (kern-dice-roll (string-append "1d" (number->string (occ-ability-thief kchar)))))
+                    )
+                ;; roll to succeed
+                ;(println "succeed: " roll "+" bonus " vs " dc)
+                (cond ((or (= roll 20) (> (+ roll bonus ) dc))
+                       (send-signal kchar ktarg 'unlock)
+                       (kern-char-task-end kchar)
+                       )
+                      (else
+                       (kern-log-msg "Picklock broke!")
+                       (kern-obj-remove-from-inventory kchar t_picklock 1)
+                       (kern-char-task-end kchar) 
+                       )
+                      )))))))
+        
+
+(mk-reusable-item 
+  't_picklock "picklock" s_picklock norm
+  (lambda (kobj kuser)
+    (if (not (has-skill? kuser sk_unlock))
+        result-lacks-skill
+        (let ((ktarg (ui-target (kern-obj-get-location kuser) 1 (mk-ifc-query 'unlock))))
+          (cond ((null? ktarg) result-no-target)
+                (else
+                 (kern-char-task-begin kuser "picking a lock" 'picklock-proc ktarg)
+                 result-ok
+                 ))))))
+
+;; gem -- use peer spell
+(mk-usable-item 't_gem "gem" s_gem norm
+                (lambda (kgem kuser)
+                  (powers-view kuser kuser 12)
+                  result-ok))
+
+;; sledge-hammer -- shatter rocks
+(mk-reusable-item 't_pick "pick" s_pick v-hard
+                  (lambda (ktool kuser)
+                    (let ((loc (kern-ui-target (kern-obj-get-location kuser)
+                                               1)))
+                      (if (null? loc)
+                          result-no-target
+                          (let ((kter (kern-place-get-terrain loc)))
+                            (cond ((eqv? kter t_boulder)
+                                   (kern-log-msg (kern-obj-get-name kuser)
+                                                 " pulverizes a boulder!")
+                                   (kern-place-set-terrain loc t_grass)
+                                   (cond ((> (kern-dice-roll "1d20") 16)
+                                          (kern-log-msg "The pick shatters!")
+                                          (kern-obj-remove-from-inventory kuser ktool 1)))
+                                   result-ok)
+                                  (else
+                                   result-no-effect)))))))
+
+;; sextant -- gives location
+(mk-reusable-item 't_sextant "sextant" s_sextant hard
+                  (lambda (ktool kuser)
+                    (let ((loc (kern-obj-get-location kuser)))
+                      (cond ((kern-place-is-wilderness? (loc-place loc))
+                             (kern-log-msg "You are at [x=" 
+                                           (cadr loc) " y=" (caddr loc) "]")
+                             result-ok)
+                            (else
+                             (kern-log-msg "Usable only in the wilderness!")
+                             result-not-here)))))
+
+;; ----------------------------------------------------------------------------
+;; special object for testing multi-turn tasks
+(define (test-task-proc kchar)
+  (cond ((< (kern-dice-roll "1d20") 3)
+         (kern-char-task-end kchar)
+         #t
+         )
+        (else
+         #t
+         )))
+
+(mk-reusable-item 
+ 't_test_obj "test object" s_gem 0
+ (lambda (ktool kuser)
+   ;; test-task-proc must be passed in quotes or saving/reloading won't
+   ;; work. The kernel enforces this. The only legitimate reason for failure
+   ;; would be if the player is in the wilderness when he tries do to this,
+   ;; hence the result-not-here on failure (yeah, this is probably not a good
+   ;; assumption going forward).
+   (if (kern-char-task-begin kuser "a test task" 'test-task-proc nil)
+       result-ok
+       result-not-here)
+   ))
+
+;;----------------------------------------------------------------------------
+;; shovel & buried object generator
+;;----------------------------------------------------------------------------
+(define (buried-mk objtype-tag quan) (list objtype-tag quan))
+(define (buried-objtype-tag buried) (car buried))
+(define (buried-quan buried) (cadr buried))
+
+(define (buried-digup kburied)
+  (display "buried-digup")(newline)
+  (let* ((buried (kobj-gob-data kburied))
+         (kobj (kern-mk-obj (eval (buried-objtype-tag buried))
+                            (buried-quan buried))))
+    (kern-obj-put-at kobj
+                     (kern-obj-get-location kburied))
+    (kern-log-msg "You dig up something!")
+    (kern-obj-remove kburied)))
+
+(define buried-ifc
+  (ifc nil
+       (method 'digup buried-digup)))
+
+(mk-obj-type 't_buried nil nil layer-none buried-ifc)
+
+(define (mk-buried objtype-tag quan)
+  (bind (kern-mk-obj t_buried 1)
+        (buried-mk objtype-tag quan)))
+
+(define (is-buried? kobj)
+  (eqv? (kern-obj-get-type kobj)
+        t_buried))
+
+(mk-reusable-item 't_shovel "shovel" s_shovel v-hard
+                (lambda (kshovel kuser)
+                  (let ((ktarg (filter is-buried?
+                                       (kern-get-objects-at 
+                                        (kern-obj-get-location kuser)))))
+                    (cond ((null? ktarg)
+                           (kern-log-msg "Nothing buried here!")
+                           result-no-effect)
+                          (else
+                           (signal-kobj (car ktarg) 'digup (car ktarg) nil)
+                           result-ok)))))
+                                                 
+(mk-reusable-item 't_chrono "chronometer" s_chrono hard
+                  (lambda (kclock kuser)
+                    (let* ((time (kern-get-time))
+                           (hour (number->string
+                                  (if (< (time-hour time) 13)
+                                      (time-hour time)
+                                      (- (time-hour time) 12))))
+                           (minbase (number->string (time-minute time)))
+                           (min (if (< (time-minute time) 10)
+                                    (string-append "0" minbase)
+                                    minbase)))
+                      (kern-log-msg "The chronometer reads " hour ":" min)
+                      result-ok)))
+                       
+(define clock-hand-icons (list s_clock_hand_n s_clock_hand_ne s_clock_hand_se s_clock_hand_s s_clock_hand_sw s_clock_hand_nw))
+
+(define (clock-get-hand number)
+       (if (> number 5)
+               (clock-get-hand (- number 6))
+               (list-ref clock-hand-icons number)
+       ))
+
+(define clock-ifc
+  (let ((readclock 
+         (lambda (kclock kuser)
+           (let* ((time (kern-get-time))
+                  (hour (number->string
+                         (if (< (time-hour time) 13)
+                             (time-hour time)
+                             (- (time-hour time) 12))))
+                  (minbase (number->string (time-minute time)))
+                  (min (if (< (time-minute time) 10)
+                           (string-append "0" minbase)
+                           minbase)))
+             (kern-log-msg "The clock reads " hour ":" min)
+             result-ok))))
+    (ifc '()
+         (method 'handle 
+                 readclock)
+         (method 'xamine 
+                 readclock)
+         (method 'step
+                 (lambda (kmirror kuser)
+                   ))
+         (method 'update-gfx
+                 (lambda (kclock)
+                   (let* ((time (kern-get-time))
+                          (hour-hand (clock-get-hand (floor (/ (time-hour time) 2))))
+                          (min-hand (clock-get-hand (floor (/ (+ (time-minute time) 5) 10)))))
+                     (kern-obj-set-sprite kclock (mk-composite-sprite (list s_clock_body hour-hand min-hand)))
+                     )))
+         (method 'init
+                 (lambda (kmirror)
+                   (kern-obj-set-pclass kmirror pclass-wall)
+                   ))  
+         (method 'exec
+                 (lambda (kclock)
+                   (kern-sound-play-ambient sound-clock (kern-obj-get-location kclock))
+                   (let (
+                                       (minute (time-minute (kern-get-time)))
+                                       (ticks (kern-time-get-remainder))
+                               )
+                               ;; TODO it may be possible to get this to work while loitering too
+                               (if (and (equal? minute 0) (equal? ticks 0))
+                                       (kern-sound-play-at sound-clock-chime (kern-obj-get-location kclock)))
+                   )
+                   ))  
+         (method 'on-entry
+                 (lambda (kclock)
+                   (kern-sound-play-ambient sound-clock (kern-obj-get-location kclock))
+                   ))
+         )))
+
+(define broken-clock-ifc
+  (let ((readclock 
+         (lambda (kclock kuser)
+           (kern-log-msg (gob kclock))
+           )))
+    (ifc '()
+         (method 'handle 
+                 readclock)
+         (method 'xamine
+                 readclock)
+         (method 'step
+                 (lambda (kmirror kuser)
+                   ))
+         (method 'init
+                 (lambda (kmirror)
+                   (kern-obj-set-pclass kmirror pclass-wall)
+                   ))
+         )))
+
+(mk-obj-type 't_clock "clock"
+             (mk-composite-sprite (list s_clock_body s_clock_hand_n s_clock_spin))
+             layer-mechanism clock-ifc)
+
+(define (mk-clock)
+       (let ((kclock (kern-mk-obj t_clock 1)))
+          (kern-obj-add-effect kclock ef_graphics_update nil) 
+          (bind kclock nil)
+          kclock))
+
+(mk-obj-type 't_broken_clock "clock"
+             s_clock_stopped
+             layer-mechanism broken-clock-ifc)
+       
+(define (mk-broken-clock icona iconb message)
+  (let ((kclock (kern-mk-obj t_broken_clock 1)))
+    (bind kclock message)
+    (kern-obj-set-sprite kclock (mk-composite-sprite (list s_clock_stopped icona iconb)))
+    kclock))
+
+
+(define (get-char-at location)
+  (define (get-char-from list)
+    (cond ((null? list) nil)
+          ((kern-obj-is-char? (car list)) (car list))
+          (else (get-char-from (cdr list))))
+    )
+  (get-char-from (kern-get-objects-at location))
+  )
+
+;;------------------------------------------------
+;; mirrors
+
+(define mirror-ifc
+  (ifc '()
+       (method 'handle 
+               (lambda (kmirror kuser)
+                 (kern-log-msg (kern-obj-get-name kuser) " spots " (kern-obj-get-name kuser) " in the mirror")
+                 result-ok))
+       (method 'step
+               (lambda (kmirror kuser)
+                 ))
+       (method 'remote-sensor
+               (lambda (kmirror kuser)
+                 (let* ((mirror-loc (kern-obj-get-location kmirror))
+                        (target-loc (list (car mirror-loc) (cadr mirror-loc) (+ (caddr mirror-loc) 1)))
+                        (character (get-char-at target-loc)))
+                   (if (null? character)
+                       (kern-obj-set-sprite kmirror (mk-composite-sprite (list s_mirror_bg (eval (gob kmirror)) s_mirror_fg)))
+                       (kern-obj-set-sprite kmirror (mk-composite-sprite (list s_mirror_bg (kern-obj-get-sprite character) (eval (gob kmirror)) s_mirror_fg))))
+                   (kern-map-set-dirty)
+                   )))
+       (method 'init
+               (lambda (kmirror)
+                 (kern-obj-set-pclass kmirror pclass-wall)
+                 ))
+       ))
+
+(mk-obj-type 't_mirror "mirror"
+             '()
+             layer-mechanism mirror-ifc)
+
+(define (mk-mirror background-tag)
+  (let ((kmirror (kern-mk-obj t_mirror 1)))
+    (bind kmirror background-tag)
+    (kern-obj-set-sprite kmirror (mk-composite-sprite (list s_mirror_bg (eval background-tag) s_mirror_fg)))
+    kmirror))
+
+;;---------------------------------------------------------
+;; bookshelf
+
+(define shelf-ifc
+  (ifc '()
+       (method 'step
+               (lambda (kobj kuser)
+                 ))
+       (method 'init
+               (lambda (kobj)
+                 (kern-obj-set-pclass kobj pclass-wall)
+                 ))
+       ))
+
+(mk-obj-type 't_shelf "set of shelves"
+             s_bookshelf
+             layer-mechanism shelf-ifc)
+
+(define (mk-shelf)
+  (let ((kshelf (kern-mk-obj t_shelf 1)))
+    (bind kshelf nil)
+    kshelf))
+
+;;---------------------------------------------------------
+;; blocker
+
+(define blocker-ifc
+  (ifc '()
+       (method 'step
+               (lambda (kobj kuser)
+                 ))
+       (method 'init
+               (lambda (kobj)
+                 (kern-obj-set-pclass kobj pclass-space)
+                 ))
+       ))
+
+(mk-obj-type 't_blocker nil
+             '()
+             layer-mechanism blocker-ifc)
+
+(define (mk-blocker)
+  (let ((kstop (kern-mk-obj t_blocker 1)))
+    (bind kstop nil)
+    kstop))
+
+;; grease -- inert object, required for the Wriggle skill
+(mk-obj-type 't_grease "grease" s_grease layer-item obj-ifc)
+
+;;----------------------------------------------------------------------------
+;; rope-and-hook -- use the wrogue's Reach skill. Works like telekineses but
+;; range is limited by wrogue ability.
+;;
+
+(mk-reusable-item 
+ 't_rope_hook "rope & hook" s_rope_hook hard
+ (lambda (kobj kuser)
+   (if (not (has-skill? kuser sk_reach)) 
+       result-lacks-skill
+       (cast-ui-ranged-any (lambda (kchar ktarg power)
+                             (cond ((not (check-roll dc-reach (occ-ability-thief kuser)))
+                                    (take kchar t_rope_hook 1)
+                                    (kern-obj-put-at (kern-mk-obj t_rope_hook 1)
+                                                     (kern-obj-get-location ktarg))
+                                    result-failed
+                                    )
+                                   (else
+                                    ((kobj-ifc ktarg) 'handle ktarg kchar)
+                                    result-ok
+                                    )))
+                           kuser
+                           (powers-telekinesis-range (occ-ability-thief kuser))
+                           (occ-ability-thief kuser)
+                           kern-obj-is-mech?))))
diff --git a/worlds/haxima-1.002/tooth.scm b/worlds/haxima-1.002/tooth.scm
new file mode 100644 (file)
index 0000000..b1c6227
--- /dev/null
@@ -0,0 +1,164 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define tooth-lvl 2)
+(define tooth-species sp_rat)
+(define tooth-occ oc_wrogue)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; In the monster village of Kun.
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_tooth
+               (list 0 0 campfire-4 "sleeping")
+               (list 6 0 black-market-counter "working")
+               (list 19 0 cantina-12 "idle")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (tooth-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Tooth is a nervous ratling, running a black market and pawn shop 
+;; in the monster village of Kun.  It appears that he is suffering from 
+;; the surplus (or lack) of some stimulant.
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (tooth-hail knpc kpc)
+  (kern-log-msg "You meet a shifty old rat with one enormous incisor. He shakes and shivers nervously. "
+                "Too much caffeine? Black lotus withdrawal? You aren't sure.")
+  (say knpc "Psst. Looking for a deal? I got deals. All kinds of deals! Good deals! Bad deals! "
+       "You name it, you make it, it's your call! No questions asked. No answers given.")
+  )
+
+(define (tooth-default knpc kpc)
+  (say knpc "Don't know. Don't know about that. Information? Not my game.")
+  )
+
+(define (tooth-name knpc kpc)
+  (say knpc "Tooth. I'm well-known! Well-respected. My customers love me. "
+       "They always come back. Tell their friends about me? No way! "
+       "Deals are too good. They keep it to themselves. I'm a well-kept secret! A well-known secret!")
+  )
+
+(define (tooth-join knpc kpc)
+  (say knpc "Can't, mate. Got my shop to run. Bills to pay. Guards to dodge. Too busy! Need the action!")
+  )
+
+(define (tooth-job knpc kpc)
+  (say knpc "Deals! Deals! Deals! Deals! Deals! Let's make one. Right now. "
+       "Right here. Let's do it. Ready? Here we go.")
+  (tooth-trade knpc kpc)
+  )
+
+(define (tooth-bye knpc kpc)
+  (say knpc "Going so soon? Leaving already? I've got more stuff! Lots more! "
+       "Good stuff! But it won't stay! No! It flies off the shelves! Leave at your own risk...!"
+       "[He goes on like this as you walk away]")
+  )
+
+(define tooth-merch-msgs
+  (list nil ;; closed
+        "Look here, look at this marvelous stuff! All quality! Rare, valuable, hard-to-find!" ;; buy
+        "Got stuff? I'll take it. Where did you get it? I don't want to know." ;; sell
+        "Everything reasonably priced! How do I stay in business? I don't know! See for yourself!" ;; trade
+        "Is that all? I've got more!" ;; sold-something
+        "Wait! Where you going? Come back, have another look! Did you see my collection of scrolls?" ;; sold-nothing
+        "Come back when you have more! I'm always looking!" ;; bought-something
+        "I need the good stuff! Magical stuff, gems, artifacts!" ;; bought-nothing
+        "Don't forget the basics! Oil, gems, picklocks!" ;; traded-something
+        "Wait! Where you going? Come back, have another look! Did you see my collection of scrolls?" ;; traded-nothing
+        ))
+
+(define tooth-catalog
+  (list
+   (list t_picklock            5 "Unlock doors! Takes a bit of skill!")
+   (list t_gem                20 "Find hidden rooms and passages! Thieves love 'em!")
+   (list t_grease             25 "In a tight squeeze? Grease is the word!")
+
+   (list t_oil                 5 "Perfect for fighting slimes!")
+   (list t_slime_vial         30 "Kal Xen Nox in a bottle! Great for escaping the guards!")
+   (list t_arrow               3 "Gotta have lots of arrows!")
+   (list t_bolt                3 "Can't have too many bolts!")
+   (list t_smoke_bomb          4 "Make a clean getaway under cover!")
+
+   (list t_spiked_helm       300 "Use your head in a fight!")
+   (list t_spiked_shield     300 "Rare item! For aggressive fighters!")
+
+   (list t_dagger_4           (* 4 65) "Very nice! Small, easy to conceal, but with a fierce bite!")
+   (list t_sword_2            (* 2 85) "Better than the average sword! Look at that keen edge!")
+   (list t_sword_4            (* 4 85) "The finest! The very best! A weapon for the true artist of death!")
+   (list t_morning_star_2     (* 2 105) "A truly awesome weapon! Lay waste to whole parties!")
+
+   (list t_leather_helm_2     (* 2 100) "For the wrogue who needs that little bit of extra protection!")
+   (list t_chain_coif_4       (* 4 100) "See that tight weave? The banded reinforcement? Turns any blade and softens the blow!")
+   (list t_iron_helm_4        (* 4 150) "Very rare! Blows to the head will feel like pillows!")
+
+   (list t_armor_leather_2    (* 2 150) "Want to pilfer a Gint armory? Steal gems from trolls? You'll need something light but effective like this!")
+   (list t_armor_leather_4    (* 4 150) "This once belonged to an old wrogue! He died of old age on a bed of gold coins! Now you can, too!")
+   (list t_armor_chain_4      (* 4 330) "This is perfect for the scrapper who likes to be in the thick without getting slowed down!")
+   (list t_armor_plate_4      (* 4 660) "Shrug off the blows of gints and trolls in this amazing plate armour! There's nothing like it anywhere else!")
+
+   (list t_xen_corp_scroll    (* 7 base-scroll-cost) "The assassin's favorite! Kills instantly!")
+   (list t_sanct_lor_scroll   (* 7 base-scroll-cost) "The wrogue's favorite! Perfect for sneaking in and out unseen!")
+   (list t_an_xen_ex_scroll   (* 6 base-scroll-cost) "If you can't beat them, have them join you with this charm spell!")
+   (list t_in_ex_por_scroll   (* 4 base-scroll-cost) "Magic doors won't stop you when you carry plenty of these!")
+   (list t_wis_quas_scroll    (* 4 base-scroll-cost) "Perfect for finding hidden doors (and invisible foes)!")
+   (list t_in_quas_xen_scroll (* 7 base-scroll-cost) "Ever wish there was two of you? With this scroll there can be!")
+   (list t_an_tym_scroll      (* 8 base-scroll-cost) "For when you really get into trouble this scroll will stop time and let you get out!")
+   ))
+
+(define (tooth-trade knpc kpc) (conv-trade knpc kpc "trade" tooth-merch-msgs tooth-catalog))
+(define (tooth-buy   knpc kpc) (conv-trade knpc kpc "buy"   tooth-merch-msgs tooth-catalog))
+(define (tooth-sell  knpc kpc) (conv-trade knpc kpc "sell"  tooth-merch-msgs tooth-catalog))
+
+(define tooth-conv
+  (ifc nil
+
+       ;; basics
+       (method 'default tooth-default)
+       (method 'hail tooth-hail)
+       (method 'bye  tooth-bye)
+       (method 'job  tooth-job)
+       (method 'name tooth-name)
+       (method 'join tooth-join)
+
+       (method 'trad tooth-trade)
+       (method 'buy  tooth-buy)
+       (method 'sell tooth-sell)
+       (method 'deal tooth-trade)
+       ))
+
+(define (mk-tooth)
+  (bind 
+   (kern-mk-char 
+    'ch_tooth           ; tag
+    "Tooth"             ; name
+    tooth-species         ; species
+    tooth-occ              ; occ
+    s_rat     ; sprite
+    faction-men      ; starting alignment
+    0 4 1            ; str/int/dex
+    0  ; hp bonus
+    0 ; hp per-level bonus
+    0 ; mp off
+    1 ; mp gain
+    max-health ; hp
+    -1                  ; xp
+    max-health ; mp
+    0
+    tooth-lvl
+    #f               ; dead
+    'tooth-conv         ; conv
+    sch_tooth           ; sched
+    'townsman-ai              ; special ai
+    nil
+    nil              ; readied
+    )
+   (tooth-mk)))
diff --git a/worlds/haxima-1.002/tower.png b/worlds/haxima-1.002/tower.png
new file mode 100644 (file)
index 0000000..044e8d9
Binary files /dev/null and b/worlds/haxima-1.002/tower.png differ
diff --git a/worlds/haxima-1.002/town-entry.scm b/worlds/haxima-1.002/town-entry.scm
new file mode 100644 (file)
index 0000000..d25c8bd
--- /dev/null
@@ -0,0 +1,41 @@
+;; ----------------------------------------------------------------------------
+;; trigrave-entry.scm
+;;
+;; This file defines the on-entry procedure executed whenever the player enters
+;; Trigrave. The purpose of this procedure is to ensure the inn doors are all
+;; re-locked when the player enter. This procedure may be extended to add other
+;; functions.
+;;
+;; ----------------------------------------------------------------------------
+
+(define all-inn-room-doors
+  (list 'trigrave-inn-room-1-door
+        'trigrave-inn-room-2-door
+        'trigrave-inn-room-3-door
+        'trigrave-inn-room-4-door
+
+        'oparine-inn-room-1-door        
+        'oparine-inn-room-2-door        
+        'oparine-inn-room-3-door        
+        'oparine-inn-room-4-door        
+        'oparine-inn-room-5-door 
+
+        'white-stag-door
+
+        'glasdrin-inn-room-1-door        
+        'glasdrin-inn-room-2-door        
+
+        'bole-inn-room-door
+
+        ))
+
+(define (lock-door door-tag)
+  (send-signal nil (eval door-tag) 'lock)
+  )
+
+;; lock all inn room doors in all towns
+(define (lock-inn-room-doors kplace kplayer)
+  (kern-log-enable #f) ;; disable log messages
+  (map lock-door all-inn-room-doors)
+  (kern-log-enable #t) ;; re-enable log messages
+  #t)
diff --git a/worlds/haxima-1.002/traps.scm b/worlds/haxima-1.002/traps.scm
new file mode 100644 (file)
index 0000000..acf1892
--- /dev/null
@@ -0,0 +1,128 @@
+;;----------------------------------------------------------------------------
+;; traps.scm -- Traps that can be placed on chests, doors, etc. Most of the
+;; procedures which apply the effects of these trap can be found over in
+;; effects.scm, where they are shared in common.
+;;
+;; Traps are not kernel objects and do not have kernel types; they are entirely
+;; an invention of the script. In order for a trap to exist in the game world
+;; it must be attached to a kernel object like a door or a chest.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Trap Implementaion
+;;----------------------------------------------------------------------------
+
+;; Define what a trap "type" is. Each type has a name and the procedure to call
+;; when the trap is triggered. The procedure should be of the form
+;;
+;;  (lambda (<kchar> <kobj>) ...)
+;;
+;; Where kchar is the kernel object for the character that triggered the trap,
+;; and kobj is the kernel object which the trap was attached to.
+;;
+(define (mk-trap-type namestr proc-tag) (list 'trap-type namestr proc-tag))
+(define (trap-type-name ttype) (cadr ttype))
+(define (trap-type-proc ttype) (caddr ttype))
+
+;; Define what a trap is. A trap has a type and some state variables. Currently
+;; the only state variable is a "detected" flag, which is set if the player has
+;; detected the trap. The avoidance is hard-coded currently, but depends on if
+;; the trap has already been detected. The detection and fumble difficulties
+;; are also hard-coded (these are used when s)earching trapped objects).
+(define (mk-trap type) (list 'trap type #f #f))
+(define (trap-type trap) (cadr trap))
+(define (trap-detected? trap) (caddr trap))
+(define (trap-set-detected! trap val) (set-car! (cddr trap) val))
+(define (trap-tripped? trap) (cadddr trap))
+(define (trap-set-tripped! trap val) (set-car! (cdddr trap) val))
+(define (trap-name trap) (trap-type-name (trap-type trap)))
+(define (trap-avoid-dc trap) (if (trap-detected? trap) 10 20))
+(define (trap-detect-dc trap) 18)
+(define (trap-fumble-dc trap) 12)
+
+;; Trigger a trap. The trap parm is one of our scripted traps conforming to the
+;; above, kobj is the kernel object the trap is applied to, and kchar is the
+;; kernel character object that triggered the trap. This proc will
+;; automatically use the character's thiefly skill to roll to avoid the trap.
+(define (trap-trigger trap kobj kchar)
+  (let ((roll (kern-dice-roll "1d20"))
+        (bonus (occ-thief-dice-roll kchar))
+        (ttype (trap-type trap))
+        (avoid (trap-avoid-dc trap))
+        (already-tripped? (trap-tripped? trap))
+        )
+    (trap-set-detected! trap #t)
+    (trap-set-tripped! trap #t)
+    (cond (already-tripped? nil)
+          ((or (= roll 20)
+               (> (+ roll bonus) avoid))
+           (kern-log-msg (kern-obj-get-name kchar) 
+                         " ^c+gavoids^c- a " 
+                         (trap-type-name ttype) 
+                         " trap!"))
+          (else
+           (kern-log-msg (kern-obj-get-name kchar) " ^c+rtrips^c- a "
+                         (trap-type-name ttype)
+                         " trap!")
+           (apply (eval (trap-type-proc (trap-type trap)))
+                  (list kchar kobj))))))
+
+;; S)earch a trap. Roll to detect. If the roll is bad then the trap is
+;; triggered (whether or not it was already detected). If the roll is good then
+;; the trap is detected.
+(define (trap-search trap kobj kchar)
+  (let ((roll (kern-dice-roll "1d20"))
+        (bonus (occ-thief-dice-roll kchar))
+        (ttype (trap-type trap))
+        )
+    (cond ((and (not (trap-detected? trap))
+                (or (= roll 20) 
+                    (> (+ roll bonus) 
+                       (trap-detect-dc trap))))
+           (kern-log-msg (kern-obj-get-name kchar) 
+                         " ^c+gfinds^c- a " 
+                         (trap-type-name ttype) 
+                         " trap!")
+           (trap-set-detected! trap #t))
+          ((or (= roll 1)
+               (< (+ roll bonus) (trap-fumble-dc trap)))
+           (trap-trigger trap kobj kchar)
+           ))))
+
+;;----------------------------------------------------------------------------
+;; Trap Types
+;;----------------------------------------------------------------------------
+(define (lightning-trap-proc actor subject) (apply-lightning actor))
+(define (burn-trap-proc actor subject) (burn actor))
+(define (poison-trap-proc actor subject) (apply-poison actor))
+(define (sleep-trap-proc actor subject) (apply-sleep actor))
+
+(define (spike-trap-proc actor subject)
+  (kern-obj-apply-damage actor "ouch" 
+                         (kern-dice-roll "1d6")))
+
+(define (bomb-trap-proc actor subject)
+  (define (hit loc)
+    (map burn (kern-get-objects-at loc))
+    (if (terrain-ok-for-field? loc)
+        (kern-obj-put-at (kern-mk-obj F_fire 1) loc)))
+  (shake-map 10)
+  (map hit 
+       (get-8-neighboring-tiles (kern-obj-get-location subject))))
+
+(define (self-destruct-trap-proc actor subject)
+  (shake-map 3)
+  (kern-obj-put-at (kern-mk-field F_fire 10)
+                   (kern-obj-get-location subject))
+  (kern-obj-put-at (kern-mk-obj sulphorous_ash 1)
+                   (kern-obj-get-location subject))
+  (ifccall subject 'self-destruct)
+  )
+
+(define lightning-trap (mk-trap-type "lightning" 'lightning-trap-proc))
+(define burn-trap (mk-trap-type "burn" 'burn-trap-proc))
+(define poison-trap (mk-trap-type "poison" 'poison-trap-proc))
+(define sleep-trap (mk-trap-type "sleep" 'sleep-trap-proc))
+(define spike-trap (mk-trap-type "spike" 'spike-trap-proc))
+(define bomb-trap (mk-trap-type "bomb" 'bomb-trap-proc))
+(define self-destruct-trap (mk-trap-type "self-destruct" 'self-destruct-trap-proc))
diff --git a/worlds/haxima-1.002/traps_1.scm b/worlds/haxima-1.002/traps_1.scm
new file mode 100644 (file)
index 0000000..fc7fddb
--- /dev/null
@@ -0,0 +1,58 @@
+;; ----------------------------------------------------------------------------
+;; Level 1 of the Thief's Ladder
+;; ----------------------------------------------------------------------------
+(mk-dungeon-room
+ 'p_traps_1 "Riddles in the Dark"
+ (list
+  "rr rr rr rr rr rr rr xx xx xx xx xx xx xx xx xx xx rr rr "
+  "rr rr rr xx xx xx xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, x! ,, ,, ,, x! rr rr "
+  "rr rr rr xx ,, ,, ,, ,, ,, ,, ,, ,, xx ,, ,, ,, xx rr rr "
+  "rr rr xx xx ,, xx xx xx xx ,, xx xx xx xx ,, xx xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx rr rr "
+  "rr rr xx xx ,, xx xx xx xx ,, xx xx xx xx ,, xx xx rr rr "
+  "rr rr xx ,, ,, ,, xx ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+  "rr rr x! ,, ,, ,, x! ,, ,, ,, ,, ,, ,, ,, ,, xx rr rr rr "
+  "rr rr xx ,, ,, ,, xx xx ,, ,, ,, xx xx xx xx xx rr rr rr "
+  "rr rr xx xx xx xx xx xx xx xx xx xx rr rr rr rr rr rr rr "
+  )
+ (put (mk-riddle 'egg 't_lava 3 5 3 9 #f
+                 "All who would pass must answer the riddle:\n\n"
+                 "  In a marble hall white as milk\n"
+                 "  Lined with skin soft as silk\n"
+                 "  Within a fountain crystal clear\n"
+                 "  A golden apple doth appear\n"
+                 "  No doors there are to this stronghold\n"
+                 "  Yet thieves break in to steal its gold.\n"
+                 ) 4 14)
+ (put (mk-riddle 'few 't_lava 8 5 3 9 #f
+                 "All who would pass must answer the riddle:\n\n"
+                 "  I know a word of letters three.\n"
+                 "  Add two, and fewer there will be."
+                 ) 9 4)
+ (put (mk-riddle 'eye 't_lava 13 5 3 9 #f
+                 "All who would pass must answer the riddle:\n\n"
+                 "  Pronounced as one letter,\n"
+                 "  but written with three.\n"
+                 "  Two letters there are\n"
+                 "  and two only in me.\n"
+                 "  I'm double, and single,\n"
+                 "  and black, blue and gray.\n"
+                 "  When read from both ends\n"
+                 "  I'm the same either way."
+                 ) 14 14)
+ (put (mk-ladder-down 'p_traps_2 9 15) 14 2)
+ (put (mk-ladder-up 'p_bole 43 6) 4 16)
+ )
+
+(mk-place-music p_traps_1 'ml-dungeon-town)
+
+(kern-place-add-on-entry-hook p_traps_1 'quest-thiefrune-den1)
diff --git a/worlds/haxima-1.002/traps_2.scm b/worlds/haxima-1.002/traps_2.scm
new file mode 100644 (file)
index 0000000..d89c357
--- /dev/null
@@ -0,0 +1,62 @@
+;; ----------------------------------------------------------------------------
+;; Level 2 of the Thief's Ladder
+;; ----------------------------------------------------------------------------
+(mk-dungeon-room
+ 'p_traps_2 "The Choice"
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, xx xx xx ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx xx ,, ,, ,, ,, ,, xx xx xx xx xx ,, ,, ,, ,, ,, xx xx "
+  "xx xx xx ,, ,, ,, xx xx ,, ,, ,, xx xx ,, ,, ,, xx xx xx "
+  "xx xx xx xx ,, xx xx ,, ,, ,, ,, ,, xx xx ,, xx xx xx xx "
+  "xx xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx xx xx "
+  "xx xx xx ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, xx xx xx "
+  "xx xx xx xx ,, xx xx xx xx ~x xx xx xx xx ,, xx xx xx xx "
+  "xx xx xx xx ,, xx xx .C .H ~O .O .S .E xx ,, xx xx xx xx "
+  "xx xx xx xx ,, xx xx !! !! ~! !! !! !! xx ,, xx xx xx xx "
+  "xx xx xx xx ,, xx xx ,, ,, ,, ,, ,, ,, xx ,, xx xx xx xx "
+  "xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx "
+  "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, ,, xx xx xx xx xx xx "
+  "xx xx xx xx xx xx xx !! !! !! !! !! !! xx xx xx xx xx xx "
+  "xx xx xx xx xx xx xx .W .I .S .E .L .Y xx xx xx xx xx xx "
+  )
+ (put (mk-step-clue "Doesn't the other way look better?") 13 15)
+ (put (mk-step-clue "Doesn't the other way look better?") 6 15)
+
+ ;; secret path through wall
+ (put (mk-secret-path) 9 14)
+ (put (mk-secret-path) 9 13)
+ (put (mk-secret-path) 9 12)
+ (put (mk-secret-path) 9 11)
+ (put (mk-secret-path) 9 10)
+ (put (mk-secret-path) 9 9)
+ ;; ladders "down" that link to each other
+ (put (mk-ladder-down 'p_traps_2 14 3) 4 3)
+ (put (mk-ladder-down 'p_traps_2 4 3) 14 3)
+ ;; monster generators
+ (put (spawn-pt 'bandit) 4 3)
+ (put (spawn-pt 'bomber) 3 4)
+ (put (spawn-pt 'blackguard) 5 4)
+
+ (put (spawn-pt 'skeletal-warrior) 14 4)
+ (put (spawn-pt 'skeletal-spear-thrower) 13 3)
+ (put (spawn-pt 'skeletal-archer) 15 3)
+ ;; doors
+ (put (mk-door) 14 8)
+ (put (mk-door) 4 8)
+ ;; true ladder down
+ (put (mk-ladder-down 'p_traps_3 9 9) 9 9)
+ (put (mk-ladder-up 'p_traps_1 14 2) 9 15)
+ )
+(mk-place-music p_traps_2 'ml-dungeon-adventure)
+
+(kern-place-add-on-entry-hook p_traps_2 'quest-thiefrune-den2)
diff --git a/worlds/haxima-1.002/traps_3.scm b/worlds/haxima-1.002/traps_3.scm
new file mode 100644 (file)
index 0000000..b04f94e
--- /dev/null
@@ -0,0 +1,90 @@
+;; ----------------------------------------------------------------------------
+;; Level 3 of the Thief's Ladder
+;; ----------------------------------------------------------------------------
+(kern-load "traps_3_mechs.scm")
+(mk-dungeon-room
+ 'p_traps_3 "Fun with Levers"
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx xx xx ,, x! xx xx xx x! ,, x! xx xx xx x! ,, xx xx xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx xx xx ,, x! xx xx xx x! ,, x! xx xx xx x! ,, xx xx xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, x! ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx ,, ,, ,, ,, ,, xx "
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+
+ ;; monster generators
+ (put (spawn-pt 'queen-spider) 6 3)
+ (put (spawn-pt 'skeletal-warrior)   6 15)
+ (put (spawn-pt 'yellow-slime) 15 15)
+ (put (spawn-pt 'bandit) 15 3)
+ ;; portcullisses
+ (put (kern-tag 't3_pc1  (mk-open-portcullis) ) 6 3)
+ (put (kern-tag 't3_pc2  (mk-open-portcullis) ) 6 9)
+ (put (kern-tag 't3_pc3  (mk-open-portcullis) ) 6 15)
+ (put (kern-tag 't3_pc4  (mk-open-portcullis) ) 12 3)
+ (put (kern-tag 't3_pc5  (mk-open-portcullis) ) 12 9)
+ (put (kern-tag 't3_pc6  (mk-open-portcullis) ) 12 15)
+ (put (kern-tag 't3_pc7  (mk-portcullis) ) 3 6)
+ (put (kern-tag 't3_pc8  (mk-portcullis) ) 9 6)
+ (put (kern-tag 't3_pc9  (mk-portcullis) ) 15 6)
+ (put (kern-tag 't3_pc10 (mk-portcullis) ) 3 12)
+ (put (kern-tag 't3_pc11 (mk-portcullis) ) 9 12)
+ (put (kern-tag 't3_pc12 (mk-portcullis) ) 15 12)
+
+ ;; levers
+ (put (mk-lever-with-id 't3_ctrl 0)  3  3)
+ (put (mk-lever-with-id 't3_ctrl 1) 15  3)
+ (put (mk-lever-with-id 't3_ctrl 2)  3  9)
+ (put (mk-lever-with-id 't3_ctrl 3) 15  9)
+ (put (mk-lever-with-id 't3_ctrl 4)  3 15)
+ (put (mk-lever-with-id 't3_ctrl 5)  9 15)
+ (put (mk-lever-with-id 't3_ctrl 6) 15 15)
+
+ ;; special control mechanism
+ (put (kern-tag 't3_ctrl 
+                (mk-t3-ctrl (list 't3_pc1
+                                  't3_pc2
+                                  't3_pc3
+                                  't3_pc4
+                                  't3_pc5
+                                  't3_pc6
+                                  't3_pc7
+                                  't3_pc8
+                                  't3_pc9
+                                  't3_pc10
+                                  't3_pc11
+                                  't3_pc12)
+                            (list (list #f #t #f #t #f #t #t #f #t #f #t #f)
+                                  (list #t #t #t #t #t #t #f #f #f #f #f #f)
+                                  (list #t #f #t #f #t #f #f #t #f #t #f #t)
+                                  (list #f #t #f #t #f #t #f #t #f #t #f #t)
+                                  (list #f #f #f #f #f #f #t #t #t #t #t #t)
+                                  (list #t #f #t #f #t #f #t #f #t #f #t #f)
+                                  (list #f #f #t #t #t #t #t #t #t #t #f #f)
+                                  ))) 0 0)
+
+
+ ;; ladder back up
+ (put (mk-ladder-up 'p_traps_2 9 9) 9 9)
+ (put (mk-ladder-down 'p_traps_4 9 9) 9 3)
+
+ )
+
+(mk-place-music p_traps_3 'ml-dungeon-adventure)
+
+(kern-place-add-on-entry-hook p_traps_3 'quest-thiefrune-den3)
diff --git a/worlds/haxima-1.002/traps_3_mechs.scm b/worlds/haxima-1.002/traps_3_mechs.scm
new file mode 100644 (file)
index 0000000..08127f3
--- /dev/null
@@ -0,0 +1,41 @@
+;; Define a mech that will control the 12 portcullisses in traps_3.
+
+;; Give it a list of 7 lists of 12 bools for sets:
+;;   ((#t #t #t #t #t #t #f #f #f #f #f #f) ... ))
+(define (t3-ctrl-mk port-tags sets) (cons port-tags sets))
+(define (t3-ctrl-ports ctrl) (car ctrl))
+(define (t3-ctrl-sets ctrl) (cdr ctrl))
+
+;; Note: can't use tagged levers and expect the tags to work in the case
+;; statement here. This is due to what I might describe as an "aliasing"
+;; problem, where the tags and the klvr both refer to the same thing but are
+;; not themselves the same thing. So use a special extension to the lever which
+;; keeps an id in the bim members "field".
+(define (t3-ctrl-exec kself klvr)  
+  ;;(display "t3-ctrl-exec")(newline)
+  (let* ((ctrl (kobj-gob-data kself))
+         (ports (t3-ctrl-ports ctrl))
+         (sets (t3-ctrl-sets ctrl))
+         (n (bim-members (kobj-gob-data klvr))))
+  (define (change port on?)
+    ;; use safe-eval on the port because on startup all the levers fire, and
+    ;; the target portcullisses might not be defined yet depending on the order
+    ;; of declaration.
+    (let ((kport (safe-eval port)))
+      (if (notnull? kport)
+          (if on?
+              ((kobj-ifc (eval port)) 'open-remote (eval port) kself)
+              ((kobj-ifc (eval port)) 'close-remote (eval port) kself)))))
+  (map change ports (list-ref sets n))))
+
+(define t3-ctrl-ifc
+  (ifc '()
+       (method 'on t3-ctrl-exec)
+       (method 'off t3-ctrl-exec)
+       ))
+
+(mk-obj-type 't_t3_ctrl nil nil layer-none t3-ctrl-ifc)
+
+(define (mk-t3-ctrl ports sets)
+  (bind (kern-mk-obj t_t3_ctrl 1)
+        (t3-ctrl-mk ports sets)))
diff --git a/worlds/haxima-1.002/traps_4.scm b/worlds/haxima-1.002/traps_4.scm
new file mode 100644 (file)
index 0000000..7cd329d
--- /dev/null
@@ -0,0 +1,33 @@
+;; ----------------------------------------------------------------------------
+;; Level 4 of the Thief's Ladder
+;; ----------------------------------------------------------------------------
+(mk-dungeon-room
+ 'p_traps_4 "Labyrinth of Burning Glass"
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ~, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,B ~, ,B ~, ,B ~, ,B ~, ,B ~, ,C ,, ,A ~, ,B ,, xx "
+  "xx ,, ~, ,, ,, ,, ,, ,, ,, ,, ,, ,, ~, ,, ,, ,, ~, ,, xx "
+  "xx ,, ,B ,, ,B ~, ,B ~, ,C ~, ,A ,, ,C ~, ,A ,, ,B ,, xx "
+  "xx ,, ~, ,, ~, ,, ,, ,, ~, ,, ,, ,, ~, ,, ,, ,, ~, ,, xx "
+  "xx ,, ,B ,, ,B ~, ,B ,, ,C ~, ?B ~, ,C ,, ,B ~, ,C ,, xx "
+  "xx ,, ~, ,, ,, ,, ~, ,, ~, ,, ,, ,, ~, ,, ~, ,, ~, ,, xx "
+  "xx ,, ,C ~, ,A ,, ,B ,, ,B ~, ,B ~, ,C ~, ,C ,, ,B ,, xx "
+  "xx ,, ~, ,, ,, ,, ~, ,, ,, ,, ,, ,, ,, ,, ~, ,, ~, ,, xx "
+  "xx ,, ,B ,, ,B ~, ,D ~, ,B ~, ,B ~, ,A ,, ,A ,, ,A ,, xx "
+  "xx ,, ~, ,, ~, ,, ~, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,B ,, ,B ,, ,B ,, ,B ~, ,B ~, ,B ,, ,A ~, ,B ,, xx "
+  "xx ,, ~, ,, ~, ,, ~, ,, ~, ,, ,, ,, ~, ,, ,, ,, ~, ,, xx "
+  "xx ,, ,B ,, ,B ,, ,A ,, ,B ,, ,A ,, ,B ~, ,B ~, ,B ,, xx "
+  "xx ,, ~, ,, ~, ,, ,, ,, ~, ,, ~, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx ,, ,A ,, ,B ~, ,B ~, ,C ~, ,C ~, ,B ~, ,B ~, ,A ,, xx "
+  "xx ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, xx "
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+ (put (mk-ladder-up 'p_traps_3 9 3) 9 9)
+ (put (mk-ladder-down 'p_thiefs_den 9 9) 9 7)
+ )
+
+(mk-place-music p_traps_4 'ml-dungeon-adventure)
+
+(kern-place-add-on-entry-hook p_traps_4 'quest-thiefrune-den4)
diff --git a/worlds/haxima-1.002/treasury.scm b/worlds/haxima-1.002/treasury.scm
new file mode 100644 (file)
index 0000000..b257826
--- /dev/null
@@ -0,0 +1,77 @@
+(mk-dungeon-room
+ 'p_treasury2 "Lost Treasury of Luximene"
+ (list
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx ,T ,R ,E ,A ,S ,U ,R ,Y @@ xx xx xx xx xx "
+      "xx xx xx xx xx @@ @@ @@ ,O @@ ,F @@ @@ @@ xx xx xx xx xx "
+      "xx xx xx xx xx @@ ,L ,U ,X ,I ,M ,E ,N ,E xx xx xx xx xx "
+      "xx xx xx xx xx cc cc cc ,, cc ,, cc cc cc xx xx xx xx xx "
+      "xx xx xx xx xx cc pp ,, ,, ,, ,, ,, pp cc xx xx xx xx xx "
+      "xx xx xx xx xx cc ,, ,, ,, cc ,, ,, ,, cc xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, cc cc cc ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, cc cc ,, cc cc ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, cc cc cc ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx ,, ,, ,, cc ,, ,, ,, xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx ,, ,, ,, ,, ,, xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx ,, ,, ,, xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  )
+ (put (mk-ladder-down 'p_treasury 9 9) 9 9)
+
+ ;; special treasures
+ (put (mk-chest 
+       'bomb-trap
+       '((1 t_eldritch_blade)
+         (1 t_armor_plate_4)
+         (1 t_iron_helm_4)
+         (1 t_doom_staff)
+        (1 t_spell_book_force_magick_high_magick)
+        (1 t_spell_book_gate_magick)
+        (1 t_spell_book_illusion_2)
+         ))
+      9 5)
+ )
+
+(mk-place-music p_treasury2 'ml-dungeon-adventure)
+(define (can-drop? loc)
+  (and (is-floor? loc)
+       (loc-is-empty? loc)))
+
+;; piles of gold
+(put-random-stuff p_treasury2
+                  (mk-rect 5 5 9 9)
+                  can-drop?
+                  (lambda (loc)
+                    (kern-obj-put-at (kern-mk-obj t_gold_coins (kern-dice-roll "5d20")) loc))
+                  20)
+                  
+;; random mundane treasures
+(put-random-stuff p_treasury2
+                  (mk-rect 5 5 9 9)
+                  can-drop?
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-treasure-chest) loc))
+                  5)
+
+;; some gems to add sparkle   
+(put-random-stuff p_treasury2
+                  (mk-rect 5 5 9 9)
+                  can-drop?
+                  (lambda (loc)
+                    (kern-obj-put-at (kern-mk-obj t_gem 1) loc))
+                  10)
+
+;; a couple of corpses
+(put-random-stuff p_treasury2
+                  (mk-rect 5 5 9 9)
+                  can-drop?
+                  (lambda (loc)
+                    (kern-obj-put-at (mk-corpse-with-loot)
+                                     loc))
+                  3)
diff --git a/worlds/haxima-1.002/trigrave.scm b/worlds/haxima-1.002/trigrave.scm
new file mode 100644 (file)
index 0000000..81aa297
--- /dev/null
@@ -0,0 +1,334 @@
+;;----------------------------------------------------------------------------
+;; Trigrave
+;;
+;; This town is at the heart of the starting region. It's a frontier town in
+;; the province of a lord who rules from the south, so don't expect anything
+;; too fancy. Here the player will find the basic shops and amenities needed to
+;; get by.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Map
+;;
+;; This is the terrain map for the place. It may be altered at run-time so it
+;; must be saved and loaded with every session.
+;;
+;; This is a "composite" map. The individual building maps are defined
+;; separately and then blitted onto the terrain map.
+;;----------------------------------------------------------------------------
+(kern-mk-map
+ 'm_lusty_juggs 14 10 pal_expanded
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  "xx x! @@ .L .U .S .T .Y x! xx cc cc cc xx "
+  "ws cc cc 00 cc cc 00 cc cc xx cc cc cc xx "
+  "sT cc cc 00 cc cc 00 cc cc x! xx cc xx xx "
+  "cc cc cc cc cc cc cc cc cc cc cc cc cc xx "
+  "cc cc cc cc cc cc cc cc cc cc cc cc && xx "
+  "xx cc cc 00 cc cc 00 cc cc x! cc cc && xx "
+  "ws cc cc 00 cc cc 00 cc cc xx cc cc cc xx "
+  "xx x! @@ .J .U .G .S @@ x! xx cc cc cc xx "
+  "xx xx xx xx xx xx xx xx xx xx xx ws xx xx "
+  )
+)
+
+(kern-mk-map
+ 'm_iron_works 7 12 pal_expanded
+ (list
+  "xx xx xx xx xx xx xx "
+  "xx .I .R .O .N @@ xx "
+  "xx .W .O .R .K .S xx "
+  "ws cc cc cc cc cc xx "
+  "sA cc cc cc cc cc xx "
+  "cc cc cc cc cc __ xx "
+  "xx cc cc cc cc !! xx "
+  "ws cc cc cc cc cc xx "
+  "xx xx cc xx cc xx xx "
+  "xx cc cc x! cc cc xx "
+  "xx cc cc xx cc cc xx "
+  "xx xx xx xx xx xx xx "
+  ))
+
+(kern-mk-map 
+ 'm_quiet_inn 13 11 pal_expanded
+ (list
+  "xx xx xx xx xx xx xx xx xx xx xx xx xx "
+  "xx cc cc x! .G .R .A .Y @@ x! cc cc xx "
+  "xx cc cc x! @@ .D .O .V .E x! cc cc xx "
+  "cc cc cc cc cc cc cc cc cc cc cc cc xx "
+  "xx xx xx x! @@ .I .N .N @@ x! xx xx xx "
+  "xx cc cc xx cc cc cc cc cc xx cc cc xx "
+  "xx cc cc cc cc cc cc cc cc cc cc cc xx "
+  "xx xx xx x! cc cc cc cc cc x! xx xx xx "
+  "xx cc cc cc cc cc cc cc cc cc cc cc xx "
+  "xx cc cc xx cc cc cc cc cc xx cc cc xx "
+  "xx xx xx xx ws x! cc x! ws xx xx xx xx "
+  )
+ )
+
+(kern-mk-map
+ 'm_dry_goods 7 10 pal_expanded
+ (list
+  " xx xx xx xx xx xx xx "
+  " xx @@ .D .R .Y @@ xx "
+  " xx .G .O .O .D .S xx "
+  " cc cc cc cc cc cc ws "
+  " xx @@ @@ @@ @@ @@ xx "
+  " xx cc cc cc cc cc sE "
+  " xx cc cc cc cc cc cc "
+  " xx cc cc cc cc cc xx "
+  " xx cc cc cc cc cc ws "
+  " xx xx xx xx xx xx xx "
+  )
+ )
+
+
+(kern-mk-map 
+ 'm_trigrave 32 32 pal_expanded
+       (list
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt td .. .. .. tb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt td .. .. .. tb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb ta tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt td .. .. .. .. .. bb ta tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. .. .. .. tD tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt td .. .. .. .. .. bb t3 tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb t3 tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt td .. .. .. tb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tc t& ta tt tt tt tt tt tt tt td .. .. .. tb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tc bb .. bb tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tc sI .. .. .. ta tt tt tt tt tt tc .. .. .. .. .. ta tt tt tt tt tt tt tt tt tt tt "
+               "bb te bb te bb .. .. .. .. .. bb te bb te bb .. .. .. .. .. .. .. bb te bb te bb te bb te bb ta "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "bb t7 bb t7 bb t7 bb t7 bb .. .. .. .. .. .. .. bb t7 bb t7 bb t7 bb t7 bb t7 bb t7 bb t7 bb t3 "
+               "tt tt tt tt tt tt tt tt tt t5 .. .. .. .. .. t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt td .. .. .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt bb .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt td .. .. .. .. ta tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt bb .. .. .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt td .. .. .. .. .. .. tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt bb .. .. .. .. .. .. .. .. tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt .. .. .. .. .. .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt bb .. .. .. .. .. .. t3 tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt td .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt bb .. .. .. tb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+               "tt tt tt tt tt tt tt tt tt tt t5 .. .. .. bb tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt tt "
+       )
+ )
+
+;;----------------------------------------------------------------------------
+;; NPCs
+;;
+;; NPC's are defined in two steps. Step 1 is to kern-load their read-only
+;; definition file (this file includes their conversation, schedule,
+;; constructor, etc). Step 2 is to call kern-mk-char to instantiate them.
+;;----------------------------------------------------------------------------
+(kern-load "jim.scm")
+(bind 
+ (kern-mk-char 'ch_jim ; tag
+               "Jim"                ; name
+               sp_human            ; species
+               nil                 ; occ
+               s_townsman          ; sprite
+               faction-men         ; starting alignment
+               4 1 2              ; str/int/dex
+               0 0                 ; hp mod/mult
+               0 0                 ; mp mod/mult
+               max-health -1 max-health 0 4  ; hp/xp/mp/AP_per_turn/lvl
+               #f                  ; dead
+               'jim-conv          ; conv
+               sch_jim           ; sched
+               'townsman-ai                 ; special ai
+               nil                 ; container
+               (list t_mace   ; we need a 'hammer'
+                                       t_armor_chain)
+               )
+ (jim-mk))
+
+(kern-load "gwen.scm")
+(bind 
+ (kern-mk-char 'ch_gwen ; tag
+               "Gwen"               ; name
+               sp_human            ; species
+               nil                 ; occ
+               s_gwen ; sprite
+               faction-men         ; starting alignment
+               0 1 2              ; str/int/dex
+               0 0                 ; hp mod/mult
+               0 0                 ; mp mod/mult
+               max-health -1 max-health 0 2  ; hp/xp/mp/AP_per_turn/lvl
+               #f                  ; dead
+               'gwen-conv          ; conv
+               sch_gwen           ; sched
+               'townsman-ai                 ; special ai
+               (mk-inventory (list (list 1 t_dagger)))                 ; container
+               nil                 ; readied
+               )
+ (gwen-mk))
+
+(kern-load "chanticleer.scm")
+(bind 
+ (kern-mk-char 'ch_chant ; tag
+               "Chanticleer"          ; name
+               sp_human            ; species
+               nil                 ; occ
+               s_chanticleer     ; sprite
+               faction-men         ; starting alignment
+               0 4 2              ; str/int/dex
+               0 0                 ; hp mod/mult
+               0 0                 ; mp mod/mult
+               max-health -1 max-health 0 5  ; hp/xp/mp/AP_per_turn/lvl
+               #f                  ; dead
+               'chant-conv         ; conv
+               sch_chant           ; sched
+               'townsman-ai                 ; special ai
+               (mk-inventory (list (list 1 t_sword)))                 ; container
+               (list t_armor_leather)                 ; readied
+               )
+ (chant-mk))
+
+(kern-load "earl.scm")
+(bind 
+ (kern-mk-char 'ch_earl     ;; tag
+               "Earl"       ;; name
+               sp_human     ;; species
+               nil          ;; occ
+               s_townsman   ;; sprite
+               faction-men  ;; starting alignment
+               0 5 3       ;; str/int/dex
+               0 0          ;; hp mod/mult
+               0 0          ;; mp mod/mult
+               max-health -1 max-health 0 4  ;; hp/xp/mp/AP_per_turn/lvl
+               #f                  ; dead
+               'earl-conv   ;; conv
+               sch_earl     ;; sched
+               'townsman-ai          ;; special ai
+               (mk-inventory (list
+                       (list 1 t_staff)
+                       (list 1 t_sling)))          ;; container
+               nil          ;; readied
+               )
+ (earl-mk))
+
+(kern-load "miggs.scm")
+(mk-miggs 'ch_miggs)
+
+;;----------------------------------------------------------------------------
+;; Special Objects
+;;----------------------------------------------------------------------------
+(define jims-chest
+  (mk-chest
+   nil ;; trap
+   '((1 t_scratched_shield)
+                (1 t_armor_plate)
+                (1 t_iron_helm))))
+
+(define jims-other-chest
+  (mk-chest
+   'spike-trap ;; trap
+   '((100 t_gold_coins)
+                (3 t_dagger)
+                (3 t_mace)
+                (3 t_sword)
+                )))
+
+(define earls-chest
+  (make-invisible
+   (mk-chest
+    nil ;; trap
+    '((1 t_stun_wand)
+                 (3 t_xen_corp_scroll)
+                 (3 t_in_vas_por_ylem_scroll)
+                 (5 t_vas_mani_scroll)))))
+  
+;;----------------------------------------------------------------------------
+;; Place
+;;
+;; The place definition instantiates the place.
+;;----------------------------------------------------------------------------
+(kern-mk-place 
+ 'p_trigrave     ; tag
+ "Trigrave"      ; name
+ s_town          ; sprite
+
+ ;; Blit the buildings over the basic terrain map.
+ (if #f
+     m_trigrave
+     (blit-maps m_trigrave
+                (list 17 21 m_lusty_juggs 0 0 14 10)
+                (list 24 1  m_iron_works  0 0 7  12)
+                (list 1  1  m_quiet_inn   0 0 13 11)
+                (list 1 21  m_dry_goods   0 0 7  10)))
+ #f              ; wraps
+ #f              ; underground
+ #f              ; large-scale (wilderness)
+ #f              ; tmp combat place
+ nil ; subplaces
+ nil ; neighbors
+ (list ; objects
+
+  ;; characters
+  (list ch_jim   15 15)
+  (list ch_gwen  15 15)
+  (list ch_chant 15 15)
+  (list ch_earl  15 15)
+  (put ch_miggs 15 15)
+
+  ;; Inn
+  (list (kern-tag 'trigrave-inn-room-1-door (mk-locked-door))  4 7)
+  (list (kern-tag 'trigrave-inn-room-2-door (mk-locked-door))  4 9)
+  (list (kern-tag 'trigrave-inn-room-3-door (mk-locked-door)) 10 9)
+  (list (kern-tag 'trigrave-inn-room-4-door (mk-locked-door)) 10 7)
+  (list (mk-locked-door) 1 4)
+  (list (mk-door)  4  4)
+  (list (mk-door) 10  4)
+  (list (mk-door)  7 11)
+  (list (mk-bed)   2  6)
+  (list (mk-bed)  12  6)
+  (list (mk-bed)  12  9)
+  (list (mk-bed)  12  2)
+
+  ;; Earl's room in the inn
+  (put (mk-bed)   2  9)
+  (put earls-chest 2 10)
+
+  ;; General store
+  (list (mk-locked-door)  1 24)
+  (list (mk-door)         7 27)
+  ;; Iron Works
+  (list (mk-door)                                  24 6)
+  (list (mk-locked-door)                           26 9)
+  (list (kern-tag 'tiw-portcullis (mk-portcullis)) 28 9)
+  (list (mk-lever 'tiw-portcullis)                 25 11)
+  (list (mk-bed)                                   25 10)
+  (put jims-chest                                  28 11)
+  (put jims-other-chest                            29 11)
+
+  ;; Lusty Juggs (tavern)
+  (list (mk-locked-door) 28 24)
+  (list (kern-tag 'tlj-d-1 (mk-connected-door 'tlj-d-2)) 17 25)
+  (list (kern-tag 'tlj-d-2 (mk-connected-door 'tlj-d-1)) 17 26)
+  (list (mk-clock) 25 23)
+  (put (mk-bed) 27 22)
+
+  ;; Chickens!
+  (put (mk-npc 'chicken 5) 15 15)
+  (put (mk-npc 'chicken 5) 16 16)
+  
+
+  )
+ (list 'lock-inn-room-doors) ;; hooks
+ (list  ;; edge entrances
+  (list south 18 0)
+  (list north  12 31)
+  )
+ )
+
+(mk-place-music p_trigrave 'ml-small-town)
diff --git a/worlds/haxima-1.002/troll.scm b/worlds/haxima-1.002/troll.scm
new file mode 100644 (file)
index 0000000..41091ec
--- /dev/null
@@ -0,0 +1,276 @@
+; (define (troll-display . args)
+;   (display (kern-get-ticks))
+;   (display ":")
+;   (apply display args))
+; (define (troll-newline) (newline))
+
+(define (troll-display . args) )
+(define (troll-newline) )
+(define troll-melee-weapon t_horns)
+
+;;----------------------------------------------------------------------------
+;; Troll AI
+;;----------------------------------------------------------------------------
+(define (troll-is-critical? ktroll)
+  (< (kern-char-get-hp ktroll) 5))
+
+(define (troll-wander ktroll) 
+  (troll-display "troll-wander")(troll-newline)
+  (wander ktroll))
+
+(define (troll-flee ktroll) 
+  (troll-display "troll-flee")(troll-newline)
+  (flee ktroll))
+
+(define (troll-foes-in-weapon-range ktroll karms kfoes)
+  (troll-display "troll-foes-in-weapon-range")(troll-newline)
+  (all-in-range (kern-obj-get-location ktroll) 
+                (kern-arms-type-get-range karms)
+                 kfoes))
+
+(define (weaker? a b)
+  (< (kern-char-get-hp a) (kern-char-get-hp b)))
+
+(define (troll-pick-target ktroll foes)
+  (troll-display "troll-pick-target")(troll-newline)
+  (foldr (lambda (a b) (if (weaker? a b) a b))
+         (car foes) 
+         (cdr foes)))
+
+(define (troll-pathfind-foe ktroll foes)
+  (troll-display "troll-pathfind-foe")(troll-newline)
+  (let ((ktarg (troll-pick-target ktroll foes)))
+    (if (notnull? ktarg)
+        (pathfind ktroll (kern-obj-get-location ktarg)))))
+
+(define (troll-attack ktroll karms foes)
+  (troll-display "troll-attack")(troll-newline)
+  (kern-char-attack ktroll 
+                    karms
+                    (troll-pick-target ktroll 
+                                       foes)))
+
+;; Given an "origin" location and a list of locations, find the location in the
+;; list closest to the coordinates.
+(define (loc-closest origin lst)
+  (if (null? lst) nil
+      (foldr (lambda (a b) (if (loc-closer? a b origin) a b))
+             (car lst)
+             (cdr lst))))
+
+(define (troll-stronger? ktroll foes)
+  (> (kern-char-get-strength ktroll)
+     (foldr (lambda (a b) (+ a (kern-char-get-strength b))) 
+            0 
+            foes)))
+
+(define (troll-has-ranged-weapon? ktroll)
+  (in-inventory? ktroll troll-ranged-weapon))
+
+;; troll-get-ammo -- give troll a boulder and convert terrain to grass
+(define (troll-get-terrain-ammo ktroll coords)
+  (troll-display "troll-get-terrain-ammo")(troll-newline)
+  (kern-obj-add-to-inventory ktroll troll-ranged-weapon 1)
+  (kern-place-set-terrain coords t_grass)
+  (kern-map-repaint)
+  (kern-obj-dec-ap ktroll troll-ripup-boulder-ap)
+  )
+
+;; ----------------------------------------------------------------------------
+;; troll-get-loose-ammo -- search the objects at the location for ammo and give
+;; it to the th character
+;; ----------------------------------------------------------------------------
+(define (troll-get-loose-ammo ktroll loc)
+  (troll-display "troll-get-loose-ammo")(troll-newline)
+  (kobj-get-at ktroll loc troll-ranged-weapon))
+
+;; ----------------------------------------------------------------------------
+;; troll-terrain-is-ammo -- true iff the given location's terrain can be
+;; converted by a troll into ammo
+;; ----------------------------------------------------------------------------
+(define (troll-terrain-is-ammo? coords)
+  (eqv? t_boulder (kern-place-get-terrain coords)))
+
+;; ----------------------------------------------------------------------------
+;; troll-find-nearest-ammo -- return the closest location with ammo objects or
+;; with terrain that can be converted to ammo objects.
+;; ----------------------------------------------------------------------------
+(define (troll-find-nearest-ammo ktroll)
+  (troll-display "troll-find-nearest-ammo")(troll-newline)
+  (define (scanobjlst lst)
+    (foldr (lambda (a b) 
+             (or a (eqv? (kern-obj-get-type b) troll-ranged-weapon)))
+           #f
+           lst))
+  (define (check lst loc)
+    (if (troll-terrain-is-ammo? loc)
+        (cons loc lst)
+        (if (scanobjlst (kern-get-objects-at loc))
+            (cons loc lst)
+            lst)))
+  (let* ((loc (kern-obj-get-location ktroll))
+         (rad (kern-obj-get-vision-radius ktroll))
+         (coords (profile foldr-rect (loc-place loc)
+                              (- (loc-x loc) (/ rad 2))
+                              (- (loc-y loc) (/ rad 2))
+                              (* 1 rad)
+                              (* 1 rad)
+                              check
+                              nil)))
+    (troll-display coords)(troll-newline)
+    (profile loc-closest loc coords)))
+
+(define (troll-find-nearest-ammo2 ktroll)
+  (troll-display "troll-find-nearest-ammo2")(troll-newline)
+  (let* ((loc (kern-obj-get-location ktroll))
+         (rad (kern-obj-get-vision-radius ktroll))
+         (coords (profile kern-search-rect (loc-place loc)
+                                   (- (loc-x loc) (/ rad 2))
+                                   (- (loc-y loc) (/ rad 2))
+                                   (* 1 rad)
+                                   (* 1 rad)
+                                   t_boulder
+                                   troll-ranged-weapon)))
+    (profile loc-closest loc coords)))
+
+(define (troll-find-nearest-ammo3 ktroll)
+  (troll-display "troll-find-nearest-ammo3")(troll-newline)
+  (define (scanobjlst lst)
+    (foldr (lambda (a b) 
+             (or a (eqv? (kern-obj-get-type b) troll-ranged-weapon)))
+           #f
+           lst))
+  (define (check lst loc)
+    (if (troll-terrain-is-ammo? loc)
+        (cons loc lst)
+        (if (scanobjlst (kern-get-objects-at loc))
+            (cons loc lst)
+            lst)))
+  (let* ((loc (kern-obj-get-location ktroll))
+         (rad (kern-obj-get-vision-radius ktroll))
+         (coords (profile kern-fold-rect (loc-place loc)
+                          (- (loc-x loc) (/ rad 2))
+                          (- (loc-y loc) (/ rad 2))
+                          (* 1 rad)
+                          (* 1 rad)
+                          check
+                          nil)))
+    (troll-display coords)(troll-newline)
+    (profile loc-closest loc coords)))
+
+(define (troll-find-nearest-ammo4 ktroll)
+  (troll-display "troll-find-nearest-ammo4")(troll-newline)
+  (let* ((loc (kern-obj-get-location ktroll))
+         (rad (kern-obj-get-vision-radius ktroll))
+         (terrain-coords (profile kern-search-rect-for-terrain (loc-place loc)
+                                  (- (loc-x loc) (/ rad 2))
+                                  (- (loc-y loc) (/ rad 2))
+                                  (* 1 rad)
+                                  (* 1 rad)
+                                  t_boulder))
+         (closest-terrain (profile loc-closest loc terrain-coords))
+         (obj-coords (profile kern-search-rect-for-obj-type (loc-place loc)
+                              (- (loc-x loc) (/ rad 2))
+                              (- (loc-y loc) (/ rad 2))
+                              (* 1 rad)
+                              (* 1 rad)
+                              troll-ranged-weapon))
+         (closest-obj (profile loc-closest loc obj-coords)))
+    (cond ((null? closest-obj) closest-terrain)
+          ((null? closest-terrain) closest-obj)
+          (else
+           (if (loc-closer? closest-obj closest-terrain loc)
+               closest-obj
+               closest-terrain)))))
+
+;; ----------------------------------------------------------------------------
+;; troll-get-ammo -- given the location of an ammo object or terrain that can
+;; be converted to ammo, have the troll get the ammo
+;; ----------------------------------------------------------------------------
+(define (troll-get-ammo ktroll loc)
+  (troll-display "troll-get-ammo")(troll-newline)
+  (if (troll-terrain-is-ammo? loc)
+      (troll-get-terrain-ammo ktroll loc)
+      (troll-get-loose-ammo ktroll loc)))
+
+;; ----------------------------------------------------------------------------
+;; troll-hunt-for-ammo2 -- find the nearest available ammo and pathfind to it
+;; or pick it up. Returns false iff none available.
+;; ----------------------------------------------------------------------------
+(define (troll-hunt-for-ammo ktroll)
+  (troll-display "troll-hunt-for-ammo")(troll-newline)
+  (let ((nearest (profile troll-find-nearest-ammo2 ktroll))
+        (kloc (kern-obj-get-location ktroll)))
+    (troll-display "nearest=")(troll-display nearest)(troll-newline)
+    (if (null? nearest)
+        #f
+        (begin
+          (do-or-goto ktroll nearest troll-get-ammo)
+          #t))))
+
+(define (troll-display-objs lst)
+  (if (null? lst)
+      (troll-newline)
+      (begin
+        (troll-display (kern-obj-get-name (car lst)))
+        (troll-display " ")
+        (troll-display-objs (cdr lst)))))
+
+(define (troll-no-hostiles ktroll)
+  (troll-display "troll-no-hostiles")(troll-newline)
+  (troll-wander ktroll))
+
+(define troll-taunts
+  (list
+   "[primal howl]"
+   "[hateful roar]"
+   "[raging bellow]"
+   ))
+
+(define (troll-taunt ktroll ktarg)
+  (taunt ktroll ktarg troll-taunts)
+  (npcg-set-taunted! (gob ktroll) #t))
+
+(define (troll-hostiles ktroll foes)
+  (troll-display "troll-hostiles")(troll-newline)
+  (if (troll-is-critical? ktroll) 
+      (troll-flee ktroll)
+      (let ((melee-targs (troll-foes-in-weapon-range ktroll 
+                                                     troll-melee-weapon 
+                                                     foes)))
+        (troll-display "troll-ai:melee-targs=")
+        (troll-display melee-targs)
+        (troll-newline)
+        (or (npcg-taunted? (gob ktroll))
+            (troll-taunt ktroll (car foes)))
+        (if (null? melee-targs)
+            (if (troll-has-ranged-weapon? ktroll)
+                (let 
+                    ((ranged-foes 
+                      (troll-foes-in-weapon-range ktroll
+                                                  troll-ranged-weapon
+                                                  foes)))
+                  (troll-display "troll-ai:ranged-foes=")
+                  (troll-display ranged-foes)
+                  (troll-newline)
+                  (if (null? ranged-foes)
+                      (troll-pathfind-foe ktroll foes)
+                      (troll-attack ktroll troll-ranged-weapon 
+                                    ranged-foes)))
+                (or (troll-hunt-for-ammo ktroll)
+                    (troll-pathfind-foe ktroll foes)))
+            (if (troll-stronger? ktroll melee-targs)
+                (troll-attack ktroll troll-melee-weapon melee-targs)
+                (evade ktroll melee-targs))))))
+
+;; ----------------------------------------------------------------------------
+;; troll-ai -- combat ai for a troll npc. Called repeatedly by the kernel on
+;; the troll's turn until the troll is out of ap.
+;; ----------------------------------------------------------------------------
+(define (troll-ai ktroll)
+  (troll-display "troll-ai")(troll-newline)
+  (let ((foes (all-visible-hostiles ktroll)))
+    (if (null? foes)
+        (troll-wander ktroll)
+        (troll-hostiles ktroll foes))
+    #t))
diff --git a/worlds/haxima-1.002/tutorial.scm b/worlds/haxima-1.002/tutorial.scm
new file mode 100644 (file)
index 0000000..6553681
--- /dev/null
@@ -0,0 +1,218 @@
+;;----------------------------------------------------------------------------
+;; The very first line of any session file should be (load "naz.scm"). This
+;; bootstraps some procedures that we need to continue. This is the only place
+;; you should use 'load'. Every other place you want to load a file you should
+;; user 'kern-load'. 'kern-load' ensures that a saved session will be able to
+;; load the file, too.
+;;----------------------------------------------------------------------------
+(load "naz.scm")
+
+;; Setup progress bar for loading. I arrived at the number by printing the
+;; current number of steps in src/foogod.c:foogod_progress_bar_finish().
+(kern-progress-bar-start "Loading" 75)
+
+;; Wrap the original definition of (load ...) with one that advances the
+;; progress bar.
+(define original-load load)  
+(define (load file)
+  (kern-progress-bar-advance 1)
+  (original-load file)
+  )
+
+;;----------------------------------------------------------------------------
+;; Load the read-only game data. See the note on 'kern-load' vs 'load' above.
+;;----------------------------------------------------------------------------
+(kern-load "game.scm")
+(kern-load "camping-map.scm")
+(kern-load "zones.scm")
+(kern-load "runes.scm")
+(kern-load "prices.scm")
+(kern-load "special.scm")
+(kern-load "town-entry.scm")
+
+;;----------------------------------------------------------------------------
+;; Time -- this needs to be set before loading any dungeon rooms
+;;----------------------------------------------------------------------------
+(define hour 13)
+(define minutes 00)
+(define time-in-minutes (+ (* hour 60) minutes))
+(define game-start-time (time-mk 0 0 0 0 hour minutes))
+
+(kern-set-clock 
+ 0 ; year
+ 0 ; month
+ 0 ; week
+ 0 ; day
+ hour  ; hour
+ minutes ; minutes
+ )
+
+;;----------------------------------------------------------------------------
+;; NPC's
+(kern-load "thorald.scm")
+
+;;----------------------------------------------------------------------------
+;; Places
+(load "tutorial_town.scm")
+(load "tutorial_cave.scm")
+
+;;----------------------------------------------------------------------------
+;; Player
+
+;; Player Character
+ (kern-mk-char 
+  'ch_wanderer
+  "The Wanderer"        ; name
+  sp_human              ; species
+  oc_wanderer           ; occ
+  s_wanderer            ; sprite
+  faction-player        ; starting alignment
+  5 5 25                 ; str/int/dex
+  pc-hp-off
+  pc-hp-gain
+  pc-mp-off
+  pc-mp-gain
+  40 0 12               ; hp/xp/mp
+  0 ; MP_per_turn
+  5                     ; lvl
+  #f                    ; dead
+  nil                   ; conv
+  nil                   ; sched
+  nil                   ; special ai
+  nil                   ; container
+  nil                   ; readied
+  )
+
+
+;; Player Party
+(kern-mk-player
+ 'player                     ; tag
+ s_wanderer         ; sprite
+ "Walk"                      ; movement description
+ sound-walking               ; movement sound
+ 100                         ; food
+ 10000                       ; gold
+ (* 60 60 5)                 ; turns to next meal (5 hours)
+ nil                         ; formation
+ m_campsite                  ; campsite map
+ nil                         ; campsite formation
+ nil                         ; vehicle
+ ;; inventory
+ (kern-mk-inventory
+  (list
+   )
+  )
+ nil ;; party members (should be nil for initial load file)
+ )
+
+;; Party members
+(kern-party-add-member player ch_wanderer)
+
+;;----------------------------------------------------------------------------
+;; Caution: tutorial_wilderness.scm must be loaded AFTER the player party is
+;; declared, because it creates npc parties using a procedure that sizes them
+;; based on the player party size.
+(load "tutorial_wilderness.scm")
+
+
+;;----------------------------------------------------------------------------
+;; Astronomy
+
+;; Sun
+(kern-mk-astral-body
+ 'sun              ; tag
+ "Fyer (the sun)"  ; name
+ 1                 ; relative astronomical distance 
+ 1                 ; minutes per phase (n/a for sun)
+ (/ (* 24 60) 360) ; minutes per degree
+ 0                 ; initial arc
+ 0                 ; initial phase
+ '()               ; script interface
+ ;; phases:
+ (list 
+  (list s_sun 255 "full")
+  )
+ )
+
+; ;; The moon Lumis is the source gate, which means it opens the source moongates
+; ;; on its phases. We designate this by using the source-moon-ifc as its ifc.
+; (mk-moon 'lumis  ; tag
+;          "Lumis" ; name
+;          2       ; hours per phase
+;          24      ; hours per revolution
+;          90      ; initial arc
+;          0       ; initial phase
+;          'source-moon-ifc ; ifc
+;          ;; gates (moons are fixed at 8 phases in mk-moon):
+;          (list 'mg-1 'mg-2 'mg-3 'mg-4
+;                'mg-5 'mg-6 'mg-7 'mg-8
+;                ))
+
+; ;; The moon Ord is the destination gate, which means its phase decides the
+; ;; destination when the player steps through a moongate. We designate this by
+; ;; giving it a nil ifc. Note that its gates do not need to be listed in the
+; ;; same order as Lumis. In fact, they don't even need to be the same set of
+; ;; gates.
+; (mk-moon 'ord    ; tag
+;          "Ord"   ; name
+;          1       ; hours per phase
+;          12      ; hours per revolution
+;          180     ; initial arc
+;          1       ; initial phase
+;          nil     ; ifc
+;          ;; gates (moons are fixed at 8 phases in mk-moon):
+;          (list 'mg-1 'mg-2 'mg-3 'mg-4
+;                'mg-5 'mg-6 'mg-7 'mg-8
+;                ))
+
+;; ----------------------------------------------------------------------------
+;; The diplomacy table. Each entry defines the attitude of the row to the
+;; column. Note that attitudes are not necessarily symmetric. Negative values
+;; are hostile, positive are friendly.
+;;
+;; Note: factions should always be allied with themselves in order for
+;; summoning AI to work properly.
+;;       
+(kern-mk-dtable
+ ;;     non pla men cgb acc mon tro spd out gnt dem fgb
+ (list   2   0   0   0  -1  -2  -2  -2   0  -2  -2   0) ;; none
+ (list   0   2   1  -2  -1  -2  -2  -2  -2  -2  -2  -2) ;; player
+ (list  -1   1   2  -1  -2  -2  -2  -2  -2  -2  -2  -2) ;; men
+ (list  -1  -2  -2   2  -1  -2   0  -2  -2  -1  -2  -2) ;; cave goblin
+ (list  -1  -1  -1  -1   2  -2  -1  -1  -2  -1  -2  -2) ;; accursed
+ (list  -2  -2  -2  -2  -2   2   0   0  -2   0  -2   0) ;; monsters
+ (list  -2  -2  -2   0  -1  -1   2  -2  -2  -1  -2  -2) ;; hill trolls
+ (list  -2  -2  -2  -2  -1   0  -2   2  -2  -1  -2   0) ;; wood spiders
+ (list   0  -2  -2  -2  -2  -2  -2  -2   2  -2  -2  -1) ;; outlaws
+ (list  -2  -2  -2  -1  -1   0  -1  -1  -2   2  -2  -1) ;; gint
+ (list  -2  -2  -2  -2  -2  -2  -2  -2  -2  -2   2  -2) ;; demon
+ (list   0  -2  -2  -2  -2   0  -2   0  -1  -1  -2   2) ;; forest goblin
+ )
+
+
+;;----------------------------------------------------------------------------
+;; Startup - this is a one-time only script that runs when the player starts
+;; the game for the first time (or whenever he starts over from scratch,
+;; loading the game from this file). It sets up the story a bit.
+(define blackgate-stages
+  (list (list '()                       0)
+        (list s_blackgate_quarter        32)
+        (list s_blackgate_half           64)
+        (list s_blackgate_three_quarters 96)
+        (list s_blackgate_full           128)))
+
+
+;;----------------------------------------------------------------------------
+;; Tutorial
+(define (tutorial kplayer)
+  (kern-obj-put-at kplayer (list p_tutorial_town 9 9))
+  (kern-log-msg "Welcome to the tutorial. If you want to go back to the main menu hit the 'q' key for Q)uit.")
+  (kern-log-msg "Your main character appears in the center of the view to the left. See him? Move him by pressing the arrow keys.")
+  )
+      
+;;----------------------------------------------------------------------------
+;; To skip the extended start scene comment out this next line and uncomment
+;; the line after it.
+(kern-add-hook 'new_game_start_hook 'tutorial)
+
+(kern-progress-bar-finish)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/tutorial_cave.scm b/worlds/haxima-1.002/tutorial_cave.scm
new file mode 100644 (file)
index 0000000..1446d84
--- /dev/null
@@ -0,0 +1,33 @@
+;;----------------------------------------------------------------------------
+;; Map
+;;----------------------------------------------------------------------------
+(mk-dungeon-room
+ 'p_tutorial_cave "Tutorial Cave"
+ (list
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+      "rr %% %% rr rr tt .. .. .. tt rr rr rr {{ rr rr rr rr rr "
+      "rr %% rr rr || .. .. .. .. .. || rr rr tt {{ rr rr rr rr "
+      "rr %% rr tt %% bb .. .. .. bb %% || rr .. tt rr rr rr rr "
+      "rr %% rr %% %% %% %% .. .. %% %% tt rr .. tt rr rr rr rr "
+      "rr rr rr tt %% bb %% .. .. bb %% %% rr .. {{ rr rr rr rr "
+      "rr .. || || %% %% .. .. .. %% %% %% rr {{ {{ rr rr rr rr "
+      "rr .. rr || %% bb .. %% %% bb %% %% rr {{ {{ rr rr rr rr "
+      "rr tt rr tt %% .. .. .. %% %% tt tt rr .. {{ rr rr rr rr "
+      "rr tt rr %% %% bb .. .. .. bb || || rr .. {{ rr rr rr rr "
+      "rr tt rr rr tt %% .. .. .. tt || rr rr .. tt rr rr rr rr "
+      "rr .. tt rr rr rr .. .. .. rr rr rr .. .. tt rr rr rr rr "
+      "rr .. .. .. && rr .. .. .. rr .. .. .. tt || rr rr rr rr "
+      "rr .. .. .. .. rr .. .. .. rr .. .. tt || rr rr rr rr rr "
+      "rr rr tt .. .. rr rr .. rr rr tt tt || rr rr rr rr rr rr "
+      "rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr rr "
+  )
+ (put (spawn-pt 'bat) 7 7)
+ (put (mk-step-clue "Now would be a good time to U)se a torch!") 7 15)
+ (put (mk-step-clue "Kill the bat, then enter F)ollow mode and look around. "
+                    "When you're done, go back to the ladder and press E)nter to climb back up.")
+      7 14)
+ (put (mk-ladder-up 'p_tutorial_wilderness 9 15) 7 17)
+ )
diff --git a/worlds/haxima-1.002/tutorial_town.scm b/worlds/haxima-1.002/tutorial_town.scm
new file mode 100644 (file)
index 0000000..7838688
--- /dev/null
@@ -0,0 +1,104 @@
+(mk-tower
+ 'p_tutorial_town "Tutorial Town"
+ (list
+      "xx xx xx xx xx xx xx xx xx ,, xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx ,, xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx ,, ,, ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx ,, ,, ,, ,, ,, xx xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx xx ,, xx xx ,, xx xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx xx ,, xx xx ,, xx xx xx ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx ,, xx xx ,, xx xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx ,, ,, xx xx xx xx ,, ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx xx ,, xx xx xx xx xx ,, ,, ,, xx xx xx xx "
+      "xx xx xx xx xx xx ,, xx xx xx xx xx xx ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx ,, ,, ,, ,, ,, ,, ,, ,, xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx ,, xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+      "xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx "
+
+  )
+  (list ;entrances
+       (list north 9 0)
+  )
+ (put (mk-chest 
+       nil 
+       '( 
+        ( 10 t_torch)
+        ( 1 t_sword)
+        ( 1 t_armor_leather)
+        ( 1 t_shield)
+        ( 1 t_halberd)
+        ))
+      5 6)
+ (put (spawn-pt 'snake) 11 13)
+ (put (kern-tag 'p1 (mk-portcullis)) 6 11)
+ (put (mk-lever 'p1) 5 10)
+ (put (kern-tag 'p2 (mk-portcullis)) 10 13)
+ (put (mk-lever 'p2) 9 14)
+ (put (mk-step-clue "To the left is a chest. O)pen it by pressing the 'o' key followed by an arrow key. "
+                    "Then G)et the items by pressing the 'g' key followed by an arrow.") 
+      6 6)
+ (put (mk-step-clue "You better R)eady your weapons and armor. "
+                    "Press the 'r' key. In the window above you can select weapons and armor to wear or "
+                    "remove by pressing the SPACEBAR. Experiment with this a bit. "
+                    "When you're done amusing yourself press the ESC key."
+                    )
+      6 8)
+ (put (mk-step-clue "To check your equipment Z)tatus, hit the 'z' key. "
+                    "Scroll through the panes with the arrow keys. "
+                    "When you're done hit the ESC key."
+                    )
+      6 9)
+ (put (mk-step-clue "To open the portcullis you need to H)andle the lever to the left. "
+                    "Press 'h', move the crosshair over the lever with the arrow keys, "
+                    "and then press enter.")
+      6 10)
+ (put (mk-step-clue "If you want to identify the objects around you, use the X)amine command by pressing 'x'. "
+                    "The cursor over whatever you want to look at. "
+                    "Non-player characters (NPCs) like the snake will be highlighted with a box. "
+                    "Red means hostile, yellow means neutral and green means friendly. "
+                    "Hostile NPC's will attack you on sight. "
+                    "When done hit the ESC key.")
+      6 13)
+ (put (mk-step-clue "Once you open the portcullis you'll have to fight the snake. "
+                    "To A)ttack press 'a' and cursor over the target, then press ENTER.")
+      9 13)
+
+ (put (mk-step-clue "To O)pen a door just try to step through it.") 13 13)
+ (put (mk-door) 13 12)
+
+ (put (mk-step-clue "S)earch corpses using the 's' key followed by an arrow key. You can also S)earch for invisible items with this command.") 12 10)
+ (put (mk-corpse2 (list (list 20 't_picklock) 
+                        (list 10 'sulphorous_ash)
+                        (list 10 'blood_moss)
+                        )) 11 10)
+
+ (put (mk-locked-door) 13 8)
+ (put (mk-step-clue "U)se the picklocks from the corpse to unlock this door. "
+                    "Press 'u' for U)se, select the item, then target the door. "
+                    "If your picklock breaks, just try again!"
+                    ) 13 9)
+
+ (put (kern-tag 'p3 (mk-portcullis)) 12 13)
+ (put (mk-lever 'p3) 11 14)
+
+ (put (mk-magic-locked-door) 13 4)
+ (put (mk-thorald) 12 5)
+ (put (mk-step-clue "T)alk to NPC's by hitting the 't' key and targeting them. "
+                    "Then enter keywords to ask them questions. Most NPC's respond to NAME and JOB. "
+                    "NPC's usually give you clues to more keywords in their responses. "
+                    "To end a conversation type 'bye' or just hit ENTER. "
+                    "If you think an NPC would be a good addition to your party, ask them to JOIN. "
+                    "Now talk to Thorald and ask him about the door. ")
+      13 7)
+
+
+ (put (mk-step-clue "You're about to leave town and enter the wilderness. "
+                    "In the wilderness your entire party will appear as a single icon. ")
+      9 0)
+ )
diff --git a/worlds/haxima-1.002/tutorial_wilderness.scm b/worlds/haxima-1.002/tutorial_wilderness.scm
new file mode 100644 (file)
index 0000000..3ff97b9
--- /dev/null
@@ -0,0 +1,81 @@
+
+
+(kern-mk-place 
+ 'p_tutorial_wilderness
+ "The Tutorial Wilderness"
+ nil          ; sprite 
+ (kern-mk-map
+  nil 19 19 pal_expanded
+  (list
+      "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ ^^ ^^ ^^ "
+      "__ __ __ .. .. .. .. .. .. .. .. .. .. .. __ __ ^^ .. ^^ "
+      "__ __ .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ ee __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. ee __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. ^^ ^^ ^^ .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. ^^ .. ^^ .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. ^^ .. ^^ .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ .. .. .. .. .. .. .. .. .. .. .. .. .. __ .. .. .. __ "
+      "__ .. .. .. .. .. .. .. ^^ .. ^^ .. .. .. __ .. .. .. __ "
+      "__ .. .. .. .. .. .. ^^ ^^ .. ^^ ^^ .. .. __ .. .. .. __ "
+      "__ __ .. .. .. .. .. .. ^^ ^^ ^^ .. .. .. __ __ .. __ __ "
+      "__ __ __ .. .. .. .. .. .. .. .. .. .. .. __ __ __ __ __ "
+      "__ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ __ "
+  )  )
+ #f  ;; wraps
+ #f  ;; underground
+ #t  ;; wilderness
+ #f  ;; tmp combat place
+
+ ;; subplaces:
+ (list
+  (list p_tutorial_town 9 9)
+  )
+
+ nil ; neighborss
+
+ ;; objects:
+ (list
+
+  (put (mk-step-clue "A)ttack the bandits to the south. "
+                     "Combat will take place on a special map. "
+                     "When combat is over press '<' or just walk off the edge of the map.")
+       9 10)
+  (put (mk-npc-party 'bandit-party-l1) 9 13)
+  (put (mk-step-clue "You can K)amp in the wilderness to heal your party. Try it now.") 9 13)
+  (put (mk-step-clue "Enter the cave below by stepping onto it.")
+       9 14)
+  (put (mk-dungeon 'p_tutorial_cave 7 17) 9 15)
+
+  (put (mk-step-clue "B)oard the ship by stepping onto it and pressing 'b'. "
+                     "Then sail to the dock in the northeast corner using the arrow keys.") 14 5)
+  (put (mk-step-clue "F)ire your cannons at the bandits on the island by pressing 'f' and an arrow key. "
+                     "A ship can only fire broadside, so you may have to maneuver a bit.") 
+       15 4)
+  (put (mk-step-clue "F)ire your cannons at the bandits on the island by pressing 'f' and an arrow key. "
+                     "A ship can only fire broadside, so you may have to maneuver a bit.") 
+       15 6)
+  (put (mk-step-clue "F)ire your cannons at the bandits on the island by pressing 'f' and an arrow key. "
+                     "A ship can only fire broadside, so you may have to maneuver a bit.") 
+       16 5)
+
+  (put (mk-ship) 15 5)
+  (put (mk-npc-party 'bandit-party-l1) 16 14)
+
+  (put (mk-step-clue "That's it for the tutorial. There's lots more info in the USERS_GUIDE. "
+                     "You'll find one in the doc directory where you installed the game, or "
+                     "you can find one online at the project website. "
+                     "You may exit the tutorial now by Q)uitting the game with the 'q' key. "
+                     "Have fun!") 17 1)
+       
+  ) ;; end of objects
+
+ nil ; hooks
+ nil ; edge entrances
+ )
diff --git a/worlds/haxima-1.002/urt.scm b/worlds/haxima-1.002/urt.scm
new file mode 100644 (file)
index 0000000..1440b37
--- /dev/null
@@ -0,0 +1,45 @@
+;; ----------------------------------------------------------------------------
+;; Urt
+;;
+;; Urt is a troll ensnared and paralyzed in the abandoned cellar. Although
+;; paralyzed, he can speak.
+;; ----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;----------------------------------------------------------------------------
+(define urt-conv
+  (ifc basic-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "(looks confused)")))
+       (method 'hail (lambda (knpc kpc) (say knpc "(grunts)")))
+       (method 'bye (lambda (knpc kpc) (say knpc "(grunts)")))
+       (method 'job (lambda (knpc kpc) (say knpc "Stuck")))
+       (method 'name (lambda (knpc kpc) (say knpc "Urt")))
+
+       (method 'eat (lambda (knpc kpc) (say knpc "Urt eat man")))
+       (method 'food (lambda (knpc kpc) (say knpc "All eater food for other")))
+       (method 'girl (lambda (knpc kpc) (say knpc "She HRENGI, UG THROGNI")))
+       (method 'hills (lambda (knpc kpc) (say knpc "VLARDOGNI in hills, "
+                                              "kill trolls. Trolls leave.")))
+       (method 'hren (lambda (knpc kpc) (say knpc "Urt not know man-word")))
+       (method 'man (lambda (knpc kpc) (say knpc "Urt look for man-child. " 
+                                            "She yummy, tender. "
+                                            "She trick Urt. "
+                                            "URN SEGESTRUM, UG VIGIDUS!")))
+       (method 'sege (lambda (knpc kpc) (say knpc "'eater' in troll-word")))
+       (method 'spiders (lambda (knpc kpc) (say knpc "Urt hate spiders")))
+       (method 'stuck (lamda (knpc kpc) (say knpc "Spiders eat Urt")))
+       (method 'thro (lambda (knpc kpc) (say knpc "Urt not know man-word")))
+       (method 'troll (lambda (knpc kpc) (say knpc "Trolls hungry. "
+                                              "Food in hills."
+                                              "Home in hills.")))
+       (method 'ug (lambda (knpc kpc) (say knpc "'will be' in troll-word")))
+       (method 'urn (lambda (knpc kpc) (say knpc "'was' in troll-word")))
+       (method 'vigi (lambda (knpc kpc) (say kpnc "'food' in troll-word")))
+       (method 'vlar (lambda (knpc kpc) (say knpc "Urt not know man-word")))
+       ))
+
diff --git a/worlds/haxima-1.002/valus.scm b/worlds/haxima-1.002/valus.scm
new file mode 100644 (file)
index 0000000..0937d45
--- /dev/null
@@ -0,0 +1,169 @@
+;;----------------------------------------------------------------------------
+;; Valus
+;;
+;; Initially a prisoner of Glasdrin, he becomes the new Steward after the
+;; trial.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;; 
+;; Initially, in a prison cell in the dungeons below Glasdrin.
+;; After the trial of the Stewardess, Valus is assigned Jeffries schedule.
+;;----------------------------------------------------------------------------
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (valus-mk) (list 'townsman))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Valus is an imprisoned nobleman, once in the service of the late 
+;; Steward of Glasdrin, now languishing in the dungeons below Glasdrin.
+;; 
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (valus-hail knpc kpc)
+  (say knpc "Welcome, stranger.")
+  )
+
+(define (valus-name knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "I am Valus, Steward of Glasdrin.")
+      (say knpc "I am Valus, lord of all I survey [he gestures around the cell].")
+  ))
+
+(define (valus-job knpc kpc)
+  (cond ((player-stewardess-trial-done?)
+         (say knpc "The people of Glasdrin released me from prison, thanks to the evidence in that diary you found. "
+              "It seems I am in your debt.")
+         (prompt-for-key)
+         (say knpc "After I was released they elected me their new Steward.")
+         )
+        (else
+         (say knpc "I'm just enjoying my retirement.")
+         )))
+
+(define (valus-join kpc kpc)
+  (cond ((player-stewardess-trial-done?) (say knpc "My duties keep me here."))
+        (else (say knpc "On the contrary, why don't you open the door and join me?"))
+        ))
+
+;; Special
+(define (valus-comm knpc kpc)
+  (if (player-stewardess-trial-done?)
+         (say knpc "Janice will make a fine commander. I remember when she was just a squad leader.")
+         (say knpc "Jeffries is the new Commander. He makes a good pet for the Stewardess. I wasn't such a good dog, myself.")
+         ))
+
+(define (valus-pet knpc kpc)
+  (say knpc "After Absalot, she blamed me for the deaths of civilians, "
+       "and accused me of drunkenness and unnatural acts with trolls.")
+  (aside 'ch_ini "I thought the part about the trolls was true.")
+  )
+
+(define (valus-trol knpc kpc)
+  (say knpc "What can I say? Those trolls know how to party. [He smiles dryly]")
+  (prompt-for-key)
+  (say knpc "But seriously, she had me imprisoned for asking too many questions. "
+       "The former Steward went insane under mysterious circumstances. "
+       "For some reason she didn't like me poking into the matter.")
+  )
+
+(define (valus-absa knpc kpc)
+  (say knpc "War is hell, friend. All of this nonsense about the Accursed aside, "
+       "the mages of Absalot were growing too powerful. "
+       "Every commander knows the legend of Isin.")
+  )
+
+(define (valus-isin knpc kpc)
+  (say knpc "According to legend, the sorceress Isin almost single-handedly defeated two armies. "
+       "The army of Tulemane was so utterly vanquished that their city has been forgotten. ")
+  (prompt-for-key)
+  (say knpc "Glasdrin's army finally overcame her, but with such heavy losses that it had to abandon its objective. "
+       "We have never forgotten the lesson.")
+  )
+
+(define (valus-less knpc kpc)
+  (say knpc "The lesson of the Battle of Isin is to never let wizards get too powerful. "
+       "And if they do, don't try to face them in open combat. "
+       "You know, I've always wondered why that battle took place.")
+  )
+
+;; new....
+(define (valus-stew knpc kpc)
+  (if (player-stewardess-trial-done?)
+      (say knpc "Now that I am steward there will be some changes around here.")
+      (say knpc "That mad-woman's policies will be the ruin of Glasdrin.")
+      ))
+
+(define (valus-poli knpc kpc)
+  (say knpc "The goal of the Stewardess is to increase her own power at the expense of all else. ")
+  )
+
+(define (valus-chan knpc kpc)
+  (say knpc "My first concern is the security, stability and dominance of Glasdrin.")
+  )
+
+(define (valus-domi knpc kpc)
+  (if (ask? knpc kpc "The only way a city or state can ensure its own security is to dominate others, don't you agree?")
+      (say knpc "Yes, all wise statesmen know this, and strive to make their own state the strongest.")
+      (say knpc "If we permit other states to surpass us in strength, then they will dominate us. "
+           "As Steward, I am responsible for taking action to prevent that.")
+      ))
+
+(define valus-conv
+  (ifc glasdrin-conv
+
+       ;; basics
+       (method 'hail valus-hail)
+       (method 'job  valus-job)
+       (method 'name valus-name)
+       (method 'join valus-join)
+
+       (method 'absa valus-absa)
+       (method 'chan valus-chan)
+       (method 'civi valus-absa)
+       (method 'comm valus-comm)
+       (method 'dog  valus-pet)
+       (method 'domi valus-domi)
+       (method 'drun valus-trol)
+       (method 'isin valus-isin)
+       (method 'jeff valus-comm)
+       (method 'less valus-less)
+       (method 'pet  valus-pet)
+       (method 'poli valus-poli)
+       (method 'reti (lambda (knpc kpc) (say knpc "Formerly, I was the Commander of Glasdrin.")))
+       (method 'ruin valus-poli)
+       (method 'secu valus-domi)
+       (method 'stab valus-domi)
+       (method 'stew valus-stew)
+       (method 'trol valus-trol)
+       (method 'unna valus-trol)
+       ))
+
+(define (mk-valus)
+  (bind 
+   (kern-mk-char 'ch_valus       ; tag
+                 "Valus"          ; name
+                 sp_human            ; species
+                 oc_warrior          ; occ
+                 s_fallen_paladin ; sprite
+                 faction-glasdrin         ; starting alignment
+                 2 1 1               ; str/int/dex
+                 0 0                 ; hp mod/mult
+                 0 0                 ; mp mod/mult
+                 max-health -1 max-health 0 5  ; hp/xp/mp/AP_per_turn/lvl
+                 #f                  ; dead
+                 'valus-conv         ; conv
+                 nil           ; sched
+                 'townsman-ai                 ; special ai
+                 nil                 ; container
+                 (list t_armor_chain
+                       t_chain_coif
+                       t_sword
+                       ))         ; readied
+   (valus-mk)))
diff --git a/worlds/haxima-1.002/vehicles.scm b/worlds/haxima-1.002/vehicles.scm
new file mode 100644 (file)
index 0000000..dce41ff
--- /dev/null
@@ -0,0 +1,420 @@
+
+;;---------------------------------------------------------------
+;; utility stuff
+
+(define (vehicle-broadside-facing vehicle dx dy)
+       (let ((facing (kern-obj-get-facing vehicle)))
+               (cond ((< dx 0) ;;west side
+                                       (if (equal? facing NORTH) NORTH SOUTH))
+                               ((> dx 0) ;;east side
+                                       (if (equal? facing SOUTH) SOUTH NORTH))
+                               ((< dy 0) ;;north side
+                                       (if (equal? facing WEST) WEST EAST))
+                               ((> dy 0) ;;south side
+                                       (if (equal? facing EAST) EAST WEST))
+                               (else facing)
+               )))
+
+(define (map-paste-centered dst-map src-map src-x src-y src-w src-h dst-x dst-y dst-w dst-h)
+       (let* ((cw (min src-w dst-w))
+               (ch (min src-h dst-h))
+               (src-cx (floor (+ src-x (/ (- src-w cw) 2))))
+               (dst-cx (floor (+ dst-x (/ (- dst-w cw) 2))))
+               (src-cy (floor (+ src-y (/ (- src-h ch) 2))))
+               (dst-cy (floor (+ dst-y (/ (- dst-h ch) 2)))))
+               (kern-blit-map dst-map dst-cx dst-cy
+                       src-map src-cx src-cy
+                       cw ch)
+       ))
+       
+(define (place-add-objects-offset place src-x src-y src-w src-h dst-x dst-y dst-w dst-h objectlist)
+       (let* ((cw (min src-w dst-w))
+               (ch (min src-h dst-h))
+               (src-cx (floor (+ src-x (/ (- src-w cw) 2))))
+               (dst-cx (floor (+ dst-x (/ (- dst-w cw) 2))))
+               (src-cy (floor (+ src-y (/ (- src-h ch) 2))))
+               (dst-cy (floor (+ dst-y (/ (- dst-h ch) 2))))
+               (dx (- dst-cx src-cx))
+               (dy (- dst-cy src-cy)))
+               (map
+                       (lambda (objectentry)
+                               (kern-obj-put-at (car objectentry) 
+                                       (list place
+                                               (+ (cadr objectentry) dx)
+                                               (+ (caddr objectentry) dy)
+                                       ))
+                       )
+                       objectlist
+               )
+       ))
+       
+(define (mk-vehicle ktype)
+  (kern-mk-vehicle ktype north 100))
+  
+(define (vehicle-object-list-rotate facing n-wid n-hgt objectlist)
+       (let* ((turn-matrix (cond 
+                               ((equal? facing NORTH) (list 0 0 1 0 0 1))
+                               ((equal? facing EAST) (list (- n-hgt 1) 0 0 -1 1 0))
+                               ((equal? facing WEST) (list 0 (- n-wid 1) 0 1 -1 0))
+                               (else (list (- n-wid 1) (- n-hgt 1) -1 0 0 -1))))
+                       (xoff (car turn-matrix))
+                       (yoff (cadr turn-matrix))
+                       (xxmult (list-ref turn-matrix 2))
+                       (xymult (list-ref turn-matrix 3))
+                       (yxmult (list-ref turn-matrix 4))
+                       (yymult (list-ref turn-matrix 5)))
+                       (map    
+                               (lambda (objectentry)
+                                       (list
+                                               (car objectentry)
+                                               (+ xoff (* xxmult (cadr objectentry)) (* xymult (caddr objectentry)))
+                                               (+ yoff (* yxmult (cadr objectentry)) (* yymult (caddr objectentry)))
+                                       )
+                               )
+                               objectlist
+                       )
+       ))
+
+(define (facing-turn-90right facing)
+       (cond ((equal? facing NORTH) EAST)
+               ((equal? facing WEST) NORTH)
+               ((equal? facing EAST) SOUTH)
+               ((equal? facing SOUTH) WEST)
+               (else facing)))
+
+(define (facing-turn-90left facing)
+       (cond ((equal? facing NORTH) WEST)
+               ((equal? facing WEST) SOUTH)
+               ((equal? facing EAST) NORTH)
+               ((equal? facing SOUTH) EAST)
+               (else facing)))
+
+               
+;;--------------------------------------------------------------------------
+;; vehicle objects: wheel
+       
+(define shipwheel-ifc
+       (ifc '()
+               (method 'init
+                       (lambda (kwheel)
+                               (kern-obj-set-facing kwheel (gob kwheel))
+               ))      
+       ))
+
+(mk-obj-type 't_shipswheel "ship's wheel" s_shipswheel layer-mechanism shipwheel-ifc)     
+         
+(define  (vehicle-mk-wheel facing)
+       (let ((kwheel (kern-mk-obj t_shipswheel 1)))
+          (kern-obj-set-facing kwheel facing) 
+          (bind kwheel facing)
+          kwheel))
+
+;;---------------------------------------------------------------------------
+;; boarding ramp handling
+
+(define onramp-ifc
+       (ifc '()
+               (method 'exec
+                       (lambda (kramp)
+                               (let* ((kloc (kern-obj-get-location kramp))
+                                       (kplace (car kloc))
+                                       (wid (kern-place-get-width kplace))
+                                       (hgt (kern-place-get-height kplace))
+                                       (rx (cadr kloc))
+                                       (ry (caddr kloc)))
+                                       (define (vehicle-check-ramp x y)
+                                               (cond ((< x 0) 0)
+                                                       ((> x wid) 0)
+                                                       ((< y 0) 0)
+                                                       ((> y hgt) 0)
+                                                       ((kern-place-is-passable (list kplace x y) kramp) 1)
+                                                       (else 
+                                                               (let ((objs (kern-get-objects-at (list kplace x y))))
+                                                                       (if (and (not (null? objs))
+                                                                                       (equal? (kern-obj-get-type (car objs)) (eval 't_onramp)))
+                                                                               1
+                                                                               0)))
+                                               ))
+                                       (define (vehicle-trigger-ramp-neighbors x y)
+                                               (cond ((< x 0) 0)
+                                                       ((> x wid) 0)
+                                                       ((< y 0) 0)
+                                                       ((> y hgt) 0)
+                                                       (else 
+                                                               (let ((objs (kern-get-objects-at (list kplace x y))))
+                                                                       (if (and (not (null? objs))
+                                                                                       (equal? (kern-obj-get-type (car objs)) (eval 't_onramp)))
+                                                                               ((kobj-ifc (car objs)) 'exec (car objs))
+                                                                               0)))
+                                               ))
+                                       (if (< 1
+                                                       (+ (vehicle-check-ramp (+ rx 1) ry)
+                                                               (vehicle-check-ramp (- rx 1) ry)
+                                                               (vehicle-check-ramp rx (+ ry 1))
+                                                               (vehicle-check-ramp rx (- ry 1))))
+                                               (begin 
+                                                       (kern-place-set-terrain (list kplace rx ry) t_deck)
+                                                       (kern-obj-remove kramp)
+                                                       (vehicle-trigger-ramp-neighbors (+ rx 1) ry)
+                                                       (vehicle-trigger-ramp-neighbors (- rx 1) ry)
+                                                       (vehicle-trigger-ramp-neighbors  rx (+ ry 1))
+                                                       (vehicle-trigger-ramp-neighbors  rx (- ry 1))
+                                               )
+                                               (kern-obj-remove kramp)
+                                       )
+                       )))
+               ))
+
+(mk-obj-type 't_onramp nil nil layer-none onramp-ifc)
+
+;;------------------------------------------------------------------------
+;; ship
+       
+(kern-mk-map 
+ 'm_ship_n 9 17 pal_expanded
+ (list
+  "-- -- -- -- -- -- -- -- --";
+  "-- -- -- #e #a #f -- -- --";
+  "-- -- #e #E ee #F #f -- --";
+  "-- #e #E ee ee ee #F #f --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #b <n #= #= #= <n #c --";
+  "-- ee ee ee oo ee ee ee --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- ee ee ee ee ee ee ee --";
+  "-- #b ee ee oo ee ee #c --";
+  "-- #b <s #= #= #= <s #c --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #g #G ee ee ee #H #h --";
+  "-- -- #g #d #d #d #h -- --";
+  "-- -- -- -- -- -- -- -- --";
+  ))
+  
+(kern-mk-map 
+ 'm_ship_s 9 17 pal_expanded
+ (list
+  "-- -- -- -- -- -- -- -- --";
+  "-- -- #e #a #a #a #f -- --";
+  "-- #e #E ee ee ee #F #f --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #b <n #= #= #= <n #c --";
+  "-- #b ee ee oo ee ee #c --";
+  "-- ee ee ee ee ee ee ee --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- ee ee ee oo ee ee ee --";
+  "-- #b <s #= #= #= <s #c --";
+  "-- #b ee ee ee ee ee #c --";
+  "-- #g #G ee ee ee #H #h --";
+  "-- -- #g #G ee #H #h -- --";
+  "-- -- -- #g #d #h -- -- --";
+  "-- -- -- -- -- -- -- -- --";
+  ))
+  
+(kern-mk-map 
+ 'm_ship_e 17 9 pal_expanded
+ (list
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --";
+  "-- -- #e #a #a #a ee #a #a #a ee #a #a #f -- -- --";
+  "-- #e #E ee <w ee ee ee ee ee ee <e ee #F #f -- --";
+  "-- #b ee ee #| ee ee ee ee ee ee #| ee ee #F #f --";
+  "-- #b ee ee #| oo ee ee ee ee oo #| ee ee ee #c --";
+  "-- #b ee ee #| ee ee ee ee ee ee #| ee ee #H #h --";
+  "-- #g #G ee <w ee ee ee ee ee ee <e ee #H #h -- --";
+  "-- -- #g #d #d #d ee #d #d #d ee #d #d #h -- -- --";
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --";
+  ))
+  
+(kern-mk-map 
+ 'm_ship_w 17 9 pal_expanded
+ (list
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --";
+  "-- -- -- #e #a #a ee #a #a #a ee #a #a #a #f -- --";
+  "-- -- #e #E ee <w ee ee ee ee ee ee <e ee #F #f --";
+  "-- #e #E ee ee #| ee ee ee ee ee ee #| ee ee #c --";
+  "-- #b ee ee ee #| oo ee ee ee ee oo #| ee ee #c --";
+  "-- #g #G ee ee #| ee ee ee ee ee ee #| ee ee #c --";
+  "-- -- #g #G ee <w ee ee ee ee ee ee <e ee #H #h --";
+  "-- -- -- #g #d #d ee #d #d #d ee #d #d #d #h -- --";
+  "-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --";
+  ))
+  
+(define vehicle-ship-handler
+       (lambda (place vehicle off_x off_y)
+               (let* ((facing (vehicle-broadside-facing vehicle off_x off_y))
+                       (vmap (get-cardinal-lref (list m_ship_n m_ship_w m_ship_e m_ship_s) facing))
+                       (src-w (kern-terrainmap-get-width vmap))
+                       (src-h (kern-terrainmap-get-height vmap))
+                       (dst-x (combat-off-to-dst off_x))
+                       (dst-y (combat-off-to-dst off_y))
+                       (dst-w (combat-off-to-len (kern-place-get-width place) off_x))
+                       (dst-h (combat-off-to-len (kern-place-get-height place) off_y)))
+               (map-paste-centered (kern-place-get-terrain-map place) vmap
+                       0 0 src-w src-h
+                       dst-x dst-y dst-w dst-h)        
+               (place-add-objects-offset place
+                       0 0 src-w src-h
+                       dst-x dst-y dst-w dst-h
+                       (vehicle-object-list-rotate facing 9 17 
+                       (list
+                               (list (vehicle-mk-wheel facing) 4 12)
+                               (list (arms-mk-cannon (facing-turn-90right facing)) 7 8)
+                               (list (arms-mk-cannon (facing-turn-90left facing)) 1 8)
+                               (list (kern-mk-obj t_onramp 1) 0 6)
+                               (list (kern-mk-obj t_onramp 1) 8 6)
+                               (list (kern-mk-obj t_onramp 1) 0 10)
+                               (list (kern-mk-obj t_onramp 1) 8 10)
+                       )))
+       )))
+               
+  
+(kern-mk-vehicle-type 't_ship   ; tag
+                      "ship"    ; name
+                      s_ship    ; sprite
+                      m_ship_n    ; map
+                      t_cannon  ; ordnance
+                      #t        ; vulnerable
+                      #t        ; occupants die when destroyed
+                      #t        ; must turn
+                      "sail"    ; move description
+                      sound-ship-move ; move sound
+                      1           ; tailwind penalty
+                      4           ; headwind penalty
+                      2           ; crosswind penalty
+                      100         ; max hp
+                      speed-ship  ; speed
+                      mmode-ship  ; pmask
+                      vehicle-ship-handler;
+                      )
+
+(define (mk-ship)
+  (kern-mk-vehicle t_ship north 100))
+       
+;;----------------------------------------------------------------------------
+;; voidship
+;;----------------------------------------------------------------------------
+(kern-mk-map 
+ 'm_voidship_n 9 17 pal_expanded
+ (list
+  "** ** ** ** ** ** ** ** **"
+  "** ** ** ** ** ** ** ** **"
+  "** ** ** #i #A #j ** ** **"
+  "** ** #i #E ee #F #j ** **"
+  "** #i #E ee ee ee #F #j **"
+  "** #B ee ee 00 ee ee #C **"
+  "** #B ee ee 00 ee ee #C **"
+  "** #B ee ee ee ee ee #C **"
+  "** ee ee ee ee ee ee ee **"
+  "** #B ee ee ee ee ee #C **"
+  "#n #m #O ee ee ee #N #m #o"
+  "#m #m #M ee 00 ee #m #m #M"
+  "#m #m #M ee ## ee #m #m #M"
+  "#m #m #M #D ## #D #m #m #M"
+  "#m #m #M ** ** ** #m #m #M"
+  "#p #M #q ** ** ** #p #M #q"
+  "** ** ** ** ** ** ** ** **"
+  ))
+  
+(kern-mk-map 
+ 'm_voidship_s 9 17 pal_expanded
+ (list
+  "** ** ** ** ** ** ** ** **"
+  "#n #m #o ** ** ** #n #m #o"
+  "#m #m #M ** ** ** #m #m #M"
+  "#m #m #M #A ## #A #m #m #M"
+  "#m #m #M ee ## ee #m #m #M"
+  "#m #m #M ee 00 ee #m #m #M"
+  "#p #M #Q ee ee ee #P #M #q"
+  "** #B ee ee ee ee ee #C **"
+  "** ee ee ee ee ee ee ee **"
+  "** #B ee ee ee ee ee #C **"
+  "** #B ee ee 00 ee ee #C **"
+  "** #B ee ee 00 ee ee #C **"
+  "** #k #G ee ee ee #H #l **"
+  "** ** #k #G ee #H #l ** **"
+  "** ** ** #k #D #l ** ** **"
+  "** ** ** ** ** ** ** ** **"
+  "** ** ** ** ** ** ** ** **"
+  ))
+  
+(kern-mk-map 
+ 'm_voidship_e 17 9 pal_expanded
+ (list
+  "** #n #m #m #m #m #o ** ** ** ** ** ** ** ** ** **";
+  "** #m #m #m #m #m #M #A ee #A #A #A #j ** ** ** **";
+  "** #p #M #M #M #M #Q ee ee ee ee ee #F #j ** ** **";
+  "** ** ** #B ee ee ee ee ee ee ee ee ee #F #j ** **";
+  "** ** ** ## ## 00 ee ee ee ee 00 00 ee ee #C ** **";
+  "** ** ** #B ee ee ee ee ee ee ee ee ee #H #l ** **";
+  "** #n #m #m #m #m #O ee ee ee ee ee #H #l ** ** **";
+  "** #m #m #m #m #m #M #D ee #D #D #D #l ** ** ** **";
+  "** #p #M #M #M #M #q ** ** ** ** ** ** ** ** ** **";
+  ))
+  
+
+(kern-mk-map 
+ 'm_voidship_w 17 9 pal_expanded
+ (list
+  "** ** ** ** ** ** ** ** ** ** #n #m #m #m #m #o **";
+  "** ** ** ** #i #A #A #A ee #A #m #m #m #m #m #M **";
+  "** ** ** #i #E ee ee ee ee ee #P #M #M #M #M #q **";
+  "** ** #i #E ee ee ee ee ee ee ee ee ee #C ** ** **";
+  "** ** #B ee ee 00 00 ee ee ee ee 00 ## ## ** ** **";
+  "** ** #k #G ee ee ee ee ee ee ee ee ee #C ** ** **";
+  "** ** ** #k #G ee ee ee ee ee #N #m #m #m #m #o **";
+  "** ** ** ** #k #D #D #D ee #D #m #m #m #m #m #M **";
+  "** ** ** ** ** ** ** ** ** ** #p #M #M #M #M #q **";
+  ))
+    
+(define vehicle-voidship-handler
+       (lambda (place vehicle off_x off_y)
+               (let* ((facing (vehicle-broadside-facing vehicle off_x off_y))
+                       (vmap (get-cardinal-lref (list m_voidship_n m_voidship_w m_voidship_e m_voidship_s) facing))
+                       (src-w (kern-terrainmap-get-width vmap))
+                       (src-h (kern-terrainmap-get-height vmap))
+                       (dst-x (combat-off-to-dst off_x))
+                       (dst-y (combat-off-to-dst off_y))
+                       (dst-w (combat-off-to-len (kern-place-get-width place) off_x))
+                       (dst-h (combat-off-to-len (kern-place-get-height place) off_y)))
+               (map-paste-centered (kern-place-get-terrain-map place) vmap
+                       0 0 src-w src-h
+                       dst-x dst-y dst-w dst-h)        
+               (place-add-objects-offset place
+                       0 0 src-w src-h
+                       dst-x dst-y dst-w dst-h
+                       (vehicle-object-list-rotate facing 9 17 
+                       (list
+                               (list (vehicle-mk-wheel facing) 4 6)
+                               (list (arms-mk-cannon (facing-turn-90right facing)) 7 6)
+                               (list (arms-mk-cannon (facing-turn-90left facing)) 1 6)                         
+                               (list (kern-mk-obj t_onramp 1) 0 8)
+                               (list (kern-mk-obj t_onramp 1) 8 8)
+                       )))     
+       )))
+  
+(kern-mk-vehicle-type 't_voidship   ; tag
+                      "voidship"    ; name
+                      s_void_ship   ; sprite
+                      m_voidship_n    ; map
+                      t_cannon  ; ordnance
+                      #t        ; vulnerable
+                      #t        ; occupants die when destroyed
+                      #t        ; must turn
+                      "sail"    ; move description
+                      sound-ship-move ; move sound
+                      1           ; tailwind penalty
+                      4           ; headwind penalty
+                      2           ; crosswind penalty
+                      100         ; max hp
+                      speed-ship  ; speed
+                      mmode-voidship  ; pmask
+                      vehicle-voidship-handler;
+                      )
+
+
+(define (mk-voidship)
+  (kern-mk-vehicle t_voidship north 100))
+
diff --git a/worlds/haxima-1.002/void-temple.scm b/worlds/haxima-1.002/void-temple.scm
new file mode 100644 (file)
index 0000000..34a341c
--- /dev/null
@@ -0,0 +1,53 @@
+;; ----------------------------------------------------------------------------
+;; Map
+;; ----------------------------------------------------------------------------
+(mk-19x19-town
+ 'p_void_temple "Temple of the Void" s_shrine
+ (list
+  "cc cc cc cc cc cc cc .. .. .. .. .. cc cc cc cc cc cc cc "
+  "cc cc cc cc cc cc cc cc .. .. .. cc cc cc cc cc cc cc cc "
+  "cc cc t3 tt tt *3 *1 *5 bb .. bb *3 *1 *5 tt tt t5 cc cc "
+  "cc cc tt tt *3 ** *. ** *5 cc *3 ** ** ** *5 tt tt cc cc "
+  "cc cc tt *3 *. ** ** ** *4 cc *2 ** ** *. *. *5 tt cc cc "
+  "cc cc *3 ** ** *. ** ** *c cc *a ** ** ** ** *. *5 cc cc "
+  "cc cc *2 *. *. ** *. *c bb .. bb *a *. ** *. ** *4 cc cc "
+  ".. cc *a ** *. ** *c .g .. .. .. .h *a ** ** ** *c cc .. "
+  ".. .. bb *a *8 *c bb .. .. .. .. .. bb *a *8 *c bb .. .. "
+  ".. .. .. cc cc cc .. .. .. .. .. .. .. cc cc cc .. .. .. "
+  ".. .. bb *3 *1 *5 bb .. .. .. .. .. bb *3 *1 *5 bb .. .. "
+  ".. cc *3 ** ** ** *5 .j .. .. .. .l *3 ** *. ** *5 cc .. "
+  "cc cc *2 *. *. ** ** *5 bb .. bb *3 ** *. *. *. *4 cc cc "
+  "cc cc *a *. *. ** ** *. *5 cc *3 ** ** *. ** ** *c cc cc "
+  "cc cc tt *a ** *. ** *. *4 cc *2 *. *. *. *. *c tt cc cc "
+  "cc cc tt tt *a *. *. ** *c cc *a ** *. *. *c tt tt cc cc "
+  "cc cc ta tt tt *a *8 *c bb .. bb *a *8 *c tt tt tc cc cc "
+  "cc cc cc cc cc cc cc cc .. .. .. cc cc cc cc cc cc cc cc "
+  "cc cc cc cc cc cc cc .. .. .. .. .. cc cc cc cc cc cc cc "
+  )
+  nil ;;entrances
+ (put (kern-mk-obj t_rune_d 1) 9 9)
+
+ (put (kern-mk-obj F_sleep_perm 1)  15 9)
+ (put (kern-mk-obj F_fire_perm 1)   14 9)
+ (put (kern-mk-obj F_energy_perm 1) 13 9)
+ (put (kern-mk-obj F_sleep_perm 1)  3 9)
+ (put (kern-mk-obj F_fire_perm 1)   4 9)
+ (put (kern-mk-obj F_energy_perm 1) 5 9)
+ (put (kern-mk-obj F_sleep_perm 1)  9 3)
+ (put (kern-mk-obj F_fire_perm 1)   9 4)
+ (put (kern-mk-obj F_energy_perm 1) 9 5)
+ (put (kern-mk-obj F_sleep_perm 1)  9 15)
+ (put (kern-mk-obj F_fire_perm 1)   9 14)
+ (put (kern-mk-obj F_energy_perm 1) 9 13)
+ (put (spawn-pt 'wisp) 7 9)
+ (put (spawn-pt 'wisp) 9 7)
+ (put (spawn-pt 'wisp) 11 9)
+ (put (spawn-pt 'wisp) 9 11)
+ )
+
+(mk-place-music p_void_temple 'ml-outdoor-adventure)
diff --git a/worlds/haxima-1.002/voidgap-mech.scm b/worlds/haxima-1.002/voidgap-mech.scm
new file mode 100644 (file)
index 0000000..dcf92bd
--- /dev/null
@@ -0,0 +1,241 @@
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Deeps random map
+
+
+;probability for edge terrains... out of 83
+(define voidgap-terrain-edges
+       (list
+               (list 20 'm_deeptempl_wall #f)
+               (list 25 'm_deeptempl_water #f)
+               (list 30 'm_deeptempl_hole #f)
+               (list 33 'm_deeptempl_lava #f)
+               (list 35 'm_deeptempl_swamp #t)         
+               (list 100 'm_deeptempl_passage #t)
+       ))
+
+;probability for area terrains... out of 149
+(define voidgap-terrain-area
+       (list
+               (list 40 'm_deeptempl_wall)
+               (list 55 'm_deeptempl_water)
+               (list 70 'm_deeptempl_hole)             
+               (list 75 'm_deeptempl_lava)             
+               (list 80 'm_deeptempl_swamp)            
+               (list 150 'm_deeptempl_passage)
+       ))
+
+;map areas replaced by the various blitting ops
+(define voidgap-room-blitstats
+       (prmap-mk-blitstats 19 19 3 4 3))
+
+
+;parameters to random number generators
+(define (voidgap-rno) (+ (kern-dice-roll "1d70" 33)))
+(define voidgap-random-type-ew (prmap-mk-prng-params (voidgap-rno) (voidgap-rno) 0 (voidgap-rno) 83))
+(define voidgap-random-type-ns (prmap-mk-prng-params (voidgap-rno) (voidgap-rno) 0 (voidgap-rno) 83))
+(define voidgap-random-type-area (prmap-mk-prng-params (voidgap-rno) (voidgap-rno) 0 (voidgap-rno) 149))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; critter lists
+
+(define voidgap-monster-types
+       (list 
+               (list 
+                       (list 100 'bat)
+               )
+               (list
+                       (list 100 'rat)
+                       (list 200 'bat)
+               )
+               (list
+                       (list 100 'giant-spider)
+                       (list 150 'queen-spider)
+               )
+               (list
+                       (list 100 'cave-goblin-slinger)
+                       (list 200 'cave-goblin-berserker)
+                       (list 250 'cave-goblin-priest)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'cave-goblin-berserker-m)
+                       (list 300 'troll-m)
+                       (list 350 'troll-geomancer-m)
+               )
+               (list
+                       (list 100 'green-slime)
+                       (list 200 'yellow-slime)
+               )       
+               (list
+                       (list 100 'zorn)
+               )
+               (list
+                       (list 20 'ghast)
+                       (list 200 'demon)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'cave-goblin-berserker-m)
+                       (list 150 'troll-m)
+                       (list 350 'gint-warrior-m)
+                       (list 400 'gint-mage-m)
+               )
+               (list
+                       (list 50 'cave-goblin-slinger-m)
+                       (list 100 'headless)
+                       (list 150 'cave-goblin-berserker-m)
+                       (list 200 'troll-m)
+                       (list 250 'gint-warrior-m)
+                       (list 350 'gazer)
+               )
+               (list
+                       (list 25 'cave-goblin-slinger-m)
+                       (list 50 'cave-goblin-berserker-m)
+                       (list 300 'dragon)
+               )
+               (list
+                       (list 20 'ghast)
+                       (list 70 'skeletal-warrior)
+                       (list 120 'skeletal-spear-thrower)
+                       (list 150 'craven-archer)
+                       (list 300 'death-knight)
+                       (list 350 'demon)
+               )
+               (list
+                       (list 100 'skeletal-warrior)
+                       (list 200 'skeletal-spear-thrower)
+                       (list 250 'lich)
+               )
+               (list 
+                       (list 100 'headless)
+                       (list 150 'skeletal-warrior)
+                       (list 200 'skeletal-spear-thrower)
+                       (list 220 'craven-archer)
+                       (list 250 'death-knight)
+                       (list 260 'demon)
+                       (list 330 'warlock)
+               )
+       )
+)
+
+(define voidgap-group-types
+       (list
+               (list 10 0 100 "1d4+3") ;bats
+               (list 20 1 100 "1d4+3") ;rats
+               (list 30 1 200 "1d6+4") ;bats n rats
+               (list 40 5 100 "1d3+2") ;slime
+               (list 50 2 100 "1d4+3") ;spiders
+               (list 60 3 100 "1d3+1") ;goblins
+               (list 70 2 110 "1d4+3") ;spiders 1q
+               (list 80 13 100 "1d6+4") ;headless
+               (list 90 2 150 "1d6+4") ;spiders +qs
+               (list 100 5 200 "1d6+3") ;slime+
+               (list 110 3 200 "1d6+4") ;goblin war
+               (list 120 7 20 "1d6+1")  ;ghost
+               (list 130 11 120 "1d6+4") ;skels
+               (list 140 4 300 "1d6+3") ;trolls
+               (list 150 6 100 "1d2")   ;zorn
+               (list 160 8 350 "1d6+3") ;gint
+               (list 170 7 22 "1d6+1")  ;ghost + d
+               (list 180 11 300 "2d4+4") ;deathknights
+               (list 190 11 310 "2d4+4") ;deathknights +d
+               (list 200 3 210 "1d6+5") ;goblin war +p
+               (list 210 7 200 "1d3")   ;demons
+               (list 220 3 250 "2d4+4") ;goblin tribe
+               (list 230 4 350 "1d6+5") ;trolls +m
+               (list 240 8 400 "2d4+4") ;gint + m
+               (list 250 10 300 "1d4")  ;dragon
+               (list 260 10 80 "1d6+3") ;dragon + gob  
+               (list 270 9 260 "1d6+3") ;gazer
+               (list 280 13 330 "2d4+4") ;warlock              
+               (list 290 12 205 "2d4+4") ;lich 
+               (list 300 9 320 "2d4+4") ;gazers
+       )
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; handles
+
+(define (voidgap-link-factory x y z map dir)
+               (list 'm_deeptempl_break nil)
+               )
+
+(define (voidgap-room-custom-hardlinks rxloc ryloc rzloc hardlinks)
+       (vector-merge
+               (prmap-room-hardlinkentry-get rxloc ryloc rzloc hardlinks)
+               (vector
+                       (if (> ryloc 1) (list nil 'm_deeptempl_wall) nil)
+                       (if (< rxloc -7) (list nil 'm_deeptempl_wall) nil)
+                       (if (> rxloc 1) (list nil 'm_deeptempl_wall) nil)
+                       (if (< ryloc -7) (list nil 'm_deeptempl_wall) nil)
+               )
+       ))      
+               
+(define (voidgap-room-init-contents kplace roomdata)
+       (let* (
+                       (rxloc (prmap-roomdata-x roomdata))
+                       (ryloc (prmap-roomdata-y roomdata))
+                       (distance (sqrt (+ (* rxloc rxloc) (* ryloc ryloc))))
+               )
+               (if (and (null? (kern-place-get-beings kplace))
+                               (< (kern-dice-roll "1d100") 
+                                       (min 75 (+ 25 (* 15 (sqrt distance))))))
+                       (begin 
+                       (map (lambda (monster)
+                               (begin 
+
+                                       (prmap-room-addmonster kplace monster)))
+                               (prmap-mk-monster-group voidgap-group-types voidgap-monster-types 
+                                       (string-append "1d" (number->string (+ 100 (ceiling (* 40 (sqrt distance))))))
+                                       (+ 200 (* 30 (sqrt distance)))))
+                                       )
+               )
+       ))
+
+(define (voidgap-init-cohesion mapdata)
+       (if (list-ref mapdata 10)
+               (begin
+                       ;;(kern-log-msg "begin cohesion check")
+                       (prmap-ensure-cohesion mapdata -5 0 -5 0 0 voidgap-link-factory)
+                       ;;(kern-log-msg "end cohesion check")
+                       (mutable-list-set mapdata 10 #f)
+               )))
+               
+(define (voidgap-room-handle-deeps kplace kplayer)
+       (let* (
+               (roomdata (get-roomdata kplace))
+               (mapdata (prmap-get-mapdata (eval 'p_voidgap_1)))
+               )
+               (prmap-room-freeze-current mapdata)
+               (prmap-room-init-neighbors kplace roomdata)
+               (prmap-room-init-links kplace roomdata mapdata)
+               (prmap-room-cleanout kplace)
+               (prmap-room-thaw kplace mapdata)                
+               (prmap-room-blit-map kplace roomdata mapdata)
+               (voidgap-room-init-contents kplace roomdata)
+       ))
+
+(define (voidgap-room-handle-start kplace kplayer)
+       (let* (
+               (roomdata (get-roomdata (eval 'p_voidgap_1)))
+               (mapdata (prmap-get-mapdata (eval 'p_voidgap_1)))
+               )
+               (voidgap-init-cohesion mapdata)
+               (prmap-room-freeze-current mapdata)
+               (prmap-roomdata-setxyz roomdata -1 0 0)
+               (kern-place-set-neighbor west kplace (eval 'p_voidgap_1))
+       ))      
+       
+(define (voidgap-room-handle-end kplace kplayer)
+       (let* (
+               (roomdata (get-roomdata (eval 'p_voidgap_1)))
+               (mapdata (prmap-get-mapdata (eval 'p_voidgap_1)))
+               )
+               (voidgap-init-cohesion mapdata)
+               (prmap-room-freeze-current mapdata)
+               (prmap-roomdata-setxyz roomdata -5 -5 0)
+               (voidgap-room-init-contents kplace roomdata)
+               (kern-place-set-neighbor east kplace (eval 'p_voidgap_1))
+       ))      
+       
\ No newline at end of file
diff --git a/worlds/haxima-1.002/voidgap-passage.scm b/worlds/haxima-1.002/voidgap-passage.scm
new file mode 100644 (file)
index 0000000..b7847a4
--- /dev/null
@@ -0,0 +1,368 @@
+(kern-mk-place 
+       'p_voidgap_entrance
+       "Passage to Voidgap"
+       s_dungeon          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn r8 rn rn rn rn "
+               "rn rn r8 r8 r8 r8 r8 rn r8 rn rn rn rn rc {{ ra r8 r8 rn "
+               "rn rc {4 {{ {{ {{ {2 re bb ra r8 xx rc {{ {{ {2 .. .. ra "
+               "rc .. {4 {{ {{ {3 .. .. .. .. {4 xx {{ {{ {{ {2 .. .. .! "
+               ".. .. .. {1 {1 .. .. .. .. .. .. x! {5 {{ {3 .. .. .! .. "
+               ".. .. .. .. .. .. .. .. .. .. .. w+ .. {1 .. .. .. .. .! "
+               ".. .. .. .. .. bb .. .. .. .. .. .. .. .. bb .. .. .. .. "
+               ".. .. .. .. .. .. .. .. {8 .. .. w+ .. .. .. .. .. .. .! "
+               ".. .. .. .. .. .. {8 {c {{ {2 .. .. .. .. .. .. .. .! .. "
+               ".. .. bb .. .. {c {{ {{ {{ {2 .. w+ .. .. .. .. .. {8 .! "
+               ".. .. .. .. {c {{ {{ rf {{ {2 .. x! .. .. .. .. {4 {{ {a "
+               ".. .. .. {4 {{ {{ {{ {{ {3 .. .. xx .. .. .. .. {4 {{ {{ "
+               ".. r7 .. .. r3 r5 {{ {{ {2 {8 {8 xx .. r3 r5 .. .. {5 {{ "
+               "r1 rn r1 r1 rn rn r1 r5 {4 {{ {{ xx r3 rn rn r1 r1 r1 r1 "
+               "rn rn rn rn rn rn rn rn r5 {{ {{ rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn r1 r1 rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+
+       )       
+       )
+
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        (list ; objects
+               (put (mk-monman) 0 0)
+               
+                (put (mk-windowed-door) 11 8)
+               (put (mk-windowed-door)  11 10)
+               
+                (put (guard-pt 'knight)  13 8)
+                (put (guard-pt 'knight)  13 10)
+                (put (guard-pt 'halberdier)  14 9)
+                (put (guard-pt 'crossbowman)  15 10)
+                (put (guard-pt 'crossbowman)  15 8)
+                
+               (put (spawn-pt 'cave-goblin-slinger-m) 3 7)
+               (put (spawn-pt 'cave-goblin-berserker-m) 6 12)
+               (put (spawn-pt 'cave-goblin-slinger-m) 4 11)
+               (put (spawn-pt 'cave-goblin-berserker-m) 7 8)
+               (put (spawn-pt 'troll-m) 2 8)
+        )
+
+        (list
+                'on-entry-to-dungeon-room
+               'voidgap-room-handle-start
+               ) ;; hooks
+ (list  ;; edge entrances
+  (list northwest 18 14)
+  (list southwest 18 6)
+  )
+ )
+
+(mk-place-music p_voidgap_entrance 'ml-castle)
+(kern-mk-place 
+       'p_voidgap_exit
+       "Tunnels at Voidgap"
+       s_dungeon          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+       (list
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn r8 r8 rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rc .. .. ra r8 r8 rn rn rn r8 r8 r8 r8 r8 r8 r8 rn "
+               "r8 rc .. .. {4 {{ {{ {{ ra r8 rc {{ {{ {{ {2 bb .. .. ra "
+               ".! .. .. .. .. {1 {5 {{ {{ {{ {{ {{ {{ {{ {2 .. .. .. .. "
+               ".! .! .. .. .. .. .. {1 {5 {{ {{ rf {{ {3 .. .. .. .. .. "
+               ".. .. .. .. .. .. .. bb .. {1 {5 {{ {3 .. .. .. .. .. .. "
+               ".! .. .. .. .. .. .. .. .. .. .. {1 .. .. .. .. .. .. .. "
+               ".! .. .. .. .. .. .. .. .. .. .. .. .. .. bb .. .. .. .. "
+               ".. .! .. bb .. .. .. .. .. rf .. .. .. .. .. .. .. .. .. "
+               ".! .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "{8 {8 {8 .. .. .. .. bb .. .. .. .. .. .. .. .. .. .. .. "
+               "{{ {{ {{ {2 .. .. .. .. .. .. .. .. .. .. .. .. bb .. .. "
+               "{{ {3 {1 .. .. r3 r5 .. .. .. r3 r5 .. .. .. r3 r5 .. .. "
+               "r5 .. r3 r1 r1 rn rn r1 r1 r1 rn rn r1 r1 r1 rn rn r1 r1 "
+               "rn r1 rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+               "rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn rn "
+
+       )       
+       )
+
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        nil ; objects
+        (list
+               'voidgap-room-handle-end
+               ) ;; hooks
+ (list  ;; edge entrances
+  (list northeast 0 14)
+  (list southeast 0 5)
+  )
+ )
+
+(mk-place-music p_voidgap_exit 'ml-dungeon-adventure)
+
+
+(kern-mk-place 
+       'p_voidgap_1
+       "Voidgap Tunnels"
+        nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+       nil; objects
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'voidgap-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+
+ (kern-mk-place 
+       'p_voidgap_2
+       "Voidgap Tunnels"
+       nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        nil
+        (list
+               ;'on-entry-to-dungeon-room
+               'voidgap-room-handle-deeps
+       ) ;; hooks
+       nil
+)
+   (kern-mk-place 
+       'p_voidgap_3
+       "Voidgap Tunnels"
+        nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        nil
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'voidgap-room-handle-deeps
+       ) ;; hooks
+       nil
+ )
+   (kern-mk-place 
+       'p_voidgap_4
+       "Voidgap Tunnels"
+        nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        nil
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'voidgap-room-handle-deeps
+       ) ;; hooks
+       nil
+ )
+ (kern-mk-place 
+       'p_voidgap_5
+       "Voidgap Tunnels"
+         nil          ; sprite
+       (kern-mk-map nil 19 19 pal_expanded
+               (list
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn rc .. .. .. .. .. .. .. .. .. ra rn rn rn rn "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "r8 r8 rc .. .. .. .. .. .. .. .. .. .. .. .. .. ra r8 r8 "
+               ".. .. .. .. .. .. .A .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               ".. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. "
+               "r1 r1 r5 .. .. .. .. .. .. .. .. .. .. .. .. .. r3 r1 r1 "
+               "rn rn rn .. .. .. .. .. .. .. .. .. .. .. .. .. rn rn rn "
+               "rn rn rn rn r5 .. .. .. .. .. .. .. .. .. r3 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               "rn rn rn rn r4 .. .. .. .. .. .. .. .. .. r2 rn rn rn rn "
+               )
+       )
+        #f              ; wraps
+        #t              ; underground
+        #f              ; large-scale (wilderness)
+        #f              ; tmp combat place
+        nil ; subplaces
+        nil ; neighbors
+        nil
+        
+        (list
+               ;'on-entry-to-dungeon-room
+               'voidgap-room-handle-deeps
+       ) ;; hooks
+       nil
+ )
+
+
+(mk-place-music p_voidgap_1 'ml-dungeon-adventure)
+(mk-place-music p_voidgap_2 'ml-dungeon-adventure)
+(mk-place-music p_voidgap_3 'ml-dungeon-adventure)
+(mk-place-music p_voidgap_4 'ml-dungeon-adventure)
+(mk-place-music p_voidgap_5 'ml-dungeon-adventure)
+
+(prmap-linkrooms-2d 'p_voidgap_1 'p_voidgap_2 'p_voidgap_3 'p_voidgap_4 'p_voidgap_5)
+
+(prmap-set-mapdata p_voidgap_1 (prmap-mk-mapdata "voidgap" voidgap-random-type-ns voidgap-random-type-ew voidgap-random-type-area 'deep-terrain-edges 'deep-terrain-area 'deep-room-blitstats 'voidgap-room-custom-hardlinks))
+
+(let ((voidgap-hardlinks (prmap-params-hardlinks (prmap-get-mapdata p_voidgap_1))))
+       (define (link-rm xloc yloc zloc dir target maptemplate passable )
+               (prmap-room-hardlink-set! xloc yloc zloc voidgap-hardlinks dir target maptemplate passable nil)
+               )
+               
+;;---------------------------------------------------------
+;; hardlink setup
+;; 
+;;                     x       y       z       dir             target                          template                                passable
+
+(link-rm       1       0       0       west    nil                                     'm_deeptempl_wall               #f)
+(link-rm       0       1       0       south   nil                                     'm_deeptempl_wall               #f)
+(link-rm       -1      0       0       east    'p_voidgap_entrance     'm_deeptempl_passage    #f)
+(link-rm       0       -1      0       north   nil                                     'm_deeptempl_wall               #f)
+
+(link-rm       -7      -5      0       east    nil                                     'm_deeptempl_wall               #f)
+(link-rm       -6      -4      0       south   nil                                     'm_deeptempl_wall               #f)
+(link-rm       -5      -5      0       west    'p_voidgap_exit 'm_deeptempl_passage    #f)
+(link-rm       -6      -6      0       north   nil                                     'm_deeptempl_wall               #f)
+)
+
+;;flag for checking if cohesion check still needs to be performed
+(mutable-list-set (prmap-get-mapdata p_voidgap_1) 10 #t)
\ No newline at end of file
diff --git a/worlds/haxima-1.002/walk.wav b/worlds/haxima-1.002/walk.wav
new file mode 100644 (file)
index 0000000..60f6427
Binary files /dev/null and b/worlds/haxima-1.002/walk.wav differ
diff --git a/worlds/haxima-1.002/warritrix.scm b/worlds/haxima-1.002/warritrix.scm
new file mode 100644 (file)
index 0000000..b5cf0bf
--- /dev/null
@@ -0,0 +1,193 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define warr-lvl 8)
+(define warr-species sp_ghast)
+(define warr-occ oc_warrior)
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;----------------------------------------------------------------------------
+(define (warr-mk) (list 3))
+(define (warr-must-go? gob) (= 0 (car gob)))
+(define (warr-end-conv gob) (set-car! gob (- (car gob) 1)))
+
+;;----------------------------------------------------------------------------
+;; Conv
+;; 
+;; Clarissa (known as the Warritrix) was in life a powerful female Warrior
+;; of superlative might and warcraft.  Now slain, she may be encountered
+;; as a shade, summoned by the use of the Rune of Leadership,
+;; found among her effects where her corpse lies (in the Broken Sanctuary
+;; in the Lost Halls).
+;;----------------------------------------------------------------------------
+
+;; Basics...
+(define (warr-hail knpc kpc)
+  (meet "The spectre of a calm, stately woman confronts you.")
+  (say knpc "Hail, Wanderer.")
+  (quest-data-update 'questentry-warritrix 'found 1)
+  (quest-data-icon! 'questentry-warritrix 's_ghost)
+  (quest-data-complete 'questentry-warritrix)
+  )
+
+(define (warr-name knpc kpc)
+  (say knpc "I was Clarissa, known to many as the Warritrix.")
+  )
+
+(define (warr-join knpc kpc)
+  (say knpc "Would that we had met in life!")
+  )
+
+(define (warr-job knpc kpc)
+  (say knpc "To serve justice. Do you the same?")
+  (if (yes? kpc)
+      (begin
+        (say knpc "To serve justice you must know what is just. "
+             "I was ordered to explore these caves completely, "
+             "and when my party was weak from fighting off monsters, "
+             "we were ambushed by Accursed assassins, and all slain. "
+             "Tell me, is it just to avenge my death on my betrayers?")
+        (yes? kpc)
+        (say knpc "Justice hastens not to punish, but rather to reward. "
+             "Betrayers will be rewarded with ruin, "
+             "schemers and plotters will bring their own downfall, "
+             "those who seek power will be powerless in their hour of need. "
+             "Do not avenge me, but rather seek the truth.")
+        )
+      (say knpc "Injustice is served well by inaction."))
+  )
+
+(define (warr-trut knpc kpc)
+  (say knpc "To find the truth, you must find evidence."))
+
+(define (warr-warr knpc kpc)
+  (say knpc "It was a title I bore to gratify others. "
+       "In truth, I was just another paladin."))
+
+(define (warr-evid knpc kpc)
+  (say knpc "The wrogues are masters of finding what others try to hide, "
+       "and the MAN is master of all wrogues.")
+       (quest-wise-subinit 'questentry-the-man)
+       (quest-data-update 'questentry-the-man 'common 1)
+       )
+
+(define (warr-wise knpc kpc)
+  (say knpc "The Wise are deceived and divided in their opinions. "
+       "The Accursed have done their work well."))
+
+(define (warr-bye knpc kpc)
+  (if (warr-must-go? (gob knpc))
+      (begin
+        (say knpc "We will not meet again, Wanderer.")
+        (kern-log-msg "The spirit vanishes.")
+        (kern-obj-remove knpc))
+      (begin
+        (say knpc "Have you asked me all you need to know?")
+        (if (yes? kpc)
+            (say knpc "Know that I must go soon, I am called to the Void.")
+            (say knpc "Then I will try to remain a bit longer.")
+            )
+        (warr-end-conv (gob knpc)))))
+
+;; Quest-related
+(define (warr-rune knpc kpc)
+  (say knpc "You may keep the Rune. I know not its purpose. I have carried it "
+       "all these years in honour of King Clovis, my godfather, "
+       "who gave it to me."))
+
+(define (warr-clov knpc kpc)
+  (say knpc "King Clovis carried a Rune of his own. He fell in battle during the "
+       "Goblin Wars and the Rune was lost. Do you wish to find it?")
+  (if (yes? kpc)
+               (begin
+      (say knpc "If anyone knows where it is, it would be the goblins. "
+           "Go to Green Tower and seek out Gen. Ask him of ^c+mClovis^c-.")
+               (quest-data-update 'questentry-rune-f 'gen 1)
+        (quest-data-assign-once 'questentry-rune-f)
+           )
+      (say knpc "If you do, ask me now, for like all who are dead I am pulled "
+           "to the Void, and cannot resist for long."
+           ))
+  )
+
+(define (warr-just knpc kpc)
+  (say knpc "Justice is the only ideal which needs no theory "
+       "or philosophy or deity to uphold it. It is the undeniable, "
+       "irresistible ideal."))
+
+(define (warr-absa knpc kpc)
+  (say knpc "The Stewardess ordered the destruction of Absalot under the "
+       "pretense that it spread Accursed practices. "
+       "But is not the lust for power a true sign of one Accursed?")
+  (yes? kpc)
+  (say knpc "Indeed it is.")
+  )
+
+(define (warr-void knpc kpc)
+  (say knpc "All spirits are Wanderers in the Void."))
+
+(define (warr-assa knpc kpc)
+  (say knpc "They were expecting us, although no one knew we were here "
+       "except the Stewardess of Glasdrin and Commander Jeffries."))
+
+(define (warr-jeff knpc kpc)
+  (say knpc "The silver deeds of noble youth are tarnished by the guilt of "
+       "age. Better is one who striving, dies, than a hero ruined "
+       "by success."))
+
+(define (warr-powe knpc kpc)
+  (say knpc 
+       "Those who see an enemy in every face can never have enough power, "
+       "but the fearless hold it in contempt."))
+
+(define warr-conv
+  (ifc basic-conv
+
+       ;; basics
+       (method 'hail warr-hail)
+       (method 'bye  warr-bye)
+       (method 'job  warr-job)
+       (method 'name warr-name)
+       (method 'join warr-join)
+       
+       (method 'rune warr-rune)
+       (method 'clov warr-clov)
+       (method 'just warr-just)
+       (method 'absa warr-absa)
+       (method 'stew warr-absa)
+       (method 'warr warr-warr)
+       (method 'evid warr-evid)
+       (method 'wise warr-wise)
+       (method 'void warr-void)
+       (method 'trut warr-trut)
+       (method 'assa warr-assa)
+       (method 'jeff warr-jeff)
+       (method 'powe warr-powe)
+       ))
+
+(define (mk-warritrix)
+  (bind 
+   (kern-mk-char 
+    'ch_warr           ; tag
+    "Warritrix"        ; name
+    warr-species         ; species
+    warr-occ              ; occ
+    s_ghost     ; sprite
+    faction-men      ; starting alignment
+    10 0 10            ; str/int/dex
+    5 2              ; hp mod/mult
+    5 2              ; mp mod/mult
+    max-health ; hp
+    -1                   ; xp
+    max-health ; mp
+    0  ;; AP_per_turn
+    warr-lvl
+    #f               ; dead
+    'warr-conv         ; conv
+    nil              ; schedule
+    nil              ; special ai
+    nil              ; container
+    nil              ; readied
+    )
+   (warr-mk)))
diff --git a/worlds/haxima-1.002/weather-vane.scm b/worlds/haxima-1.002/weather-vane.scm
new file mode 100644 (file)
index 0000000..aadba1a
--- /dev/null
@@ -0,0 +1,18 @@
+;; A weather vane points away from the wind direction
+
+(define (weather-vane-exec kobj)
+  (kern-obj-set-facing kobj
+                       (kern-get-wind)))
+
+(define weather-vane-ifc
+  (ifc '()
+       (method 'exec weather-vane-exec)
+       ))
+
+;; Make a kernel portcullis type
+(mk-obj-type 't_weather_vane "weather vane" s_weather_vane layer-mechanism
+             weather-vane-ifc)
+
+;; Define a constructor
+(define (mk-weather-vane)
+  (kern-mk-obj t_weather_vane 1))
diff --git a/worlds/haxima-1.002/westpass.scm b/worlds/haxima-1.002/westpass.scm
new file mode 100644 (file)
index 0000000..0788d4c
--- /dev/null
@@ -0,0 +1,39 @@
+(mk-tower
+ 'p_westpass "Westpass"
+       (list
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {a tt tt || || || || || || "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ {{ tt tt || || || || || || "
+               "^^ ^^ ^^ {{ bb && bb {{ ^^ ^^ {{ tt tt || || || || || || "
+               "^^ ^^ {{ {3 .. .. .. {5 {{ ^^ {C ta tt tt || || || || || "
+               "^^ ^^ {{ {2 .. .. .. .. {5 {{ bb t% tt tt tt || || || || "
+               "^^ ^^ bb .. .. .. .. .. .. bb {A {2 ta tt tt tt || || || "
+               "^^ ^^ ^5 bb {8 .. .. .. .. .. bb .. t% ta tt tt tt tt tt "
+               "^^ ^^ ^^ ^^ {{ {a .. .. .. .. bb .. .. t% ta tt tt tt tt "
+               "^^ ^^ ^^ ^^ bb {{ {2 .. .. bb .. .. .. .. .. .. .. .. .. "
+               "^^ ^^ ^^ ^^ bb {A {2 .. .. /c /d /d /d /d /d /d /d /d /d "
+               "^^ ^^ ^^ ^^ bb bb .. .. .. bb .. .. .. .. .. .. .. .. .. "
+               "^^ ^^ ^^ {{ {{ {2 .. .. .. .. bb .. .. tC t3 tt tt tt tt "
+               "^^ ^^ {{ {3 {1 .. .. .. {8 .. bb .. tC t3 tt tt tt tt tt "
+               "^^ {{ {3 .. .. .. .. bb ^^ bb {& tC t3 tt tt tt || || || "
+               "^^ {{ {2 .. .. .. {4 {{ ^^ {{ {{ t3 tt tt tt || || || || "
+               "^^ {{ {a .. .. .. {c {{ ^^ ^^ {{ ta tt tt || || || || || "
+               "^^ {{ {{ {a {8 {c {{ ^^ ^^ ^^ {{ {% tt || || || || || || "
+               "^^ ^^ {{ {{ {{ {{ ^^ ^^ ^^ ^^ {{ {{ tt || || || || || || "
+               "^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ {{ tt || || || || || || "
+       )
+              (list ; edge entrances
+               (list southwest 12 0)
+               (list northwest 12 18)
+               )
+ (put (mk-ladder-down 'p_eastpass 14 9) 4 14)
+ (put (guard-pt 'ranger) 9 7)
+ (put (guard-pt 'ranger) 9 11)
+ (put (guard-pt 'ranger) 5 4)
+ (put (guard-pt 'ranger) 4 12)
+
+ (put (spawn-pt 'forest-goblin-stalker) 11 8)
+ (put (spawn-pt 'forest-goblin-hunter)  11 9)
+ (put (spawn-pt 'forest-goblin-stalker) 11 10)
+ )
+
+(mk-place-music p_westpass 'ml-castle)
diff --git a/worlds/haxima-1.002/wind-bridge.scm b/worlds/haxima-1.002/wind-bridge.scm
new file mode 100644 (file)
index 0000000..c2ec0f8
--- /dev/null
@@ -0,0 +1,105 @@
+;; A wind bridge appears to rotates in the wind. It blits a map to lay down the
+;; bridge terrain. Position the object in the upper left corner of where the
+;; bridge map should be blitted. The bridge will delay a few turns before
+;; turning, giving the player some time to get to safety.
+
+(kern-mk-map
+ 'm_wind_bridge_ns 9 9 pal_expanded
+ (list
+  "vv vv vv vv ee vv vv vv vv "
+  "vv vv vv vv ee vv vv vv vv "
+  "vv vv vv vv ee vv vv vv vv "
+  "vv vv vv ee ee ee vv vv vv "
+  "vv vv vv ee oo ee vv vv vv "
+  "vv vv vv ee ee ee vv vv vv "
+  "vv vv vv vv ee vv vv vv vv "
+  "vv vv vv vv ee vv vv vv vv "
+  "vv vv vv vv ee vv vv vv vv "
+  ))
+
+(kern-mk-map
+ 'm_wind_bridge_ew 9 9 pal_expanded
+ (list
+  "vv vv vv vv vv vv vv vv vv "
+  "vv vv vv vv vv vv vv vv vv "
+  "vv vv vv vv vv vv vv vv vv "
+  "vv vv vv ee ee ee vv vv vv "
+  "ee ee ee ee oo ee ee ee ee "
+  "vv vv vv ee ee ee vv vv vv "
+  "vv vv vv vv vv vv vv vv vv "
+  "vv vv vv vv vv vv vv vv vv "
+  "vv vv vv vv vv vv vv vv vv "
+  ))
+
+(define (wind-bridge-mk) (list here 0))
+(define (wind-bridge-facing gob) (car gob))
+(define (wind-bridge-delay gob) (cadr gob))
+(define (wind-bridge-set-facing! gob val) (set-car! gob val))
+(define (wind-bridge-inc-delay! gob) (set-car! (cdr gob) (+ 1 (cadr gob))))
+(define (wind-bridge-reset-delay! gob) (set-car! (cdr gob) 0))
+
+(define (wind-bridge-exec kobj)
+  (let ((wind (kern-get-wind))
+        (gob (gob kobj))
+        (loc (kern-obj-get-location kobj))
+        )
+     (define (check-fall offset)
+               (map chasm-fall (kern-get-objects-at (mk-loc (loc-place loc)
+                            (+ (loc-x loc) (car offset))
+                            (+ (loc-y loc) (cadr offset))))
+               ))
+    ;;(println "wind=" wind "gob=" gob "loc=" loc)
+     (define (turn amap dir)
+      (cond ((< (wind-bridge-delay gob) 2)
+             (kern-log-msg "The bridge creaks in the wind!")
+             (wind-bridge-inc-delay! gob))
+            (else
+             (kern-blit-map (kern-place-map (loc-place loc))
+                            (loc-x loc)
+                            (loc-y loc)
+                            amap 0 0 9 9)
+             (map check-fall
+               (list
+                       (list 4 0)
+                       (list 4 1)
+                       (list 4 2)
+                       (list 4 6)
+                       (list 4 7)
+                       (list 4 8)
+                       (list 0 4)
+                       (list 1 4)
+                       (list 2 4)
+                       (list 6 4)
+                       (list 7 4)
+                       (list 8 4)
+                                       )                       
+                                       )
+             (wind-bridge-set-facing! gob dir)
+             (wind-bridge-reset-delay! gob)
+             )))
+    (cond ((and (or (= wind north)
+                    (= wind south))
+                (not (= (wind-bridge-facing gob) north)))
+           (turn m_wind_bridge_ns north)
+           )
+          ((and (or (= wind east)
+                    (= wind west))
+                (not (= (wind-bridge-facing gob) east)))
+           (turn m_wind_bridge_ew east)
+           )
+          (else
+           (wind-bridge-reset-delay! gob)
+          ))))
+
+(define wind-bridge-ifc
+  (ifc '()
+       (method 'exec wind-bridge-exec)
+       ))
+       
+;; Make a kernel portcullis type
+(mk-obj-type 't_wind_bridge nil nil layer-mechanism wind-bridge-ifc)
+
+;; Define a constructor
+(define (mk-wind-bridge)
+  (bind (make-invisible (kern-mk-obj t_wind_bridge 1))
+        (wind-bridge-mk)))
diff --git a/worlds/haxima-1.002/wind_1a.wav b/worlds/haxima-1.002/wind_1a.wav
new file mode 100644 (file)
index 0000000..62abc3d
Binary files /dev/null and b/worlds/haxima-1.002/wind_1a.wav differ
diff --git a/worlds/haxima-1.002/yellow-slime.scm b/worlds/haxima-1.002/yellow-slime.scm
new file mode 100644 (file)
index 0000000..542eb01
--- /dev/null
@@ -0,0 +1,17 @@
+(define range-of-acid-spray 2) ;; dup of arms table entry
+
+(define (attack-a-target-with-acid-spray kchar hostiles)
+  ;(display "attack-a-target-with-acid-spray")(newline)
+  (and (<= (distance kchar (car hostiles)) range-of-acid-spray)
+       (begin
+         (kern-char-attack kchar t_acid_spray (car hostiles))
+         #t)))
+
+(define (yellow-slime-ai kchar)
+  ;(display "yellow-slime-ai")(newline)
+  (let ((hostiles (all-visible-hostiles kchar)))
+    ;(display "hostile: ")(display hostiles)(newline)
+    (if (null? hostiles)
+        #f
+        (or (ai-summon kchar summon-slimes)
+            (attack-a-target-with-acid-spray kchar hostiles)))))
diff --git a/worlds/haxima-1.002/zane.scm b/worlds/haxima-1.002/zane.scm
new file mode 100644 (file)
index 0000000..7e099e3
--- /dev/null
@@ -0,0 +1,186 @@
+;;----------------------------------------------------------------------------
+;; Constants
+;;----------------------------------------------------------------------------
+(define zane-start-lvl 8)
+
+;;----------------------------------------------------------------------------
+;; Schedule
+;;
+;; The schedule below is for the place "Enchanter's Tower Ground Floor"
+;;----------------------------------------------------------------------------
+(kern-mk-sched 'sch_zane
+               (list 0  0  enchtwr-zane-bed        "sleeping")
+               (list 6  0  enchtwr-campsite        "idle")
+               (list 8  0  enchtwr-dining-room-1   "eating")
+               (list 9  0  enchtwr-campsite        "idle")
+               (list 12 0  enchtwr-dining-room-1   "eating")
+               (list 13 0  enchtwr-hall            "idle")
+               (list 19 0  enchtwr-dining-room-1   "eating")
+               (list 20 0  enchtwr-dining-room     "idle")
+               (list 21 0  enchtwr-campsite        "idle")
+               (list 22 0  enchtwr-zane-bed        "sleeping")
+               )
+
+;;----------------------------------------------------------------------------
+;; Gob
+;;
+;; Quest flags, etc, go here.
+;;----------------------------------------------------------------------------
+(define (zane-mk) nil)
+
+;;----------------------------------------------------------------------------
+;; Conv
+;;
+;; Zane is a ranger of the Fens. He camps at the Enchanter's Tower,
+;; where he sells various outdoorsman gear needful for questing among 
+;; the poisonous swamps of the region.
+;;----------------------------------------------------------------------------
+(define zane-merch-msgs
+  (list nil ;; closed
+        "I don't trust those town armories. I make my own equipment. Lemme show you what I got." ;; buy
+        nil ;; sell
+        nil ;; trade
+        "Watch your step out there." ;; bought-something
+        "Suit yourself, bub." ;; bought-nothing
+        nil
+        nil
+        nil
+        nil
+        ))
+
+(define zane-catalog
+  (list
+   ;; reagents
+   (list ginseng        (* 5 reagent-price-mult) "This stuffs good for healing.")
+   (list garlic         (* 4 reagent-price-mult) "You gotta have garlic for warding.")
+   (list blood_moss     (* 6 reagent-price-mult) "Hard to find this stuff.")
+   (list nightshade     (* 8 reagent-price-mult) "This only grows in really damp places.")
+   (list mandrake       (* 10 reagent-price-mult) "All the powerful spells require these guys.")
+   
+   ;; potions
+   (list t_heal_potion            21 "This stuff really helps in emergencies.")
+   (list t_cure_potion            21 "Even the best get poisoned sometimes. You gotta carry extra of these guys.")
+   (list t_poison_immunity_potion 21 "If you know you have to cross poisonous terrain, drink one of these first.")
+   
+   ;; bows, arrows and bolts 
+   ;; (as an accomplished Ranger, he is also a bowyer and fletcher)
+   (list t_self_bow    30 "This little guy is lightweight and rapid fire.")
+   (list t_bow         90 "The basic bow is the perfect all-around weapon. Cheap, light, with good range.")
+   (list t_long_bow   300 "These are perfect for hunting fast game in the open.")
+   (list t_great_bow  700 "The paladin's worst nightmare. This baby will take out armored troops at long range.")
+   
+   (list t_arrow        2 "I make these special, but I can part with a quiverful.")
+   (list t_bolt         2 "I make crossbow bolts to trade with town militias.")
+   ))
+
+(define (zane-trade knpc kpc) (conv-trade knpc kpc "buy" zane-merch-msgs zane-catalog))
+
+(define (zane-ench knpc kpc)
+  (say knpc "Yeah, he's locked himself inside, see. "
+       "He doesn't need people interrupting "
+       "him all the time. If you're serious, you'll find a way in."))
+
+(define (zane-fens knpc kpc)
+  (say knpc "You're right in the middle of 'em, bub. They can be dangerous, "
+       "so watch yourself."))
+  
+(define zane-conv
+  (ifc ranger-conv
+       ;; default if the only "keyword" which may (indeed must!) be longer than
+       ;; 4 characters. The 4-char limit arises from the kernel's practice of
+       ;; truncating all player queries to the first four characters. Default,
+       ;; on the other hand, is a feature of the ifc mechanism (see ifc.scm).
+       (method 'default (lambda (knpc kpc) (say knpc "Ask somebody else.")))
+       (method 'hail (lambda (knpc kpc) (say knpc "[He nods]")))
+       (method 'bye (lambda (knpc kpc) (say knpc "Be seeing ya, buddy")))
+       (method 'job (lambda (knpc kpc) 
+                      (say knpc "I'm a Ranger. I patrol the Fens.")))
+       (method 'name (lambda (knpc kpc) (say knpc "Zane.")))
+       (method 'join (lambda (knpc kpc) 
+                       (say knpc "Sorry, bub, I already got a job to do.")))
+       (method 'ench zane-ench)
+       (method 'fens zane-fens)
+       (method 'dang
+               (lambda (knpc kpc)
+                 (say knpc "Poisonous and teeming with monsters. "
+                      "You planning to spend much time in them?")
+                 (if (kern-conv-get-yes-no? kpc)
+                     (begin
+                       (say knpc "You'll want the poison immunity spell. "
+                            "You know it?")
+                       (if (kern-conv-get-yes-no? kpc)
+                           (say knpc "Good. I can sell you the fixin's.")
+                           (say knpc "Mix Nightshade and Garlic and chant "
+                                "Sanct Nox. I've got extra reagents I can "
+                                "sell you.")
+                           ))
+                     (say knpc "Ok")
+                     )))
+       (method 'pois
+               (lambda (knpc kpc)
+                 (say knpc "A green potion or the An Nox spell will cure "
+                      "poison.")))
+       (method 'poti
+               (lambda (knpc kpc)
+                 (say knpc "I got some extra I can sell you.")))
+       (method 'mons
+               (lambda (knpc kpc)
+                 (say knpc "Slimes, bandits and undead mostly.")))
+       (method 'reag
+               (lambda (knpc kpc)
+                 (say knpc "I collect 'em where I can. "
+                      "I can sell you my extras.")))
+       (method 'buy zane-trade)
+       (method 'sell zane-trade)
+       (method 'trad zane-trade)
+       ))
+
+;;----------------------------------------------------------------------------
+;; First-time constructor
+;;----------------------------------------------------------------------------
+(define (mk-zane-first-time tag)
+  (bind 
+   (kern-char-arm-self
+    (kern-mk-char 
+     tag ;;..........tag
+     "Zane" ;;.......name
+     sp_human ;;.....species
+     oc_ranger ;;.. .occupation
+     s_companion_ranger ;;..sprite
+     faction-men ;;..faction
+     +1 ;;...........custom strength modifier
+     0 ;;...........custom intelligence modifier
+     +1 ;;...........custom dexterity modifier
+     +1 ;;............custom base hp modifier
+     +1 ;;............custom hp multiplier (per-level)
+     0 ;;............custom base mp modifier
+     0 ;;............custom mp multiplier (per-level)
+     max-health ;;..current hit points
+     -1  ;;...........current experience points
+     max-health ;;..current magic points
+     0 ;; AP_per_turn
+     zane-start-lvl  ;;..current level
+     #f ;;...........dead?
+     'zane-conv ;;...conversation (optional)
+     sch_zane ;;.....schedule (optional)
+     'townsman-ai ;;..........custom ai (optional)
+
+     ;;..............container (and contents)
+     (mk-inventory
+      (list
+       (list 10  t_food)
+       (list 100 t_arrow)
+       (list 1   t_great_bow)
+       (list 1   t_dagger)
+       (list 1   t_sword)
+       (list 1   t_leather_helm)
+       (list 1   t_armor_leather)
+       (list 5   t_torch)
+       (list 5   t_cure_potion)
+       (list 5   t_heal_potion)
+       ))
+
+     nil ;;.........readied arms (in addition to the container contents)
+     nil ;;..........hooks in effect
+     ))
+   (zane-mk)))
diff --git a/worlds/haxima-1.002/zones.scm b/worlds/haxima-1.002/zones.scm
new file mode 100644 (file)
index 0000000..c44ab08
--- /dev/null
@@ -0,0 +1,332 @@
+(define (zone-place-tag z) (car z))
+(define (zone-x z) (cadr z))
+(define (zone-y z) (caddr z))
+(define (zone-w z) (cadddr z))
+(define (zone-h z) (list-ref z 4))
+
+;; Gregor's Hut
+(define (mk-zone x y w h) (list 'p_gregors_hut x y w h))
+(define gh-all             (mk-zone 0  0  32 32))
+(define gh-living-room     (mk-zone 10 16 7  4))
+(define gh-ilyas-room      (mk-zone 7  18 2  2))
+(define gh-ilyas-bed       (mk-zone 7  18 1  1))
+(define gh-gregors-room    (mk-zone 7  15 2  2))
+(define gh-gregors-bed     (mk-zone 7  16 1  1))
+(define gh-kitchen         (mk-zone 10 10 7  5))
+(define gh-storeroom       (mk-zone 18 10 2  5))
+(define gh-stable          (mk-zone 18 16 2  4))
+(define gh-pasture         (mk-zone 21 10 5  10))
+(define gh-graveyard       (mk-zone 29 29 3  3))
+(define gh-table-1         (mk-zone 13 11 1  1))
+(define gh-table-2         (mk-zone 13 13 1  1))
+
+;; Moongate clearing
+(define (mk-zone x y w h) (list 'p_moongate_clearing x y w h))
+(define mgc-roadbend  (mk-zone 10 20 3 3))
+(define mgc-cave      (mk-zone  1 23 6 3))
+
+;; Enchanter's Tower
+(define (mk-zone x y w h) (list 'p_enchanters_tower x y w h))
+(define enchtwr-campsite         (mk-zone  5  5  3   3))
+(define enchtwr-dining-room-1    (mk-zone  9 11  1   1))
+(define enchtwr-dining-room-2    (mk-zone 11 11  1   1))
+(define enchtwr-dining-room      (mk-zone  8  8  5   5))
+(define enchtwr-bedroom-1        (mk-zone 18 11  5   2))
+(define enchtwr-hall             (mk-zone 11 18  9   6))
+(define enchtwr-ench-bed         (mk-zone 21 11  1   1))
+(define enchtwr-zane-bed         (mk-zone  7  6  1   1))
+
+;; Bole
+(define (mk-zone x y w h) (list 'p_bole x y w h))
+(define bole-bed-kathryn  (mk-zone 31 21  1  1))
+(define bole-bedroom-thud (mk-zone 31 20  2  2))
+(define bole-bed-2        (mk-zone 38 18  1  1))
+(define bole-bed-3        (mk-zone 31 21  1  1))
+(define bole-bed-4        (mk-zone 38 21  1  1))
+(define bole-bed-may      (mk-zone 44 17  1  1))
+(define bole-bed-melvin   (mk-zone 40 17  1  1))
+(define bole-bed-bill     (mk-zone 23 19  1  1))
+(define bole-bed-hackle   (mk-zone 5  8   1  1))
+(define bole-bedroom-may  (mk-zone 40 18  5  4))
+(define bole-bills-hut    (mk-zone 20 15  4  5))
+(define bole-courtyard    (mk-zone 24 25  5  5))
+(define bole-dining-hall  (mk-zone 31 23  5  7))
+(define bole-hackles-hut  (mk-zone 5   8  5  5))
+(define bole-hackles-yard (mk-zone 2   3  5 13))
+(define bole-kitchen      (mk-zone 39 23  3  7))
+(define bole-n-woods      (mk-zone 22  0  8 11))
+(define bole-table-1      (mk-zone 32 26  1  1))
+(define bole-table-2      (mk-zone 34 26  1  1))
+(define bole-table-3      (mk-zone 34 27  1  1))
+(define bole-table-4      (mk-zone 32 27  1  1))
+
+;; Trigrave
+(define (mk-zone x y w h) (list 'p_trigrave x y w h))
+(define trigrave-chants-bed      (mk-zone 12  6   1  1))
+(define trigrave-forge           (mk-zone 25  4   5  5))
+(define trigrave-jims-bed        (mk-zone 25 10   1  1))
+(define trigrave-tavern-hall     (mk-zone 18 23   8  6))
+(define trigrave-tavern-kitchen  (mk-zone 27 25   3  5))
+(define trigrave-miggs-bed       (mk-zone 27 22   1  1))
+(define trigrave-tavern-table-1a (mk-zone 19 23   1  1)) 
+(define trigrave-tavern-table-1d (mk-zone 21 23   1  1)) 
+(define trigrave-tavern-table-3a (mk-zone 19 27   1  1)) 
+(define trigrave-tavern-table-3b (mk-zone 21 27   1  1)) 
+(define trigrave-inn-counter     (mk-zone  5  4   9  3))
+(define trigrave-gwens-bed       (mk-zone 12  2   1  1))
+(define trigrave-gwens-room      (mk-zone 11  2   2  3))
+(define trigrave-inn-room-1      (mk-zone  2  6   2  2))
+(define trigrave-inn-room-2      (mk-zone  2  9   2  2))
+(define trigrave-inn-room-3      (mk-zone 11  6   2  2))
+(define trigrave-inn-room-4      (mk-zone 11  9   2  2))
+(define trigrave-east-west-road  (mk-zone  0 15  32  3))
+(define trigrave-earls-bed       (mk-zone  2  9   1  1))
+(define trigrave-earls-counter   (mk-zone  2 24   5  1))
+(define trigrave-earls-room      (mk-zone  2  9   2  2))
+
+;; Oparine
+(define (mk-zone x y w h) (list 'p_oparine x y w h))
+(define alkemist-shop    (mk-zone  3 28 4 3))
+(define alkemist-bed     (mk-zone  5 22 1 1))
+(define alkemist-bedroom (mk-zone  5 22 3 3))
+(define bilge-water-counter    (mk-zone 21  4  5  1))
+(define bilge-water-storage    (mk-zone 19  2  1  3))
+(define bilge-water-bedroom    (mk-zone 27  2  2  3))
+(define bilge-water-bed        (mk-zone 27  2  1  1))
+(define bilge-water-hall       (mk-zone 22  6  3  7))
+(define bilge-water-seat-1     (mk-zone 19  7  1  1))
+(define bilge-water-seat-2     (mk-zone 20  7  1  1))
+(define bilge-water-seat-3     (mk-zone 21  7  1  1))
+(define bilge-water-seat-4     (mk-zone 19  9  1  1))
+(define bilge-water-seat-5     (mk-zone 20  9  1  1))
+(define bilge-water-seat-6     (mk-zone 21  9  1  1))
+(define bilge-water-seat-7     (mk-zone 10 10  1  1))
+(define bilge-water-seat-8     (mk-zone 20 10  1  1))
+(define bilge-water-seat-9     (mk-zone 21 10  1  1))
+(define bilge-water-seat-10    (mk-zone 19 11  1  1))
+(define bilge-water-seat-11    (mk-zone 20 11  1  1))
+(define bilge-water-seat-12    (mk-zone 21 11  1  1))
+(define bilge-water-seat-13    (mk-zone 25  7  1  1))
+(define bilge-water-seat-14    (mk-zone 26  7  1  1))
+(define bilge-water-seat-15    (mk-zone 27  7  1  1))
+(define bilge-water-seat-16    (mk-zone 25  9  1  1))
+(define bilge-water-seat-17    (mk-zone 26  9  1  1))
+(define bilge-water-seat-18    (mk-zone 27  9  1  1))
+(define bilge-water-seat-19    (mk-zone 25 10  1  1))
+(define bilge-water-seat-20    (mk-zone 26 10  1  1))
+(define bilge-water-seat-21    (mk-zone 27 10  1  1))
+(define bilge-water-seat-22    (mk-zone 25 11  1  1))
+(define bilge-water-seat-23    (mk-zone 26 11  1  1))
+(define bilge-water-seat-24    (mk-zone 27 11  1  1))
+(define sea-witch-shop    (mk-zone  2 40  5  2))
+(define sea-witch-counter (mk-zone  3 43  3  1))
+(define sea-witch-broom   (mk-zone  3 45  3  2))
+(define sea-witch-beach   (mk-zone  3 49  3  1))
+(define sea-witch-bay     (mk-zone  2 52  5  3))
+(define sea-witch-bed     (mk-zone  3 45  1  1))
+(define sea-witch-shore   (mk-zone  3 50  3  1))
+(define cheerful-counter  (mk-zone 3 4  8  1))
+(define cheerful-room-1   (mk-zone 3 9 2  2))
+(define cheerful-room-2   (mk-zone 3 12 2  2))
+(define cheerful-room-3   (mk-zone 6 15 2  2))
+(define cheerful-room-4   (mk-zone 9 9 2  2))
+(define cheerful-room-5   (mk-zone 9 12 2  2))
+(define cheerful-bed-1   (mk-zone 3 4  1  1))
+(define cheerful-bed-2   (mk-zone 3 9  1  1))
+(define cheerful-bed-3   (mk-zone 6 15  1  1))
+(define cheerful-bed-4   (mk-zone 10 9  1  1))
+(define cheerful-bed-5   (mk-zone 10 12  1  1))
+(define oparine-innkeepers-hut   (mk-zone  3 15 2 2))
+(define oparine-innkeepers-bed   (mk-zone  4 15 1 1))
+(define black-barts-ship  (mk-zone 24 26  5  6))
+(define black-barts-broom (mk-zone 15 28  2  2))
+(define black-barts-bed   (mk-zone 15 28  1  1))
+
+;;----------------------------------------------------------------------------
+;; Glasdrin
+(define (mk-zone x y w h) (list 'p_glasdrin x y w h))
+
+;; hospital
+(define gh-ward (mk-zone 20 5 6 4))
+
+;; citadel
+(define gc-hall (mk-zone 12 4 7 7))
+(define gc-train (mk-zone 10 23 3 3))
+
+;; axe-n-shielf
+(define gas-counter (mk-zone 6 5 5 1))
+
+;; holy grail
+(define ghg-counter (mk-zone 23 26 3 1))
+(define ghg-s1 (mk-zone 24 21 1 1))
+(define ghg-s2 (mk-zone 25 22 1 1))
+(define ghg-s3 (mk-zone 25 23 1 1))
+(define ghg-s4 (mk-zone 24 24 1 1))
+(define ghg-s5 (mk-zone 23 23 1 1))
+(define ghg-s6 (mk-zone 23 22 1 1))
+(define ghg-hall (mk-zone 22 20 5 5))
+
+;; doc patch's hut
+(define gdp-hut (mk-zone 25 10 2 2))
+(define gdp-bed (mk-zone 26 10 1 1))
+
+;; palisade inn
+(define gpi-counter (mk-zone 4 19 5 1))
+
+;; beds
+(define ga-bed (mk-zone  4 13 1 1))
+(define gj-bed (mk-zone 26 13 1 1))
+(define gc-bed (mk-zone  4 10 1 1))
+(define gv-bed (mk-zone 11 14 1 1))
+(define gi-bed (mk-zone 29 28 1 1))
+(define gcj-bed (mk-zone 19 14 1 1))
+(define gjan-bed (mk-zone 1 29 1 1))
+
+;; fountain
+(define g-fountain (mk-zone 14 16 3 3))
+(define gs-altar (mk-zone 27 1 3 3))
+
+;;----------------------------------------------------------------------------
+;; Prison ('neath Glasdrin)
+(define (mk-zone x y w h) (list 'p_engineers_hut x y w h))
+(define prison-hall (mk-zone 7 2 5 5))
+
+;;----------------------------------------------------------------------------
+;; Engineer's Hut
+(define (mk-zone x y w h) (list 'p_engineers_hut x y w h))
+(define eng-bed (mk-zone 16 15 1 1))
+(define eng-workshop (mk-zone 3 3 6 9))
+
+;;----------------------------------------------------------------------------
+;; The MAN's Hideout
+(define (mk-zone x y w h) (list 'p_mans_hideout x y w h))
+(define mans-bed (mk-zone 3 3 1 1))
+(define mans-supper (mk-zone 4 15 1 1))
+(define mans-hall (mk-zone 7 6 5 7))
+(define mans-tools (mk-zone 14 2 3 3))
+(define mans-dock (mk-zone 15 13 1 1))
+
+;;----------------------------------------------------------------------------
+;; Poor House
+(define (mk-zone x y w h) (list 'p_poor_house x y w h))
+(define poorh-hall (mk-zone 4 6 5 3))
+(define poorh-dining (mk-zone 10 7 5 7))
+(define poorh-pasture (mk-zone 11 1 7 5))
+(define poorh-bunkroom (mk-zone 5 10 3 5))
+(define poorh-bed1 (mk-zone 4 10 1 1))
+(define poorh-bed2 (mk-zone 4 12 1 1))
+(define poorh-bed3 (mk-zone 4 14 1 1))
+(define poorh-bed4 (mk-zone 8 10 1 1))
+(define poorh-bed5 (mk-zone 8 12 1 1))
+(define poorh-bed6 (mk-zone 8 14 1 1))
+(define poorh-sup1 (mk-zone 12 8 1 1))
+(define poorh-sup2 (mk-zone 13 9 1 1))
+(define poorh-sup3 (mk-zone 13 10 1 1))
+(define poorh-sup4 (mk-zone 13 11 1 1))
+(define poorh-sup5 (mk-zone 12 12 1 1))
+(define poorh-sup6 (mk-zone 11 11 1 1))
+(define poorh-sup7 (mk-zone 11 10 1 1))
+(define poorh-sup8 (mk-zone 11 9  1 1))
+
+;;----------------------------------------------------------------------------
+;; Green Tower (incomplete)
+(define (mk-zone x y w h) (list 'p_green_tower x y w h))
+(define gt-ws-hall (mk-zone 46 50 12 8))
+(define gt-ws-tbl1 (mk-zone 47 52 1 1))
+(define gt-ws-tbl2 (mk-zone 49 53 1 1))
+(define gt-jorn-bed (mk-zone 20 57 1 1))
+(define gt-jorn-hut (mk-zone 21 57 4 4))
+(define gt-abe-bed (mk-zone 3 3 1 1))
+(define gt-ruins (mk-zone 6 50 7 7))
+(define doris-bed (mk-zone 58 61 1 1))
+(define abigail-bed (mk-zone 60 61 1 1))
+(define white-stag-counter (mk-zone 47 59 10 1))
+(define gt-woods (mk-zone 7 20 5 5))
+(define gt-tower (mk-zone 30 30 5 5))
+
+;;----------------------------------------------------------------------------
+;; Green Tower Lower (incomplete)
+(define (mk-zone x y w h) (list 'p_green_tower_lower x y w h))
+(define gtl-cell1 (mk-zone 8 1 2 3))
+(define gtl-jailor-bed (mk-zone 1 14 1 1))
+(define gtl-jail (mk-zone 1 1 10 14))
+
+;;----------------------------------------------------------------------------
+;; Necromancer's Lair
+(define (mk-zone x y w h) (list 'p_necromancers_lair x y w h))
+(define nl-bed (mk-zone 15 3 1 1))
+(define nl-lab (mk-zone 3 15 3 4))
+(define nl-tbl (mk-zone 9 2 1 1))
+(define nl-lib (mk-zone 15 13 3 4))
+
+;;----------------------------------------------------------------------------
+;; Old Absalot
+(define (mk-zone x y w h) (list 'p_old_absalot x y w h))
+(define oa-bed1 (mk-zone 4 8 1 1))
+(define oa-tbl1 (mk-zone 25 17 1 1))
+(define oa-tbl2 (mk-zone 27 17 1 1))
+(define oa-tbl3 (mk-zone 26 19 1 1))
+(define oa-altar (mk-zone 10 2 6 3))
+(define oa-baths (mk-zone 25 23 5 7))
+(define oa-temple (mk-zone 10 5 6 6))
+(define oa-bed2 (mk-zone 21 1 1 1))
+(define oa-bed3 (mk-zone 23 1 1 1))
+(define oa-bed4 (mk-zone 23 3 1 1))
+(define oa-bed5 (mk-zone 23 5 1 1))
+(define oa-slaves (mk-zone 1 12 6 7))
+(define oa-dining-hall (mk-zone 23 13 7 8))
+
+;;----------------------------------------------------------------------------
+;; Entrance to Kurpolis
+(define (mk-zone x y w h) (list 'p_kurpolis_entrance x y w h))
+(define ke-bed1 (mk-zone  5 17  1  1))
+(define ke-bed2 (mk-zone  7 17  1  1))
+(define ke-hall (mk-zone  1  9  3  3))
+(define ke-dine (mk-zone  5  1  9  5))
+(define ke-tbl1 (mk-zone  9  2  1  1))
+(define ke-tbl2 (mk-zone  9  4  1  1))
+(define ke-bunk (mk-zone  5 14  9  5))
+
+;;----------------------------------------------------------------------------
+;; Paladin's Hold
+(define (mk-zone x y w h) (list 'p_paladins_hold x y w h))
+(define ph-bed1 (mk-zone 13 17  1  1))
+(define ph-bed2 (mk-zone 15 17  1  1))
+(define ph-bed3 (mk-zone 17 17  1  1))
+(define ph-hall (mk-zone  4  7  5  5))
+(define ph-dine (mk-zone 10  1  9  5))
+(define ph-tbl1 (mk-zone 13  2  1  1))
+(define ph-tbl2 (mk-zone 13  4  1  1))
+(define ph-tbl3 (mk-zone 16  3  1  1))
+(define ph-medik (mk-zone 13 14 5  4))
+(define ph-arms (mk-zone   1 14 4  4))
+
+;;----------------------------------------------------------------------------
+;; Kun
+(define (mk-zone x y w h) (list 'p_kun x y w h))
+(define cantina-counter (mk-zone 4 5 3 1))
+(define cantina-counter-zzz (mk-zone 5 5 1 1))
+(define cantina (mk-zone 1 2 9 7))
+(define cantina-1 (mk-zone 3 3 1 1))
+(define cantina-2 (mk-zone 4 3 1 1))
+(define cantina-3 (mk-zone 5 3 1 1))
+(define cantina-4 (mk-zone 6 3 1 1))
+(define cantina-5 (mk-zone 7 3 1 1))
+(define cantina-6 (mk-zone 8 4 1 1))
+(define cantina-7 (mk-zone 8 5 1 1))
+(define cantina-8 (mk-zone 8 6 1 1))
+(define cantina-9 (mk-zone 3 7 1 1))
+(define cantina-10 (mk-zone 4 7 1 1))
+(define cantina-11 (mk-zone 5 7 1 1))
+(define cantina-12 (mk-zone 6 7 1 1))
+(define cantina-13 (mk-zone 7 7 1 1))
+(define cantina-14 (mk-zone 2 6 1 1))
+(define cantina-15 (mk-zone 2 5 1 1))
+(define cantina-16 (mk-zone 2 4 1 1))
+(define black-market (mk-zone 9 14 9 3))
+(define black-market-counter (mk-zone 9 16 9 3))
+(define campfire-1 (mk-zone 1 14 1 1))
+(define campfire-2 (mk-zone 2 13 1 1))
+(define campfire-3 (mk-zone 2 15 1 1))
+(define campfire-4 (mk-zone 3 14 1 1))
+(define kun-road (mk-zone 12 1 3 10))
diff --git a/worlds/haxima-1.002/ztats-quest-ui.scm b/worlds/haxima-1.002/ztats-quest-ui.scm
new file mode 100644 (file)
index 0000000..2477b32
--- /dev/null
@@ -0,0 +1,243 @@
+;; Implements the Quest Log pane of the Ztats UI
+
+(define (zqug-mk) (list nil nil 0 0 0))
+(define (zqug-dims! gob dims) (set-car! gob dims))
+(define (zqug-dims gob) (list-ref gob 0))
+(define (zqug-party! gob kparty) (set-car! (cdr gob) kparty))
+(define (zqug-party gob) (list-ref gob 1))
+(define (zqug-cur-entry gob) (list-ref gob 2))
+(define (zqug-cur-entry! gob val) (list-set-ref! gob 2 val))
+(define (zqug-max-entry! gob val) (list-set-ref! gob 3 val))
+(define (zqug-max-entry gob) (list-ref gob 3))
+(define (zqug-top-entry gob) (list-ref gob 4))
+(define (zqug-top-entry! gob val) (list-set-ref! gob 4 val))
+
+(define sprite-offset-x 40)
+(define sprite-offset-y (/ (- 32 kern-ascii-h) 2))
+(define sprite-lineheight 40)
+
+(define (zqug-store-max-entry! zqug)
+  (let ((pgob (gob (zqug-party zqug))))
+    (if (null? pgob)
+        0
+        (let ((qlst (tbl-get pgob 'quests)))
+          (if (null? qlst)
+              0
+              (zqug-max-entry! zqug (1- (length qlst)))
+              )))))
+
+(if use-quest-pane
+
+(kern-ztats-add-pane
+
+ ;; enter
+ (lambda (zqug kparty dir dims)
+   (kern-status-set-title "Quest Log")
+   (zqug-dims! zqug dims)
+   (zqug-party! zqug kparty)
+   (zqug-store-max-entry! zqug)
+   )
+
+ ;; scroll
+ (lambda (zqug dir)
+   (let* ((top (zqug-top-entry zqug))
+          (cur (zqug-cur-entry zqug))
+          (max (zqug-max-entry zqug))
+          (winh (/ (rect-h (zqug-dims zqug)) sprite-lineheight))
+          (midwin (/ winh 2))
+          (maxtop (- (1+ max) winh))
+         )
+
+     (define (up n top cur)
+       (cond ((and (> cur 0) (> n 0))
+              (if (and (> top 0)
+                       (< cur (- max midwin)))
+                  (up (1- n) (1- top) (1- cur))
+                  (up (1- n) top (1- cur)))
+              )
+             (else
+              (zqug-top-entry! zqug top)
+              (zqug-cur-entry! zqug cur)
+              )))
+
+     (define (down n top cur)
+       (cond ((and (< cur max) (> n 0))
+              (if (and (< top maxtop)
+                       (>= cur midwin))
+                  (down (1- n) (1+ top) (1+ cur))
+                  (down (1- n) top (1+ cur)))
+              )
+             (else
+             (println "down" top " " cur)
+              (zqug-top-entry! zqug top)
+              (zqug-cur-entry! zqug cur)
+              )))
+
+     (cond ((= dir scroll-up) (up 1 top cur) #t)
+           ((= dir scroll-down) (down 1 top cur) #t)
+           ((= dir scroll-pageup) (up winh top cur) #t)
+           ((= dir scroll-pagedown) (down winh top cur) #t)
+           ((= dir scroll-top)
+            (zqug-top-entry! zqug 0)
+            (zqug-cur-entry! zqug 0)
+            #t)
+           ((= dir scroll-bottom)
+            (zqug-top-entry! zqug maxtop)
+            (zqug-cur-entry! zqug max)
+            #t)
+           (else #f)
+           )))
+
+ ;; paint
+ (lambda (zqug)
+   (let* ((dims (zqug-dims zqug))
+          (pgob (gob (zqug-party zqug)))
+          (winh (/ (rect-h dims) kern-ascii-h))
+          (top (zqug-top-entry zqug))
+          (cur (zqug-cur-entry zqug))
+          )
+
+       (define (scrnprn qlst entry line)
+               (if (and (notnull? qlst)
+                       (< line winh))
+                        (if (< entry top)
+                       (scrnprn (cdr qlst) (1+ entry) line)
+                       (let* ((rect (rect-crop-down dims (* line sprite-lineheight)))
+                                                       (icon (safe-eval (qst-icon (car qlst))))
+                                                       (colorplus (cond ((qst-complete? (car qlst)) "^c+g")
+                                                                               ((qst-failed? (car qlst)) "^c+r")
+                                                                               (#t "^c+w")))
+                                                       (rect (if (null? (quest-tbl-get (car qlst) 'qparent))
+                                                                               rect
+                                                                               (rect-crop-offset rect 12 0)))
+                                               )
+                                       (if (> (rect-h rect) 0)
+                                               (begin
+                                                       (if (not (null? icon))
+                                                               (kern-screen-draw-sprite rect 0 icon)
+                                                       )
+                                                       (kern-screen-print (rect-offset rect sprite-offset-x sprite-offset-y) 0 colorplus (qst-title (car qlst)) "^c-" )
+                                                       (if (!= entry cur)
+                                                               (kern-screen-shade rect 128)
+                                                       )
+                                                       (scrnprn (cdr qlst) (1+ entry) (1+ line))
+                                               ))
+                               ))
+               ))
+     
+     (if (null? pgob)
+         (scrnprn "No Quests!")
+         (let ((qlst (tbl-get pgob 'quests)))
+           (if (not qlst)
+               (scrnprn "No Quests Yet! (But keep trying!)")
+               (scrnprn qlst 0 0)
+               )))))
+
+ ;; select proc - run the ztats quest applet
+ (lambda (zqug)
+
+   ;; ztats quest applet gob
+   (define (zqag-mk) (list nil))
+   (define (zqag-dims! zqag val) (set-car! zqag val))
+   (define (zqag-dims zqag) (car zqag))
+
+   (let* ((pgob (gob (zqug-party zqug)))
+          (qlst (tbl-get pgob 'quests))
+                        (offset-page 0)
+                               )
+     (if qlst
+         (let ((qst (list-ref qlst (zqug-cur-entry zqug))))
+
+                               (qst-status qst)
+
+           ;; paint proc - render the quest details pane
+           (define (paint zqag)
+             (let* ((rect (zqag-dims zqag))
+                    (icon (safe-eval (qst-icon qst)))
+                    (line-offset sprite-lineheight)
+                 (display-lines-available (floor (/ (- (rect-h rect) sprite-lineheight kern-ascii-h) kern-ascii-h)))
+                    (max-offset (length (qst-descr qst)))
+                    )
+               (kern-screen-erase rect)
+               (if (not (null? icon))
+                       (kern-screen-draw-sprite rect 0 icon)
+               )
+
+               (kern-screen-print (rect-down rect sprite-offset-y) kern-sp-centered "^c+c" (qst-title qst) "^c-")
+           
+               ;; set offset to sane values
+               (if (> offset-page (- max-offset display-lines-available))
+                     (set! offset-page (- max-offset display-lines-available))
+               )
+               (if (< offset-page 0)
+                     (set! offset-page 0)
+               )
+               
+                                       (let ((offset-loop offset-page))
+                               (map (lambda (line)
+                                       (if (and (eqv? offset-loop 0) (< (+ line-offset kern-ascii-h kern-ascii-h) (rect-h rect)))
+                                               (begin
+                                       (set! line-offset (+ line-offset kern-ascii-h))
+                                       (kern-screen-print (rect-down rect line-offset) 0 line )
+                                               )
+                                               (set! offset-loop (- offset-loop 1))
+                                       ))
+                                       (qst-descr qst)
+                               ))              
+
+               (kern-screen-update rect)
+               ))
+           
+           (kern-applet-run
+            
+            ;; run proc - paint & push a keyhandler that exits when player hits ESC
+            (lambda (zqag dims)
+              ;;(kern-status-set-title "Quest") //doesnt work right
+              (zqag-dims! zqag dims)
+              (paint zqag)
+              (kern-event-run-keyhandler
+               (lambda (key mod)       
+                 (cond ((or (= key kern-key-esc)
+                                                                       (= key kern-key-space)
+                                                                       (= key kern-key-return)
+                                                                       (= key kern-key-enter))
+                        #t)
+                                                               ((= key kern-key-up)
+                                                                       (if (> offset-page 0)
+                                                                               (set! offset-page (- offset-page 1))
+                                                                       )
+                                                                       (paint zqag)
+                                                                       #f
+                                                               )
+                                                               ((= key kern-key-down)
+                                                                       (set! offset-page (+ offset-page 1))
+                                                                       (paint zqag)
+                                                                       #f
+                                                               )
+                                                               ((or (= key kern-key-pgup) (= key kern-key-kp-pgup))
+                                                                       (set! offset-page (- offset-page (- (floor (/ (rect-h dims) kern-ascii-h)) 7)))
+                                                                       (if (< offset-page 0)
+                                                                               (set! offset-page 0)    
+                                                                       )
+                                                                       (paint zqag)
+                                                                       #f
+                                                               )
+                                                               ((or (= key kern-key-pgdn) (= key kern-key-kp-pgdn))
+                                                                       (set! offset-page (+ offset-page (- (floor (/ (rect-h dims) kern-ascii-h)) 7)))
+                                                                       (paint zqag)
+                                                                       #f
+                                                               )
+                       (else 
+                        #f)))))
+      
+            ;; paint
+            paint
+          
+            ;; zqa gob
+            (zqag-mk)
+            )))))
+
+ ;; zqu gob
+ (zqug-mk))
+)