An Inform 7 Quine (by Juhana Leinonen)

In a 14-year-old rec.arts.int-fiction post, @Juhana wrote:

During the slow holidays I started to think if making a quine in Inform 7 would be possible. Quine is a computer program that does nothing else but prints its own complete source code – see
Quine (computing). Turns out it is possible and here it is for your amusement: a quine for Inform 7!

I find this so overwhelmingly cool that I wanted it to see some more daylight, so I checked with Juhana that there was no objection to posting it here. Though it was written, I assume, for 5G67 or 5J39, it still compiles in 6M62 and took just a couple of very minor tweaks to make it a character-perfect quine. (Note that the source should not end with a linefeed: it should be exactly 2470 characters long.)

"Quine" by Juhana Leinonen

Quine is a room.

When play begins: say "[quine-list]".

To insta-quit: (- quit; -).

The L is a list of text that varies. The B is a list of numbers that varies. The Q is a list of numbers that varies. The S1 is a list of numbers that varies. The S2 is a list of numbers that varies.

The L is { "", "Quine", "", " by Juhana Leinonen", "", "Quine is a room.", "", "When play begins: say ", "", "", "quine-list", "", "", ".", "", "To insta-quit: (- quit; -).", "", "The L is a list of text that varies. The B is a list of numbers that varies. The Q is a list of numbers that varies. The S1 is a list of numbers that varies. The S2 is a list of numbers that varies.", "", "", "The L is { ", "", " };", "", "", "The B is { 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28, 60, 61, 62 }. The Q is { 1, 3, 10, 13, 30, 34, 36, 40, 42, 46, 48, 52, 64, 75, 77, 84 }. The S1 is { 10, 31, 37, 43, 49, 65, 68, 71, 78, 81 }. The S2 is { 12, 33, 39, 45, 51, 67, 70, 73, 80, 83 };", "", "To say quine-list:", "let c be 0; repeat with x running through L begin; ", "increase c by 1; if c is 22 begin; list-print; otherwise; say ", "", "", "x", "", "", "; if c is listed in Q, say ", "", "", "unicode 34", "", "", "; if c is listed in B, say ", "", "", "line break", "", "", "; if c is listed in S1, say ", "", "", "unicode 91", "", "", "; if c is listed in S2, say ", "", "", "unicode 93", "", "", "; end if; end repeat; insta-quit;", "", "To list-print:", "remove entry 86 from L; repeat with x running through L begin; say ", "", "", "unicode 34", "", "", "x", "", "", "unicode 34", "", ", ", "", "; end repeat; say ", "", "", "unicode 34", "", "", "unicode 34", "", "", ";", "" };

The B is { 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28, 60, 61, 62 }. The Q is { 1, 3, 10, 13, 30, 34, 36, 40, 42, 46, 48, 52, 64, 75, 77, 84 }. The S1 is { 10, 31, 37, 43, 49, 65, 68, 71, 78, 81 }. The S2 is { 12, 33, 39, 45, 51, 67, 70, 73, 80, 83 };

To say quine-list:
let c be 0; repeat with x running through L begin; increase c by 1; if c is 22 begin; list-print; otherwise; say "[x]"; if c is listed in Q, say "[unicode 34]"; if c is listed in B, say "[line break]"; if c is listed in S1, say "[unicode 91]"; if c is listed in S2, say unicode 93; end if; end repeat; insta-quit;

To list-print:
remove entry 86 from L; repeat with x running through L begin; say "[unicode 34][x][unicode 34], "; end repeat; say "[unicode 34][unicode 34]";
10 Likes

Oh god, I’m relieved this topic isn’t what I expected it to be. The announcement of a new Frankenstein-like project smooshing Quixe and Twine together for some purpose I couldn’t even imagine.

-Wade

5 Likes

While that is so hilarious I’m glad it happened, I’ve changed the subject to make it look less project-announce-y. :grinning:

2 Likes

I got errors compiling this:

  >--> In the sentence 'The S2 is\ a list of numbers that varies' (source text, line 9),
    I can't find a verb that I know how to deal with.
  >--> I am reading the sentence 'The S1 \ is {10, 31, 37, 43, 49, 65, 68, 71,
    78, 81}' (source text, line 22) as saying that a thing called 'S1 \' is a
    value, but this makes no sense to me - it would be like saying 'the chair
    is 10'.
  >--> I am reading the sentence 'The S2 is {12, 33, 39, 45, 51, 67, 70, 73,
    80, 83}' (source text, line 23) as saying that a thing called 'S2' is a
    value, but this makes no sense to me - it would be like saying 'the chair
    is 10'.

argh, my bad, sorry. I’ve replaced the source in the initial post.

Still doesn’t quite work after removing the backslashes and extra linebreaks. The output is truncated by a few characters in the last line. It ends with
remove entry 86 from L; repeat with x running through L begin; say "[unicode 34][x][unicode 34], "; end repeat; say "[unicode 34][unicode
instead of
remove entry 86 from L; repeat with x running through L begin; say "[unicode 34][x][unicode 34], "; end repeat; say "[unicode 34][unicode 34]";

Try starting over with a fresh copy of the code as copy-pasted via the copy-code button in the source box’s upper right… by trying to hand-correct the bad version you probably ended up with something a little off from what it’s supposed to be.

I just verified that copy-pasting what’s there now compiles and works.

I was copy-pasting before, but actually, I just realized that the truncation only occurs when compiled to Z-code, not Glulx. That’s weird.

Ah! I’d only tried Glulx. It seems like my trivial changes were more about updating it for Glulx compatibility than 6M62 compatibility. This one works in Z-code. The difference is the S2 assignment assertion ending with a . instead of a ; (this is different: the r.a.i-f post has ;).

[Edited: I had originally indicated that another difference was "say "[unicode 93]" instead of say unicode 93 toward the end of To say quine-list (this is the same as in the original r.a.i-f post)" but I’d just managed to confuse myself. While the original r.a.i-f post does have [unicode 93], I couldn’t get that to work; both the Z-code version in this post and the Glulx version in the initial post use unicode 93 without brackets.]

And if I could tell you why those differences are relevant, then I would achieve enlightenment all in a flash.

"Quine" by Juhana Leinonen

Quine is a room.

When play begins: say "[quine-list]".

To insta-quit: (- quit; -).

The L is a list of text that varies. The B is a list of numbers that varies. The Q is a list of numbers that varies. The S1 is a list of numbers that varies. The S2 is a list of numbers that varies.

The L is { "", "Quine", "", " by Juhana Leinonen", "", "Quine is a room.", "", "When play begins: say ", "", "", "quine-list", "", "", ".", "", "To insta-quit: (- quit; -).", "", "The L is a list of text that varies. The B is a list of numbers that varies. The Q is a list of numbers that varies. The S1 is a list of numbers that varies. The S2 is a list of numbers that varies.", "", "", "The L is { ", "", " };", "", "", "The B is { 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28, 60, 61, 62 }. The Q is { 1, 3, 10, 13, 30, 34, 36, 40, 42, 46, 48, 52, 64, 75, 77, 84 }. The S1 is { 10, 31, 37, 43, 49, 65, 68, 71, 78, 81 }. The S2 is { 12, 33, 39, 45, 51, 67, 70, 73, 80, 83 }.", "", "To say quine-list:", "let c be 0; repeat with x running through L begin; ", "increase c by 1; if c is 22 begin; list-print; otherwise; say ", "", "", "x", "", "", "; if c is listed in Q, say ", "", "", "unicode 34", "", "", "; if c is listed in B, say ", "", "", "line break", "", "", "; if c is listed in S1, say ", "", "", "unicode 91", "", "", "; if c is listed in S2, say ", "", "", "unicode 93", "", "", "; end if; end repeat; insta-quit;", "", "To list-print:", "remove entry 86 from L; repeat with x running through L begin; say ", "", "", "unicode 34", "", "", "x", "", "", "unicode 34", "", ", ", "", "; end repeat; say ", "", "", "unicode 34", "", "", "unicode 34", "", "", ";", "" };

The B is { 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28, 60, 61, 62 }. The Q is { 1, 3, 10, 13, 30, 34, 36, 40, 42, 46, 48, 52, 64, 75, 77, 84 }. The S1 is { 10, 31, 37, 43, 49, 65, 68, 71, 78, 81 }. The S2 is { 12, 33, 39, 45, 51, 67, 70, 73, 80, 83 }.

To say quine-list:
let c be 0; repeat with x running through L begin; increase c by 1; if c is 22 begin; list-print; otherwise; say "[x]"; if c is listed in Q, say "[unicode 34]"; if c is listed in B, say "[line break]"; if c is listed in S1, say "[unicode 91]"; if c is listed in S2, say unicode 93; end if; end repeat; insta-quit;

To list-print:
remove entry 86 from L; repeat with x running through L begin; say "[unicode 34][x][unicode 34], "; end repeat; say "[unicode 34][unicode 34]";

I think the code in that last post still doesn’t work in Z-code? It still says unicode 93 instead of "[unicode 93]" in To say quine-list, but after changing that, it still doesn’t work.

I find this slightly disturbing. I knew Z-Code and Glulx had slightly different sets of features on the presentation/cosmetic level, but I didn’t know it was possible for the same code to output different text in the two. Most likely this code is tripping some weird edge case, but it would be distressing to find that one has to re-test everything when changing a project from Z-code to Glulx or vice versa.

It works perfectly for me with fizmo-console 0.7.14 and bocfel 1.3.2 built with cheapglk 1.0.6. It can’t work with dfrotz which only allows a screen-width up to 255 characters, so it introduces line-breaks. What interpreter are you using?

I tried with both Inform 6.33N and Inform 6.35. One would hope not to get different results there and I did not.

I’ve tried in dfrotz 2.44, Windows Frotz 1.20, and the Inform IDE (though I think the IDE is actually using dfrotz?). Same results in all three.

OK, going back to something very close to the original post’s line-breaks, this produces the same output as dfrotz set to a 72-column screen width. (And also can be read in an intfiction source code textarea without horizontal scrolling… unless you’re on a narrow device.)

"Quine" by Juhana Leinonen

Quine is a room.

When play begins: say "[quine-list]".

To insta-quit: (- quit; -).

The L is a list of text that varies. The B is a list of numbers that
varies. The Q is a list of numbers that varies. The S1 is a list of
numbers that varies. The S2 is a list of numbers that varies.

The L is { "", "Quine", "", " by Juhana Leinonen", "", "Quine is a
room.", "", "When play begins: say ", "", "", "quine-list", "", "", ".",
"", "To insta-quit: (- quit; -).", "", "The L is a list of text that
varies. The B is a list of numbers that varies. The Q is a list of
numbers that varies. The S1 is a list of numbers that varies. The S2 is
a list of numbers that varies.", "", "", "The L is { ", "", " };", "",
"", "The B is { 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27,
28, 60, 61, 62 }. The Q is { 1, 3, 10, 13, 30, 34, 36, 40, 42, 46, 48,
52, 64, 75, 77, 84 }. The S1 is { 10, 31, 37, 43, 49, 65, 68, 71, 78, 81
}. The S2 is { 12, 33, 39, 45, 51, 67, 70, 73, 80, 83 }.", "", "To say
quine-list:", "let c be 0; repeat with x running through L begin; ",
"increase c by 1; if c is 22 begin; list-print; otherwise; say ", "",
"", "x", "", "", "; if c is listed in Q, say ", "", "", "unicode 34",
"", "", "; if c is listed in B, say ", "", "", "line break", "", "", ";
if c is listed in S1, say ", "", "", "unicode 91", "", "", "; if c is
listed in S2, say ", "", "", "unicode 93", "", "", "; end if; end
repeat; insta-quit;", "", "To list-print:", "remove entry 86 from L;
repeat with x running through L begin; say ", "", "", "unicode 34", "",
"", "x", "", "", "unicode 34", "", ", ", "", "; end repeat; say ", "",
"", "unicode 34", "", "", "unicode 34", "", "", ";", "" };

The B is { 4, 5, 6, 7, 14, 15, 16, 17, 18, 19, 22, 23, 24, 26, 27, 28,
60, 61, 62 }. The Q is { 1, 3, 10, 13, 30, 34, 36, 40, 42, 46, 48, 52,
64, 75, 77, 84 }. The S1 is { 10, 31, 37, 43, 49, 65, 68, 71, 78, 81 }.
The S2 is { 12, 33, 39, 45, 51, 67, 70, 73, 80, 83 }.

To say quine-list:
let c be 0; repeat with x running through L begin; increase c by 1; if c
is 22 begin; list-print; otherwise; say "[x]"; if c is listed in Q, say
"[unicode 34]"; if c is listed in B, say "[line break]"; if c is listed
in S1, say "[unicode 91]"; if c is listed in S2, say unicode 93; end if;
end repeat; insta-quit;

To list-print:
remove entry 86 from L; repeat with x running through L begin; say
"[unicode 34][x][unicode 34], "; end repeat; say "[unicode 34][unicode
34]";

That still doesn’t work for me in Windows Frotz or dfrotz. Whatever issue I’m having is very persistent.

The previous version does seem to work in Gargoyle - or rather, it’s not truncated, though extraneous line breaks are introduced.

I should’ve thought of this sooner: odds seem pretty good this is a \n vs. \r\n newline thing. But it’s too late for more playing with this right now…

Very cool. Quines are such a sweet, dorky programming challenge I love to see people do but would NEVER try.