New to PunyInform and Inform6

Hello to the community,

I have just found PunyInform and start to learn it. There is a german podcast speaking with the author Stefan Vogt and his text adventures like Hibernated which drew my attention.

Many year ago I played the adventures from Infocom on my C64, now I played them again on Frotz. I like the idea that new games could be played on nearly every machine from past to present.

I downloaded the documentation, but from time to time I have problems with my programming;=)

As I am new in this forum I woud like to ask, if it is ok to ask for help here or if there would a better place to do so?

Greetings from Germany and a great thank for the ressources here!

Thomas

3 Likes

I think asking here is fine, but I would also recommend the PunyInform discord!

2 Likes
Object Tree "Tree"
	with 
		name 'branches' 'tree' 'trunk' 'leaves', 
		description "^You approach the massive tree, its gnarled branches stretching high above you. As you reach for the sturdy trunk, 
		the rough bark feels solid under your hands. Carefully, you find your footing on the lower branches, pulling yourself up with 
		a surge of excitement. With each step higher, the view opens up around you. The forest floor becomes a tapestry of green, and 
		the wildflowers below seem to sway gently in the breeze. The air is cooler up here, and you can hear the rustle of leaves as 
		they dance in the wind.",
		d_to Clearing,
		u_to TreeTop, 
		cant_go "There is no other way than down or up in the tree",
	has light, has scored;

How can I add “Climb” to this location? A little hint would be great;=)

Thomas

I’m not up-to-date on PunyInform, but since it’s mostly modeled after the Standard Library, hopefully this will be useful information.

It looks like the Tree object is intended to be a room.

The ##Climb action is built into the Standard Library, but it expects an object on which to act, i.e. a command of form >CLIMB TREE instead of just >CLIMB. The room itself would not normally be that object.

You would either need to create an actual “tree” object to place within the room, and use the before property of that, and/or you would need to implement something to allow >CLIMB without a direct object.

Extend 'climb' first
	    * -> Climb;


Object dummy_tree "tree" Tree
	    with
	            name 'branches' 'tree' 'trunk' 'leaves',
	            react_before [;
	                    Climb:
	                            if (noun == nothing) <<Climb self>>;
	            ],
	            before [;
	                    Climb:
	                            if (location == Treetop) "You're as high up as you can get.";
	                            else <<Go u_obj>>;
	            ],
	    found_in Clearing Tree Treetop,
	    has scenery;
1 Like

Firstly, a few general comments:

  1. Remove the name property from Tree, as you will need this for the dummy_tree object (see below).
  2. Remove the linefeed (^) from the start of the description.
  3. Change “You approach” to something like “You are in”, as the "approach"ing is only valid when you first enter the location and you are not approaching the tree, but midway up it.
  4. The has property is an array of attributes, so you can say has light scored, rather than separate has properties.

Now, let’s think about this logically. You have three locations: Clearing, Tree and Treetop. You can go up from Clearing to Tree and from Tree to Treetop. You can go down from Treetop to Tree and Tree to Clearing.

Climbing the tree from Clearing is the same as going up. Climbing the tree from Treetop is the same as going down, but climbing the tree from Tree (midway up the tree) is ambiguous, because you don’t know whether that means up or down.

You need a scenery object for the tree. As its name and description are probably the same, this should be a floating object, as in @otistdog’s example. You also need a before rule to handle climbing the tree and this can simply redirect to the appropriate up or down movements. This is done slightly differently in PunyInform compared to the standard library.

Putting all this together, the tree scenery object needs to look like this:

Object dummy_tree "tree"
with
  name 'branches' 'tree' 'trunk' 'leaves',
  before
  [;
    Climb:
      if (self in Clearing)
        <<Go FAKE_U_OBJ>>;
      if (self in Treetop)
        <<Go FAKE_D_OBJ>>;
      "Up or down?";
  ],
  found_in Clearing Tree Treetop,
has scenery;
2 Likes

Hello Garry,

I thank you so much for your valued advice. This evening I will implement this and surely will learn a lot. As I said I have read some manuals, but often I am not sure, if I think to complicate or not;=)

Thomas

1 Like

You may also want to add the capability to “climb up/down” and “climb up/down tree”.

This can be done with a react_before rule in dummy_tree.

E.g.

Extend 'climb'
  * noun noun -> ClimbWithSecondNoun;

[ ClimbWithSecondNounSub;
  "I'm not sure how to do that here.";
];

Object -> dummy_tree "tree"
	with name 'tree',
    react_before [ obj;
      Climb, ClimbWithSecondNoun:
        if(noun == Directions && second == self or 0) {
          obj = DirPropToFakeObj(selected_direction);
          <<Go obj>>;
        }
    ],
	has scenery;

Thank you so much, now it works like a charm;=) I have a second question. When implementing my farmhouse I have some furnitures in it like a bed. In the bed I can find a book when I search for it. Here is my code for this:

Object Farmhouse "Farmhouse"
	with 
		name 'farmhouse' 'house' 'room',
		description "Through the windows the sunlight illuminates the room. The warm, earthy scent of aged wood fills the air in this tiny 
		farmhouse, with its exposed beams overhead and weathered walls. The sunlight bathes the room in a soft glow, revealing a handful of 
		simple but essential furnishings. You can see a bed. ",
		n_to OutsideFarmhouse, 
	has light scored;
	
Object -> bed "bed",
    with 
		name 'bed',
		description "Against one wall, a narrow bed covered in a patched woolen blanket looks sturdy yet well-worn.", 
	has enterable supporter static scenery;
	
Object ->-> book "book",
    with 
		name 'book',
		description "The leather-bound book is small and rugged, its cover worn smooth by countless fingers that have traced its edges.",
	has scored;`

At first I think this would work fine. I have to search the bed to find the book.

Farmhouse

Through the windows the sunlight illuminates the room. The warm, earthy scent of aged wood fills the air in this tiny farmhouse, with its exposed beams overhead and weathered walls. The sunlight bathes the room in a soft glow, revealing a handful of simple but essential furnishings. You can see a bed, a table with four chairs and a kitchen.

Through the open door you can see the yard in front of the little farmhouse to the north.

[The score has just gone up by 1 point.]

examine bed
Against one wall, a narrow bed covered in a patched woolen blanket looks sturdy yet well-worn.

search bed
On the bed is a book.

This is all fine for me, but when I enter the farmhouse and say “Get All” I will see the book in the bed without searching the bed.

Is has scenery not a good idea?

Thomas

There are different ways to do this.

You can place the book elsewhere (typically nowhere), then move it to the bed when the player searches the bed.

Another option is to give the book the concealed attribute from the start, but remove it when the player searches the bed or does any action that involves the book.

1 Like

Everything is complicate in the beginning;=) Do you have a line of code for me for removing CONCEALED when searching the bed?

Thomas

1 Like

I will learn;=) With the first hint “climb” I was able to fix some other parts of my first little IF in PunyInform…

Thomas

1 Like

give book ~concealed.

This said, I strongly suggest AGAINST using the verb “search” for such a thing. An EXAMINE should be enough (or you can use both). You risk making the players mad. :slight_smile:

ETA: also remember to test if the book has been found already, otherwise it will pop-up any time the player examines the bed.
I usually do this by using the general flag.

Something in the lines of:

if (self hasnt general) {
    move book to [location];
    give self general;
    "Oh! You found a book!";
}

Use this in an after routing, instead of before, so the examine rule will launch anyway.

1 Like

Worth noting: If you decide to move the book into the player’s inventory when they find it, you must also set update_moved = true;. This makes sure that the book gets the moved attribute (meaning it has been moved by the player), and the player’s score gets updated if the book has the scored attribute.

If you just leave the book in the bed, and it’s up to the player to pick it up, this will be handled by TakeSub.

1 Like

Personally, I would recommend against using the -> notation for placing objects, as it can get horribly confusing when you start moving things around in your code. Instead, explicitly place the object where you want it by giving its parent after the object’s textual name. This is described in section 3.3 of the DM4.

Also, an object should be scenery or static, not both. Use scenery if it’s part of the room description and you don’t want it listed as a separate object. Use static otherwise.

Try this. The book is initially nowhere. Examining the bed will cause it to appear once and only once. In addition, examining the bed will tell you what’s on it, so you don’t have to guess.

Object bed "bed" Farmhouse
with 
  name 'bed',
  description
  [;
    if (book in nothing)
      move book to self;
    print "Against one wall, a narrow bed covered in a patched woolen blanket looks sturdy yet well-worn.";
    <<Search self>>;
  ],
has enterable static supporter;
	
Object book "book",
with 
  name 'book',
  description "The leather-bound book is small and rugged, its cover worn smooth by countless fingers that have traced its edges.",
has scored;

I think you should also make the woolen blanket a separate object, rather than a part of the bed. Otherwise, searching the bed will tell you there’s nothing on it, but that’s not true. There’s a blanket on it. In fact, you could hide the book under the blanket for a nicer and more logical solution.

3 Likes

The above example by Garry is perfect. Just watch out because a book is something that can get lost (or burnt into a fireplace or whatever) and that would — I think — revert its placement in “nothing”. So any time you destroy the book it will be found anew in the bed. For cases like this it’s better to use the “general” trick I exemplified above.

2 Likes

If the book can be destroyed, then don’t remove book;, but move book to limbo; Limbo is a dummy location which is declared as Object limbo;

This is a common trick that many authors use. In this way, you can still use the general attribute for something else. I always use it to indicate that the book has been read. For example:

Object book "book"
with
  description
  [;
    print "It's a musty old leather-bound book with a gilt title 'Magic Spells of the Druids'.";
    if (self hasnt general)
      print " Perhaps you should read it.";
    "";
  ],
  before
  [;
    Read:
      give self general;
      "You flick through the pages until you come to the MUNCHO spell. If you CAST MUNCHO, you can satisfy your hunger.";
  ],
has;
2 Likes

That makes sense and I will implement it…

Thomas

Thank you so much, this helps really a lot. I changed some locations and can learn a lot…

Do you think it could be possible in the future to make some good ressources for beginners like me especially for PunyInform?

Thomas

1 Like

I found that "Constant OPTIONAL_FLEXIBLE_INVENTORY; " let me choose the form of my inventory, so that I can write “inventory tall” to have one item in one line. Is it possible to declare that as the the default form?

Thomas

1 Like

You can set inventory_style = 0; in Initialise.

2 Likes