So I created a PERSON class in Puny Inform and gave that class a Describe method to produce a message, so then every PERSON printed a default ‘(The SELF) is standing here people watching’ type message. I then create a PERSON for example ‘Mr X’ and that PERSON prints ‘Mr X is standing here people watching’ (all well and good). But then I want to ‘override’ that class describe method within the Mr X PERSON creation. I add a describe method to that and instead of overriding the class method I get an error message ‘Mr X (object number 55) has no property describe to read**’ before it then prints the description in the Mr X describe routine. Is there a way to let an object of a class override an inherited method ? I have checked the puny inform docs and dm4 inform 6 but could not see anything that would help (although I could be completely blind to it).
Verify that the property before the describe routine is comma separated. It is very common to forget a comma in the Inform language. So common that an extension was written to warn about them: http://ifarchive.org/if-archive/infocom/compilers/inform6/library/contributions/debugmcs.h
It’s absolutely possible to override a property value given in a class.
DM me the source of the class and the object, or put it here, and we’ll figure out what’s happening.
I am not sure I understand why yet but the problematic ‘error message’ appears to be coming from the PrintOrRun routine in puny.h which reads :
[ PrintOrRun p_obj p_prop p_no_string_newline _val;
_val = p_obj.p_prop;
if (p_obj.#p_prop > WORDSIZE || _val ofclass Routine) return RunRoutines(p_obj, p_prop);
if(_val ofclass String) {
print (string) p_obj.p_prop;
if(p_no_string_newline == 0) new_line;
}
];
The ‘specific’ line causing the programming error is _val = p.obj.p.prop
This works fine if either the class (PERSON) or the character derived from the class has a describe section, but not both?
PrintOrRun is used to print a string or run a routine held by the describe property.
It would be easier to help you if you showed your source.
I found a problem with the PrintOrRun routine, in that it would read the property value without checking first if the property held an array. This would work as designed, but would give an error in strict mode when the property did indeed hold an array.
The describe property is additive, which means if both the class and the object has a value, they are put into a property array.
We pretty much never use strict mode, which is probably why this went undetected for a long time. I’m glad you found it.
Pushed a fix to the Github repo.
I was just in the process of writing a test case project to highlight the issue - Thanks for the prompt reply Here is that case ‘scenario’ –
!% -~S
!% $OMIT_UNUSED_ROUTINES=1
!% +include_path=c:/Puny/lib,h:/Puny/Test
! The very first lines of the main source code file for a game can
! contain compiler options, like the two 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.
Constant Story "Test";
Constant Headline
"^PunyInform Test^";
! 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 CUSTOM_ABBREVIATIONS;
Constant CUSTOM_PLAYER_OBJECT = myPlayer;
Constant OPTIONAL_NO_DARKNESS;
!Constant OPTIONAL_ALLOW_WRITTEN_NUMBERS;
!Constant OPTIONAL_FLEXIBLE_INVENTORY;
!Constant OPTIONAL_EXTENDED_METAVERBS;
!Constant OPTIONAL_EXTENDED_VERBSET;
!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; ! You need to set 'reactive' now against all reactive people / things
!Constant OPTIONAL_ORDERED_TIMERS;
!Constant OPTIONAL_PROVIDE_UNDO;
!Constant OPTIONAL_REACTIVE_PARSE_NAME;
Constant RUNTIME_ERRORS = 2; ! 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 = Lab;
Include "globals.h";
! Define your own global variables here, if any
! Define the entry point routines you need here, like Amusing, DarkToDark etc.
!-------------------------------------------------------------------------------
! C H O O S E O B J E C T S
!-------------------------------------------------------------------------------
!
! Objects deals with various situations where the parser cannot
! decide which object the player refers to in his input.
!
!-------------------------------------------------------------------------------
! PAG - Add replaced Entry Routines to Utility.inf
!Replace Look;
!Replace GoDir;
!Replace GiveSub;
!Replace PushDirSub; ! Replacement to allow to push things in a direction
!Replace AskToSub;
! Uncomment to add PunyLib extensions
!Include "ext_menu.h";
!Include "ext_flags.h";
!Include "ext_quote_box.h";
!Include "ext_cheap_scenery.h";
Include "puny.h";
! ===================================
! Add Own Fake Actions Here
! ===================================
! Uncomment to add PunyLib extensions
!Include "ext_waittime.h";
! ====================================
! Classes, verbs etc for game
! ====================================
[Initialise;
lookmode = 2; ! Verbose by default
"The test starts here ....";
];
!------ Game starts here
class Person
with
local_description,
description [_worn _held _o;
if (self.local_description > 0){
PrintOrRun(self, local_description, true);
} else {
print "You see nothing unusual about ", (the) self, ".";
}
if (PrintContents(1, self) ~= 0){
! set work flag for all held but not worn
_held = false;
objectloop (_o in self){
give _o ~workflag; ! Set work flag to false
if (_o hasnt worn){
_held = true; ! There are some held items
give _o workflag; ! Set the work flag for the held item
}
}
if (_held){
print " ", (The) self, " is holding ";
PrintContents(0, self, WORKFLAG_BIT); ! using workflag print held but not worn items
print ".";
}
! set work flag for worn items
_worn = false;
objectloop (_o in self){
give _o ~workflag; ! Set work flag to false
if (_o has worn){
_worn = true; ! There are some worn items
give _o workflag; ! Set the work flag for the worn item
}
}
if (_worn){
print " ";
print "^", (The) self, " is wearing ";
PrintContents(0, self, WORKFLAG_BIT); ! using workflag print held but not worn items
print ".";
}
}
"";
],
describe [;
print_ret "^", (The) self, " is standing here people watching.";
],
life [;
print_ret "^ ~I'm not interested~.";
],
has animate transparent reactive;
Object Lab "Inside a test lab"
with
description "This lab is awaitng yout test.";
! =====================================
! Custom Player
! =====================================
Person myPlayer "Player"
with
pushObject 0,
parse_name [ _words;
while(NextWordStopped() == self.&name-->0 or self.&name-->1 or
self.&name-->2 or self.&name_other-->0 or
self.&name_other-->1 or self.&name_other-->2) _words++;
return _words;
],
life [;
Give:
move noun to self;
print "~Well thank you very much ";
PrintOrRun(player, short_name_other, true);
"!~";
],
name 'me' 'myself' 'self',
short_name "yourself",
name_other 1,
short_name_other 1,
local_description "As good looking as ever!",
capacity MAX_CARRIED,
character 0,
has proper concealed ;
! =====================================
! Person Based of class
! =====================================
Person MrX Lab
with
description "It's the notorious Mr X.",
describe [;
print_ret "^", (The) Self, " is here, looking suspicious.";
];
I have pulled the checked in code and can confirm that it now appears to be working correctly. Much appreciated for the quick ‘fix’ - AG