Try it online!
The unprintable character is 0x18.
The trouble with the usual
"-based Fungeoid quines is that if we repeat the entire source code, then we also get additional
" and the string no longer covers the entire source code. I assume that's why the existing answer uses the cheat-y
g approach instead.
This answer does use the
"-based approach, but instead of including a
" in the source, we write it into the program at runtime. That way, there will only ever be one
" regardless of how often the program is repeated (because we only write it to one specific coordinate, independently of program size).
The general idea is then that we create a representation of the whole source code on the stack, but only cycle through the first 29 of the characters (i.e. the program length) with the length of the loop determined by the size of the code. Therefore, we can actually append arbitrary characters (except linefeeds) after
@ and the result will always be a cyclic repetition of the core program, one character longer than the source.
4P Push 4! = 24. This is the code point of the unprintable, which we're
using as a placeholder for the quote.
.a+ Duplicate it and add 10, to get 34 = '"'.
80p Write '"' to cell (8,0), i.e. where the first unprintable is.
Placeholder, becomes " by the time we get here, and pushes the code
points of the entire program to the stack. However, since we're already
a good bit into the program, the order will be messed up: the bottom
of the stack starts at the 24 (the unprintable) followed by all
characters after it (including those from extraneous repetitions). Then
on top we have the characters that come in front of the `"`.
So if the initial program has structure AB, then any valid program has
the form ABC (where C is a cyclic repetition of the initial program),
and the stack ends up holding BCA. We don't care about C, except to
determine how big the program is. So the first thing we need to do is
bring B to the top, so that we've got the initial program on top of
a2* Push 10*2 = 20.
&w Run the following section 21 times, which is the length of B.
dt, Pull up the value at the bottom of the stack.
k End of loop.
d&w Run the following section D+1 times, where D is the length of ABC.
74* Push 28, one less than the number of characters in AB.
, Pull up the 29th stack element, which is the next character to print.
.o Print a copy of that character.
k End of loop.
@ Terminate the program.