Jump to content
Sign in to follow this  
kl99

10 liner Programming Style

Recommended Posts

Hi,

Programming within only 10 lines of code requires a different coding style.

Let us take this thread to share the findings and ideas everyone had to tweak in some more bytes.

 

Here is my first:

 

Variable Name Length

Use single char variable names. BASIC allows A,B,C,D,E,F,G,...X,Y,Z,@,[,],_ as Names for the first character, which in most cases should be enough. Same for String Variables or Arrays.

 

Skip Variable Initialize to 0

You can skip initializing a variable to 0 before its first reference as this is done by the system.

 

Replace repeating numbers in code

You save length in your code lines if you replace a number (BASIC calls them numeric constant) that is showing up multiple times across your program by a reference to a variable having that numeric value.

The more occurences you can replace the more you save. The more digits the number had the more you save.

 

A nice combination of this tip with the tip skipping initialize to 0 would be replacing each occurence of the number 0 in your program with "_" and simply never initialize or change its value.

 

  • Like 2

Share this post


Link to post
Share on other sites
On 8/14/2019 at 3:47 AM, kl99 said:

A nice combination of this tip with the tip skipping initialize to 0 would be replacing each occurence of the number 0 in your program with "_" and simply never initialize or change its value.

 

What benefit does this provide?

Share this post


Link to post
Share on other sites

Let's take Gladiator by FarmerPotato, written in XB and extend each line with ! characters to see how many more "bytes" would fit in each line.

10 CALL CLEAR :: CALL SCREEN(8):: CALL MAGNIFY(2):: S=2 :: T=1 :: R=80 :: C=128 :: Q=160 :: E=2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 CALL CHAR(113,"003030300000000000000030303000000000000000303030",116,"2556360A060A090F661F66060A0A00090606076E1665")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
30 CALL CHAR(97,"606848706070506860604078606050D86060406070686070",100,"1819121C101814641818101E1030484C30302030303E186C")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
40 CALL CHAR(105,"102040000000000000000000007000000000000000000070",108,"020408000000000000000000000E0000000000000000000E")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50 CALL SPRITE(#1,104+S,12,R-4,C+6,#2,112+T,7,R-1,C-1,#3,96+S,2,R,C,#4,115+E,16,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
60 L=K :: CALL JOYST(1,X,Y):: CALL KEY(1,K,Z):: Y=2-Y/4 :: IF K=18 THEN S=Y ELSE IF L=18 THEN F=4 :: S=Y+3 ELSE T=Y :: IF X THEN C=C+X ELSE IF S>3 THEN S=S-3 :: F=0 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
70 E=INT(RND*3+1):: Q=Q-1 :: CALL PATTERN(#1,104+S,#2,112+T,#3,96+S,#4,115+E):: CALL LOCATE(#1,R-4,C+6,#2,R-1,C-1,#3,R,C,#4,R,Q)!!!!!!!!!!
80 IF C+8+F<Q THEN 60 ELSE IF F AND S<>E+3 THEN 100 ELSE IF T=E OR S-3=E THEN C=C-8 :: Q=Q+8 :: GOTO 70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
90 CALL COLOR(#4,9):: FOR I=1 TO 7 :: CALL SOUND(-100,999,2):: CALL SOUND(-100,880,2):: NEXT I :: C=C-8 :: Q=Q+16 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
100 CALL COLOR(#3,9):: FOR I=1 TO 7 :: CALL SOUND(-100,999-I*100,2):: NEXT I :: C=C-16 :: Q=Q+8 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

You can fit 502 ! characters in those 10 untouched lines.

 

Now let's introduce 5 numeric variables as Numeric Constants for M=1,N=2,O=3,P=4,_=0

10 CALL CLEAR :: M=1 :: N=2 :: O=3 :: P=4 :: CALL SCREEN(8):: CALL MAGNIFY(N):: S=N :: T=M :: R=80 :: C=128 :: Q=160 :: E=N !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 CALL CHAR(113,"003030300000000000000030303000000000000000303030",116,"2556360A060A090F661F66060A0A00090606076E1665")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
30 CALL CHAR(97,"606848706070506860604078606050D86060406070686070",100,"1819121C101814641818101E1030484C30302030303E186C")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
40 CALL CHAR(105,"102040000000000000000000007000000000000000000070",108,"020408000000000000000000000E0000000000000000000E")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50 CALL SPRITE(#M,104+S,12,R-P,C+6,#N,112+T,7,R-M,C-M,#O,96+S,N,R,C,#P,115+E,16,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
60 L=K :: CALL JOYST(M,X,Y):: CALL KEY(M,K,Z):: Y=N-Y/P :: IF K=18 THEN S=Y ELSE IF L=18 THEN F=P :: S=Y+O ELSE T=Y :: IF X THEN C=C+X ELSE IF S>O THEN S=S-O :: F=_ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
70 E=INT(RND*O+M):: Q=Q-M :: CALL PATTERN(#M,104+S,#N,112+T,#O,96+S,#P,115+E):: CALL LOCATE(#M,R-P,C+6,#N,R-M,C-M,#O,R,C,#P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
80 IF C+8+F<Q THEN 60 ELSE IF F AND S<>E+O THEN 100 ELSE IF T=E OR S-O=E THEN C=C-8 :: Q=Q+8 :: GOTO 70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
90 CALL COLOR(#P,9):: FOR I=M TO 7 :: CALL SOUND(-100,999,N):: CALL SOUND(-100,880,N):: NEXT I :: C=C-8 :: Q=Q+16 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
100 CALL COLOR(#O,9):: FOR I=M TO 7 :: CALL SOUND(-100,999-I*100,N):: NEXT I :: C=C-16 :: Q=Q+8 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Suddenly you can fit 566 ! characters in those lines, meaning across 10 lines we saved 64 bytes.

The definition of the constants in Line 10 did cost use some bytes but as soon as we start to reference those variables instead of using the actual number, we save bytes.

This was only basic replacement of each reference of the number 0, 1, 2, 3, 4 and saved us already a lot.

Now let's tweak a bit more...

50 CALL SPRITE(#M,104+S,P*O,R-P,C+6,#N,112+T,7,R-M,C-M,#O,96+S,N,R,C,#P,115+E,P*P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Instead of "12" we use P*O and instead of "16" we use P*P and voila we save 2 more bytes alone in that line.

 

Line 10 can be tweaked for 2 additional bytes by not defining Q=160 but with R+R:

10 CALL CLEAR :: M=1 :: N=2 :: O=3 :: P=4 :: CALL SCREEN(8):: CALL MAGNIFY(N):: S=N :: T=M :: R=80 :: C=128 :: Q=R+R :: E=N !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

If we define a constant for the number 100 in Line 90 and use it twice in the same line, then we need for the definition plus 2 references as much bytes as the untouched line.

And each further occurence of a 3 digit number saves us 4 bytes.

90 H=100 :: CALL COLOR(#P,9):: FOR I=M TO 7 :: CALL SOUND(-H,999,N):: CALL SOUND(-H,880,N):: NEXT I :: C=C-8 :: Q=Q+P*P :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
100 CALL COLOR(#O,9):: FOR I=M TO 7 :: CALL SOUND(-H,999-I*H,N):: NEXT I :: C=C-P*P :: Q=Q+8 :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

let's check the program in completeness after such kind of tweaks...

10 CALL CLEAR :: M=1 :: N=2 :: O=3 :: P=4 :: D=8 :: H=100 :: J=112 :: CALL SCREEN(D):: CALL MAGNIFY(N):: S=N :: T=M :: R=80 :: C=P*P*D :: Q=R+R :: E=N !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 CALL CHAR(J+M,"003030300000000000000030303000000000000000303030",J+O,"2556360A060A090F661F66060A0A00090606076E1665")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
30 CALL CHAR(H-O,"606848706070506860604078606050D86060406070686070",H,"1819121C101814641818101E1030484C30302030303E186C")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
40 CALL CHAR(105,"102040000000000000000000007000000000000000000070",J-P,"020408000000000000000000000E0000000000000000000E")!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50 CALL SPRITE(#M,H+P+S,P*O,R-P,C+6,#N,J+T,7,R-M,C-M,#O,H-P+S,N,R,C,#P,J+O+E,P*P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
60 L=K :: CALL JOYST(M,X,Y):: CALL KEY(M,K,Z):: Y=N-Y/P :: IF K=18 THEN S=Y ELSE IF L=18 THEN F=P :: S=Y+O ELSE T=Y :: IF X THEN C=C+X ELSE IF S>O THEN S=S-O :: F=_ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
70 E=INT(RND*O+M):: Q=Q-M :: CALL PATTERN(#M,H+P+S,#N,J+T,#O,H-P+S,#P,J+O+E):: CALL LOCATE(#M,R-P,C+6,#N,R-M,C-M,#O,R,C,#P,R,Q)!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
80 IF C+D+F<Q THEN 60 ELSE IF F AND S<>E+O THEN 100 ELSE IF T=E OR S-O=E THEN C=C-D :: Q=Q+D :: GOTO 70 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
90 CALL COLOR(#P,9):: FOR I=M TO 7 :: CALL SOUND(-H,999,N):: CALL SOUND(-H,880,N):: NEXT I :: C=C-D :: Q=Q+P*P :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
100 CALL COLOR(#O,9):: FOR I=M TO 7 :: CALL SOUND(-H,999-I*H,N):: NEXT I :: C=C-P*P :: Q=Q+D :: GOTO 50 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

now we have 607 ! characters, meaning we saved over 100 bytes across the 10 lines.

  • Like 4

Share this post


Link to post
Share on other sites

Initialize Variables to identical value together

100 A,B=1
110 PRINT A
120 PRINT B

Instead of A=1 :: B=1 you can use A,B=1.

 

How many bytes in your line takes a number? Does every number use the same number of bytes?

 

First of all, how many digits your number has is important. The number 10 uses one more byte than 0-9.

A negative number also takes one more byte for storing the negative character.

Therefore really bad are numbers typically used with CALL LOAD and CALL PEEK, where you have to pass a >83xx hex number.

The internal timer that sits on >8379 has to be called with "-31879", which uses 5 more byte than the number 4.

If the precise value doesn't count, it makes sense to reduce numbers like 100 for defining the length of a sound to 99 or to a constant (tip above) that is close to that number. For the same reason it also makes sense to prefer to use Ascii Chars 32-99 instead of 100-159 to save a byte on each reference.

A special case are line numbers. I didn't see a change to the length for defining the code for the line if the line number was defined by 1 digit or 5. Even if you have references to lines like you have in GOTO x or GOSUB x or THEN x ELSE x.

If somebody studied this in more detail, please share with us.

 

Share this post


Link to post
Share on other sites

To use or to not use DATA statements

 

There are several ways to use DATA statements. You can go set pointers with RESTORE x to re-read some data once again, or before other data. If you need or utilitize the RESTORE then of course there is no need to discuss whether to use DATA statements or not.

But if you only use it to initialize your numeric variables and string variables once, in the order they appear, then it is time to check the gain from them over a plain initialize of the same variables in a X=1 :: Y=9 :: ... way.

 

DATA Statements

 

First let's try to find out how much an entry in a DATA statement takes.

1 DATA 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1

We can fit up to 39 single digit numbers in one DATA statements.

Trying to fit a 40th number would result in a too long line.

But we can increase one number by two digits and that is really the maximum that fits.

1 DATA 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,100

Every increase by a digit uses an extra byte, every negation of a number is an extra byte.

 

We can therefore define DATA statements like below to figure out the actual usage of a single entry:

1x 155                  (1 time a 155 digit number)
1x 151, 1x 1         (1 time a 151 digit number, 1 time a 1 digit number)
1x 147, 2x 1
1x 143, 3x 1
1x 139, 4x 1
1x 135, 5x 1
1x 131, 6x 1
1x 127, 7x 1
1x 123, 8x 1

...
1x  11, 36x 1
1x   7, 37x 1
1x   3, 38x 1       (1 time a 3 digit number, 38 times a 1 digit number)

 

This leads to the assumption that each entry takes 3 bytes plus 1 byte per digit, so at least 4 bytes.

Tests revealed that strings are treated the same. Each entry takes 3 bytes plus 1 byte per character. Quotes are not counted.

 

In addition to the DATA statement we need a READ statement that takes 2 additional bytes for reading one additional numeric variable.

And it needs 3 additional bytes for reading one additional string variable.

 

Summary:

Numeric Variable: 6 bytes or more

String Variable: 7 bytes or more

 

Direct Variable definition

 

Now we compare those findings to the costs of a direct variable definition.

3 A=1 :: B=1 :: C=1 :: D=1 :: E=1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

space for 129 ! characters

3 A=1 :: B=1 :: C=1 :: D=1 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

space for 135 ! characters

 

From this we can calculate that one definition plus seperator costs at least 6 bytes.

Each additional digit is an extra byte, negation is an extra byte, an increase on the length of the variable name is an extry byte per character.

 

Let's switch to String Variables:

3 A$="A" :: B$="A" :: C$="A" :: D$="A" :: E$="A" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

space for 124 ! characters.

3 A$="A" :: B$="A" :: C$="A" :: D$="A" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

space for 131 ! characters.

 

From this we now know that each definition plus seperator costs at least 7 bytes.

This is different from numeric variables because of the required $ character in the variable name.

 

Summary:

Numeric variable: 6 bytes or more

String variable: 7 bytes or more

 

My Conclusio

 

From a line length in best case DATA statements cost the same amount of bytes as direct variable initialization.

However you can not use a line with a DATA statement for anything else. So you will need to ensure that you use the whole program line to not loose bytes compared to direct variable definition.

Also excluded from the comparison was the cost of the bytes required for the necessary READ command or even commands, only the additional bytes per variable for a read were taken into account.

With direct variable definition you have the advantage of placing it wherever space is left or at the spot in the program where you need it.

Speed was not taken into consideration.

Also not taken into consideration were special ways of reading in the DATA values into Array Variables (100 FOR I=1 TO 16 :: READ C(I):: NEXT I).

This could give you the edge again over direct variable definition.

 

Share this post


Link to post
Share on other sites

How to enter special characters (non-printable) Ascii characters >= 127

 

I was also experimenting with using characters above 126 in string variables to store data in those.

 

These are my findings how to achieve entering a certain Ascii Character.

There is no way to enter Ascii Values 160-175 in immediate/edit mode.

Same is true for Ascii Values 0-31 afaik.

Some key combinations require the so called REM trick depending on the used Basic. RXB has some limitations as it allows some additionals keyboard shortcuts to move to the end of the line or beginning. The REM trick goes back to Stephen Shaw and the 80's.

The Editor somehow behaves different once it detected there is a REM line being entered.

 

FCTN+V        127
CTRL+,        128
CTRL+A        129
CTRL+B        130
CTRL+C        131
CTRL+D        132*    might require REM trick
CTRL+E        133*    might require REM trick
CTRL+F        134
CTRL+G        135
CTRL+H        136
CTRL+I        137
CTRL+J        138
CTRL+K        139
CTRL+L        140
CTRL+M        141
CTRL+N        142
CTRL+O        143
CTRL+P        144
CTRL+Q        145
CTRL+R        146
CTRL+S        147*    might require REM trick
CTRL+T        148
CTRL+U        149
CTRL+V        150
CTRL+W        151
CTRL+X        152*    might require REM trick
CTRL+Y        153
CTRL+Z        154
CTRL+.        155
CTRL+;        156
CTRL+=        157
CTRL+8        158
CTRL+9        159

---

CTRL+0        176
CTRL+1        177
CTRL+2        178
CTRL+3        179
CTRL+4        180
CTRL+5        181
CTRL+6        182
CTRL+7        183
FCTN+,        184
FCTN+.        185
FCTN+/        186
CTRL+/        187
FCTN+0        188
FCTN+;        189
FCTN+B        190
FCTN+H        191
FCTN+J        192
FCTN+K        193
FCTN+L        194
FCTN+M        195
FCTN+N        196
FCTN+Q        197
FCTN+Y        198

 

Share this post


Link to post
Share on other sites

A quick investigation with Classic99 debug:

A=0

In its entirety (excluding line length and null line terminator bytes,) this statement is >41,>BE,>C8,>01,>30.  The number part alone takes three bytes: >C8 (numeric literal indicator?) >01 (number length) and >30 (ASCII representation of the number zero.)

 

Whereas

B=A

The entire statement (excluding line length and null line terminator bytes) takes up just three bytes: >42 (ASCII "B") >B2 (tokenized "=") >41 (ASCII "A")

 

Thus each positive numeric literal takes up two bytes plus the ASCII representation of its value -- negative values are prefixed by >C2,>C8 giving one additional byte. This is also exactly how it appears in the VDP RAM crunch buffer at >0820.  Interesting wizardry afoot.  I remember reading in a Commodore 64 BASIC guide a long time ago that using a period in place of a 0 (zero) uses less memory and processes more quickly.  TI XB will accept this for entry, but the value still consumes three bytes (>C8,>01,>2E) and, while it passes pre-scan, execution halts with

* SYNTAX ERROR

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...