"use strict";

var DEFINE_DIARY_EVENTS = {
	CHAPTER1 : {
		EARTHQUAKE : {
			requisites : function(diary){return true;},
			story: "There was another earthquake this morning.  Earthquakes are scary."
		},
		GUYS_ADVICE : {
			requisites : function(diary){return (diary.check(1,"EARTHQUAKE"));},
			story: "Guy (he's the man who has been taking care of me since they dug me out) advised that I go pray to the Goddess to settle my nerves."
		},
		SHRINEQUAKE : {
			requisites : function(diary){return (diary.check(1,"GUYS_ADVICE"));},
			story: "Rinda (she's the old lady who watches over the village shrine) prayed to the Sky Dragon on my behalf to keep me safe from earthquakes.  But then... another earthquake occurred!"
		},
		TRAPPED : {
			requisites : function(diary){return (diary.check(1,"SHRINEQUAKE"));},
			story: "Huge stones fell from the ceiling; one of them blocked the entrance!  We were trapped in the shrine!"
		},
		PUSH : {
			requisites : function(diary){return (diary.check(1,"SHRINEQUAKE")) && !(diary.check(1,"RESCUE"));},
			story: "I was able to push the rock blocking the entrance.  It was HEAVY, but eventually I got it out of the way!  Girl power!"
		},
		RESCUE : {
			requisites : function(diary){return (diary.check(1,"SHRINEQUAKE")) && !(diary.check(1,"PUSH"));},
			alternative: "PUSH",
			story: "A workman eventually rescued us, but... it was awkward."
		},
		SMOKE : {
			requisites : function(diary){return (diary.check(1,"PUSH") || diary.check(1,"RESCUE"));},
			story: "The second earthquake opened up fissures releasing strange purple smoke.  It seems to make fish violent, and now it's filling our house... with Guy trapped inside!  Rinda is old and wise; maybe she knows how to stop it?"
		},
		SHRINEQUAKE2 : {
			requisites : function(diary){return (diary.check(1,"SMOKE"));},
			story: "I have the worst luck!  Rinda sent me back to the village, but then ANOTHER earthquake occurred and we were trapped AGAIN!"
		},
		CATACOMBS : {
			requisites : function(diary){return (diary.check(1,"SHRINEQUAKE2"));},
			story: "Rinda thought the shrine's Goddess treasure might help us, and opened a secret door to the catacombs.  Catacombs?  Here?  I was excited, but a little scared!"
		},
		TRIDENT : {
			requisites : function(diary){return (diary.check(1,"CATACOMBS"));},
			story: "Just inside the catacombs I found a beautiful, sparkling trident!  This must be it!  I wonder what kind of magical powers it has?"
		},
		NOTRIDENT : {
			requisites : function(diary){return (diary.check(1,"TRIDENT"));},
			story: ". . . The trident was just a ceremonial prop.  Rinda was annoyed that I tried to take it.  How was I supposed to know??"
		},
		TREASURE : {
			requisites : function(diary){return (diary.check(1,"CATACOMBS"));},
			story: "The catacombs were full of the strange smoke I'd seen outside!  Fish exposed to it attacked me on sight, but I don't seem to be affected... I wonder why?  There were also more _HEAVY_ blocks dislodged by the earthquake.  Finding a way around them was hard, but I did use a few to my advantage!  And the treasure?  WOW!  It's a pair of bracelets which let me lift and move large objects just by raising my hands!"
		},
		HURRY : {
			requisites : function(diary){return (diary.check(1,"TREASURE"));},
			story: "Rinda says these are the 'Bracelets of the Dragon's Claw,' a magical treasure infused with the Goddess Sky Dragon's power.  That's a long name, but I don't mind, since they make those blocks SO much less annoying!  Rinda even let me borrow them to go rescue Guy!"
		},
		BOSS : {
			requisites : function(diary){return (diary.check(1,"HURRY"));},
			story: "Guy... I was... too late.  The smoke had gotten to him by the time I made it back to the village.  He went crazy just like the fish had, and began throwing boulders at everyone.  He shouted at me that it was all my fault for leaving him, but that he didn't need me anymore because the smoke had made him all-powerful, and that he hated me... I thought he couldn't make me feel any worse, but then he began trying to kill me!!  I had to defend myself, but... I ended up killing him instead.  Am I a terrible person?  Is that why I lost my memory?  As Guy was dying, he seemed confused, as if he didn't remember what was going on either.  I don't know if that made everything better or worse..."
		},
	},

	CHAPTER2 : {
		LEAVING_HOME : {
			requisites : function(diary){return (diary.check(1,"BOSS"));},
			story: "The village gate was damaged beyond repair in the earthquakes and fighting.  I felt bad defacing village property, but I needed to get it out of the way to even begin my journey.  Dragon's Strength certainly is useful.  But what is the world even like outside the village?  I wish I could remember..."
		},
		HELP_GRACIE : {
			requisites : function(diary){return (diary.check(2,"LEAVING_HOME"));},
			story: "A little girl met me just outside the gate.  She seemed really excited about something and wanted me to help.  It was hard to tell if she wanted me to help her or her mom or a tree or something else, but I followed her anyway."
		},
		HELP_MELODY : {
			requisites : function(diary){return (diary.check(2,"HELP_GRACIE"));},
			story: "The little girl's name was Grace, and her mother Melody is keeper of another shrine and treasure.  Her shrine was infested by smoke at about the same time Rinda's was.  When Melody tried to get word to the keeper of yet a third shrine, a large branch came flying out of the forest and trapped her on the beach.  It was no trouble to lift with the Bracelets, though.  We need to find out what's going on, but to explore properly, I'll need the Goddess' necklace from deep inside the Nautilus.  Leaving the water without it is EXHAUSTING!"
		},
		PORTALS : {
			requisites : function(diary){return (diary.check(2,"HELP_MELODY"));},
			story: "Something strange is going on in the Nautilus... the walls are all wrong, and there are these ghostly portals all over which seem to connect to the same place only... different?"
		},
		MET_PAOLA : {
			requisites : function(diary){return (diary.check(2,"HELP_MELODY"));}, // be nice and don't "require" PORTALS
			story: "Darkened chambers that seem to change shape around us, ghosts we can only see out of the corners of our eyes until they're right on top of us, and more of that strange purple smoke... My nerves are shot!  Gracie seems as cheerful as ever, though, especially now that we've found her ghost-friend.  I hope Paola really is just lonely, but something about her seemed too sinister to just take at face value..."
		},
		BOSS_GOOD : {
			requisites : function(diary){return (diary.check(2,"MET_PAOLA") && !diary.check(2,"BOSS_BAD"));},
			story: "My own childhood is still a confused haze, but I can't imagine playtime was ever so stressful as today!  Schoolyard games take on a whole other character when one playmate is dead already and wants nothing more than friends to keep her company in the afterlife.  I almost have to blame Paola's behavior on the smoke, though- after intervening between her and poor Gracie a few times, she settled down and made an odd comment about joining me and my friends instead.  What friends?  Are there other ghosts following me who I just can't see?  Is that why I'm so unlucky?"
		},
		BOSS_BAD : {
			requisites : function(diary){return (diary.check(2,"MET_PAOLA") && !diary.check(2,"BOSS_GOOD"));},
			alternate: "BOSS_GOOD",
			story: "I'm not in the mood to see anyone right now.  I could only watch helplessly while Paola terrorized Gracie for minutes on end in the name of fun.  Between the swimming and the fright, the poor girl's heart must have given out.  Gracie is dead.  Can I really accept the Goddess' necklace when it was purchased at such a cost?"
		},
		TREASURE : {
			requisites : function(diary){return (!diary.check(2,"BOSS_GOOD") != !diary.check(2,"BOSS_BAD"));},
			story: "I didn't feel the same sort of spontaneous empowerment upon clasping this 'Collar of the Dragon's Breath' as I did upon donning the Bracelets.  The sensation is more one of warmth and hardiness.  I could easily believe the dry breeze above water won't be nearly as biting.  I'm not seeing any physical change, but my tail also feels suddenly wound-up inside; or compressed somehow.  I can't shake the feeling that stretching it out against solid ground would feel remarkable."
		},
	},

	CHAPTER3 : {
		MET_RAVIENE : {
			requisites : function(diary){return (diary.check(2,"TREASURE"));},
			story: "I decided to follow Melody's request and investigate the great forest.  Something really must be going on, because at the outskirts I met another woman who was also looking for the Goddess' treasures.  I've never seen anyone with wings like that, so I think she must be one of the skychildren.  She can cast powerful magic, and seemed to know something about me, but became weird and flustered after one of her spells failed.  How odd...  At least she told me where the remaining treasures are!"
		},
		MET_BOBO : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE"));},
			story: "Snake woman meet chief Bobo.  Talk get I... Why am I writing in monkey?  Why am I THINKING in monkey?!  I remember my name, start feeling confident enough to speak up, and this is what happens...  Anyway, I ~think~ that if I return the seed of the Sky Tree, the chief may give up the Belt.  And that's a start."
		},
		FOUND_KEEPER : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE"));},
			story: "I found a body at the entrance to the forest shrine.  I think it was the keeper.  Unless he died suddenly of a mysterious illness in the prime of life, I have to guess Raviene was in a mood to show off again...  Does that woman have NO conscience?!  And... why do ~I~ suddenly care so much about a perfect stranger??"
		},
		DRAINED_SEED : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE"));},
			story: "If I ever meet my past self, I've got to get on her case to pay more attention in math class! ... If I ever meet my past self... heh.  Wouldn't that just be too simple?  Anyway, after puzzling around with the reservoir levels, I finally flushed the Sky Tree seed out to the monkey village.  But who designs these systems, anyway?  That was far too much work!"
		},
		BOSS : {
			requisites : function(diary){return (diary.check(3,"DRAINED_SEED"));},
			story: "I climbed up to the treetops over the monkey village to try to find Bobo, but when I did...  Oh, Goddess; if Bobo was a monster, then I must be even more of one.  The smoke had obviously affected his mind, and even more distressingly, his very physique, making him huge and grotesque.  But when he began attacking me, all I could do was fight for my life.  And, just like Guy, I... killed him.  It wouldn't have shaken me up so badly, I don't think, except that just like Guy, he seemed to come back around to sanity in his dying breaths.  Even worse, he didn't even have the Goddess' Belt on him at the time.  I suppose if I hadn't dealt with him, he might have killed others, but, I just... I just don't know.  All I can do now is keep trying to get to the bottom of this Malfose business before EVERYONE kills each other.  Or... before I kill everyone...?"
		},
		TREASURE : {
			requisites : function(diary){return (diary.check(3,"BOSS"));},
			story: "Bobo must have dropped the Belt into the lake when I wasn't watching.  I found it on top of a heap of detritus at the bottom of the reservoir drainage system.  But what to do with it?  I feel marvelously stronger after putting it on, but I'm still just a seachild- I can't jump all the way up a mountain!  Is there anywhere else I CAN get to now?"
		},
		ACTIVATED_SEED : {
			requisites : function(diary){return (diary.check(3,"TREASURE"));},
			story: "The Goddess' Belt let me climb up into a peculiar tunnel which appears to connect the drainage system of the forest temple with the ocean behind the sea village.  I met a strange old man there who said something about waking up the Sky Seed.  Should I go back and check on it?"
		},
		GROWN_SEED : {
			requisites : function(diary){return (diary.check(3,"ACTIVATED_SEED"));},
			story: "I heard the Sky Tree might grow quickly, but I never expected THIS fast!  As soon as I approached the Seed with the Goddess' Treasures, it sprouted, and almost immediately grew up to the shoulder of the mountain!  I guess this means I get to climb up to the next shrine after all."
		},
	},

	CHAPTER4 : {
		MET_RAVIENE : {
			requisites : function(diary){return (diary.check(3,"GROWN_SEED"));},
			story: "I can't say I was surprised to find Raviene waiting for me on the mountainside."
		},
		RAVIENE_EMPATH : {
			requisites : function(diary){return (diary.check(4,"MET_RAVIENE") && !diary.check(4,"RAVIENE_NEMESIS"));},
			story: "I still can't fathom her agenda, but now... I'm not even sure what my role in it is anymore.  Even with everything that's gone on, and all the terrible things I suspect her of, I wanted to hear her side before passing judgment.  I didn't know whether to expect more cold glibness, or any measure of regret, or what.  But... my concern... seemed to hurt her somehow; physically, it almost seemed.  Guy, Bobo, arguably Gracie and Paola, and now Raviene?  Is everyone just inherently sad and frustrated and hurt by the time I meet them, and I just bring it out?  Or am I... somehow more directly to blame??"
		},
		RAVIENE_NEMESIS : {
			requisites : function(diary){return (diary.check(4,"MET_RAVIENE") && !diary.check(4,"RAVIENE_EMPATH"));},
			alternate: "RAVIENE_EMPATH",
			story: "She's clearly involved in all of this somehow, but she still thinks she \"needs\" me for something.  When I pressed her for details, she got weirdly offended and flew off.  I don't like to feel I'm working for her, but I can't stop following up on this just because she wants me to do what I'm already doing.  How could I explain myself to everyone then??  I AM going to find our Goddess, and I AM going to get answers.  If Raviene likes that, fine.  If not, she can kiss my tail!"
		},
		CRETACEOUS_HAM : {
			requisites : function(diary){return (diary.check(3,"GROWN_SEED"));},
			story: "I found a truly immense pig trapped in a mountain cavern at the end of a precarious climb.  It seemed set on mauling anyone and anything in its domain, so for safety, I put it down.  But I can't let the meat go to waste..."
		},
		CRETACEOUS_HAM_LOAF : {
			requisites : function(diary){return (diary.check(4,"CRETACEOUS_HAM"));},
			story: "Beryll at the Musty Frog took the giant pig off my hands and prepared a house specialty ham loaf.  She gave me a slice, but the smell is so strong I'm afraid to touch it, let alone taste it!  Is there anyone in the world eccentric enough to actually eat this??"
		},
		LIFE_RING : {
			requisites : function(diary){return (diary.check(4,"CRETACEOUS_HAM_LOAF"));},
			story: "The keeper of the mountain shrine certainly has the \"Crazy Old Man\" part down.  He ate the whole hazardous ham slice (dear Goddess- SEVENTEEN chilis?) and gave me an old silver ring for my trouble.  I don't know what it does, but if it lets him survive that kind of cooking, it must be pretty powerful!"
		},
		TREASURE : {
			requisites : function(diary){return (diary.check(4,"RAVIENE_NEMESIS") || diary.check(4,"RAVIENE_EMPATH"));},
			story: "Apparently... I'm the Goddess' Emissary?  I met the keeper of the shrine on the mountain top, and he just gave me the Goddess' Circlet, no questions asked.  It almost seems too simple..."
		},
		MET_GABE : {
			requisites : function(diary){return ((diary.check(4,"RAVIENE_NEMESIS") || diary.check(4,"RAVIENE_EMPATH")) && !diary.check(4,"MET_GABE",true));}, // not going to swear that the jumps to skyshrine couldn't be made with a favorable tailwind
			story: "The circlet let me reach the island floating over the bay, where I met an awkward kid who got really flustered as soon as I mentioned the Emissary... I guess she really must be a big deal up here..."
		},
		LIKED_GABE : {
			requisites : function(diary){return ((diary.check(4,"RAVIENE_NEMESIS") || diary.check(4,"RAVIENE_EMPATH")) && !diary.check(4,"MET_GABE",true));},
			alternate: "MET_GABE",
			story: "I guess Raviene really is an anomaly.  When I headed to the shrine complex on the island over the bay, I was greeted by a winged boy who looked nearly my age.  Awkward, perhaps, but polite and harmless.  He seemed at a loss for words, so I ribbed him a bit, whereupon he got all flustered.  I... think he might like me?"
		},
		DISLIKED_GABE : {
			requisites : function(diary){return ((diary.check(4,"RAVIENE_NEMESIS") || diary.check(4,"RAVIENE_EMPATH")) && !diary.check(4,"MET_GABE",true));},
			alternate: "MET_GABE",
			story: "Why must all skychildren have crazy character flaws?  Raviene enjoys being obnoxious and stuck-up, Zeke up on the mountain shrine seems irresponsibly laid-back, and the very first person I met when I reached the floating island was an awkward horny adolescent geek who couldn't seem to see past my body until I mentioned why I was there."
		},
		GARBAGE_CHUTE : {
			requisites : function(diary){return diary.check(4,"MET_GABE",true);},
			story: "Anyway, I found the sky shrine, but as soon as I entered, I was caught between two columns of solid light and dropped straight into the heart of the island!  It sounded like maybe some kind of defensive ward against Malfose, but... in that case, how would ~I~ have set it off?"
		},
		HAS_KEYS : {
			requisites : function(diary){return (diary.check(4,"GARBAGE_CHUTE") && diary.check(4,"TREASURE"));}, // but if you get through the inside of the island with no circlet, something is fishy...
			story: "In the center of the sky island, I found... what I can only describe as a laboratory.  It was full of horrible equipment, runes, and a set of logbooks describing... a golem.  A new one.  Made from... no... I can't write about it."
		},
		RAVI_DIARY : {
			requisites : function(diary){return diary.check(4,"HAS_KEYS");},
			story: "There was a diary in the chamber above the Sky Shrine.  I think it was Raviene's.  I was too curious not to read it all the way through, but now... I'm honestly feeling too many different things to know what to say here.  On the one hand, the parts I least want to believe are the ones that do the best job of explaining why she knows more about me than I know about myself.  If they're really true, then... I don't want to forgive her.  But if everything else is true... I have to feel for her.  She's as inextricably tangled up in this mess as I am, and no closer to the right answers..."
		},
		BOSS : {
			requisites : function(diary){return (diary.check(4,"GARBAGE_CHUTE") && diary.check(4,"TREASURE"));},
			story: "With the front door warded, I had to work my way up through the \"purification\" mechanisms deep under the shrine to get into the sanctuary from below.  Just when I thought I was in the clear, I got caught in a second ward.  This one claimed I was full of dark energy, but that I used to be allowed through as an exceptional case.  Then it tried to build a wall on top of me.  This is supposed to be the domain of the Goddess, so why do I feel so much less safe here than anywhere else?"
		},
		NOTREASURE : {
			requisites : function(diary){return (diary.check(4,"BOSS") && !diary.check(4,"NOTREASURE",true));},
			story: "When I finally made it into the sanctuary of the Sky Shrine to speak with the High Priestess, she- Raviene- simply laughed at me and took all the Goddess' Treasures.  Without their aid, I could do nothing; barely even crawl.  The only way out led through that accursed security ward.  Relegated once again to the murky pool at the bottom of the flying island, I am alone with my thoughts.  What has this all been for??  Honestly, I'm not sure I can go on from here.  There IS nowhere left to go.  I can see now that it was only some perverse fate, someone's dark machinations, that brought me this far.  An illusion of purpose had made it all bearable- all the death, all the suffering.  But now... I want it to end."
		},
		NOTREASURE_EMPATH : {
			requisites : function(diary){return (diary.check(4,"BOSS") && !diary.check(4,"NOTREASURE",true));}, // replaces NOTREASURE
			alternate: "NOTREASURE",
			story: "I finally made it into the sanctuary of the Sky Shrine.  I would have never imagined someone like Raviene would be the High Priestess, but there she was.  She was not kind, but I can't shake the feeling that she isn't... happy... either.  Citing a grand plan that she had made me, perhaps literally, part of, she took all the Goddess' Treasures for herself.  I tried to sympathize, but she only withdrew from me.  Left to my own devices, there was only one exit I could crawl to- that accursed security ward.  Relegated once again to the murky pool at the bottom of the flying island, I am alone with my thoughts.  What has this all been for??  Honestly, I'm not sure I can go on from here.  There IS nowhere left to go.  I can see now that it was only some perverse fate, someone's dark machinations, that brought me this far.  An illusion of purpose had made it all bearable- all the death, all the suffering.  But now... I want it to end."
		},
		NOTREASURE_NEMESIS : {
			requisites : function(diary){return (diary.check(4,"BOSS") && !diary.check(4,"NOTREASURE",true));}, // replaces NOTREASURE
			alternate: "NOTREASURE",
			story: "I finally made it into the sanctuary of the Sky Shrine to speak with the High Priestess, only to discover the High Priestess is none other than that obnoxious b.../witch Raviene.  I hate her SO much.  After a long, disturbing exposition, she laughed at me and took all the Goddess' Treasures for her own crazy vendetta.  Not content simply to have won, she then forced me to crawl back over to the security trap and imprison myself.  Relegated once again to the murky pool at the bottom of the flying island, I am alone with my thoughts.  What has this all been for??  Honestly, I'm not sure I can go on from here.  There IS nowhere left to go.  I can see now that it was only some perverse fate, someone's dark machinations, that brought me this far.  An illusion of purpose had made it all bearable- all the death, all the suffering.  But now... I want it to end."
		},
		FALL : {
			requisites : function(diary){return (diary.check(4,"NOTREASURE",true));},
			story: "Simply waiting to die is interminable.  Rallying what strength I had, I made a go of escape: The path leading to the catacombs' Nadir Gate was uniformly downwards, and in theory, manageable.  Once down the first ledge, backtracking was impossible.  Successive subsequent falls quickly broke what spirit I thought I'd mustered.  Without the Goddess' protection, every hop, slip, and scramble hurt more than the last.  I did reach the Gate, and the small landing outside, but as helpless as ever and only more hopelessly injured.  Or perhaps the more correct term is \"damaged,\" after all.  Faced with challenging my immortality through prolonged exposure and blood loss, simply obliterating myself on the ground far below seemed a far more compelling prospect..."
		},
		SLEEP : {
			requisites : function(diary){return (diary.check(4,"NOTREASURE",true));},
			alternate: "FALL",
			story: "Simply waiting to die is interminable.  Rallying what strength I had, I made a go of escape: The path leading to the catacombs' Nadir Gate was uniformly downwards, and in theory, manageable.  Once down the first ledge, backtracking was impossible.  Successive subsequent falls quickly broke what spirit I thought I'd mustered.  Without the Goddess' protection, every hop, slip, and scramble hurt more than the last.  I did reach the Gate, and the small landing outside, but as helpless as ever and only more hopelessly injured.  Or perhaps the more correct term is \"damaged,\" after all.  Looking down, I found my arms giving way before I could muster the courage to make the one final lunge to what might have been oblivion.  Instead, cold, exhausted, and bloodied as I was, I closed my eyes, hoping oblivion might find me first."
		},
	},

	CHAPTER5 : {
		AWAKE : {
			requisites : function(diary){return (diary.check(4,"FALL",true));},
			story: "How am I alive?  I can't be alive... but I'm awake, and the world hasn't changed."
		},
		CHARIS_ADVICE : {
			requisites : function(diary){return (diary.check(5,"AWAKE"));},
			story: "It... sounds like I did nearly destroy myself.  But it didn't work.  Charis brought me back somehow.  Why?"
		},
		MET_GABE : {
			requisites : function(diary){return (diary.check(5,"CHARIS_ADVICE") && !diary.check(5,"MET_GABE",true));},
			story: "Nowhere to go.  Nothing to do.  I went up to the bay monument just to be out of everyone's way, but that sky acolyte found me and forced the Circlet on me again.  Raviene will probably kill us both for that.  Or at least him.  Why can't I just die instead?"
		},
		LIKED_GABE : {
			requisites : function(diary){return (diary.check(5,"CHARIS_ADVICE") && !diary.check(5,"MET_GABE",true));},
			alternate: "MET_GABE",
			story: "I'm useless, I'm a monster, and I failed everyone.  Why don't they leave me alone?  I wanted to just go somewhere and try to stop existing, but Gabe- that boy from the sky shrine- found me.  He risked his neck to return the Goddess' Circlet to me, and refused to believe that I'm only some cursed golem.  And now... I kinda don't want to let him down."
		},
		DISLIKED_GABE : {
			requisites : function(diary){return (diary.check(5,"CHARIS_ADVICE") && !diary.check(5,"MET_GABE",true));},
			alternate: "MET_GABE",
			story: "Goddess, just let me die.  I can't fix my own problems, let alone everyone else's.  I don't want to be a hero.  I don't want a Circlet that lets me be useless anywhere in the world.  Why can't everyone just leave me alone?"
		},
		MET_ZEKE : {
			requisites : function(diary){return (diary.check(5,"MET_GABE",true));},
			story: "I don't even know why I went up the mountain.  Maybe to try jumping off again.  That may be why I gave the Circlet back to Zeke, too.  It's all a haze anymore.  Nothing mattered to me at that point.  Zeke seemed to realize this, and sent me... somewhere..."
		},

		MOOD_0 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));},
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, but on a scale of one to okay, I still feel like a big zero."
		},
		MOOD_1 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, but on a scale of one to okay, I'm still at the bottom end."
		},
		MOOD_2 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, but on a scale of one to okay, I'm still only about a two."
		},
		MOOD_3 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, but on a scale of one to okay, I'm not even half way there."
		},
		MOOD_4 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, but on a scale of one to okay... I still need improvement."
		},
		MOOD_5 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, and on a scale of one to okay... well, I'm not okay, but I could be worse."
		},
		MOOD_6 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, and on a scale of one to okay... I'm not perfect, but a lot of things are better."
		},
		MOOD_7 : {
			requisites : function(diary){return (diary.check(5,"MET_ZEKE") && !diary.check(5,"MOOD_0",true));}, // replaces MOOD_0
			alternate: "MOOD_0",
			story: "I found myself in a crystal tunnel, with mirrors every few yards.  I had to look myself in the eye and answer some difficult questions.  I think it was supposed to help me find myself, and on a scale of one to okay... I think I may have worked my way up to a 7.  7 is a good number.  I'm never going to be as happy as I was before all of this started, but I think I'm in as good shape as possible under the circumstances."
		},
		BLESSING : {
			requisites : function(diary){return diary.check(5,"MOOD_0",true);},
			story: "After all the introspection, I finally met... the Goddess.  She was presenting herself as my own reflection the whole time.  Far from a grand, imposing being with all the answers, the Goddess herself is largely alone and afraid of what the world is becoming; that is to say, of what she herself is becoming.  No matter how much I'm suffering myself, I can't turn a blind eye to the suffering of someone who the entire world is in turn looking to for help.  In an ironic turn of fate, I, a despicable Malfosian golem, trailing harm in my wake, seem to be the only hope the world has left.  The Goddess has blessed me with access to all the Treasures' powers to continue my journey to Malfose, but it feels like something else is also now trying to burn its way out of me..."
		},

		BOSS : {
			requisites : function(diary){return (diary.check(5,"BLESSING",true) && !diary.check(5,"BOSS",true));},
			story: "Of course, the moment I leave the Mountain Shrine, I run into Raviene giving Gabe a lecture- Gabe is the acolyte from earlier.  I was glad to see I'm not the only one she lays into, but then she performed yet another of her horrific acts: poisoning Gabe, on the spot, with dark smoke and the same kind of one-sided self-centered vitriol I'm coming to see as Malfose's hallmark.  Zeke the shrinekeeper was able to wall Gabe in with me, but it still came down to me and my 'innate' powers of violence to subdue him.  Which... meant he as good as died afterward.  But his soul at least is where he wanted it to be, so... I should feel less bad?  I still don't, really."
		},
		BOSS_KILL : {
			requisites : function(diary){return (diary.check(5,"BLESSING",true) && !diary.check(5,"BOSS",true));},
			alternate: "BOSS",
			story: "The additional power inside me that was released when the Goddess lifted my seal... is the power to kill.  Before, I only killed people indirectly.  Today... I killed the acolyte boy.  His name was Gabe.  One kick and it was all over.  I didn't mean to- oh, Goddess, I swear I didn't mean to!  But it's exactly as he said- I am Malfose.  It doesn't matter what I want; everything I do turns to destruction.  The only thing I'll never kill is myself."
		},

		// Ch 5 2nd half

		VILLAGE_SEAL : {
			requisites : function(diary){return diary.check(5,"BOSS",true);},
			story: "The Goddess' power is waning, and my own dark power was enough to shatter the seal on the cave system below the land village.  Who knows what will be released if I fail now..."
		},
		NAUTILUS_SEAL : {
			requisites : function(diary){return diary.check(5,"BOSS",true);},
			story: "I remembered seeing a cracked Goddess seal deep within the Nautilus.  With my own dark powers, I was able to break it, revealing the hole from which darkness has no doubt been leaking into the ship..."
		},

		SEALKEY_1 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "I dissolved a Goddess Key near what must be the bottom of this labyrinth.  It MUST have released some kind of seal nearby- I could feel the energy dissipate!"
		},
		SEALKEY_2 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "A nook high in the plugged chamber beneath the village well contained a strange key with the Goddess' insignia.  It disappeared as soon as I touched it..."
		},
		SEALKEY_3 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "Dead-ends are frustrating, particularly when they're tricky to get to.  At least the far end of the upper level of the caves had a Goddess Key.  What happened to it after I touched it I'm less certain of..."
		},
		SEALKEY_4 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "After some tricky passageways in the caves' upper level, I found a chamber with a strange rock formation, a Goddess Key, and a slight air current from near the ceiling..."
		},
		SEALKEY_5 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "Either whoever placed the key I found in the middle of the cave system was a sadist, or there have been some cave-ins since it was left there."
		},
		SEALKEY_6 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "These caves would be much easier to navigate if some passages weren't walled off with stone slabs.  But I guess retrieving a key from a plugged well is easier than from a spike pit."
		},
		SEALKEY_7 : {
			requisites : function(diary){return diary.check(5,"VILLAGE_SEAL");},
			story: "Water seems to obey some bizarre and special laws down here.  But I suppose if it didn't, the Goddess Key in one odd angular chamber would have been all but inaccessible."
		},

		RAVI_SAVE : {
			requisites : function(diary){return (
					(diary.check(4,"RAVIENE_EMPATH") || diary.check(4,"NOTREASURE_EMPATH")) && // must have shown empathy
					diary.check(4,"RAVI_DIARY") && // must have read her diary (and, by extension, her lab book)
					(diary.check(5,"VILLAGE_SEAL") || diary.check(5,"NAUTILUS_SEAL")) && // must have gotten here
					!diary.check(5,"RAVI_SAVE",true) // must not have killed her already
				);},
			story: "By the time I negotiated the cave, Raviene was already there, stuck at the final seal set up to keep Malfose in.  I realized that if she couldn't get through, then I stood no chance.  So I encouraged her, and she blew up in my face### No, that's not fair.  I'm just... still a bit out of sorts.  She took, like, half my compassion because apparently it had been hers all along and offloading it onto me is what made her so horrid to begin with.  So... she's better now, I guess.  And I'll live, or whatever it is I do.  More to the point, cooperating should make the final push that much easier.  I just... is it wrong to wish I could feel sorry for her?  She's clearly been through a lot, and I feel... broken, I guess... for not caring as much as I used to..."
		},
		RAVI_ROUGH : {
			requisites : function(diary){return ((diary.check(5,"VILLAGE_SEAL") || diary.check(5,"NAUTILUS_SEAL")) && !diary.check(5,"RAVI_SAVE",true));},
			alternate: "RAVI_SAVE",
			story: "By the time I negotiated the cave, Raviene was already there, stuck at the final seal set up to keep Malfose in.  It was amusing to see her, for all her bluster, stopped by one single barrier.  But when I commented, she snapped.  I should have seen it coming, given her past.  I couldn't fault her, let alone risk killing her, so I just did what I could to stay safe until she exhausted herself and we could talk.  Whereupon she sucked out, like, half my compassion.  Ugh.  But that means she's better now, I guess.  And I'll live, or whatever it is I do.  And we can finally cooperate, which will make the last push easier.  I just... feel a bit broken now.  Like all the caring I just did must have been an act because I don’t know that I'd do it again.  And like not caring makes me a faulty human."
		},
		RAVI_KILL : {
			requisites : function(diary){return ((diary.check(5,"VILLAGE_SEAL") || diary.check(5,"NAUTILUS_SEAL")) && !diary.check(5,"RAVI_SAVE",true));},
			alternate: "RAVI_SAVE",
			story: "By the time I negotiated the cave, Raviene was already there, stuck at the final seal set up to keep Malfose in.  It was amusing to see her, for all her bluster, stopped by one single barrier.  But when I commented, she... snapped... and I had to... kill again.  Goddess, can this be the last time?  Please?  Even Ravi didn't seem to deserve it, in the end.  Like, if I'd only known more about her, if I'd only been nicer, we could have found another way..."
		},

		MALFOSE_DEAD : {
			requisites : function(diary){return diary.check(5,"RAVI_SAVE",true);},
			story: "The remaining corridors beyond the seal were surprisingly clean and well-structured.  I guess Malfose had plenty of time for housekeeping.  At the end of it all, Malfose himself.  God?  Demon?  Merely a man drunk on his own power?  The fewer of his words that are recorded for history, the better.  Simply know that he is gone.  It's over.  I can rest."
		},

	},

	CHAPTER0 : { // anytime events
		MET_DEATH : {
			requisites : function(diary){return true;},
			story: "I don't know what happened just now...  Something hit me.  It hurt a lot and everything went black.  It was so dark and cold and lonely that I thought I might have died.  I managed to follow a faint light to the surface of a strange river.  The only thing visible for miles was a cloaked figure on a small raft.  I tried to talk to him, but he said some strange things I didn't understand.  He seemed upset, though, and created some kind of door out of thin air, insisting I leave.  I went through the door and suddenly I woke up back here..."
		},

		GREY_LOC_VILLAGE : {
			requisites : function(diary){return true;},
			story: "What is that odd archway in the village?  Between Charis & Lela's house and the chief's is all solid rock from the outside..."
		},
		GREY_LOC_BAYSHRINE : {
			requisites : function(diary){return (diary.check(2,"LEAVING_HOME"));},
			story: "I was so pleased to have found a rear entrance to the collapsed bay shrine that I almost didn't think to question how, with walls collapsing into the earth, one window could open onto clear sea."
		},
		//GREY_LOC_NAUTILUS : { // retired at the end of ch4 alpha; grey doesn't really do dungeons
		//	requisites : function(diary){return (diary.check(2,"HELP_MELODY"));},
		//	story: "I got lost deep in the Nautilus in a tight, winding passage that doubled back on itself to an apparent dead-end.  But part of the hull's bracing seemed to be missing..."
		//},
		GREY_LOC_FOREST : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE"));},
			story: "I finally managed to climb into the upper branches of the forest.  This is confusing- how can a tree grow into a ring, let alone without a trunk?"
		},
		GREY_LOC_SKY : {
			requisites : function(diary){return (diary.check(4,"MET_RAVIENE"));}, // I would say TREASURE, but I know speedrunners...  if you're up there without having climbed the mountain, tho, I call shennanigans
			story: "It took me awhile to notice how this was out of place, but deep in the shade under the floating island, on the bare rock, I spotted a small tuft of grass.  How can grass grow in that kind of place?"
		},

		GREY_1 : {
			requisites : function(diary){return (diary.greyCount()==1);},
			story: "When I went to take a closer look, a strange figure in a grey coat and hat appeared out of nowhere and offered me tea.  I didn't really know what to say, so I sat down and accepted the offer.  The tea was good (the arrival of the teapot was as inexplicable as its owner's), but I don't know what to say about the conversation..."
		},
		GREY_2 : {
			requisites : function(diary){return (diary.greyCount()==2);},
			story: "My further investigation was met by that same strange grey figure from last time.  The tea and the conversation were different, and I'm still not sure I can explain either."
		},
		GREY_3 : {
			requisites : function(diary){return (diary.greyCount()==3);},
			story: "I'm beginning to accept the fact that wherever something seems out of place, I'm likely to encounter the grey stranger.  The tea we share continues to be good, but I've asked myself more than once now whether there's anything... special... in it.  How many people would come up with such elaborately irrelevant musings while sober?"
		},
		GREY_4 : {
			requisites : function(diary){return (diary.greyCount()==4);},
			story: "But of course, it was just another idiosyncrasy of environment presaging tea and philosophy with you-know-who.  Soooo much philosophy.  Is this what they call the butterfly effect?  Am I just a butterfly dreaming I'm a woman?  Can I assume anything I see and feel is real?"
		},

		GREY_CHALLENGE : {
			requisites : function(diary){return (diary.check(0,"GREY_4"));},
			story: "There are some things one does not expect to find inside a mountain.  The night sky, teleporting grey strangers, kittens, and a giant bunny are among them.  Today was duly unexpected.  But all things considered?  I think I'm glad I stopped in."
		},
	},

	SOULS :
	{
		GUY : {
			requisites : function(diary){return (diary.check(1,"BOSS"));},
			value: 1,
			story: "It was strange... when I passed the spot where Guy died, I suddenly felt stronger.  But it also felt, just briefly, like I was in his head, living his life..."
		},

		PAOLA : {
			requisites : function(diary){return (diary.check(2,"BOSS_GOOD"));},
			value: 1,
			story: "Paola had mentioned something about joining me.  Passing the spot where I last saw her, it almost feels like she has.  A small, capricious voice bubbling at the back of my head, and a fresh sense of wonder at the world..."
		},

		GOGO : {
			requisites : function(diary){return (diary.check(2,"TREASURE"));},
			value: 1,
			story: "Did I sense... a monkey?  Living deep in a cave under an island?  His own undersea castle?  Was he trying to mimic the seachildren or something?"
		},

		MELI : {
			requisites : function(diary){return (diary.check(3,"TREASURE"));},
			value: 2,
			story: "In an abandoned house at the back of the landchildren's village, I found a desk with a few notes, a bottle, and a picture.  Of me.  As soon as I picked it up, I experienced a wave of memories.  Most of them felt like my own, memories I'd simply forgotten.  I lived in the sea, but became fascinated with a ship, and eventually, one of her crew.  We became friends, maybe more, and had taken to meeting at convenient shorelines just to sit and talk.  Needless to say, it was usually just the two of us, so the day... that day... we were isolated.  The memories here get confused, as if it's both me and someone else remembering them, only differently.  It was so confusing and dissonant, so intense and graphic, that I couldn't handle the sudden recollection.  I may have thrown up a bit under the desk.  I remember clinging to someone, being carried hastily back towards the water...  Carrying someone terribly important... it felt like... tripping?  Falling?  Being dropped?  Thrown to the ground?  Terror... excruciating pain, all over... desperation...  And then, one of us... died?  I must have hit my head in the fall and passed out.  The next thing I remember is waking up in Guy's bed, with little worse than bruises, a headache, and amnesia.  I'm CERTAIN I am the girl in the picture; everything seems so fresh in my mind now.  But... the house was a wreck, the picture had years of dust and fading, and I look just the same?"
		},

		YORICK : {
			requisites : function(diary){return (diary.check(3,"FOUND_KEEPER"));},
			value: 1,
			story: "Remember when I first mentioned the strange cloaked skeletal figure on the raft?  It's dismal to mention my ending up back there, but it does seem to be where I'm fated to go when I... die?  Anyway, this one time I jump up onto his small lean-to and he absolutely loses it!  I mean, I'm just trying to be this chill, laid-back guy keeping an eye on the Goddess' water when she lets loose about magic and souls and... or... why did I just write 'guy'?  Why did I just write 'she'?  Goddess help me, I'm getting so confused these days..."
		},

		BOBO : {
			requisites : function(diary){return (diary.check(3,"BOSS"));},
			value: 1,
			story: "Something drew me to climb up to the platform where Bobo was when he attacked me and I had to...  Anyway, from that vantage, even I felt taken with a vibrant rush of primal energy.  Primal energy, but tinged with regret and frustration at... myself?  Or at someone who looked like me from the outside?  The whole thing was fleeting, but even so, that part of the sensation was unnerving enough to ruin the moment..."
		},

		GABE : {
			requisites : function(diary){return (diary.check(5,"BOSS"));},
			value: 1,
			story: "Souls... that's what I've been seeing... feeling... when anyone dies near me.  Just by getting close, I absorb their soul.  And grow stronger.  Gabe offered to come with me, in me, as a soul.  I agreed.  It still feels... profane..."
		},

		RAVIENE : {
			requisites : function(diary){return (
					(diary.check(4,"RAVIENE_EMPATH") || diary.check(4,"NOTREASURE_EMPATH")) && // must have shown empathy
					diary.check(4,"RAVI_DIARY") && // must have read her diary (and, by extension, her lab book)
					(diary.check(5,"VILLAGE_SEAL") || diary.check(5,"NAUTILUS_SEAL")) && // must have gotten here
					!diary.check(5,"RAVI_KILL") // must not have killed her already
				);},
			value: -1,
			story: "...But of course, I ~AM~ broken now.  For the first time, I'm less than I used to be.  Just like being near a free soul apparently draws it into me so I feel stronger, Ravi managed to rip something out of me leaving me weaker.  Good news for all the other souls I already imprison, but still rough for \"me.\""
		},
	},

	TEARS :
	{
		BY_CASTLE : {
			requisites : function(diary){return (diary.check(1,"TREASURE"));},
			value: 4,
			story: "I found a really pretty teardrop jewel in the castle-shaped rock behind the village.  I wonder if there are any others?"
		},
		S1_ALTAR : {
			requisites : function(diary){return (diary.check(1,"GUYS_ADVICE"));},
			value: 4,
			story: "I tried praying to the Sky Dragon at Rinda's shrine, and a pretty teardrop appeared!  I guess the Goddess really does listen!"
		},
		S1_FREEBIE : {
			requisites : function(diary){return (diary.check(1,"TREASURE"));},
			value: 4,
			story: "There was a shiny teardrop buried under a collapsed gate in Rinda's shrine.  How odd."
		},
		S2_ALTAR : {
			requisites : function(diary){return (diary.check(2,"HELP_GRACIE"));},
			value: 4,
			story: "Even though the altar in the old bay shrine was in rough shape, I felt it was appropriate to pay my respects.  The Goddess sent me another teardrop, so I guess it was a good idea."
		},
		NAUTILUS : {
			requisites : function(diary){return (diary.check(2,"HELP_MELODY"));},
			value: 4,
			story: "I thought I saw a teardrop in the back of the Nautilus, but when I tried to get to it, I found myself in some kind of horrible nightmare puzzle.  I won't be disappointed if I don't see another one for a long while..."
		},
		S3_ALTAR : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE"));},
			value: 4,
			story: "The first time I prayed at the forest shrine's water altar, the Goddess not only filled the reservoirs, but sent me a teardrop!  She is truly a generous deity."
		},
		S3_FREEBIE : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE"));},
			value: 4,
			story: "In the back room of the forest shrine, I saw something sparkling in the middle of the large wooden room numeral hanging from the ceiling.  When I realized it was one of the magical teardrops, I had to put in the extra effort to get up to it.  It was not an easy jump."
		},
		MOUNTAIN : {
			requisites : function(diary){return (diary.check(4,"RAVIENE_NEMESIS") || diary.check(4,"RAVIENE_EMPATH"));},
			value: 4,
			story: "It occurred to me that as tall as the upper cavern of the mountain was, there must be something on the face opposite the floating islands.  I'm glad I checked- nestled in a hollow in the rock, I found one of the shining teardrops!"
		},
		S4_ALTAR : {
			requisites : function(diary){return (diary.check(4,"RAVIENE_NEMESIS") || diary.check(4,"RAVIENE_EMPATH"));},
			value: 4,
			story: "The whole mountain shrine appears to be made of crystal, including the altar!  I felt closer to the Goddess than ever when I prayed, and I was rewarded with another teardrop."
		},
		S5_ALTAR : {
			requisites : function(diary){return (diary.check(4,"BOSS"));},
			value: 4,
			story: "After getting safe through the catacombs of the sky shrine, it felt appropriate to offer a quick prayer to the Goddess.  Even though this shrine may be hostile, it seems the Goddess herself is still supportive enough to grant me another teardrop."
		},
	},

	DIARIES : {
		HOME : {
			requisites : function(diary){return !(diary.check(1,"SHRINEQUAKE")) || (diary.check(1,"HURRY"));},
			room: "village_caves",
			story: "Sometimes, at the end of a long day, the best place to sleep is in your own bed."
		},
		SHRINE1 : {
			requisites : function(diary){return (diary.check(1,"GUYS_ADVICE"));},
			room: "shrine1_entrance",
			story: "The village shrine seems a safe enough place to pause and take stock of my situation."
		},
		REEF : {
			requisites : function(diary){return (diary.check(2,"HELP_GRACIE"));},
			room: "reef",
			story: "What's this funny dry room by the Nautilus for, anyway?  Do landchildren visit here?"
		},
		LANDTOWN : {
			requisites : function(diary){return (diary.check(2,"HELP_GRACIE"));},
			room: "landtown_inside",
			story: "The land village doesn't get many seachild visitors, but the townsfolk continue to be hospitable."
		},
		NAUTILUS : {
			requisites : function(diary){return (diary.check(2,"MET_PAOLA"));},
			room: "nautilus_vestibule",
			story: "I must be somewhere near the bow of the Nautilus, but it's difficult to be certain."
		},
		FOREST : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE") && !DIARY_REQPAK.C4_ESCAPE(diary));},
			room: "deep_woods",
			story: "Loving the forest.  Hating the bugs."
		},
		SHRINE3 : {
			requisites : function(diary){return (diary.check(3,"MET_RAVIENE") && !DIARY_REQPAK.C4_ESCAPE(diary));},
			room: "forestshrine_vestibule",
			story: "I guess the forest keeper won't be using this diary anymore, so I might as well."
		},
		SHRINE4 : {
			requisites : function(diary){return (diary.check(4,"RAVIENE_EMPATH",true)  && !DIARY_REQPAK.C4_ESCAPE(diary));},
			room: "mountainshrine_sanctuary",
			story: "An ordinary paper book seems so small and transient in a hall of stone and crystal, but I don't suppose writing in anything else would be as easy..."
		},
		CATACOMBS5_1 : {
			requisites : function(diary){return (diary.check(4,"TREASURE") && !DIARY_REQPAK.C5_DEJECTION(diary));}, // hmmm... IS there a way to get here without tripping GARBAGE_CHUTE?  I wonder...
			room: "skyshrine_spiral_1",
			story: "Great Goddess, WHY hollow out an entire island just to fill it with traps?"
		},
		CATACOMBS5_2 : {
			// be sure requisites rule out returning/respawning here between losing the treasures and regaining the circlet
			requisites : function(diary){return (diary.check(4,"TREASURE") && !DIARY_REQPAK.C4_ESCAPE(diary));},
			room: "skyshrine_spiral_2",
			story: "What is this room?  A lab?  I'm not sure writing here is a good idea, but beggars can't be choosers..."
		},
		UNDERDARK : {
			requisites : function(diary){return (diary.check(5,"VILLAGE_SEAL"));},
			room: "underdark_6",
			story: "I'm all alone, somewhere deep underground, surrounded by Entirely Too Many Spikes, and this is probably the last diary I'll ever see..."
		},
		// Hey future-self-
		// Did you add any new diaries to DEFINE_DIARY_ORDER?
		// If not, GO_DeathsDoor might create a softlock.
	},
	ENDINGS: {
		LIVED: {
			story: "And today... is the first day of the rest of my life."
		},
		DIED: {
			story: "Anyone who reads this, know that today... I died content."
		},
	}

};
var DIARY_REQPAK = {
	C4_ESCAPE : function(diary){return diary.check(4,"NOTREASURE",true) && !diary.check(5,"MET_GABE",true);},
	C5_DEJECTION : function(diary){return diary.check(5,"AWAKE",true) && !diary.check(5,"MET_GABE",true);},
};

// for Ch5 and remainder of game
// -7 to +7 range
// even +7 will never quite be "normal"
var MOOD_TO_BURN = {
	"-7": "#140a10",
	"-6": "#281430",
	"-5": "#3c1e50",
	"-4": "#502870",
	"-3": "#643290",
	"-2": "#783ca0",
	"-1": "#8c46c0",

	"0": "#a5f",//"#a050f0";  "#fff" minus "#5a0" or perhaps "#edf" minus "#480"
	// "#50a000" / 8 = "#0a1400"
	"1": "#aa64f0",
	"2": "#b478f0",
	"3": "#be8cf0",
	"4": "#c8a0f0",
	"5": "#d2b4f0",
	"6": "#dcc8f0",
	"7": "#e6dcf0",
};

var DEFINE_DIARY_ORDER = [
	"HOME",
	"SHRINE1",
	"REEF",
	"LANDTOWN",
	"NAUTILUS",
	"FOREST",
	"SHRINE3",
	"SHRINE4",
	"CATACOMBS5_1",
	"CATACOMBS5_2",
	"UNDERDARK",
];

var DEFINE_DIARY_DIVIDER = "*--===<xXx>===--*";

/*
the persistent data storage container
tracks progress state, and manages save/restore functionality
*/
var Diary = function(){
	this.reset();
};
	Diary.prototype.reset = function(){
		// quick reference for powers
		this.hasBracelets = false; // allows grab/hold; .5/.75/1.25 chi/frame when holding light/med/heavy
		this.hasCollar = false; // allows land mobility; .5 chi/frame when grounded, 1 to jump
		this.hasBelt = false; // allows high jump & extends kickwave range; 2 chi to jump
		this.hasCirclet = false; // allows air-jump & increases airspeed; 4 chi to air-jump
		this.hasBlessing = false; // powers up kickwave; 8 chi to use powered shockwave
		this.hasRing = false; // unofficial 5th treasure, obtained by completing Cretaceous Ham sideboss quest.  Gradually restores life; free to use

		// life
		this.life = 5;
		// max life = 5 + souls
		this.max_life = 5;
		this.souls = []; // each soul adds a specified amount of life

		// chi
		this.chi = 32; // power to use Goddess gear
		this.subchi = 0; // 8 subchi = 1 chi; used during recharge
		this.fastchi = 0; // DG homage bonus mechanic; ticks of 2x chi regain remaining
		// max chi is 32 + tears
		this.max_chi = 32;
		// recharge rate = max_chi>>3 subchi/frame (4 to start)
		this.tears = []; // each Goddess Tear adds generally 4 chi (but can vary)

		// progress
		this.chapters = [];
		this.chapters[1] = {}; // 1-indexed array.  Because I can because js.  Nyah.

		// ordered sequence of events in the playthrough
		// {chaptergory: , eventname: } pairs
		this.narrative = [];

		// quick record of which diaries the player has even touched.
		// Pernicious issue 2022.09.03: 
		// In SPEEDRUN EXTREME or similar no-saved-data scenario,
		// death recovery to furthest valid diary could allow
		// deathwarp forwards to e.g. end of sky shrine or even
		// end of underdark.  Preferred behavior would be last-touched
		// diary or furthest reached diary.
		this.tagged = "HOME";

		// conditional-tested because we reset on init
		// and currently init immediately, before
		// main logic.
		// if you reload to an empty/prior state,
		// don't persist tint
		if (window.SDS){
			SDS.screenFX = null;
			SDS.screenFXColor = null;
		}
		// And sorry, no, NG+ ends here.
		if (window.GLOBAL_SCRATCHPAD){
			GLOBAL_SCRATCHPAD.fullclear();
		}


		// metadata calculated from stored data

		// keys from the underdark
		this.key_count = 0;
	};

	Diary.prototype.braceletsActive = function(){
		if (this.hasBlessing) return true;

		return this.hasBracelets && (this.subchi + 8*this.chi > 0); // bracelet actions need chi
	};
	Diary.prototype.braceletsHold = function(weight){
		if (this.hasBlessing) return;

		switch (weight){
			case DEFINE_PROJECTILE_WEIGHT.LIGHT:
				this.subchi-=4;
			break;
			case DEFINE_PROJECTILE_WEIGHT.LIGHT:
				this.subchi-=6;
			break;
			case DEFINE_PROJECTILE_WEIGHT.LIGHT:
				this.subchi-=10;
			break;
			default:
				this.subchi-=6;
			break;
		}

		this.balanceChi();
	};
	Diary.prototype.braceletsPunchCharge = function(){
		if (this.hasBlessing) return;

		this.subchi-=8;
		this.balanceChi();

		// evil caveat: if you charge ALL the way to the end of your meter,
		// take an extra hit:
		if (this.chi<=0){
			this.subchi-=256;
			this.balanceChi();
		}
	};
	Diary.prototype.collarActive = function(){
		if (this.hasBlessing) return true;

		return this.hasCollar && (this.subchi + 8*this.chi >= 4); // just need to be standing to jump; can go negative when jumping
	};
	Diary.prototype.collarDrain = function(){
		if (this.hasBlessing) return;

		this.subchi-=4;
		this.balanceChi();
	};
	Diary.prototype.collarJump = function(){
		if (this.hasBlessing) return;

		this.subchi-=32;
		this.balanceChi();
	};
	Diary.prototype.collarDash = function(){
		if (this.hasBlessing) return;

		this.subchi-=16;
		this.balanceChi();

		// evil caveat: if you dash ALL the way to the end of your meter,
		// take an extra hit:
		if (this.chi<=0){
			this.subchi-=256;
			this.balanceChi();
		}
	};
	Diary.prototype.beltActive = function(){
		if (this.hasBlessing) return true;

		return this.hasBelt && (this.subchi + 8*this.chi >= 0); // belt functions largely passive; just be sure we have chi
	};
	Diary.prototype.circletActive = function(){
		if (this.hasBlessing) return true;

		return this.hasCirclet && (this.subchi + 8*this.chi >= 0); // again, can go negative, but must have some chi
	};
	Diary.prototype.circletFly = function(){
		if (this.hasBlessing) return;

		this.subchi-=256;
		this.balanceChi();
	};

	// for consistency
	Diary.prototype.blessingActive = function(){
		return this.hasBlessing;
	}
	Diary.prototype.blessingShot = function(){
		//var dmg = (this.chi<<3)+this.subchi;
		//this.chi=0;
		//this.subchi=0;
		var dmg = this.chi;
		this.chi = 0;
		this.balanceChi(); // for consistency, in case we splice in any more post-spend checks later
		return dmg;
	}

	Diary.prototype.balanceChi = function(){
		while (this.subchi<0){
			this.subchi+=8;
			this.chi--;
		}
		//this.chi = Math.max(this.chi,0);
	}

	Diary.prototype.chiCharge = function(recursed){
		this.subchi+=this.max_chi>>3;
		while (this.subchi>=8){
			this.chi++;
			this.subchi-=8;
		}
		if (this.chi>=this.max_chi){
			this.chi=this.max_chi;
			this.subchi=0;
		}
		else if(this.fastchi>0 && !recursed){
			--this.fastchi;
			this.chiCharge(true);
		}
	};

	Diary.prototype.computeMetadata = function(){
		this.key_count = 0;
		for (var i=1; i<8; ++i){
			if (this.check(5,"SEALKEY_"+i)) ++this.key_count;
		}
	};


	Diary.prototype.note = function(chapter,eventname){
		var chaptername = "CHAPTER"+chapter;
		var valid=false;
		for (var c in DEFINE_DIARY_EVENTS){
			if (c==chaptername){
				for (var e in DEFINE_DIARY_EVENTS[c]){
					if (e==eventname){
						valid = true;
					}
				}
			}
		}
		if (!valid){
			alert(
				"The game is trying to log an undefined story event."+
				"  Odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer."+
				"  [CHAPTER"+chapter+" "+eventname+"]");
		}
		else{
			valid = DEFINE_DIARY_EVENTS[chaptername][eventname].requisites(this);
			if (!valid){
				alert(
					"Congratulations.  You have performed a sequence-break, "+
					"and the game is trying to log a story event for which the prerequisites have not been met."+
					"  On the one hand, that's kinda cool.  On the other, "+
					"odds are save/load will break, and the game may not be completable."+
					"  If you want to see this fixed, please inform the developer, and be ready to provide "+
					"details on what you did, as well as the contents of your game diary."+
					"  [CHAPTER"+chapter+" "+eventname+"]");
			}
		}

		if (!this.chapters[chapter]) this.chapters[chapter]={};
		this.chapters[chapter][eventname]=true;
		this.narrative.push({
			chaptergory: chaptername,
			eventname: eventname
		});
		this.computeMetadata();
		return valid;
	};

	Diary.prototype.check = function(chapter,eventname,orAlternate){
		if (!this.chapters[chapter]) return false;
		if (!orAlternate){
			if (!this.chapters[chapter][eventname]) return false;
			return this.chapters[chapter][eventname];
		}
		else{
			if (this.chapters[chapter][eventname]) return this.chapters[chapter][eventname];
			// else...
			var chaptername = "CHAPTER"+chapter;
			for (var e in DEFINE_DIARY_EVENTS[chaptername]){
				if (DEFINE_DIARY_EVENTS[chaptername][e].alternate === eventname && this.chapters[chapter][e]) return this.chapters[chapter][e];
			}
			return false;
		}
	};
	Diary.prototype.clear = function(chapter,eventname){
		if (!this.chapters[chapter]) return false;
		if (!this.chapters[chapter][eventname]) return false;
		delete this.chapters[chapter][eventname];

		var chaptername = "CHAPTER"+chapter;
		for (var i=0; i<this.narrative.length; ++i){
			if (this.narrative[i].chaptergory===chaptername && this.narrative[i].eventname===eventname){
				this.narrative.splice(i,1);
				break;
			}
		}
		this.computeMetadata();
		return true;
	};

	Diary.prototype.collectSoul = function(soul){
		var valid=false;
		for (var s in DEFINE_DIARY_EVENTS.SOULS){
			if (s==soul){
				valid = true;
			}
		}
		if (!valid){
			alert(
				"The game is trying to log an undefined soul pickup."+
				"  Odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+soul+"]");
		}
		else if (this.souls.indexOf(soul) != -1){
			alert(
				"The game is trying to log a duplicate soul pickup."+
				"  Odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+soul+"]");
		}
		else if (!DEFINE_DIARY_EVENTS.SOULS[soul].requisites(this)){
			alert(
				"Congratulations.  You have performed a sequence-break, "+
				"and the game is trying to log a soul pickup for which the prerequisites have not been met."+
				"  On the one hand, that's kinda cool.  On the other, "+
				"odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer, and be ready to provide "+
				"details on what you did, as well as the contents of your game diary."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+soul+"]");
		}
		
		if (valid){
			this.souls.push(soul);
			this.max_life+=DEFINE_DIARY_EVENTS.SOULS[soul].value;
			this.life=this.max_life;
			this.narrative.push({
				chaptergory: "SOULS",
				eventname: soul
			});
		}

		this.computeMetadata();

		return valid;
	};
	Diary.prototype.hasSoul = function(soul){
		return (this.souls.indexOf(soul) != -1);
	};

	Diary.prototype.collectTear = function(tear){
		var valid=false;
		for (var t in DEFINE_DIARY_EVENTS.TEARS){
			if (t==tear){
				valid = true;
			}
		}
		if (!valid){
			alert(
				"The game is trying to log an undefined tear pickup."+
				"  Odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+tear+"]");
		}
		else if (this.tears.indexOf(tear) != -1){
			alert(
				"The game is trying to log a duplicate tear pickup."+
				"  Odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+tear+"]");
		}
		else if (!DEFINE_DIARY_EVENTS.TEARS[tear].requisites(this)){
			alert(
				"Congratulations.  You have performed a sequence-break, "+
				"and the game is trying to log a tear pickup for which the prerequisites have not been met."+
				"  On the one hand, that's kinda cool.  On the other, "+
				"odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer, and be ready to provide "+
				"details on what you did, as well as the contents of your game diary."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+tear+"]");
		}
		
		if (valid){
			this.tears.push(tear);
			this.max_chi+=DEFINE_DIARY_EVENTS.TEARS[tear].value;
			this.chi=this.max_chi;
			this.narrative.push({
				chaptergory: "TEARS",
				eventname: tear
			});
		}

		this.computeMetadata();

		return valid;
	};
	Diary.prototype.hasTear = function(tear){
		return (this.tears.indexOf(tear) != -1);
	};

	Diary.prototype.empathy = function(){
		var emp = 0;
		if (this.check(4,"RAVIENE_EMPATH")) ++emp;
		if (this.check(4,"NOTREASURE_EMPATH")) ++emp;

		if (this.check(4,"RAVIENE_NEMESIS")) --emp;
		if (this.check(4,"NOTREASURE_NEMESIS")) --emp;

		return emp;
	};

	// assumes something else has already checked for duplicates
	Diary.prototype.greyCount = function(){
		var count = 0;
		for (var i=0; i<this.narrative.length; i++){
			if (this.narrative[i].eventname.match(/GREY_LOC_/)) ++count;
		}
		return count;
	};

	/* returns a string containing the narrative so far */
	Diary.prototype.record = function(diaryname){
		var valid=false;
		for (var d in DEFINE_DIARY_EVENTS.DIARIES){
			if (d==diaryname){
				valid = true;
			}
		}
		for (var d in DEFINE_DIARY_EVENTS.ENDINGS){
			if (d==diaryname){
				valid = true;
			}
		}
		if (!valid){
			alert(
				"The game is trying to save at an unknown diary."+
				"  Odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+diaryname+"]");
		}
		else if (DEFINE_DIARY_EVENTS.DIARIES[diaryname] && !DEFINE_DIARY_EVENTS.DIARIES[diaryname].requisites(this)){
			alert(
				"Congratulations.  You have performed a sequence-break, "+
				"and the game is trying to save at a diary for which the prerequisites have not been met."+
				"  On the one hand, that's kinda cool.  On the other, "+
				"odds are save/load will break, and the game may not be completable."+
				"  If you want to see this fixed, please inform the developer, and be ready to provide "+
				"details on what you did, as well as the contents of your game diary."+
				"  [CHAPTER"+(this.chapters.length-1)+" "+diaryname+"]");
		}
		

		var narrative = "";
		for (var i=0; i<this.narrative.length; i++){
			var chaptergoryData = DEFINE_DIARY_EVENTS[this.narrative[i].chaptergory];
			if (chaptergoryData){
				var eventdata = chaptergoryData[this.narrative[i].eventname];
				if (eventdata){
					// TODO?: more efficient stringbuilding- form an array then concat...
					narrative = narrative + eventdata.story + "\n";

					if (this.narrative[i].chaptergory=="DIARIES"){
						narrative = narrative + "\n" + DEFINE_DIARY_DIVIDER + "\n\n";
					}
				}
			}
		}

		// don't add another duplicate entry
		if (!(
			this.narrative[this.narrative.length-1].chaptergory=="DIARIES" &&
			this.narrative[this.narrative.length-1].eventname==diaryname)){
			var diarydata = DEFINE_DIARY_EVENTS.DIARIES[diaryname] || DEFINE_DIARY_EVENTS.ENDINGS[diaryname];
			if (diarydata){
				narrative = narrative + diarydata.story + "\n";
				this.narrative.push({
					chaptergory: "DIARIES",
					eventname: diaryname
				});
			}
		}


		return narrative;
	};

	/* attempts to parse the narrative string.
	   If successful, populates this diary's data and returns
	   {roomname: , diaryname: } for spawning.  Otherwise,
	   returns null and clears the diary. */
	Diary.prototype.read = function(narrative){
		this.reset();
		SDS.meters.visible = true;
		GLOBAL_TIME_FRAMES=0;
		GLOBAL_TIME_SECONDS=0;
		GLOBAL_TIME_MINUTES=0;
		GLOBAL_TIME_HOURS=0;
		GLOBAL_COMPLETION=0;
		GLOBAL_SPEEDRUN=false;
		GLOBAL_SPEEDRUN_EXTREME=false;
		GLOBAL_TIME_IN=false;

		// special case keywords/codes
		if (narrative==="SPEEDRUN"){
			GLOBAL_SPEEDRUN=true;
			return null;
		}
		if (narrative==="SPEEDRUN EXTREME"){
			GLOBAL_SPEEDRUN=true;
			GLOBAL_SPEEDRUN_EXTREME=true;
			return null;
		}


		var narrativelines = narrative.split("\n");

		var valid=true;
		var currentdiary = "";
		var last_was_diary = false;
		for (var i=0; valid && i<narrativelines.length; i++){
			var found=(narrativelines[i].length==0 || narrativelines[i]==DEFINE_DIARY_DIVIDER);
			for (var cg in DEFINE_DIARY_EVENTS){
				for (var en in DEFINE_DIARY_EVENTS[cg]){
					if (DEFINE_DIARY_EVENTS[cg][en].story==narrativelines[i]){
						found=true;
						if (cg.substr(0,7)=="CHAPTER"){
							valid = valid && this.note(cg.substr(7),en);

							last_was_diary = false;
						}
						else{
							switch(cg){
								case "SOULS":
									valid = valid && this.collectSoul(en);
									last_was_diary = false;
								break;
								case "TEARS":
									valid = valid && this.collectTear(en);
									last_was_diary = false;
								break;
								case "DIARIES":
									currentdiary = en;
									this.narrative.push({
										chaptergory: "DIARIES",
										eventname: en
									});
									last_was_diary = true;
								break;
								default: // ENDINGS, etc
									valid = false;
									last_was_diary = false;
								break
							}
						}
						//console.log(cg);
					}
				}
			}
			valid = valid && found;
		}

		valid = valid && last_was_diary
			&& DEFINE_DIARY_EVENTS.DIARIES[currentdiary]
			&& DATA_SDS_MAP_ROOMS[DEFINE_DIARY_EVENTS.DIARIES[currentdiary].room];

		if (!valid){
			this.reset();
			return null;
		}

		GLOBAL_SPEEDRUN=false;

		this.hasBlessing=this.check(5,"BLESSING") ? true : false;
		this.hasBracelets=(this.hasBlessing || this.check(1,"TREASURE")) ? true : false;
		this.hasCollar=(this.hasBlessing || this.check(2,"TREASURE")) ? true : false;
		this.hasBelt=(this.hasBlessing || this.check(3,"TREASURE")) ? true : false;
		this.hasCirclet=(this.check(4,"TREASURE") || this.check(5,"MET_GABE",true)) ? true : false;	
		
		this.hasRing=this.check(4,"LIFE_RING") ? true : false;	
		
		if (this.check(4,"NOTREASURE",true) && !this.check(5,"BLESSING")){
			this.hasBracelets=false;
			this.hasCollar=false;
			this.hasBelt=false;
			if (!this.check(5,"MET_GABE",true) || this.check(5,"MET_ZEKE")){
				this.hasCirclet=false;
			}
		}
		if(this.check(4,"NOTREASURE",true) && !this.check(5,"AWAKE")){
			SDS.bgmOverride = "Shadows of the Past";
		}
		SDS.screenFX = null;
		SDS.screenFXColor = null;
		if(this.check(5,"AWAKE") && !this.check(5,"MOOD_0",true)){
			SDS.bgmOverride = "Secondhand Feelings";

			SDS.screenFX = "color-burn";
			SDS.screenFXColor = MOOD_TO_BURN["0"];//"#a5f";
		}
		else{
			for (var i=0; i<8; ++i){
				if(this.check(5,"MOOD_"+i)){
					SDS.screenFX = "color-burn";
					SDS.screenFXColor = MOOD_TO_BURN[i.toString()];
				}
			}
		}


		return {
			diaryname: "Diary_"+currentdiary,
			roomname: DEFINE_DIARY_EVENTS.DIARIES[currentdiary].room
		};
	};

var GLOBAL_DIARY = new Diary();

/*
the temporary data storage container for largely per-room data
in javascript, it is really just an unnecessary wrapper around an Object
but philosophically, I prefer to have it as its own thing
*/
var Scratchpad = function(){
	this.cache = {};
	this.persisted = {};
};
	Scratchpad.prototype.note = function(key,value){
		this.cache[key]=value;
	};
	Scratchpad.prototype.check = function(key){
		return this.cache[key];
	};
	Scratchpad.prototype.persist = function(key){
		this.persisted[key]=true;
	};
	Scratchpad.prototype.unpersist = function(key){
		delete this.persisted[key];
	};

	Scratchpad.prototype.reset = function(){
		for (var item in this.cache){
			if (!this.persisted[item]) delete this.cache[item];
		}
	};

	Scratchpad.prototype.fullclear = function(){
		// we can afford to leak a tiny bit of garbage
		// to not get into any weird 
		// iterating-over-vanishing-state issues.
		// also plz full clear even nonpersisted data plz thx
		this.cache = {};
		this.persisted = {};
	};

var GLOBAL_SCRATCHPAD = new Scratchpad();