? OSP Code Golfing Tips Sharing Thread (Page 1) ● SmileBASIC Source Forums

Sign In

*Usernames are case-sensitive
Forgot my password
Space-Restriction Challenge QSP Phase Ends on March 26!

OSP Code Golfing Tips Sharing Thread

  • #1 ✎ 973 Yttria Head Admin SmileBASIC Code Golf for the Uninitiated This thread will contain tips for getting a little more out of the OSP space restriction than pretty code allows. Remember, outside of code golf, these tricks are unhelpful and usually downright harmful. Writing clean, readable, and easily understood code is more important than saving a few characters. That said, restriction challenges can be fun, and these quirks can be useful in these extreme situations. With that out of the way: Constructing programs Don't write illegible code right away. Start by writing out your logic/program flow in language or diagrams, so you know what your program does before you don't anymore If you can't see far enough ahead to know how the logic works out already, you can still start by writing out your program as normal SmileBASIC code first. On your first draft, don't omit whitespace, keep variable names meaningful, and don't worry about optimizing numbers. You can prepare code structure so that it will be easier to optimize later, but this should be things like avoiding functions, not using long data strings, and adding comments, NOT "optimizing." You might continue to make changes to this draft, but get it to a point where it works the way you want it to, i.e. the "function" is complete. Be sure to check for any bugs at this stage too: it will be much harder to fix them later. Make a backup of this file to reference later (you might also want to write the golfed version in the same file to reference it, so having a copy is good). The next step is less destructive edits, such as moving instructions around (see notes on when spaces/instruction separators are actually necessary), changing loop types, and trying to find better approaches to your logic. Then, optimize out redundancy and comments (you should know your code pretty well, and there's always the clean copy). Start removing whitespace, and especially play with newlines/instruction separation/instruction parsing. If you have hardcoded data, try to reduce it (see data section) or even remove the need for it. Know how long your variables are so you can exclude them from the total score. The last step, once all logic has been golfed, is to remove formatting and replace variable/label/function names with one-letter mnemonics. You should be able to estimate your final score before this step, so don't do it prematurely just to measure code size. Also, write down the reduced symbols and their meaning somewhere, whether in a sticky note or as remarks in the clean file. Also, I've noticed that some people disable the syntax highlighting or make it useless colors. This is a mistake here. The highlighter is your friend as to what is valid in OSP. Easy Stuff ? vs. PRINT ? is shorthand for PRINT On the subject of printing, you can usually use a comma or semicolon to separate numeric arguments, rather than converting with STR$ cost: 1 use when: always function aliasing and redundancy optimization Almost all operations that need no arguments (e.g. operate on globals) can be converted to a function or alias if they are used more than 2 or so times DEF X <body> END cost: 10 + calls (-1 if last character in body is non-alphanumeric) use when: len(body) * calls - calls > 10 example: 'before B=POP(STACK):FOO(B+1):B=POP(STACK):FOO(B+1):B=POP(STACK) 'after DEF P B=POP(STACK)END:P:FOO(B+1)P:FOO(B+1):P words and whitespace The definition for a word is [A-Z][A-Z0-9]* (case insensitive). Instructions are words. This means that unless the next character is a letter or a number, you don't need whitespace following a statement. cost: - use when: statements can be rearranged such that a non-alphanumeric follows another word example: 'before GOTO @L 'after [email protected] numbers and whitespace similarly, since a digit can't be the first character in a word, and numbers with letters in them are invalid, whitespace/command separators following numeric literals are usually unnecessary I=I+1FOO(), for example, is perfectly valid and read as I=I+1:FOO(). There is an exception however: decimal numbers allow scientific notation with an upper or lowercase E immediately following the first numeric part. This means that 12END is illegal (since "ND" is not a valid exponent) cost: - use when: number is not followed by a word beginning with E Omitting end quotes The end of a line also ends strings. In OSP this isn't usually useful, but if you can end a string before the line wrap, it might save a single character cost: -1 use when: strings are perfectly aligned with the wrap point. Data Literal data should be avoided whenever possible. Nothing kills your character count faster than the epic poem you wrote for an intro crawl. While generative content may be an option in some cases, there are some tricks that can help cut down the cost of using data. Don't use separate DATA statements DATA"A" DATA"B" 'is the same as DATA"A","B" cost: 1 (,) use when: always, net saving is 3 * lines Use string variables instead of DATA it's best to avoid DATA, but the biggest reason is because of the code needed to read it in. At best it's something like DIM A[9]COPY A, @L and forget about a iterating loop. Instead, it's usually possible to assign a string to variable and then access that. This works for numeric data using ASC() and with strings with a little more cleverness in formatting. note that all source characters must be on the keyboard. This means full source compression is usually not a viable option[\b] Minutia Some constants are shorter than the numeric values they represent: #AQUA = &HFF00F8F8 #BLACK = &HFF000000 #BLUE = &HFF0000FF #CYAN = &HFF0000F8 #FUCHSIA = &HFFF800F8 #GRAY = &HFF808080 #GREEN = &HFF008000 #LIME = &HFF00F800 #MAGENTA = &HFFF800F8 #MAROON = &HFF800000 #NAVY = &HFF000080 #OLIVE = &HFF808000 #PURPLE = &HFF800080 #RED = &HFFF80000 #SILVER = &HFFC0C0C0 #TEAL = &HFF008080 #WHITE = &HFFF8F8F8 #YELLOW = &HFFF8F800 #X = 128 #Y = 256 #L = 512 #R = 1024 #ZL = 2048 #ZR = 4096 To loop to the start of the program (if losing all variable states is okay), @B [email protected] '8 chars EXEC. '5 chars RGB() is a function. It returns a numeric value. If your arguments are constants, replace the call with the literal value: GCOLOR RGB(255,128,0) GCOLOR-32768
    numbers are only shorter in hex if they're REALLY big, because of the &H part
    Specifically, when a leading space is needed, these ranges are shorter for hex numbers, since they don't need a leading space: GCOLOR&HF4240 GCOLOR 1000000 GCOLOR&HFFFFF GCOLOR 1048575 GCOLOR&H989680 GCOLOR 10000000 GCOLOR&HFFFFFF GCOLOR 16777215 GCOLOR&H5F5E100 GCOLOR 100000000 GCOLOR&HFFFFFFF GCOLOR 268435455 GCOLOR&H3B9ACA00 GCOLOR 1000000000 GCOLOR&H7FFFFFFF GCOLOR 2147483647 GCOLOR&H80000000 GCOLOR-2147483648 GCOLOR&HC4653600 GCOLOR-1000000000
    In addition, take advantage of the left shift operator for shortening large numbers. Omit type suffixes on function arguments. Multiplication is shorter than POW() for exponents <= 4 A*A*A*A POW(A,4) For increment and decrement by 1, INC/DEC and assignment are equal A=A+1 INC A Otherwise, INC/DEC loses by one character. Knowing math stuff helps. For example, distributive property: A=B*(C+D-E) A=B*C+B*D-B*E
    Posted Edited by Yttria
  • #2 ✎ 178 Nathaniel Amazing Contributor Someone thinks I'm an awesome person who has done so much for the community! Achievements Scholar Received for knowing a great deal about programming topics Achievements Final(?) Contest Winner I won the (possibly) final SmileBASIC Source Contest! October 2018 Programming Contest A few things that are also useful: ON instead of IF IF A>0THEN B=C:ENDIF 'BEFORE ON A>[email protected]:[email protected] 'AFTER Organization is key GCLS:BEEP 10?"STRING" 'BEFORE BEEP 10GCLS?"STRING" 'AFTER N!=0 == !!N A=A+(B!=0) 'BEFORE A=A+!!B 'AFTER Arithmetic shift example GCOLOR #BLACK:GCLS 'BEFORE GCOLOR-1<<24GCLS 'AFTER Scientific notation example A=54000B=.00078 'BEFORE A=54E3B=78E-5 'AFTER Posted Edited by Nathaniel
  • #3 ✎ 973 Yttria Head Admin Some examples: Micropaint aVoid Thing-OSP DragonBarrage Cycloid Drawing OSP 0721 Posted
  • #4 ✎ 973 Yttria Head Admin (Asked in chat) Parametric equations describing coordinates can be used in some cases to generate complicated graphics or behavior patterns easily. Here's a javascript tool to test them: http://danher6.100webspace.net/curvas/ Posted
  • #5 ✎ 105 seggiepants One idea is to simply make something that is naturally simple and short. Less to squish down that way. Posted
  • #6 ✎ 458 auceps First Year My account is over 1 year old Website Beginner Programmer I'm just starting out! I'm still trying to grasp the basics. Programming Strength osu! Is Awesome! I love osu! Express Yourself Thanks to Nathaniel, I have tested and hopefully completely golfed some general-purpose loops using various commands, so you don't have to! Convenient 6-Char Key: H5S3Z3 Posted
  • #7 ✎ 327 spaceturtles Video Games I like to play video games! Hobbies Avatar Block I didn't change my avatar for 30 days. Website Intermediate Programmer I can make programs, but I still have trouble here and there. Programming Strength Yes, noobish comment/tip, but if your IF statements end on the same line they must end with ENDIF if all the code in an OSP is going to be reduced to one line else an error will occur. Posted
  • #8 ✎ 973 Yttria Head Admin
    Yes, noobish comment/tip, but if your IF statements end on the same line they must end with ENDIF if all the code in an OSP is going to be reduced to one line else an error will occur.
    This comment forgets to mention that if you can line up those ENDIFs with the end of the line, you can use a linebreak at that position to save up to ~5 characters: ... A=5 EN| DIF:B=5...... A=5 | B=5... This is one of those situations where very thoughtful code rearranging can matter. I introduced an extra constant-holding variable for this purpose in my entry.
  • #9 ✎ 952 snail_ Helper Received for being very helpful around SmileBASIC Source Achievements OSP Contest 2 Contest Participant I participated in the second SmileBASIC Source OSP Contest! Night Person I like the quiet night and sleep late. Express Yourself SPOFS is one of the few functions that allows you to omit one of its required arguments in the same sense as you would ignore an OUT return. This can save you a byte or two if you only care about changing one of the two coordinates. SPOFS I,X,Y 'X and Y change SPOFS I,,Y 'only Y changes If anyone knows any other functions that can behave like this let me know. Posted
  • #10 ✎ 973 Yttria Head Admin Parameters in this list with a ? following them can be omitted in this way: http://smilebasicsource.com/page?pid=993 Posted
  • #11 ✎ 1697 12Me21 Head Admin Syntax Highlighter Received for creating the code syntax highlighter on SBS Night Person I like the quiet night and sleep late. Express Yourself Decoding d-pad directions: X_VEL = -SGN(BUTTON()/4<<30) Y_VEL = -SGN(BUTTON()<<30) Always outputs -1, 0, or 1, and ignores other buttons. Posted
  • #12 ✎ 952 snail_ Helper Received for being very helpful around SmileBASIC Source Achievements OSP Contest 2 Contest Participant I participated in the second SmileBASIC Source OSP Contest! Night Person I like the quiet night and sleep late. Express Yourself As mentioned in the OP you can't write END immediately after a number because the parser thinks you're trying to use E notation. Using this identity you can save a character. FUNC 1:END FUNC!.END Note this will only work for 1. Posted