# BASIC 10 Liner Contest 2021

## Recommended Posts

Posted (edited)
22 hours ago, carlsson said:

That is curious. Which system are you developing for, again? Also does RND(1) generate a floating point number of an integer? Does RND(2) generate something else? I understand that the RND syntax is different for each BASIC dialect so you need to know how yours works.

Edit: Does AMS refer to the Amstrad CPC? I managed to get it to work as a single liner in the WinAPE emulator?

Yes, for my BASIC 10 Liner entry, I'm trying to create a 50/50 chance for the player when facing an opponent. The player can move left or right and the opponent must decide which way to attack, so if the player is lucky will avoid otherwise some energy is drained. The variable for deciding which way the attack takes place must be only -1 or 1, it cannot be 0. I tried variations in CPCBox, but it looks like the CPC needs to store the Random Number into an variable before it can be times by 2 to produce 0 or 2, but would be interested to see how you got around it, the closest I seem to get with a single line includes 0, which makes it unacceptable for what I need.  The quickest solution to me seems to be n=RND*1:n=n*2-1 which gives me those 1 or -1 values.

Edited by AMSDOS

##### Share on other sites
Posted (edited)

dmsc's solution works as well, at least in BASIC 1.1 running inside an ancient version of WinAPE. I am not sure why a different emulator would give different results, or otherwise I'm misunderstanding what you are trying to do.

Edit: Actually you don't need the (1) argument for RND in this dialect so that omits three characters, bringing it down to 13. However it seems that your RND generates integers, or otherwise you would get floating point numbers from -1 to 1.

Edited by carlsson

##### Share on other sites
6 minutes ago, carlsson said:

dmsc's solution works as well, at least in BASIC 1.1 running inside an ancient version of WinAPE. I am not sure why a different emulator would give different results, or otherwise I'm misunderstanding what you are trying to do.

Edit: Actually you don't need the (1) argument for RND in this dialect so that omits three characters, bringing it down to 13. However it seems that your RND generates integers, or otherwise you would get floating point numbers from -1 to 1.

Hmm, okay. I wasn't sure if it would of worked due to the decimal number on account of me having BASIC in Integer mode (which improves performance), but that's not the case with this and the line can be shortened with:

a=(RND<0.5)*2+1

but seems to be the same length as my previous attempt.

##### Share on other sites

Yes, same number of characters but one assignment less for whatever execution time it takes to assign, retrieve and assign a variable again instead of keeping a complex calculation in temporary registers and accumulator. I wasn't aware that Locomotive BASIC could be set to integer mode, it explains a few things.

##### Share on other sites

DEFINT is used to set variables to type INT, by default variables are type REAL, so it maybe common to see DEFINT a-z at the beginning, to set all variables to Type Integer. If an variable has to be another type such as a String Character, '\$' following the variable can be used to specify a string type or if an REAL needs to be used '!' following the variable can be used. Another way of specifying Integer type is '%' following the variable name, though most people would say it's better to have DEFINT a-z at the beginning since there's no Bytes, Integers are mostly used variables and improves the BASIC program by telling BASIC variables will be Integer unless something else is found.

##### Share on other sites

Yeah, the A% syntax is commonly found elsewhere but those don't work with everything, e.g. usually FOR A%=1 TO 10 does not work while I presume if you use DEFINT A, it would still work except that no decimals are maintained.

At least we concluded that it is possible to get a random number -1 or 1 (or possibly more choices without involving zero) in a single statement.

##### Share on other sites
Posted (edited)
12 hours ago, AMSDOS said:

Yes, for my BASIC 10 Liner entry, I'm trying to create a 50/50 chance for the player when facing an opponent. The player can move left or right and the opponent must decide which way to attack, so if the player is lucky will avoid otherwise some energy is drained. The variable for deciding which way the attack takes place must be only -1 or 1, it cannot be 0. I tried variations in CPCBox, but it looks like the CPC needs to store the Random Number into an variable before it can be times by 2 to produce 0 or 2, but would be interested to see how you got around it, the closest I seem to get with a single line includes 0, which makes it unacceptable for what I need.  The quickest solution to me seems to be n=RND*1:n=n*2-1 which gives me those 1 or -1 values.

I'm only working in Atari Basic, so not sure.

In Atari, this takes up more characters but is MUCH faster (almost 30% faster).

A=(PEEK(53770)<128)*2-1

Edited by erichenneke

##### Share on other sites
11 hours ago, carlsson said:

Yeah, the A% syntax is commonly found elsewhere but those don't work with everything, e.g. usually FOR A%=1 TO 10 does not work while I presume if you use DEFINT A, it would still work except that no decimals are maintained.

At least we concluded that it is possible to get a random number -1 or 1 (or possibly more choices without involving zero) in a single statement.

I hadn't really thought about it before. A% works within a FOR loop and as BASIC will determine it to be an Integer, will perform faster as opposed to if 'A' variable being a decimal number. If I apply a STEP to that FOR loop, the STEP can be a Decimal Number to the accuracy of .5, if it's any lower it won't work on an Integer based variable, the loop becomes Infinite. This obviously doesn't happen if the variable is of Decimal Type. So this is probably why .5 is acceptable in the RND statement.

##### Share on other sites
54 minutes ago, erichenneke said:

I'm only working in Atari Basic, so not sure.

In Atari, this takes up more characters but is MUCH faster (almost 30% faster).

A=(PEEK(53770)<128)*2-1

It's a nifty trick having a spot in memory to have a random number. I'm unsure where they come from on my machine, some people use a Refresh Register 'r' as a Seed, which randomly takes a number from 0..127 I think, while others argue more (machine) code should be used to select a number across the 0..255 range, which is valid, though the question sort of becomes 'How Random do you want it?'. In BASIC I think it's using the Refresh Register as an Reference since without any RANDOMIZE a pattern emerges, though the Systems Clock can also be used with RANDOMIZE to produce a Seed for RND, though some people argue it's still not accurate enough an impose RANDOMIZE RND after a RANDOMIZE TIME. Personally, I think it's better to RANDOMIZE TIME*RND instead in case RANDOMIZE is referring to the Refresh Register.

##### Share on other sites

Yeah. On computers with a jiffy timer, sampling the lowest 8 bits often is good enough random for BASIC since it runs so slow, but for the 10Liners speed tends to be secondary, code size more important.

It reminds me of the time I made a crap game that must not use the RND keyword, so I implemented an own PRNG using a lagged Fibonacci function, I think it is called. It worked well and seems to have a fairly good pool of random numbers before it loops, but took a lot of code to implement of course and would be useless to have in this particular contest.

##### Share on other sites
Posted (edited)

RE: random number -2, -1, 1, 2

Expanding on @dmsc method for atari basic

```a=(rnd(0)<.5)*2-1:a=a+a*(rnd(0)<.5)

```

is one more character than

```
a=int(rnd(0)*4)*2-3:a=a-(a=3)+(a=-3)

```

but i'm sure there is a better idea.

Edited by thank you
no need for 0.5

##### Share on other sites

I came up with this one, 26 characters (Microsoft syntax): A=INT(INT(RND(1)*4)*1.5)-2

It probably is a way to make it even shorter, without sacrificing the even distribution of the four random numbers.

##### Share on other sites

If RND is a function that returns a float between 0 and .99999999 and N is any integer, then:

`A=INT(1+RND*N)*(-1)^(RND<0.5)`

returns numbers from this list -N, ..., -3, -2, -1, 1, 2, 3, ..., N

##### Share on other sites
5 minutes ago, vitoco said:

If RND is a function that returns a float between 0 and .99999999 and N is any integer, then:

```
A=INT(1+RND*N)*(-1)^(RND<0.5)```

returns numbers from this list -N, ..., -3, -2, -1, 1, 2, 3, ..., N

Shorter:

`A=-1^(RND<.5)*INT(1+RND*N)`

TurboBasic XL syntax, BTW.

##### Share on other sites

Excellent, I did not think of scaling that way carlsson.

I did try to think of using ^ but I'm not so good at this.

Anyway I like to see the better ideas.

##### Share on other sites

Yes, a thread like this one is both fun and useful in trading optimization tricks. Some of these last examples perhaps are quite synthetic but we've gone from "it is not possible to generate a random number -1 or 1 in a single statement" to "it is actually possible to generate a random number in the sequence -N to +N in a single statement".

##### Share on other sites

A=INT(RND(0)*4)-2:A=A+(A=0)*2

##### Share on other sites

I discovered by accident, I was able to produce a series of 1s and -1s when I altered @vitoco -3 to +3 formula to:

A=(-1)^(RND<0.5)

##### Share on other sites
1 minute ago, AMSDOS said:

I discovered by accident, I was able to produce a series of 1s and -1s when I altered @vitoco -3 to +3 formula to:

A=(-1)^(RND<0.5)

Didn't the minus sign act as unary minus? I mean, does this work for you?

`A=-1^(RND<.5)`

(just to save some chars)

##### Share on other sites
6 minutes ago, AMSDOS said:

I discovered by accident, I was able to produce a series of 1s and -1s when I altered @vitoco -3 to +3 formula to:

A=(-1)^(RND<0.5)

Nice.  In Atari Basic it must have the (0) argument on the RND to work.  However, I found that you do NOT need the parenthesis around the -1 in this case.

So in Atari Basic, this works...

A=-1^(RND(0)<.5)

##### Share on other sites
2 minutes ago, erichenneke said:

So in Atari Basic, this works...

A=-1^(RND(0)<.5)

This is cool and it works, but it's very slow.

##### Share on other sites
1 minute ago, Preppie said:

This is cool and it works, but it's very slow.

yeah, i was just going to say the same thing.

##### Share on other sites
7 minutes ago, vitoco said:

Didn't the minus sign act as unary minus? I mean, does this work for you?

```
A=-1^(RND<.5)```

(just to save some chars)

No, I tried that, but I just got -1s, anything else it's Divison by Zero or Improper Argument error. I thought it was going to be shorter to what I had earlier, but it's 1 character longer, so a bit annoying.

##### Share on other sites

random acts different on emulators rather than real hardware sometimes.... consider that also

##### Share on other sites
2 minutes ago, AMSDOS said:

No, I tried that, but I just got -1s, anything else it's Divison by Zero or Improper Argument error. I thought it was going to be shorter to what I had earlier, but it's 1 character longer, so a bit annoying.

I was surprised it worked, but on Atari Basic it does...

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.

×   Your previous content has been restored.   Clear editor

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