Stop the listings and their chapters stating fixed defects as fact
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 3m21s
akbasic CI Build / sanitizers (push) Failing after 4m30s
akbasic CI Build / coverage (push) Failing after 3m40s
akbasic CI Build / akgl_build (push) Failing after 21s
akbasic CI Build / mutation_test (push) Failing after 3m27s
Some checks failed
akbasic CI Build / cmake_build (push) Failing after 3m21s
akbasic CI Build / sanitizers (push) Failing after 4m30s
akbasic CI Build / coverage (push) Failing after 3m40s
akbasic CI Build / akgl_build (push) Failing after 21s
akbasic CI Build / mutation_test (push) Failing after 3m27s
You were right that this was still everywhere. The two `.bas` files carried their workarounds as present-tense statements about the interpreter -- "a name first created inside a GOSUB costs a value slot that is never handed back", "writing PAST the terminator of a short row draws nothing at all", "SSHAPE and GSHAPE ignore the subscript on a string array", "a FOR inside a BEGIN block does not survive the RETURN" -- and every one of those is now false. A comment that lies is worse than no comment, and these were the first thing anybody opening the files would read. **The characters game takes the geometry fix.** `CW# = 16` becomes `CW# = RGR(3)`, and the grid comes from `RWINDOW`, so the game fits whatever window and font the host gives it. That was the one thing in the listing that would break on a different font, and `RGR(3)` and `RWINDOW` were added to the interpreter because of it -- leaving the constant in place while Chapter 17 teaches the function was the inconsistency worth closing. `RGR(1)` still comes first so a build with no graphics device refuses by naming the device that is missing. Everything else in both listings keeps its shape and says why. Declaring every name up front, guarding loops with `GOTO`, six scalars for six brick stamps: none is forced any more and none costs anything, so they stay, with the comments marking which rules stand and which are history. The sprites header's five traps are marked FIXED where they are fixed. The chapters follow: Chapter 17 Step 2 no longer says "the listing still has `CW# = 16`", and Chapter 18's trap section is "five things that did not do what they looked like" with the two that still stand named up front rather than left to be counted. Verified: Chapter 17 Step 2's block is once again verbatim from the listing, so every quoted fragment in both chapters matches its source with no exceptions; both games run 40 seconds on the SDL frontend with no error line; both suites green in both configurations; `docs_examples` and `docs_screenshots --check` pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,11 @@
|
||||
|
||||
Breakout, written entirely in BASIC for the AKGL BASIC interpreter, using downloaded CC0
|
||||
sprite artwork for the paddles, the balls and the powerup gems. The bricks, the HUD and
|
||||
the lettering are drawn, captured with `SSHAPE` and installed as sprites — which is the
|
||||
only way a program in this interpreter can put a picture on the screen.
|
||||
the lettering are drawn, captured with `SSHAPE` and installed as sprites — because a
|
||||
sprite is the one thing this interpreter puts on the screen for nothing. The text layer
|
||||
owns every row of the window unless a program takes some back with `WINDOW`, and even
|
||||
then a drawing has to be re-issued every frame; a sprite is drawn from state the
|
||||
interpreter keeps.
|
||||
|
||||
```sh
|
||||
../../../build-akgl/basic breakout.bas
|
||||
@@ -89,6 +92,8 @@ drawing. The two that stand are the left-operand arithmetic rule, which turned o
|
||||
decision rather than a defect and is now documented as one, and the 256-line batch tear,
|
||||
which belongs to the host.
|
||||
|
||||
**The listing is unchanged**, and deliberately: it is what a program written against those
|
||||
constraints looks like, and its comments explain what it was working around. Six separate
|
||||
scalars for six brick stamps is no longer necessary, and it is still what the file does.
|
||||
**The listing's code is unchanged**, and deliberately: it is what a program written
|
||||
against those constraints looks like, and none of the workarounds costs anything now that
|
||||
they are not needed. Six separate scalars for six brick stamps, and loops guarded by
|
||||
`GOTO` rather than wrapped in a block, are both still what the file does. Its comments say
|
||||
which of the five traps stand and which are marked FIXED.
|
||||
|
||||
@@ -7,12 +7,18 @@ REM Five things about this interpreter shape everything below, and they
|
||||
REM are worth knowing before the first line stops making sense.
|
||||
REM
|
||||
REM 1. The text layer repaints every row of the window opaque black after
|
||||
REM the program's steps have run, so anything DRAW or BOX put on the
|
||||
REM screen is wiped before it is ever presented. Sprites are drawn
|
||||
REM after the text layer, so a sprite is the only thing that can be
|
||||
REM seen. Everything drawn here is therefore captured with SSHAPE and
|
||||
REM installed as a sprite with SPRSAV -- that is what sprites 1 and 2
|
||||
REM are. They are the screen.
|
||||
REM the program's steps have run, so by default anything DRAW or BOX
|
||||
REM put on the screen is wiped before it is ever presented. Sprites are
|
||||
REM drawn after the text layer, so a sprite is the one thing that is
|
||||
REM seen for nothing. Everything drawn here is therefore captured with
|
||||
REM SSHAPE and installed as a sprite with SPRSAV -- that is what
|
||||
REM sprites 1 and 2 are. They are the screen.
|
||||
REM
|
||||
REM (WINDOW can shrink the text area and hand the rest of the window to
|
||||
REM the drawing verbs; it could not be reached from this build when
|
||||
REM this was written. It would not help here anyway: a drawing has to
|
||||
REM be re-issued every frame and fit inside one batch, and a sprite has
|
||||
REM neither constraint.)
|
||||
REM
|
||||
REM 2. The host runs 256 source lines and then presents the frame, and a
|
||||
REM present throws the drawing buffer away. So all the drawing between
|
||||
@@ -33,9 +39,10 @@ REM enough to both that a constant is spelled out rather than named
|
||||
REM and several routines that would read better as subroutines are
|
||||
REM BEGIN blocks instead.
|
||||
REM
|
||||
REM 5. Five things in this dialect do not do what they look like they do,
|
||||
REM and each one cost an evening. They are noted where they bite, and
|
||||
REM collected here so nobody has to find them twice:
|
||||
REM 5. Five things in this dialect did not do what they looked like they
|
||||
REM did, and each one cost an evening. THREE OF THEM HAVE SINCE BEEN
|
||||
REM FIXED, and are marked below; the shape of this listing is still
|
||||
REM theirs, which is why they are still written down:
|
||||
REM
|
||||
REM * **The left operand decides whether an expression is done in
|
||||
REM integers or in floats.** 0 - V% throws V%'s fraction away and
|
||||
@@ -48,12 +55,16 @@ REM result somewhere with a % on it.
|
||||
REM * A FOR whose bounds are equal does not run its body at all, so
|
||||
REM every loop over a list has the one-item case written out beside
|
||||
REM it.
|
||||
REM * A FOR inside a BEGIN block does not survive the RETURN of the
|
||||
REM routine holding it; the interpreter loses the GOSUB. Loops in
|
||||
REM this program are guarded by GOTO rather than wrapped in a block.
|
||||
REM * SSHAPE and GSHAPE ignore the subscript on a string array, so
|
||||
REM every element resolves to element zero. The six brick stamps are
|
||||
REM therefore six separate scalars.
|
||||
REM * FIXED. A FOR inside a BEGIN block that was SKIPPED did not
|
||||
REM survive the RETURN of the routine holding it; the interpreter
|
||||
REM lost the GOSUB and reported "RETURN outside the context of
|
||||
REM GOSUB". Loops in this program are guarded by GOTO rather than
|
||||
REM wrapped in a block, and are left that way because it costs
|
||||
REM nothing. TODO.md section 9 item 2.
|
||||
REM * FIXED. SSHAPE and GSHAPE ignored the subscript on a string array,
|
||||
REM so every element resolved to element zero. The six brick stamps
|
||||
REM are six separate scalars for that reason; an array works now.
|
||||
REM TODO.md section 9 item 6.
|
||||
REM * READ walks one cursor through every DATA item in the file in the
|
||||
REM order they were written, no matter which routine is reading.
|
||||
REM
|
||||
@@ -140,10 +151,11 @@ REM ------------------------------------------------------- shapes and dirt
|
||||
REM SHN# counts the SSHAPE slots spent. There are sixteen, nothing gives
|
||||
REM one back, and GRAPHIC 5 gives back all of them at once -- so the brick
|
||||
REM stamps are thrown away and rebuilt every time the pool runs dry.
|
||||
REM One scalar per row colour, and scalars rather than an array on
|
||||
REM purpose: SSHAPE and GSHAPE read the leaf they are handed without
|
||||
REM applying its subscript, so a string array element always resolves to
|
||||
REM element zero and every brick comes out the same colour.
|
||||
REM One scalar per row colour, and scalars rather than an array because
|
||||
REM SSHAPE and GSHAPE used to read the leaf they were handed without
|
||||
REM applying its subscript -- a string array element always resolved to
|
||||
REM element zero, and every brick came out the same colour. That is fixed
|
||||
REM and an array would work now; six scalars is what this listing has.
|
||||
S0$ = ""
|
||||
S1$ = ""
|
||||
S2$ = ""
|
||||
@@ -330,9 +342,10 @@ REM
|
||||
REM Rebuilding the brick stamps comes first, because everything else
|
||||
REM draws with them and GRAPHIC 5 has just thrown them away.
|
||||
REM =====================================================================
|
||||
REM Labels rather than BEGIN blocks here, and it is not a style choice: a
|
||||
REM RETURN inside a block leaves the interpreter with no GOSUB to return
|
||||
REM from and stops the program.
|
||||
REM Labels rather than BEGIN blocks here. When this was written it was not
|
||||
REM a style choice -- a loop inside a block that was skipped left the
|
||||
REM interpreter with no GOSUB to return from and stopped the program. That
|
||||
REM is fixed; the shape is kept because it reads the same either way.
|
||||
LABEL DRAWJOB
|
||||
IF SHN# < 14 THEN GOTO DRAWJOB2
|
||||
GOSUB DRAWPROTOS
|
||||
@@ -399,8 +412,9 @@ Z$ = S2$ : T1# = RS#(2) : T2# = RC#(2) : GOSUB STAMPROW
|
||||
Z$ = S3$ : T1# = RS#(3) : T2# = RC#(3) : GOSUB STAMPROW
|
||||
Z$ = S4$ : T1# = RS#(4) : T2# = RC#(4) : GOSUB STAMPROW
|
||||
Z$ = S5$ : T1# = RS#(5) : T2# = RC#(5) : GOSUB STAMPROW
|
||||
REM A FOR inside a BEGIN block does not survive the RETURN at the end of
|
||||
REM the routine that holds it, so this loop is guarded by a GOTO instead.
|
||||
REM A skipped BEGIN block holding a FOR used to break the RETURN at the end
|
||||
REM of the routine holding it, so this loop is guarded by a GOTO instead.
|
||||
REM Fixed since; left alone because a GOTO guard costs nothing.
|
||||
IF PN# = 1 THEN DRAW PC#(0), PX1#(0), PY1#(0) TO PX2#(0), PY2#(0)
|
||||
IF PN# < 2 THEN GOTO PLDONE
|
||||
FOR I# = 0 TO PN# - 1
|
||||
|
||||
Reference in New Issue
Block a user