Difference between revisions of "Christmas Star"
(→Winning entry for C64) |
(→Shortest BASIC entry for C64: fixed language) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 25: | Line 25: | ||
* mirror triangles | * mirror triangles | ||
− | Program length was measured as the | + | Program length was measured as the shortest of source, file, or "real" code (excluding basic stub and file load address). For assembler programs started with SYS or call, typically filesize minus load address (=file header) is the relevant number. A BASIC stub to start the program would also not count, but it is not allowed to use the stub#s side effects to initialize zeropage addresses. |
− | == | + | ==Remarkable Entries== |
− | === | + | === Shortest entry for C64 === |
The shortest entry for the C64 was submitted by Serato with 34 bytes (filesize 36 bytes): | The shortest entry for the C64 was submitted by Serato with 34 bytes (filesize 36 bytes): | ||
<syntaxhighlight lang="6502"> | <syntaxhighlight lang="6502"> | ||
Line 57: | Line 57: | ||
Serato's entry was provided with the following comments: | Serato's entry was provided with the following comments: | ||
<nowiki>The required octogram may be constructed as the union of four right triangles reflected four ways in x and y axes. The central loop renders one row of the triangle, plus its horizontal mirror image. The outer loop iterates over normal and mirror image screen rows. The result is all four triangles being rendered on top of each other. Saved a byte with unintended 6502 opcode ISC which combines INC and SBC to both increment a counter and load (16 minus) its value into A.</nowiki> | <nowiki>The required octogram may be constructed as the union of four right triangles reflected four ways in x and y axes. The central loop renders one row of the triangle, plus its horizontal mirror image. The outer loop iterates over normal and mirror image screen rows. The result is all four triangles being rendered on top of each other. Saved a byte with unintended 6502 opcode ISC which combines INC and SBC to both increment a counter and load (16 minus) its value into A.</nowiki> | ||
+ | |||
+ | === Shortest BASIC entry for C64 === | ||
+ | |||
+ | While BASIC programs seem to have a structural disadvantage for this kind of challenge, some entries in the spirit of oneliners are remarkably compact. | ||
+ | The shortest BASIC entry for the C64 was submitted by Serato with 68 bytes of tokenized code. | ||
+ | |||
+ | <syntaxhighlight lang="basic"> | ||
+ | 0fOy=-8to8:fOx=-8to31:?cH(33+(9oraB(aB(y)-aB(x))>4oraB(x)>4aNaB(y)>4));:nE:nE | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Expanded source code as produced by LIST: | ||
+ | |||
+ | <syntaxhighlight lang="basic"> | ||
+ | 0 fory=-8to8:forx=-8to31:printchr$(33+(9orabs(abs(y)-abs(x))>4orabs(x)>4andabs(y)>4));:next:next | ||
+ | </syntaxhighlight> | ||
==Optimized post-deadline versions== | ==Optimized post-deadline versions== | ||
− | === | + | ===32 bytes version for C64=== |
− | This shorter C64 version by Serato renders the union of four triangles rotated 90 degrees. To save space it iterates 256 times. It also uses a trick where the carry flag state is set by the loop comparison causing the active row to advance automatically at the end of each column. | + | This shorter C64 version by Serato renders the union of four triangles rotated 90 degrees. To save space it iterates 256 times. It also uses a trick where the carry flag state is set by the loop comparison causing the active row to advance automatically at the end of each column. The executable code size is 32 bytes (filesize 34 bytes). |
<syntaxhighlight lang="6502"> | <syntaxhighlight lang="6502"> | ||
plot = $E50C ; Kernal routine moves cursor to (y,x) | plot = $E50C ; Kernal routine moves cursor to (y,x) |
Latest revision as of 10:37, 7 January 2023
Contents
The challenge
During the Vintage Computing Christmas Challenge 2022, the goal was to create the shape of a given Christmas star with as few bytes as possible. All platforms and languages were allowed. The star should look exactly like the one shown below.
* * ** ** *** *** **** **** ***************** *************** ************* *********** ********* *********** ************* *************** ***************** **** **** *** *** ** ** * *
There were mainly two kinds of approaches:
- draw character by character
- mirror triangles
Program length was measured as the shortest of source, file, or "real" code (excluding basic stub and file load address). For assembler programs started with SYS or call, typically filesize minus load address (=file header) is the relevant number. A BASIC stub to start the program would also not count, but it is not allowed to use the stub#s side effects to initialize zeropage addresses.
Remarkable Entries
Shortest entry for C64
The shortest entry for the C64 was submitted by Serato with 34 bytes (filesize 36 bytes):
chrout = $FFD2 ; Kernal routine outputs char in A
plot = $E50C ; Kernal routine moves cursor to (y,x)
pnt = $d1 ; Pointer to the start of the current screen line
row = $b3 ; zp var that always starts at 3
* = $1000
do_2nd ldx row ; render "upside down" triangles
do_line ldy #9 ; render one row of triangle, and its x-mirror image
jsr plot ; move cursor to column 9 on row x
ldy #17 ; start x-mirrored image in column 17
lda #'*' ; the star of the show
do_asks jsr chrout ; print star, advancing kernal cursor to right
sta (pnt),y ; write x-mirrored star with mirrored cursor
dey ; advance mirrored cursor to left
cpy row ; test against line y=x to form diagonal
bne do_asks
cpx row ; check if these weere "upside down" triangles
bne do_2nd ; if not, draw the upside down ones
sys lda #$10 ; entry point of routine, start with y mirrored
sec ; wish this could be avoided, feels like a wasted byte
isc row ; increment bottom row counter and put (16 - row) in A
tax ; we need in x register
bpl do_line ; repeat until row < 0, then fall through
rts
Serato's entry was provided with the following comments:
The required octogram may be constructed as the union of four right triangles reflected four ways in x and y axes. The central loop renders one row of the triangle, plus its horizontal mirror image. The outer loop iterates over normal and mirror image screen rows. The result is all four triangles being rendered on top of each other. Saved a byte with unintended 6502 opcode ISC which combines INC and SBC to both increment a counter and load (16 minus) its value into A.
Shortest BASIC entry for C64
While BASIC programs seem to have a structural disadvantage for this kind of challenge, some entries in the spirit of oneliners are remarkably compact. The shortest BASIC entry for the C64 was submitted by Serato with 68 bytes of tokenized code.
0fOy=-8to8:fOx=-8to31:?cH(33+(9oraB(aB(y)-aB(x))>4oraB(x)>4aNaB(y)>4));:nE:nE
Expanded source code as produced by LIST:
0 fory=-8to8:forx=-8to31:printchr$(33+(9orabs(abs(y)-abs(x))>4orabs(x)>4andabs(y)>4));:next:next
Optimized post-deadline versions
32 bytes version for C64
This shorter C64 version by Serato renders the union of four triangles rotated 90 degrees. To save space it iterates 256 times. It also uses a trick where the carry flag state is set by the loop comparison causing the active row to advance automatically at the end of each column. The executable code size is 32 bytes (filesize 34 bytes).
plot = $E50C ; Kernal routine moves cursor to (y,x)
sys_h = $15
pnt = $d1
tblx = $d6
* = $c00
lda #22
loop2 tay
loop1 sbc #3
tax
jsr plot
lda #'*'
sta (pnt),y
tya
eor #$1f
ldy tblx
dec $2
bne loop1
dey
cpy #10
bcs loop1
dec sys_h
bpl loop2
rts