Figure Score after player asks

I’m making a goofy little game where a player gets points for every treasure placed in a container. For a while I was increasing score when an item was found and decreasing when it was dropped, but then I ran into problems with scoring after an item was found, put in carried container, removed, put in pocket, returned to container, and so forth, because it was in the player’s possession when it was in the pocket and so forth, but anyway, that’s not important.

It occurred to me to just figure the score when the player asks, by counting the treasures in the container. Who cares if he has found and dropped it three times, put it in a pocket and so forth?

So the question is, can you figure score after the player asks? I got errors from “intead of scoring” and “instead of saying score”.

Obviously I can do (psuedocode, too lazy for syntax right now):

Every turn:
score is 0;
If the treasure1 is in the container, increase score by 1;
If the treasure2 is in the container, increase score by 1. [etc]

But that seems like a lot of overhead, can I figure it only after he asks?

Thanks!

Patience, is what I need.

There were tons of examples in the documentation using “score” and after consulting many of them I figured my question was a needle in a haystack. Found it though:

Instead of requesting the score: say "test".

Then again, this compiles but isn’t working:

After requesting the score: now the score is 0; if the treasure1 is in the container, award 1 point; say "test".

Ditto with “before requesting the score”, “instead of requesting the score”, removing the line “now the score is 0”, and saying “increase score by 1” instead of “award 1 point”.

It doesn’t even say “test”, so I guess it isn’t even firing.

Carry out requesting the score: now the score is 0; if the treasure1 is in the container, award 1 point; say "test".

works.

I’ll shut up now.

erghh!!

code:

Carry out requesting the score: now the score is 0; if the treasure1 is in the container, award 1 point; [etc with 11 more treasures] if the player is not carrying the container, now the score is 0; say "test".

Play:

This is not remnant code elsewhere as I tested it in a clean project.

First, why did the score go up, even though it was apparently undone right away?

Granted, “remove” assumed you were wearing the treasure, but I can see how someone might type that to remove the treasure from the container, and if the do they don’t need to get a score reporting, much less a confusing one.

It also happens with:

[code]>take treasure1 [out of container]
Taken.

[Your score has just gone up by one point.]

score
test
You have so far scored 0 out of a possible 0, in 4 turns.[/code]

In any case this could all be solved by turning off the reporting of the score at any time other than at the player’s request, can I do that?

I’m getting the same results you are. This may be an I7 bug, or it may simply be a side effect of the way the score awarding mechanism works. I’m betting it uses a procedural rule, and procedural rules aren’t listed by the RULES ALL command, which makes the problem tricky to diagnose.

So the question I need to ask is, why are you doing it this way? Why are you trying to recalculate the score on the fly when the player asks for the score? This was an attempt to solve another problem, wasn’t it? Maybe if we can fix the original problem…

I’ll go look at that message.

–JA

I can see the problem. It took me a few minutes to work out how to do what you seem to be describing. Try this example game:

The Lab is a room.
The player is carrying a fish, a banana, and a used hypodermic syringe.
The old shipping trunk is a closed openable container in the Lab.

After inserting the fish into the trunk:
	if the fish is in the trunk for the first time:
		award 1 point;
	continue the action.
After inserting the banana into the trunk:
	if the banana is in the trunk for the first time:
		award 1 point;
	continue the action.
After inserting the syringe into the trunk:
	if the syringe is in the trunk for the first time:
		award 1 point;
	continue the action.

One possible source of problems when you award points for having the player put something somewhere is that the After rule may run even if the action failed (which can happen, in the game above, if the player tries to put something in the trunk while the trunk is closed).

The solution, which I worked out by trial and error, is a sort of double test. First, is the action “inserting the banana into the trunk”? And within that, is the banana actually IN the trunk for the first time?

Try this and see if it solves the problem.

–JA

Well, I suppose it might be a little hokey, but I didn’t want the player to retain the point scored if he removed the item from the trunk (for example) after putting it in and getting a point for it, because the goal was to get everything there and leave it there. So the point would be 1 while it’s in there and 0 when it’s out, no matter how many times it’s pulled in and out. And checking the score while moving things in and out would help guide the player to the goal.

I think this is an I7 bug. It’s not that big a deal since it ultimately results in the correct score, but the incorrect reporting is undesirable.

I ended up putting this at the front of my game:

When play begins, try switching score notification off.

As far as I can tell the scoring is working right despite the weird reporting.

Oh, that’s not too difficult. Try this:

The Lab is a room.
The player is carrying a fish.
The old shipping trunk is a closed openable container in the Lab.

A thing has a truth state called points-awarded. The points-awarded of a thing is usually false.

After inserting the fish into the trunk:
	if the fish is in the trunk:
		if the points-awarded of the fish is false:
			now the points-awarded of the fish is true;
			award 1 point;
	continue the action.

Instead of taking the fish:
	if the fish is in the trunk:
		award -1 point;
		now the points-awarded of the fish is false;
	continue the action.

I tested this a bit, not exhaustively. The point can be awarded and un-awarded over and over. Of course, you’ll need to write those two rules for every scored object in your game, but that’s par for the course in IF.

–JA

Actually, the truth state isn’t needed. This seems to do the job:

After inserting the fish into the trunk:
	if the fish is in the trunk:
		award 1 point;
	continue the action.

Instead of taking the fish:
	if the fish is in the trunk:
		award -1 point;
	continue the action.

Thanks for bringing up this topic. I’ve added it to the Handbook!

–JA

This is because changing the variable “score” automatically prints an announcement about the points won/lost at the end of the turn. SCORE, being an out-of-world action, doesn’t count as a turn, so the score announcement doesn’t print until the next action the player takes.

If you really want to calculate the score on the fly, you’ll have to do it with a different variable. Or, better, forget the variable altogether, like so:

[code]Part 1 - Score Code

A thing can be valuable. A thing is usually not valuable.
[All treasures should be marked as valuable.]

To decide what number is the dyna-score:
if the player is not carrying the chest, decide on 0;
otherwise decide on the number of valuable things in the chest.

Carry out requesting the score:
say “You have so far scored [dyna-score] out of a possible [number of valuable things], in [turn count] turns.”;
stop the action.

When play begins:
change the right hand status line to “[dyna-score]/[turn count]”.

Part 2 - Testing Stuff

Lab is a room.

The Ming vase is a valuable thing in the Lab.

The chest is a container in the Lab.

Test me with “get all / score / put vase in chest / score / drop chest / score”.[/code]

The problem with that, however, is that it never prints a score notification when things are added to or removed from the chest, and if you want to use the score to remind players what they should be doing with the treasures, that’s probably a bad thing. I would do it with rules that award and subtract points for placing items in the chest. This is an easy way to do it:

[code]Part 1 - Score Code

A thing can be valuable. A thing is usually not valuable.
[All treasures should be marked as valuable.]

After inserting a valuable thing into the chest:
award 1 point;
continue the action.

Before taking a valuable thing when the noun is in the chest:
award -1 points.

After dropping the chest when a valuable thing is in the chest:
let x be the number of valuable things in the chest;
decrease the score by x.

Part 2 - Testing Stuff

Lab is a room.

The Ming vase and the diamond necklace are valuable things in the Lab.

The chest is a container in the Lab.

Test me with “get all / score / put vase in chest / score / get vase from chest / score / put vase and necklace in chest / score / drop chest / score”.[/code]

Jim and Emerald,

Thanks so much for the code snippets. They were all much more elegant than what I was trying to hobble together.

I’m confused though – as far as I can tell it announced an increase in point where a decrease would have been appropriate (take treasure when the treasure was in the chest should have decreased a point). And also it seemed to lie, or at the very least undo what it did immediately after it did it. And if it undid, why didn’t it announce that too?

SCORE, being an out-of-world action, doesn't count as a turn, so the score announcement doesn't print until the next action the player takes.

Then why didn’t it report the loss at the turn after the turn in question?

It would be good to understand what Inform is up to for educational purposes, but in the end, this is buggy as far as the end user experience is concerned and has to be worked around. Looks like I have several options for doing that now! Thanks!

Because the increase it’s reporting is from the “award 1 point” in the “Carry out requesting the score” rule. The way your system works, the score only changes when the player types SCORE, not after the player puts a treasure in the container or takes it out again. (Look at the score in the status line.)

So the player types SCORE. The game changes the score to 0 and then adds a point for each treasure. After the next in-world action the player takes (in this case REMOVE TREASURE1, but it could just as well have been LOOK or X TREASURE1 or JUMP or something), I7 notices that the score has changed and reports the change. If you put three treasures into the container and then typed

SCORE
REMOVE TREASURE1
the game would report that your score had gone up by 3.

Does that make sense?

I’m a little late to the party, but let’s see if I can help. The reason the score reporting mechanism seems “buggy” is that you modified a fundamental part of it without taking that into account. Granted, the docs don’t explain the details, but I’ll try.

The notify score changes rule is listed in the turn sequence rulebook (see index). Since out of world actions aren’t supposed to advance time, etc., they prematurely end the turn sequence rules, skipping everything after the generate action rule (including notify score changes). When you changed the carry out rules for requesting the score (an out of world action), you didn’t just change the way the score is modified, you inadvertantly postponed notification as well.

The reason the notification is delayed until the next turn is due to the way the notification works. Basically there are actually two score variables in I7: the score and the last notified score (see List of named values in the Contents index). The notification code merely checks the current score against the last notified score and, if it is different (i.e. if the score isn’t the same as the last time this was checked) it prints a notification. So here’s what happened with my comments in italics:

Just noticed a couple of bugs in my second snippet of code. (It didn’t account for picking up the chest when it contained valuables, and it was missing a “continue the action”.) Fixed:

[code]Part 1 - Score Code

A thing can be valuable. A thing is usually not valuable.
[All treasures should be marked as valuable.]

After inserting a valuable thing into the chest:
award 1 point;
continue the action.

Before taking a valuable thing when the noun is in the chest:
award -1 points.

After taking the chest when a valuable thing is in the chest:
let x be the number of valuable things in chest;
award x points;
continue the action.

After dropping the chest when a valuable thing is in the chest:
let x be the number of valuable things in the chest;
decrease the score by x;
continue the action.

Part 2 - Testing Stuff

Lab is a room.

The Ming vase and the diamond necklace are valuable things in the Lab.

The chest is a container in the Lab.

Test me with “get all / score / put vase in chest / score / get vase from chest / score / put vase and necklace in chest / score / drop chest / score / get chest / score”.[/code]

Emerald and Mike:

Thanks for the explanations. I think I understand but I’ll have to mull it over some. It helps to know that there is both a “score” and “last notified score”.

While I know it’s not the most elegant approach, is my scoring working correctly? It seems to be but obviously I can’t have tested every contingency. What I’ve done is what I’ve described above: calculated the score on the fly after requesting score, and turned off notifications. (I’m also wondering if the way I turned off notifications is the simplest way, looks a little overkill).

I ask because I like to finish a game before going back and making things that work more elegant. It keeps me motivated to have some finished (if ameteur) stuff out there. But learning and doing it right next time is important too.

If you want to do it this way, you’ll have to: turn off score notification, turn off the ability of the player to turn it back on, and remove the score from the status line (since it won’t be accurate). The easiest way to do these three things is:[code]The notify score changes rule is not listed in the turn sequence rulebook.

Understand the command “notify” as something new.

When play begins:
change the right hand status line to “[turn count]”.[/code]Note that removing the command “notify” also removes “notify on” and “notify off” automatically.

As I suspected, more issues unforseen to me. Thanks Skinny Mike!

Found a flaw with my method. There’s no good way to end the game unless the player says score.

I am totally new to I7 myself, but this problem intrigues me. Couldn’t the desired outcome be achieved by removing the score from the status line, and have the score tabulated by looking in the chest for any item contained within with a certain property, such as “valuable”?

Here is what I mean in pseudocode:

To calculate score:
For items in chest:
If item has property “valuable” increase score +1 point
Otherwise score does not change
Go to next item.

Tommie