!% -~S
!% $OMIT_UNUSED_ROUTINES=1
!% $ZCODE_LESS_DICT_DATA=1

! The very first lines of the main source code file for a game can
! contain compiler options, like the lines above. -~S disables
! strict error checking. This is otherwise used in z5 and z8 games by
! default. While useful for debugging, it adds ~10 KB to the story file
! size and it makes the game slower.
! $OMIT_UNUSED_ROUTINES=1 makes the compiler remove all routines which
! aren't used. This can save some space.
! $ZCODE_LESS_DICT_DATA=1 removes an empty data byte for every dictionary word.

Constant Story      "Minimal";
Constant Headline   "^A sample game which uses PunyInform.^";

! Uncomment ONE of the two following lines, to show either time or score/turns
! Leaving both commented out makes the library bigger.
!Constant STATUSLINE_TIME; Statusline time;
Constant STATUSLINE_SCORE; Statusline score;

! Comment out to keep track of score
! The value is what will be shown as the score on statusline in z3
Constant NO_SCORE = 0;

! Customize the statusline in z5+ (will have no effect in z3)
!Constant OPTIONAL_SL_NO_SCORE;
!Constant OPTIONAL_SL_NO_MOVES;

! Uncomment to add optional features to PunyInform
!Constant DEBUG;
!Constant DIALECT_US ! Affects OPTIONAL_ENGLISH_NUMBER
!Constant CUSTOM_ABBREVIATIONS;
!Constant CUSTOM_PLAYER_OBJECT = myPlayerObj;
!Constant OPTIONAL_NO_DARKNESS;
!Constant OPTIONAL_ALLOW_WRITTEN_NUMBERS;
Constant OPTIONAL_EXTENDED_METAVERBS;
!Constant OPTIONAL_EXTENDED_VERBSET;
!Constant OPTIONAL_FLEXIBLE_INVENTORY;
!Constant OPTIONAL_LANGUAGE_NUMBER;
!Constant OPTIONAL_LIST_TOGETHER;
!Constant OPTIONAL_PRINT_SCENERY_CONTENTS;
!Constant OPTIONAL_SCORED;
!Constant OPTIONAL_FULL_SCORE; ! Comment out NO_SCORE when uncommenting this
!Constant OPTIONAL_FULL_DIRECTIONS;
!Constant OPTIONAL_SIMPLE_DOORS;
!Constant OPTIONAL_SHIP_DIRECTIONS;
!Constant OPTIONAL_GUESS_MISSING_NOUN;
!Constant OPTIONAL_MANUAL_SCOPE;
!Constant OPTIONAL_MANUAL_REACTIVE;
!Constant OPTIONAL_ORDERED_TIMERS;
!Constant OPTIONAL_PROVIDE_UNDO;
!Constant OPTIONAL_REACTIVE_PARSE_NAME;
!Constant RUNTIME_ERRORS = 0; ! 0, 1 or 2. 0 = smallest file, 2 = most info

! Define any library constants you need here, like MAX_SCORE, AMUSING_PROVIDED,
! MAX_CARRIED, SACK_OBJECT,  etc.

Constant INITIAL_LOCATION_VALUE = Library;

Include "globals.h";

! Define your attributes, common properties and global variables here, if any

! Define the entry point routines you need here, like Amusing, DarkToDark etc.

! Uncomment to add PunyLib extensions
!Include "ext_menu.h";
!Include "ext_flags.h";
!Include "ext_talk_menu.h"; ! Note: Also include ext_flags.h to allow use of flags
!Include "ext_quote_box.h";
!Include "ext_cheap_scenery.h";

Include "puny.h";

! Uncomment to add PunyLib extensions
!Include "ext_waittime.h";

Object Library "The Library"
	with
		description "You are in a library.",
		n_to Hall
	;

Object Hall "The hall"
	with	
		description "You are in a hall.",
		s_to Library
	;

Object Torch "torch" selfobj
	with
		name 'torch',
		after[;
			SwitchOn:
				give self light;
				! visibility_ceiling = nothing;   				! Works
				! visibility_ceiling = location;				! Doesn't work because location == thedark at this stage	
				! visibility_ceiling = real_location;   		! Works
				! visibility_ceiling = ScopeCeiling(selfobj);	! Works and is probably the cleanest work round.
			SwitchOff:
				give self ~light;
		]
	has switchable;

[Initialise;
	print "^^My games expect ~thedark.initial~ to be called whenever the player moves from a LIGHT to DARK location. However I've found an edge case where this doesn't work.
	    It's unclear whether it's a bug or I'm not understanding how PunyInform works.^^
		In this game there are two rooms, both DARK. We create LIGHT in the first room, drop the light source then move to the second room which is DARK. In this case
		~thedark.initial~ does NOT fire. Moving back to the first room and then to the second room again causes the code to fire correctly.
		^^I've added a line to ~puny.h~ to print out the variables which are causing the failure. See also the four commented out lines in the AFTER routine where I've
		experimented with ways of working round the problem. None of these feel like a sensible solution.^^Steps to recreate in game:^^
		TURN TORCH ON^DROP TORCH^N (note that _old_vc == Darkness, which I think is wrong, OnEnterDarkness NOT fired)^
		S^N (note that OnEnterDarkess fired this time and _old_vc seems correct)^^";
	thedark.initial = OnEnterDarkness;
];

[OnEnterDarkness;
	print "^*** OnEnterDarkness *** called.^";
];
