Here's the final 10-liner, as written by hand on my Atari 1200XL. It actually comes in under 10 lines. This is considered a "PUR-120" submission; each line can be entered directly into the Atari editor, which allows up to 3 physical lines (40 columns max) per logical line (40×3=120). In some cases, removing spaces and/or utilizing abbreviations had to be done to get it to fit (e.g., "N.A
", which expands to "NEXT A
" when LIST
ed.) In the end, since the program is only 8 lines long, that could've been skipped... or maybe I should've submitted this under "PUR-80"?
Per new rules in 2017 — "In addition to the tenliner, the same program must be submitted in 'long version', that means, with one command per line" — the following listing was also created. And here, each command is explained, with mnemonics given for POKE
'd memory addresses. Some screenshots of each step of the program are alos provided; click the thumbnails to view the full versions (taken with Atari800 emulator with NTSC filter enabled, for that old-skool CRT look!)
10 GRAPHICS 8
11 DPOKE 82,9984
12 ? "PieChart"
13 TRAP 30
14 C=0
15 DEG
16 COLOR 1
17 CIRCLE 159,80,80
18 DIM N(8)
|
- Switch to high-resolution (320×192) 2-color bitmapped graphics mode, with a text window at the bottom
- Set the text mode margins to 0 (left,
LMARGN ) and 39 (right, RMARGN ); (39×256)+0=9984
- Display title of the program
- Trap any errors (including a blank entry in the numeric
INPUT , or attempts to enter too many values into array N() , on line 20-21) to line 30, below
- Reset the count (
C ) of how many numbers have been entered
- Switch trigonometric functions to degrees (vs. radians) mode
- Set painting color to 1 ("the" color, vs. the blank background, in 2-color mode)
- Draw a circle of radius 80 in the center of the bitmap area (159,80)
- Create space to store up to 8 values
|
|
20 INPUT "Number ([Ret] when done)";A
21 N(C)=A
22 C=C+1
23 S=S+A
24 GOTO 20
|
- Prompt the user to enter a value, and record it (into
A )
- Store the value in the array (
N(C) )
- Increment the count of numbers entered so far (
C )
- Add to the sum of all numbers entered (
S )
- Repeat!
So for example, after entering the three values "10", "30", and "20", we'd have:
C = 3
S = 60 (10+30+20)
N() contains 10, 30, and 20
|
|
30 TRAP 30
31 IF C<2
32 ? "Min 2"
33 GOTO 20
34 ELSE
35 IF C=9
36 ? "Max 9"
37 ENDIF
38 ENDIF
|
We arrive here when an error occurs. The expected situations are the
user entering a blank response when asked for a number (which we ask them to do,
to indicate they're done entering values to chart), or when we try to store
a value beyond the bounds of array N() (we've hit the program's
limit on the number of values that may be charted).
- Reset (keep) the error trap, to this line (since it gets cleared)
- If the user entered fewer than 2 values, tell them, and go back to the loop on line 20
- If the user entered more than 8 values, tell them, but then proceed
- Otherwise, we're proceeding now (e.g., user entered 2-8 values)
|
|
40 GOSUB 1000
41 POKE 87,9
42 G=0
43 FOR A=0 TO C-1
44 COLOR A+1
45 NN=(N(A)/S)*360
46 PAINT 17*COS(G+NN/2)+39,70*SIN(G+NN/2)+80
47 G=G+NN
48 NEXT A
|
- Jump to the segment-drawing code, below; keep in mind at this point the painting color is 1
- Trick the OS's drawing routines (via
DINDEX ) into thinking we're in GRAPHICS mode 9; drawing routines will now assume 4 bits per pixel on an 80×192 bitmapped display
- Set the starting angle (
G ) to 0; remember we're in degrees mode
- Begin a loop (using variable
A ) that goes through the values we entered (from 0th to (C-1) -th)
- Set the color based on how far in the loop we are (starting with color 1); recall we can only accept up to 8 digits
- Calculate how much of angle the current segment (
N(A) ), out of the total of all values (S ), takes up; map it to 360 degrees
- Do a flood-fill within the segment (drawn via the
CIRCLE command above, and the routine at line 1000); the point it starts at is approx. 70 radius from center (keep in mind the OS thinks we're in 80×192 mode, so we divide the horizontal position by four to get that 17), at the half-way angle of the segment (via throwing G+(NN÷2) at the cosine/sine functions)
- "Move" to the next segment, by incrementing
G by the full angle of the segment (NN )
- Repeat the loop until we're done
In the end, you'll see a high res 2-color drawing of a pie chart, with a set of bit patterns (columns of on/off pixels) that fill the segments of the pie chart.
|
|
50 POKE 87,8
51 COLOR 0
52 CIRCLE 159,80,80
53 GOSUB 1000
54 POKE 623,128
55 POKE 87,9
56 COLOR 8
57 CIRCLE 39,80,20,80
|
- Tell the OS we're in
GRAPHICS mode 8; drawing routines back to assuming 1 bit per pixel (2 colors) on a 320×192 bitmapped display
- Set painting color to 0 (background; aka "erase")
- Draw a circle again (hence, erase the high-res circle)
- Jump to the segment-drawing code again (hence, erase the segment lines)
- Tell the GTIA chip to render the screen in
GRAPHICS mode 10 (via a bit in GPRIOR ); this is an 80×192 bitmapped mode which utilizes the 9 color registers (that map 128 colors to different objects/aspects of the display, e.g. the four pairs of Players & Missiles, the border/background, colors of drawn pixels or text, etc.)
- Trick the OS's drawing routines (via
DINDEX ) into thinking we're in GRAPHICS mode 9 again (see above)
- Set painting color to 8 (the "9th" color now available to the display)
- Draw a circle in the center of the screen; it's actually being drawn as an oval (20×80), since the pixels are about 4× as wide as they are tall (and hence the center being at (39,80) here)
|
|
60 GRAPHICS 42
61 DPOKE 704,12+18*256
62 DPOKE 706,36+70*256
63 DPOKE 708,100+132*256
64 DPOKE 710,164+228*256
65 POKE 712,0
|
- Ask the OS to flip the screen to
GRAPHICS mode 10 "for real" now (80×192 with 9 color-registered based colors, and no text window); in the end, this isn't particularly necessary, I suppose!
- Set the color registers (the Player/Missile ones:
PCOLR0 (the background), PCOLR1 , PCOLR2 , PCOLR3 ; and the playfield ones: COLOR0 , COLOR1 , COLOR2 , COLOR3 , and COLOR4 ) to some nice colors:
- Light grey (hue=0, brightness=12 ⇒ 12) — the background (704,
PCOLR0 )
- Dark yellow (hue=1, brightness=2 ⇒ 18)
- Dark red-orange (hue=2, brightness=4 ⇒ 36)
- Medium red (hue=4, brightness=6 ⇒ 70)
- Medium cobalt blue (hue=6, brightness=4 ⇒ 100)
- Medium (hue=8, brightness=4 ⇒ 132)
- Medium blue-grey (hue=10, brightness=4 ⇒ 164)
- Medium green (hue=14, brightness=4 ⇒ 228)
- Black (hue=0, brightness=0 ⇒ 0) — also the outline of the circle (712,
COLOR4 )
|
|
999 GOTO 999
|
Infinite loop. (Press [Break] or [Reset] to break out of the program,
and back to a READY prompt.)
|
|
1000 G=0
1001 FOR A=0 TO C-1
1002 PLOT 159,80
1003 DRAWTO 80*COS(G)+159,80*SIN(G)+80
1004 G=G+(N(A)/S)*360
1005 NEXT A
1006 RETURN
|
Similar to the segment-filling code on line 40, since it was based on this. Notice this code does not change, or make assumptions, about the painting color (set via COLOR ); it is used to both draw, and later erase, the segment lines!
- Set the starting angle (
G ) to 0; remember we're in degrees mode
- Begin a loop (using variable
A ) that goes through the values we entered (from 0th to (C-1) -th)
- Plot a point in the center of the circle (at (159,80))
- Draw a line from there, to a point on the circle (at radius 80, out from the center (159,80)), based on the current angle (
G )
- "Move" to the next segment, by incrementing
G by the angle of the segment; that is, the angle of the current segment (N(A) ), out of the total of all values (S ), mapped to 360 degrees
- Repeat the loop until we're done
- Return from this subroutine
|
|