GithubHelp home page GithubHelp logo

johanberntsson / punyinform Goto Github PK

View Code? Open in Web Editor NEW
161.0 19.0 18.0 16.42 MB

A fast and compact library for writing text adventure games for the Z-machine running on 8-bit computers as well as other platforms.

License: MIT License

Batchfile 2.71% Ruby 0.77% Makefile 0.22% C 96.24% Vim Script 0.06%
inform6 punyinform development-environment infocom zcode zmachine retrocomputing retrogaming text-adventure

punyinform's Introduction

PunyInform

PunyInform is a library written in Inform 6 which allows authors to create text adventure games / interactive fiction using the Z-machine virtual machine, to be played on 8-bit computers as well as newer platforms. It provides a parser, implementations of common verbs, as well as a framework for writing text adventures.

PunyInform is based on the Inform 6 library, developed by Graham Nelson. We are trying to make it easy for authors used to writing in Inform 6 to start using PunyInform. There is a manual describing the differences.

Games using PunyInform can be compiled to z3, z5 and z8 format. Compared to the Inform 6 library, this means we lack support for Glulx, but we have support for z3 (which the Inform 6 library lacks).

To compile games using PunyInform, we recommend the official Inform 6 compiler maintained by David Kinder, at https://github.com/DavidKinder/Inform6. Binaries can be found at the IF-Archive. PunyInform requires at least Inform v6.36. We recommended using the latest version.

You can use borogove.io to make your PunyInform game playable online. Create an account, upload your game file, and choose whether the game should be visible and playable for all visitors to the site, or only to those who have the link to your game. Another option is to upload your game file (e.g. mygame.z3) to the Parchment HTML Converter and download a single-file HTML file, which can be uploaded to sites such as Itch.io.

A minimal game in PunyInform

Motivation

The main goal of PunyInform is to allow for games which are fast and have a small memory footprint. This should make the games run well on older architectures, such as the 8-bit computers of the 1980s. Our main target is to make it suitable for games on the Commodore 64 using Ozmoo.

Status

PunyInform is fully working and has been used to write several games. We carefully add and change features and fix bugs as they are found. Please check releasenotes.txt for more details.

If you are interested in our progress, please star or follow the project here on Github. Announcements are made on https://twitter.com/FRamsberg and on https://intfiction.org/c/authoring/inform-6/66

You can read the manual on our wiki. It is also included as a PDF when you download PunyInform.

There is also a Game Author's Guide (under Documentation) with various tips for authors writing a game using PunyInform. It's not intended to teach the entire library, but more to give some tips you may find useful when you have a working knowledge of the library and you've started developing a game which you think you will release. All but the chapter on optimization is really required reading for all authors planning to release a game.

You can see what tasks we're currently working on, tasks we've done and tasks coming up on our Trello board: https://trello.com/b/mfGVsB4H/punyinform

Learning PunyInform

There are two manuals you need to know about: DM4 and the PunyInform manual. Read on to learn how to use them and where to find them. Alternatively, you can start learning PunyInform by following the tutorials under Articles.

Writing a game with PunyInform is very similar to writing a game with the Inform 6 standard library - almost everything works the same. If you want to learn PunyInform by reading manuals, you first need to read the official documentation for the Inform 6 standard library, called The Inform Designer's Manual, 4th Edition, or DM4 for short (see links above). You can assume that everything in it also goes for PunyInform (but read the short list stating the biggest differences just below the next paragraph!).

Additionally, there are two more important documents in the PunyInform distribution:

The Game Author's Guide lists some concepts that are often overlooked by new authors, leading to games with errors and problems. There's also a chapter on optimization, which is very useful for authors trying to squeeze the most out of the z3 format, and authors who want to do everything to deliver the best possible player experience on 8-bit computers.

The QuickRef document is an index of all constants, variables, routines etc that you need to know about as an author. It's not meant to be a learning resource for new authors, but to provide a very brief documentation for authors who are reasonably aquainted with the library.

As you start trying out examples, or start writing your own game, and there's something which you don't get to work, you should check the PunyInform manual, which describes everything that is different from the standard library (see links above).

The biggest differences between the standard library and PunyInform are:

  • The files you need to include, and what goes where in your source code. Start your project by copying minimal.inf in the root directory and you're good to go.

  • Parts of the PunyInform library are optional. I.e. if you want to use the directions northwest, southwest, northeast and southeast, you need to define the constant OPTIONAL_FULL_DIRECTIONS. If you want just about all the verbs and actions available in the standard library to work in PunyInform, you need to define OPTIONAL_EXTENDED_VERBSET. See Customizing the library in the PunyInform manual.

  • Directions are handled quite differently. See Direction handling in the PunyInform manual.

  • Changing library messages (like the message "Taken." that is printed when the player takes something) is done differently. See Library messages and customization in the PunyInform manual.

  • PunyInform doesn't support identical objects. You can have very similar objects like a small green book and a small red book, but the player must be able to say which one (s)he means. It is possible to hack/tweak the library into handling identical objects, see the file howto/indistinguishable.inf for an example of how to do this.

  • PunyInform doesn't have the versatile routine WriteListFrom, for printing what's in a location or in/on an object. Instead, it has a simpler routine called PrintContents. See Printing the contents of an object in the PunyInform manual.

Tools

  • To work with source code you may want a text editor which has a syntax colouring mode for Inform 6. Some popular choices include Visual Studio Code and Atom, both available for Windows, Mac and Linux.

  • To quickly build a game for play on Commodore 64, 128, Plus/4 or MEGA65, you can use Ozmoo Online.

  • To build a game for 25 different platforms at once, you can use the Puddle BuildTools. This tool set can be installed on Linux. Windows users can create a virtual machine running Linux.

  • The Parchment HTML Converter can convert your game file into an HTML file, making your game playable in a web browser.

Games Using PunyInform

60+ PunyInform games have been released. You can find just about all of them in this list of PunyInform games.

If you want to see the source code of PunyInform games, you should look at the list of PunyInform games which provide source code.

Most of these games can be downloaded from the links above. Some of the best games are also available at Ozmoo Online where you can create disk images for Commodore C64, C128, Plus/4, MEGA65, Commander X16 and Acorn/BBC computers.

Articles

Fredrik Ramsberg has written a few articles describing PunyInform for beginners:

Fredrik has also written a comparison of PunyInform and the standard Inform 6 library.

Community

If you want to ask questions about PunyInform, these are good places to go:

There are also categories/channels in the above forums where you can discuss plot, story, puzzles etc, and posts requests for beta-testers for your game.

Translations

  • PunyInformFr is a translation of the PunyInform library to French, by auraes.

  • PunyInformFr is a alternate translation of the PunyInform library to French, by Hugo Labrande.

  • PunyInform - DE is a translation of the PunyInform library to German, by Lea Santner and A. Pulvermacher.

Credits

PunyInform was conceived, designed and coded by Johan Berntsson and Fredrik Ramsberg.

Additional coding by Pablo Martinez and Tomas Öberg. PunyInform includes code from the Inform 6 standard library, by Graham Nelson.

Thanks to Stefan Vogt, Jason Compton, John Wilson, Hugo Labrande, Richard Fairweather, Adam Sommerfield, auraes, Hannesss and Garry Francis for issue reporting, advice, testing, code contributions and promotion. Thanks to David Kinder and Andrew Plotkin for helping out with compiler issues and sharing their deep knowledge of the compiler. Huge thanks to Graham Nelson for creating the Inform 6 compiler and library in the first place.

punyinform's People

Contributors

auraes avatar davidgriffith avatar dfabulich avatar fredrikr avatar hlabrand avatar johanberntsson avatar kozelek avatar sijnstra avatar toerob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

punyinform's Issues

"Switch on"

When a player types "switch on", instead of getting "I think you meant 'switch on something'", we get "you can't see any such thing". Presumably because the "on" is parsed as a noun. Is that something we need to worry about?

Similar MSG_INSERT_NOT_CONTAINER and MSG_EMPTY_CANT_CONTAIN constants

The two constants are similar, except that the second is configurable; is the first indispensable? For the translation, I will use the second one because the first one translates badly.

Constant MSG_INSERT_NOT_CONTAINER "That can't contain things.";
MSG_EMPTY_CANT_CONTAIN: print_ret (The) p_arg_1, " can't contain things.";

[ InsertSub
	if (second hasnt container) { PrintMsg(MSG_INSERT_NOT_CONTAINER); rtrue; }
[ EmptyTSub
	if(second hasnt container) { PrintMsg(MSG_EMPTY_CANT_CONTAIN, second); rtrue; }

Minor punctuation correction

Hi,

This barely qualifies as an issue at all, but I thought I'd mention it anyway:

Performing an action such as > PUT x DOWN returns the message "I don't understand that sentence" (i.e. without a full stop at the end).

Could the full stop be added, please?

Can't override SEARCH action with Cheap_Scenery SceneReply

Cheap scenery is very flexible in providing a way to let authors define scenery related replies via SceneReply.

Today I've created a SceneReply for the SEARCH action. But it did not work and that drove me crazy. Turns out (after investigating Cheap_Scenery's code) that you can define custom replies for every action except EXAMINE, which makes sense of course, and drumroll SEARCH, which I don't think makes sense. There is no use in preventing the author from defining a custom message here and the result, as it is now, is that you get the default "You find nothing special." reply. Just by taking out SEARCH from Cheap_Scenery's before [; routine you get two effects: 1) the standard "No need to concern yourself with that." message for scenery is being triggered if the author had chosen to not override SEARCH. 2) The author is able to define an own statement, for example like "There is no need searching this.". The code that would be subject for deletion is highlighted in the screenshot below.

image

Keyboard input tables initialized at each turn.

Hello,
Is it really necessary to set the values of parse_array->0 and player_input_array->0/1 at every turn and not only once at initialization?

parse_array->0 = MAX_INPUT_WORDS;
#V5
player_input_array->0 = MAX_INPUT_CHARS;
player_input_array->1 = 0;
#
player_input_array->0 = MAX_INPUT_CHARS - 1;

vehicle_mode

DM4 page 128: "If a player is inside an enterable object and tries to move, the before of the parent is called with , and can return 0 (disallow and print no), 1 (allow but move the vehicle with), 2 (silently disallow), 3 (silently allow)".
This is in verblibm.h, line 1805: run the routine "before", if k isn't 3 restore the location to the original one, if k isn't 1 rtrue (if it is 1 keep going, you and the vehicle will get moved).

Puny doesn't differentiate between 2 and 3. The only difference in Inform's code is that Inform saves the location (j=location), then restores it (location=j) if the answer of the before is 2. That's a bit confusing; but i guess it's to prevent people from changing location and then returning 2? (But why would you change the location if you're planning on printing 2??)

I'm having a hard time following Inform's logic here, so maybe I'm missing something. But maybe Puny should rephrase the comment on line 1607 of grammar.h, to emphasize "contrary to inform, we treat 2 and 3 the same, so don't change the location if you return 2 please". Or change the code to match Inform's logic (whatever it is).

Exit after routine not running for enterable supporters

Hi,

PunyInform doesn't seem to be running the Exit action defined in an after routine for an enterable supporter, and is instead displaying the default message every time.

Here's some example code:

Object example_room "Example Room"
	with description "You are in an example room, for test purposes.",
	has light;

Object platform "stone platform" example_room
	with
		name 'stone' 'platform',
		after [;
			Enter:
				"You stand on ", (the) self, ", raising yourself a couple of feet from the ground.";
			Exit:
				"You step down from ", (the) self, ", back onto the floor.";
		],
	has enterable supporter;

When compiled with PunyInform, the player is shown the standard library message when leaving the stone platform, instead of the message defined in its Exit after routine:

Example Room
You are in an example room, for test purposes.

You can see a stone platform here.

> stand on platform
You stand on the stone platform, raising yourself a couple of feet from the ground.

> get off platform
You leave the stone platform.

> 

Whereas using the standard libraries, the Exit after routine runs as expected:

Example Room
You are in an example room, for test purposes.

You can see a stone platform here.

>stand on platform
You stand on the stone platform, raising yourself a couple of feet from the ground.

>get off platform
You step down from the stone platform, back onto the floor.

>

As the above example shows, the Enter after routine works correctly each time.

MSG_PARSER_NO_INPUT

For some reason

  • when you press Return, you get "Come again?" and a missing new line before the next prompt
  • when you type an unknown verb, the new line is there.
    That's despite the code in parser.h (line 1335 and 1351) being very similar, as well as the definition of these messages...

Compiling example .inf files on ubuntu 20.04 fails

Hi,

following the site instructions to install punyinform and compile the example .inf files e.g. minimal.inf, nada.inf or library_of_horror.inf results in errors (all the same) - see below. I suspect i am doing something wrong but i can't see what.

The version of inform 6.34 was compiled from the source linked from your information page.

Any ideas?

./inform6 +lib -v3 -s -e library_of_horror.inf
Inform 6.34 for Unix (16th August 2017)
"lib/globals.h", line 242: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static

Array abbr_direction_array static
"lib/globals.h", line 242: Error: Expected ';' but found Array
Array
"lib/globals.h", line 243: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array full_direction_array static
"lib/globals.h", line 243: Error: Expected ';' but found Array
Array
"lib/globals.h", line 244: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array direction_properties_array static
"lib/globals.h", line 244: Error: Expected ';' but found Array
Array
"lib/globals.h", line 245: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array direction_name_array static
"lib/globals.h", line 245: Error: Expected ';' but found #

"lib/globals.h", line 248: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static

Array _dir_start static
"lib/globals.h", line 248: Error: Expected ';' but found Array
Array
"lib/globals.h", line 249: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array _dir_end static
"lib/globals.h", line 249: Error: Expected ';' but found #

"lib/ext_flags.h", line 35: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static

Array flag_powers static
"lib/ext_flags.h", line 35: Error: Expected ';' but found Array
Array
line 231: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array quote_stairs static
line 231: Error: Expected ';' but found Array
Array
line 245: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array quote_darkchamber static
line 245: Error: Expected ';' but found Include
Include
line 871: Error: Expected '->', '-->', 'string', 'table' or 'buffer' but found static
Array opposite_directions static
line 871: Error: Expected ';' but found #

"<veneer routine 'RV__Pr'>", line 1: Error: A function may be called with at most 3 arguments

"read", obj, identifier, 2);
In: 10 source code files 5534 syntactic lines
8217 textual lines 218165 characters (ISO 8859-1 Latin1)
Allocated:
831 symbols (maximum 10000) 1032655 bytes of memory
Out: Version 3 "Standard" story file 2.200802 (34.5K long):
5 classes (maximum 64) 27 objects (maximum 255)
64 global vars (maximum 233) 1250 variable/array space (maximum 10000)
63 verbs (maximum 200) 228 dictionary entries (maximum 2000)
124 grammar lines (version 2) 234 grammar tokens (unlimited)
68 actions (maximum 200) 29 attributes (maximum 32)
27 common props (maximum 30) 11 individual props (unlimited)
18762 bytes of Z-code 214 unused bytes stripped out (1.1%)
19462 characters used in text 12458 bytes compressed (rate 0.640)
64 abbreviations (maximum 64) 245 routines (unlimited)
4381 instructions of Z-code 2692 sequence points
6310 bytes readable memory used (maximum 65536)
35130 bytes used in Z-machine 95942 bytes free in Z-machine
Compiled with 21 errors (no output)
Completed in 0 seconds

cheers

shifters

"What is"-verb in "Library of Horror" not working in v1.6 and v1.7

EDIT: The "What is"-verb works in v1.5 and older but not in v1.6 and v1.7. I don't know if the game has been updated or only PunyInform, but if I try to compile the inf-file from v1.7 with PunyInform v1.5 then the verb "What is" works also.

I am very interested in how to implement something similar to the verb "What is" in the demo-game "Library of Horrors". But before looking at the code, I would like to have an idea of how the game actually responds to the "what is"-verb. Thus I compiled the game and tried these topics as soon as the game started:

what is library
You haven't the faintest.

what is grue
You haven't the faintest.

what is manager
You haven't the faintest.

what is a library
You haven't the faintest.

what is the library
You haven't the faintest.`

From the code I can see, that the game has responses to these 3 topics, but nothing works.

The code:
topics
1 'library' "A library is venue where books are kept and people can borrow said books."
1 'grue' "A grue is a sinister creature lurking in the dark. If anyone has actually seen a grue,
they have not lived long enough to tell the tale."
1 'manager' "Library managers oversee the daily activities and functions of a library.";

So I have the impression that the "What is"-verb is not working as intended.
Thanks

Add_to_scope causing stack overflow

Hi,

I've found that if object A has object B in an add_to_scope property, and object B is subsequently moved to either the player or the player's current location while the player is carrying object A, the interpreter crashes with a stack overflow error. I've tested the code in Windows Frotz and Ozmoo and it happens in both. The crash doesn't occur if object B is moved to a different location.

I can currently work around it by setting object A's add_to_scope property to nothing before moving object B, as I only have one object added to the first object's scope in my code. That workaround obviously isn't viable if multiple objects are in the add_to_scope property.

Order of the directions

I'm trying to devise some compact code to get around in a series of room so that I only have to code one room + reactions to directions. There's a little something that makes this annoying in Puny.

I'm trying to go from selected_direction to FAKE_OBJ.
If I read "selected_direction-N_TO_CONST+FAKE_N_OBJ", I get : "N=10001, S=10002, E=10003, W=10004, NE=10005, NW=10007, SE=10006, SW=10008"
This is different from the definitions in globals.h, where NW = 10006 and SE = 10007. This is because the direction properties (line 134) are defined in a different order (N S E W NE SE NW SW) than the FAKE
_OBJ (N S E W NE NW SE SW).

Switching the value of the constants FAKE_NW_OBJ and FAKE_SE_OBJ would make it so one can go from "selected_direction" to "FAKE_N_OBJ" and back very easily, which would be good.
Furthermore I feel like you rely on this kind of arithmetic elsewhere (puny.h : lines 697 to 722), which, if I'm not mistaken, means that Puny switches Southeast and Northwest in these functions - definitely a bug.

Thanks!

Status line doesn't print the short_name if inherited

I defined a class of objects all with the same short_name (very useful to factor code in, e.g., a maze). However, the name that is written in the status line is not the right one; instead, it's the name of the room in brackets, as if short_name was empty. The I6 library doesn't have trouble with it. File is attached (same as issue 6)
tristam.txt

Default message not appropriate for VERB and NOUN not understood.

The default message "I don't understand that word." does not seem to be appropriate if several words that are not understood are typed:

> any any                                                                                                       
I don't understand that word. (Which word?)
> any                                                                                                           
I don't understand that word.                                                                                   
                                                                                                                
> x any                                                                                                         
Sorry, I don't understand what "any" means.                                                                     
                                                                                                                
> any any                                                                                                       
I don't understand that word.   

> GET ALL FROM container/surface

Hi,

Using the latest version of PunyInform, > GET ALL FROM a container or surface returns the response "There is nothing to get."

PUT ALL IN/ON container/surface works correctly, which makes me think this is a bug rather than an intentional limitation.

Make it easier to compile sample games.

Wouldn't it be easier for beginners to add '!% +include_path=./lib' to the header of the example files, which makes compilation easier?

!% -~S
!% $OMIT_UNUSED_ROUTINES=1
!% +include_path=./lib

Status line doesn't update

Not sure this is a puny bug, but...

Several interpreters do not update the status line, or show the wrong thing, or garbage. This includes Edilbert Kirk's VIC-20 interpreter (showing garbage in the name of the room), Fabularium (no room shown, no update for score and turns) and ZXZVM for Spectrum & CPC (no room shown, no update for score and turns). If it was a problem happening on only one terp I'd say it's a terp bug, but...
Any idea what's happening?

Time broken in v3

Using the code of the manual example of "Time-based Games" and compiling to Z-Code version 3, the clock jumps around on every turn, but in a weird, predictable way.

In Initialise:

SetTime(23 * 60 + 7, 1);

Initial time displayed in the status line: 10:23 (so already wrong).

Moving around:
W --> 18:23
E --> 10:23
E --> 17:23
W --> 10:23
S --> 16:23
N --> 10:23

Compiling the same code to v5, time works as expected.

GrabIfNotHeld

This function (defined in parser.h) ends in "if(p_noun notin player) rtrue;". But a lot of places that use it (1 in parser, 3 in grammar) call it (_GrabIfNotHeld(noun)) then check "if noun notin player".

(I tried to fix it quickly but it broke my game. I'm hoping someone with better unit tests will be able to fix it :D)

Using creature grammar token

Hi,

It seems that verb routines in PunyInform don't currently differentiate between animate and inanimate objects when using the creature grammar token.

For example, defining a new verb "Talk":

Verb 'talk'
	*	'to'/'with'	creature	-> Talk;

[TalkSub;
	if (noun == player) "The conversation is hardly inspiring.";
	if (RunLife(noun,##Talk) ~= false) return;
	"You have nothing to say.";
];

Compiled with PunyInform, this code allows the player to talk to an inanimate object (e.g. > TALK TO CAR) and receive the message "You have nothing to say."

Compiled with the standard Inform libraries, the same code and the same player action returns the message "You can only do that to something animate." In other words, it appears the library is aware that the action has been invoked against an inanimate object and prevents TalkSub from running on that basis.

Should PunyInform act in the same way?

Extra line feed after a question mark

Sometimes there is a line feed after the interogation mark or not.

> restart                                                                                
Are you sure you want to restart?                                                        
n                                                                                        
                                                                                         
> quit                                                                                   
Are you sure you want to quit? n                                                         
                                                                                         
> quit                                                                                   
Are you sure you want to quit? any                                                       
Please answer yes or no:                                                                 
n   

Property nw_to missing in #Ifndef OPTIONAL_FULL_DIRECTIONS

Isn't the nw_to property missing in #Ifndef OPTIONAL_FULL_DIRECTIONS?

#Ifndef OPTIONAL_FULL_DIRECTIONS;
! These have to come outside the other direction props if we DON'T HAVE full directions
Property ne_to;
Property se_to;
Property sw_to;
#EndIf;

No more room description after an up-down

I lose the description of the location if I go up and down, or the other way around.

!% -~S
!% $OMIT_UNUSED_ROUTINES=1
Constant INITIAL_LOCATION_VALUE = room1;
Include "globals.h";
Include "puny.h";

Object room1 "Room 1"
with
description "You are in room 1.",
u_to room2,
has light;

Object room2 "Room 2"
with
description "You are in room 2.",
d_to room1,
has light;

[ Initialise; ];
Room 1                                                                              
You are in room 1.                                                                  
                                                                                    
> u                                                                                 
                                                                                    
Room 2                                                                              
You are in room 2.                                                                  
                                                                                    
> d                                                                                 
                                                                                    
Room 1                                                                              
                                                                                    
> 

"noun=Routine" tokens are incorrectly displayed in _FixIncompleteSentenceOrComplain

Consider the following verb definition with a general parsing routine to create a new token:

[NotHeld;
if(noun in player || noun == 0) {rfalse;} else {rtrue;}
];
Verb 'steal'

  • noun=NotHeld ->Take;

If a player types "steal", the message is "I think you wanted to say steal (random garbage)". The garbage happens on line 1108 of parser.h, when trying to print whatever is at the address.
If I write "*noun ->Take" it's correct ("I think you wanted to say steal something")

Could the fact that it's a routine be detected, and in that case treat it like a noun, i.e. print "something"? (Only "noun=Routine" is allowed by the I6 compiler.)

Timers out of sync when manually advancing turn count

Maybe I'm approaching this in a fundamentally wrong way...

I have several timers running to trigger events. They work exactly on spot when playing normally. However, I also have a SLEEP action which advances time significantly. I'm doing this by manually increasing turn count:

turns = turns + 50;

This works fine as far as the turn count itself is concerned. However, for the purpose of timers, the SLEEP action only advanced the time_left by one, i.e. it does not heed/notice the jump in turn count.

I can work around this by stopping the timer and restarting it with a manually recalculated timeout. Though I'm wondering if this is intended behaviour.

Make darkness and carrying capacity optional

Not an issue per se, but a proposal/feature request. I think only a miniscule number of games use these mechanics. First thing I always do in a new project is define a Room class with "has light" in order not to be further bothered by this. I see that both may have their specific uses, but in general, they can be considered a waste of space.

"Sometimes meta" verbs

Some verbs can be tagged as "meta" in their declaration (that is, they don't increase the turn counter).
Sometimes, some way to use the verb is meta, and some other isn't. ("Restart vs Restart generators" is the case I have, there's also "about vs about face", or in French "quitter vs quitter robe" (quit vs disrobe))

The standard from I6 is to use a GPR and turn on "meta" during the parsing, as at the end of this page: http://www.firthworks.com/roger/informfaq/vv.html

In puny, this doesn't work; I get "I think you wanted to say 'restart something'" when I try to restart. Is it a puny bug, or is there another way?

My code is this btw:
[ isMeta; meta = true; return GPR_PREPOSITION; ];
Extend 'restart' replace

  • isMeta ->Restart
  • noun ->SwitchOn; ! restart generator

Menu titles are not centered correctly

In the ext_menu.h extension, the centering calculation of the menu titles seems to be wrong:
j=1+(i/2-main_wid)*cw; j=1+(i/2-item_width)*cw;
This seems more correct:
j=1+((i-main_wid)/2)*cw; j=1+((i-item_width)/2)*cw;

And 'cw' being initialized to 1, multiplication and so on are of little use.

Infinite loop when using "PerformAction"

I have a house, and I have a door. I want Open, Close, Unlock, and Lock house to be redirected to the door. I write in the house:

before [; Open, Close, Unlock, Lock: PerformAction(action, mydoor);

with 'action' the global that holds the action (because i don't want to change the action, just the noun).

This causes an infinite loop. As far as I can tell:

  • PerformAction changes "action" to the first argument, "noun" to the second, and "second" to the third argument
  • Then it calls PerformPreparedAction
  • This calls BeforeRoutines
  • BeforeRoutines checks some stuff, and then (line 631 of puny.h) looks at the before of inp1. But inp1 (input 1?) is the noun that was recognized by the parser - house, not door!

So: can we change "inp1" to "noun" at this point? Or will that break? (I did, and it looks fine, but I'm not 100% sure that I should...) Or should I just never use PerformAction? (But will this be a bug that'll reappear somewhere else?)

Can with_key be a routine?

I just posted this issue on the I6 library repository. Since it's a request to support a behavior that the compiler doesn't complain about (and it's not affecting anyone else's code), I'm also requesting it here, regardless of the decision made for the I6 lib :) I'll add that it'd be great in order to save space: I'm currently folding 10 doors into one object to economize on objects, and this feature would be good (if not, I'll find a hack to make it work, but...)

Can with_key be a routine? e.g.
Object doorToApartment
with short_name [; if (divorce_happened) { return "Door to our apartment"; } else { return "Door to her apartement";} ],
with_key [; if (divorce_happened) { return newkey; } else { return oldkey; } ],

It's not specified in the DM4 or anywhere else, from what I can see. The compiler never complains either.

It would make sense, though, since there are several other properties in inform (cantgo, n_to, door_to, door_dir, etc) that are either the name of an object or a routine that returns an object. However, currently, in grammar.h, the LockSub and UnlockSub only check (I'm paraphrasing here)
"if (noun.with_key ~= second) { "Doesn't fit."; }"

Can we generalize the code so that both an object name or a routine that returns an object can be supported?

Score isn't displayed at the end of a game

Should ScoreSub() be called at the end of a game? (Line 1283 of puny.h)
"MSG_SCORE_SUCCESS" has support for when called when the game ends, which is good, but that's never used...

sw_to affects debug verbs

Hi,

This is a strange one, but easy to replicate. If I enable debugging, then define a sw_to room exit anywhere in my code, any debug verb that takes a noun (e.g. gonear, purloin) fails with the following response:

> purloin table
I only understood you as far as "purloin table" but then you lost me.

Amending the sw_to to any other direction and recompiling fixes the debug verb behaviour.

Held grammar token

Hi,

This is similar to issue #14: PunyInform doesn't seem to require that an object specified by held in a grammar definition is actually held by the player, as long as it's currently in scope.

The standard Inform 6 library will attempt to pick up the specified in-scope object if the player isn't holding it. If that Take action fails, then the new verb routine (or any associated before routines) will not run. However, PunyInform will proceed with the new action regardless.

Extra characters "***" displayed, if deadflag == GS_QUIT

In puny.h, the print() should be after the 1st deadflag test.

print "^^  *** ";
if(deadflag == GS_QUIT) @quit;
The Library                                                           
You are in a library.                                                 
                                                                      
You can see a box (which is empty) here.                              
                                                                      
> q                                                                   
Are you sure you want to quit? y                                      
                                                                                                                                       
  ***  

Maybe a useless initial space?

Is the space before each word necessary?

Constant MOVES__TX = " Moves: ";
Constant SCORE__TX = " Score: ";
Constant TIME__TX = " Time: ";

Opening a door reveals its contents

Is it correct when opening a door object that a message tries to display its content?

> open door                                                                              
You open the stone door, revealing nothing.
!% -~S
!% $OMIT_UNUSED_ROUTINES=1

Constant OPTIONAL_NO_DARKNESS;
Constant INITIAL_LOCATION_VALUE = room1;

Include "globals.h"; Include "puny.h";

Object room1 "room1"
   with
      description "You are in room1. Room2 is to the west.",
      w_to stonedoor;

Object room2 "room2"
   with
      description "You are in room2. Room1 is to the east.",
      e_to stonedoor;

Object stonedoor "stone door"
with
   name 'door',
   description "It's just a stone door.",
   door_to [;
      if (self in room1) return room2;
      return room1;
   ],
   door_dir [;
      if (self in room1) return w_to;
      return e_to;
   ],
   found_in room1 room2,
has static door openable ~open;

[ Initialise; lookmode = 2; ];

n_to, etc executed when entering a room

The code attached has different behavior in Puny and I6libs. Puny executes all the directions upon entering the new room when these directions are routines. (I'd like these to be able to be routines, in order to create interesting behavior without copy-pasting code. Didn't see anything in the manual that prohibits this behavior...)
My intuition is that Puny stores these somewhere when entering a new room, but doesn't check whether they are routines or not.

Code :

[ Move ;
print "Hahaha nope^"; rtrue;
];

Object loc "Test room"
with description "This is a test",
s_to loc2,
has ;

Object loc2 "Test room 2"
with description "",
n_to Move,
s_to Move,
e_to Move,
has ;

Maybe an extra space?

I don't know if this is done on purpose, but when displaying "*** You have won. ***", there are two spaces before the final stars: "won []***".

"_LookForLightInObj" and open containers

The condition to look for light is "if(p_obj == p_ceiling || p_obj has transparent || p_obj has supporter || (p_obj has container && p_obj has open))"

If I'm not mistaken, an open container is something that can receive objects but not automatically list them (in the description, for instance - you have to look inside). For instance, a backpack.
If you want the object list to be displayed, you have to give it "transparent". Additionally, I believe that "transparent" is also a condition adding the contents to the scope.

So:

  • putting a flashlight in an empty fish bowl should still give off light: "p_obj has transparent" should be a condition that's accepted (if it's good enough for the scope...)
  • if I put my flashlight in an open backpack, should the room still be lit? I.e. should it be "open and transparent", or "open or transparent"

Score notification when score goes down?

Inform notifies the player when the score goes up, but also when it goes down. Shouldn't Puny do the same? (There's definitely a point in my game where you can lose points.)

Parser misinterprets get/drop command followed by multiple sentences containing directions

Hi,

If the player tries to get or drop an item, followed by a series of movement commands, with the get/drop item command and movement commands all on one line, separated by full stops, then each movement command seems to be misinterpreted by PunyInform as a request to either get or drop the last direction in the sequence, instead of moving in the specified direction.

For example:

Minimal
A sample game which uses PunyInform.
Release 1 / Serial number 210110 / Inform v6.34 PunyInform v1.8 D

Example Room
You are in an example room, for test purposes. A similar-looking room lies to the west.

You can see a lead weight here.

> get weight.w.e
lead weight: Taken.
east: That's hardly portable.
east: That's hardly portable.

> 

If the subsequent movement commands are in the form (e.g.) GO NORTH rather than N or NORTH, everything works as expected:

Minimal
A sample game which uses PunyInform.
Release 1 / Serial number 210110 / Inform v6.34 PunyInform v1.8 D

Example Room
You are in an example room, for test purposes. A similar-looking room lies to the west.

You can see a lead weight here.

> get weight. go west. go east
Taken.


Another Example Room
You are in another example room, again for test purposes. The other example room is east.


Example Room

>

(Side note: it actually looks like there's an additional newline between each location in the above output, compared with how the standard I6 library outputs the same code. I can raise that as a separate issue if it's a bug rather than design.)

Wrong message after a Restore command that failed after an end.

Object -> apple "apple"
 with name 'apple',
 description "It's an apple.",
 After [;
  Take: deadflag = 2;
 ],
 has edible;
> get apple
Taken.

  *** You have won.  ***

Would you like to RESTART, RESTORE or QUIT? restore
Enter a file name.
Default is "minimal.qzl": 
Failed get. [*** Failed restore, would be better ***]

Would you like to RESTART, RESTORE or QUIT?

And something else if you're looking for trouble and you like it, with deadflag in Initialise:

[ Initialise;
   deadflag = 2;
];
  *** You have won.  ***

Would you like to RESTART, RESTORE or QUIT? restore
Enter a file name.
Default is "minimal.qzl": 
Failed  t       w xI donu k   rreal   glkgdlgdt dwfzq P.

But I think you can forget about that!

Priority of MSG_TAKE_SCENERY and MSG_TAKE_STATIC messages for the action Take.

For Pull, Push and Turn actions the static attribute has priority over the scenery attribute, but not for the Take action. It seems more interesting to me to keep the priority of the static attribute over the scenery attribute although the current behavior is consistent with that of the standard Inform 6 library.

[ PullSub;
   ...
	if (noun has static)   { PrintMsg(MSG_PULL_STATIC); rtrue; }
	if (noun has scenery)  { PrintMsg(MSG_PULL_SCENERY); rtrue; }
];
[ PushSub;
   ...
	if (noun has static)   { PrintMsg(MSG_PUSH_STATIC); rtrue; }
	if (noun has scenery)  { PrintMsg(MSG_PUSH_SCENERY); rtrue; }
];
[ TurnSub;
	...
	if (noun has static)   { PrintMsg(MSG_TURN_STATIC); rtrue; }
	if (noun has scenery)  { PrintMsg(MSG_TURN_SCENERY); rtrue; }
];

The attribute scenery has priority here:
[ TryToTakeNoun _i _k _ancestor _after_recipient;
   ...
   if(noun has scenery) { PrintMsg(MSG_TAKE_SCENERY); rtrue; }
   if(noun has static) { PrintMsg(MSG_TAKE_STATIC); rtrue; }
];

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.