AMSDOS Posted March 5, 2021 Share Posted March 5, 2021 (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 March 5, 2021 by AMSDOS Adding my quickest solution. Quote Link to comment Share on other sites More sharing options...
carlsson Posted March 5, 2021 Author Share Posted March 5, 2021 (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 March 5, 2021 by carlsson 1 Quote Link to comment Share on other sites More sharing options...
AMSDOS Posted March 5, 2021 Share Posted March 5, 2021 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. Quote Link to comment Share on other sites More sharing options...
carlsson Posted March 5, 2021 Author Share Posted March 5, 2021 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. 1 Quote Link to comment Share on other sites More sharing options...
AMSDOS Posted March 5, 2021 Share Posted March 5, 2021 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. Quote Link to comment Share on other sites More sharing options...
carlsson Posted March 5, 2021 Author Share Posted March 5, 2021 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. Quote Link to comment Share on other sites More sharing options...
erichenneke Posted March 5, 2021 Share Posted March 5, 2021 (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 March 5, 2021 by erichenneke Quote Link to comment Share on other sites More sharing options...
AMSDOS Posted March 5, 2021 Share Posted March 5, 2021 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. 2 Quote Link to comment Share on other sites More sharing options...
AMSDOS Posted March 5, 2021 Share Posted March 5, 2021 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. Quote Link to comment Share on other sites More sharing options...
carlsson Posted March 5, 2021 Author Share Posted March 5, 2021 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. 2 Quote Link to comment Share on other sites More sharing options...
thank you Posted March 5, 2021 Share Posted March 5, 2021 (edited) @carlsson 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 March 5, 2021 by thank you no need for 0.5 1 Quote Link to comment Share on other sites More sharing options...
carlsson Posted March 5, 2021 Author Share Posted March 5, 2021 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. Quote Link to comment Share on other sites More sharing options...
vitoco Posted March 5, 2021 Share Posted March 5, 2021 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 Quote Link to comment Share on other sites More sharing options...
vitoco Posted March 5, 2021 Share Posted March 5, 2021 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. 2 Quote Link to comment Share on other sites More sharing options...
thank you Posted March 5, 2021 Share Posted March 5, 2021 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. Quote Link to comment Share on other sites More sharing options...
carlsson Posted March 5, 2021 Author Share Posted March 5, 2021 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". 1 Quote Link to comment Share on other sites More sharing options...
Preppie Posted March 5, 2021 Share Posted March 5, 2021 A=INT(RND(0)*4)-2:A=A+(A=0)*2 Quote Link to comment Share on other sites More sharing options...
AMSDOS Posted March 5, 2021 Share Posted March 5, 2021 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) Quote Link to comment Share on other sites More sharing options...
vitoco Posted March 5, 2021 Share Posted March 5, 2021 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) Quote Link to comment Share on other sites More sharing options...
erichenneke Posted March 5, 2021 Share Posted March 5, 2021 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) 1 Quote Link to comment Share on other sites More sharing options...
Preppie Posted March 6, 2021 Share Posted March 6, 2021 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. Quote Link to comment Share on other sites More sharing options...
erichenneke Posted March 6, 2021 Share Posted March 6, 2021 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. Quote Link to comment Share on other sites More sharing options...
AMSDOS Posted March 6, 2021 Share Posted March 6, 2021 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. Quote Link to comment Share on other sites More sharing options...
_The Doctor__ Posted March 6, 2021 Share Posted March 6, 2021 random acts different on emulators rather than real hardware sometimes.... consider that also 1 Quote Link to comment Share on other sites More sharing options...
erichenneke Posted March 6, 2021 Share Posted March 6, 2021 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... 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.