Crash: Memory access out of range when getting a list of values from a rulebook

I had another look at this and devised what seemed like a ‘cleaner’ if slightly more complex solution by moving down another layer into the undergrowth and modifying LIST_OF_TY_Create() so that it could respond to a customised call to create a list using a weak kind of LIST_OF_TY and a kind specified by the ‘spare’ short_block parameter, which is not used when creating a fresh list.

This seemed to work fine, and it got rid of the out-of-range memory crash when block value tracing is turned on, but all kinds of other weird stuff was happening when block value tracing was on. I assumed that this was a side-effect of my tinkering, but then came to realise that block value tracing is itself broken. A minimalist version of my test game without any I6 hacking or returns from rules still goes ape when block value tracing is turned on…

First the working hack and test game:

Summary
"Spelling Test"

Wizard's Tower is a room.

The larking rules is a rulebook producing a list of texts.
The thinking rules is a rulebook producing a list of numbers.
The chilling rules is a rulebook producing a list of lists of texts.

Line1 is always {"picture", "yourself", "on", "a", "boat", "on", "a", "river"}.
Line2 is always {"with", "tangerine", "trees", "and", "marmalade", "skies"}.
Line3 is always {"somebody", "calls", "you", ",", "you", "answer", "quite", "slowly"}.
Line4 is always {"a",  "girl", "with", "kaleidoscope", "eyes"}.
Lyrics is always {Line1, Line2, Line3, Line4}.

A chilling rule:
	rule succeeds with result Lyrics.

A larking rule:
	let L be a list of texts;
	let A be "[the action name part of the current action]";
	repeat with N running from 1 to the number of characters in A:
		add character number N in A to L;
	rule succeeds with result L.

A thinking rule:
	let L be a list of numbers;
	repeat with N running from 1 to 5:
		add N * N to L;
	rule succeeds with result L.
	
Instead of chilling:
	say "As conscious thought slowly drifts and dissolves, you sense that some cosmic force is at work.";
	let spelled-text be the list of lists of texts produced by the chilling rules;
	say "After some time, images begin to swirl, condense and writhe across your mind's eye:[line break]";
	repeat with N running from 1 to the number of entries in spelled-text:
		say line break;
		repeat with M running from 1 to the number of entries in entry N in spelled-text:
			say "[entry M in entry N in spelled-text]...[run paragraph on]";
	say "[paragraph break]You wake, as if from a dream...[paragraph break]";

Instead of thinking: 
	say "As you concentrate, you sense that some cosmic force is at work.";
	let spelled-text be the list of numbers produced by the thinking rules;
	say "After some time, it produces the following list of numbers: [spelled-text]."

				
Instead of jumping, waving hands or singing: 
	say "As you lark about, you sense that some cosmic force is at work.";
	let spelled-text be the list of texts produced by the larking rules;
	say "After some time, it produces the following list of texts: [spelled-text]."
	
Singing is an action applying to nothing.
Understand "sing" as singing.
Chilling is an action applying to nothing.
Understand "chill" as chilling.





Test me with "jump  / wave / sing / think / chill".

Include (-
Constant RS_NEITHER = 0;
Constant RS_SUCCEEDS = 1;
Constant RS_FAILS = 2;
! Constant BLKVALUE_TRACE=1;

Array latest_rule_result --> 3;

[ RecordRuleOutcome usage rule1 rule2;
	if ((latest_rule_result-->0 == RS_SUCCEEDS or RS_FAILS) &&
		(KOVIsBlockValue(latest_rule_result-->1)))
		BlkValueFree(latest_rule_result-->2);
	if ((usage == RS_SUCCEEDS or RS_FAILS) && (KOVIsBlockValue(rule1))) {
		if (rule1 == LIST_OF_TY) {
			rule2 =BlkValueCopy(BlkValueCreate(rule1,BlkValueRead(rule2, LIST_ITEM_KOV_F)), rule2);
		! print "Alternate creation runs...^";
		}
		else { rule2 = BlkValueCopy(BlkValueCreate(rule1), rule2); 
		! print "Standard creation runs...^";
		}
	} 
	latest_rule_result-->0 = usage;
	latest_rule_result-->1 = rule1;
	latest_rule_result-->2 = rule2;
];
-) instead of "Latest Rule Result" in "Rulebooks.i6t".

Include (-

! Fix to allow alternate creation of Lists of kind K through combination of
! 1st parameter – weak kind LIST_OF_TY
! 2nd parameter – kind K e.g. TEXT_TY
! in addition to standard call where
! 1st parameter – strong kind e.g. KD_2_list_of_texts
! 2nd parameter – zero or short block address to recycle
 
[ LIST_OF_TY_Create skov sb list;
	! print "(1) skov=", skov, " sb=",sb,"^";
	if ((skov == LIST_OF_TY)) {
		if (sb == 0){ print "**** Programming error- tried to create List of unspecified type ****^"; 
		}
		else {skov = sb; sb=0;  ! need to set sb to 0 to get new short block allocated later from BlkValueCreateSB1(sb, list)
		! print "Parameters set...^";
		jump List_of_ty_create_continue;
		} 
	} 
	skov = KindBaseTerm(skov, 0); ! standard call parameters
	.List_of_ty_create_continue;
	! print "(2) skov=", skov, " sb=",sb,"^";
	list = FlexAllocate(27*WORDSIZE, LIST_OF_TY, BLK_FLAG_MULTIPLE + BLK_FLAG_WORD);
	BlkValueWrite(list, LIST_ITEM_KOV_F, skov, true);
	BlkValueWrite(list, LIST_LENGTH_F, 0, true);
	sb = BlkValueCreateSB1(sb, list);
	return sb;
];

-) instead of "Creation" in "Lists.i6t".

(Obviously, remove commenting out of BLKVALUE_TRACE=1 to achieve an even more psychedelic experience)

And a minimalist demonstration of broken block value tracing:

Summary
"Spelling Test"

Wizard's Tower is a room.

The skylarking rules is a rulebook.

A skylarking rule:
	let L be a list of texts;
	let A be "[the action name part of the current action]";
	repeat with N running from 1 to the number of characters in A:
		add character number N in A to L;
	now lark-text is L.

lark-text is a list of texts that varies.				
Instead of jumping, waving hands or singing: 
	say "As you lark about, you sense that some cosmic force is at work.";
	Follow the skylarking rules;
	say "After some time, it produces the following list of texts: [lark-text]."
	
Singing is an action applying to nothing.
Understand "sing" as singing.

Test me with "jump  / wave / sing".

Include (-
Constant BLKVALUE_TRACE =0;
-) after "Definitions.i6t".
2 Likes